MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / build_sidecar

Function build_sidecar

nodedb-query/src/msgpack_scan/sidecar.rs:132–184  ·  view source on GitHub ↗

Build a sidecar-indexed document from raw msgpack bytes. Scans the map keys once and appends the sidecar index. Returns `None` if the buffer is not a valid msgpack map or has too many fields (> u16::MAX). Entries are stored sorted by `field_hash` to enable binary search.

(msgpack: &[u8])

Source from the content-addressed store, hash-verified

130/// the buffer is not a valid msgpack map or has too many fields (> u16::MAX).
131/// Entries are stored sorted by `field_hash` to enable binary search.
132pub fn build_sidecar(msgpack: &[u8]) -> Option<Vec<u8>> {
133 let (count, mut pos) = map_header(msgpack, 0)?;
134 if count > u16::MAX as usize {
135 return None;
136 }
137
138 let mut entries: Vec<SidecarEntry> = Vec::with_capacity(count);
139
140 for _ in 0..count {
141 // Read key string bounds (start of str content, length of content).
142 let (key_data_start, key_data_len) = str_bounds(msgpack, pos)?;
143 let key_bytes = msgpack.get(key_data_start..key_data_start + key_data_len)?;
144 let field_hash = fnv1a_hash(key_bytes);
145
146 // Skip over the key to reach the value.
147 pos = skip_value(msgpack, pos)?;
148 let value_start = pos;
149 let value_end = skip_value(msgpack, pos)?;
150
151 let value_len = value_end.checked_sub(value_start)?;
152 if value_start > u32::MAX as usize || value_len > u32::MAX as usize {
153 return None;
154 }
155
156 entries.push(SidecarEntry {
157 field_hash,
158 value_offset: value_start as u32,
159 value_len: value_len as u32,
160 });
161
162 pos = value_end;
163 }
164
165 // Sort by hash to allow binary search during lookup.
166 entries.sort_unstable_by_key(|e| e.field_hash);
167
168 let entry_count = entries.len();
169 let total_len = msgpack.len() + entry_count * ENTRY_SIZE + TRAILER_SIZE;
170 let mut out = Vec::with_capacity(total_len);
171 out.extend_from_slice(msgpack);
172
173 for e in &entries {
174 out.extend_from_slice(&e.field_hash.to_le_bytes());
175 out.extend_from_slice(&e.value_offset.to_le_bytes());
176 out.extend_from_slice(&e.value_len.to_le_bytes());
177 }
178
179 // Trailer: entry_count (u16 LE) + magic (u32 LE).
180 out.extend_from_slice(&(entry_count as u16).to_le_bytes());
181 out.extend_from_slice(&SIDECAR_MAGIC_LE);
182
183 Some(out)
184}
185
186/// Look up a field's byte range `(start, end)` using the sidecar index.
187///

Calls 7

map_headerFunction · 0.85
str_boundsFunction · 0.85
skip_valueFunction · 0.85
fnv1a_hashFunction · 0.70
getMethod · 0.45
pushMethod · 0.45
lenMethod · 0.45