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

Function merge_fields

nodedb-query/src/msgpack_scan/writer.rs:196–276  ·  view source on GitHub ↗

Merge field updates into a msgpack map without full decode. Takes a base msgpack map and a list of `(field_name, raw_msgpack_value)` updates. Returns a new msgpack map with updated fields replaced and new fields appended. Fields not in `updates` are copied from the original.

(base: &[u8], updates: &[(&str, &[u8])])

Source from the content-addressed store, hash-verified

194/// Returns a new msgpack map with updated fields replaced and new fields appended.
195/// Fields not in `updates` are copied from the original.
196pub fn merge_fields(base: &[u8], updates: &[(&str, &[u8])]) -> Vec<u8> {
197 use std::collections::HashSet;
198
199 let update_names: HashSet<&str> = updates.iter().map(|(k, _)| *k).collect();
200
201 let (count, body_start) = match crate::msgpack_scan::reader::map_header(base, 0) {
202 Some(v) => v,
203 None => {
204 // Not a valid map — build from updates only.
205 let mut buf = Vec::with_capacity(updates.len() * 32);
206 write_map_header(&mut buf, updates.len());
207 for (k, v) in updates {
208 write_str(&mut buf, k);
209 buf.extend_from_slice(v);
210 }
211 return buf;
212 }
213 };
214
215 // Count fields: existing (not overwritten) + updates.
216 let mut kept = 0usize;
217 let mut pos = body_start;
218 for _ in 0..count {
219 let key = crate::msgpack_scan::reader::read_str(base, pos);
220 pos = match crate::msgpack_scan::reader::skip_value(base, pos) {
221 Some(p) => p,
222 None => break,
223 };
224 pos = match crate::msgpack_scan::reader::skip_value(base, pos) {
225 Some(p) => p,
226 None => break,
227 };
228 if let Some(k) = &key {
229 if !update_names.contains(&k[..]) {
230 kept += 1;
231 }
232 } else {
233 kept += 1;
234 }
235 }
236
237 let new_count = kept + updates.len();
238 let mut buf = Vec::with_capacity(
239 base.len()
240 + updates
241 .iter()
242 .map(|(k, v)| k.len() + v.len() + 4)
243 .sum::<usize>(),
244 );
245 write_map_header(&mut buf, new_count);
246
247 // Copy non-overwritten fields from base.
248 pos = body_start;
249 for _ in 0..count {
250 let key_start = pos;
251 let key = crate::msgpack_scan::reader::read_str(base, pos);
252 pos = match crate::msgpack_scan::reader::skip_value(base, pos) {
253 Some(p) => p,

Callers 1

execute_point_updateMethod · 0.85

Calls 9

map_headerFunction · 0.85
skip_valueFunction · 0.85
collectMethod · 0.80
write_map_headerFunction · 0.70
write_strFunction · 0.70
read_strFunction · 0.70
iterMethod · 0.45
lenMethod · 0.45
containsMethod · 0.45

Tested by

no test coverage detected