1pub use crate::Buffer;
4
5use crate::Scalar;
6use crate::hash::hash128;
7
8#[derive(Clone, Copy, Debug, Default)]
9pub struct Segment {
10 pub pos: usize,
11 pub len: usize,
12}
13
14impl Segment {
15 #[inline(always)]
16 pub fn end(self) -> usize {
17 self.pos - self.len
18 }
19}
20
21#[derive(Clone, Copy, Debug, Default)]
22pub struct Unit {
23 inline_len: usize,
24 inline_data: [u32; 3],
25 segment: Segment,
26}
27
28impl Unit {
29 #[inline(always)]
30 pub fn empty() -> Self {
31 Self::default()
32 }
33
34 #[inline(always)]
35 pub fn inline(words: &[u32]) -> Self {
36 assert!(words.len() <= 3);
37 let mut data = [0u32; 3];
38 data[..words.len()].copy_from_slice(words);
39 Self {
40 inline_len: words.len(),
41 inline_data: data,
42 segment: Segment::default(),
43 }
44 }
45
46 #[inline(always)]
47 pub fn segment(last: usize, now: usize) -> Self {
48 Self {
49 inline_len: 0,
50 inline_data: [0; 3],
51 segment: Segment {
52 pos: now,
53 len: now - last,
54 },
55 }
56 }
57
58 #[inline(always)]
59 pub fn size(&self) -> usize {
60 if self.inline_len != 0 {
61 self.inline_len
62 } else {
63 self.segment.len
64 }
65 }
66
67 #[inline(always)]
68 pub fn is_empty(&self) -> bool {
69 self.size() == 0
70 }
71
72 #[inline(always)]
73 pub fn is_segment(&self) -> bool {
74 self.inline_len == 0 && self.segment.len != 0
75 }
76
77 #[inline(always)]
78 pub fn inline_words(&self) -> &[u32] {
79 &self.inline_data[..self.inline_len]
80 }
81
82 #[inline(always)]
83 pub fn segment_info(&self) -> Segment {
84 self.segment
85 }
86}
87
88#[inline(always)]
89fn write_varint(buf: &mut [u8; 5], mut n: u32) -> usize {
90 let mut written = 0usize;
91 while (n & !0x7f) != 0 {
92 buf[written] = 0x80 | (n as u8 & 0x7f);
93 written += 1;
94 n >>= 7;
95 }
96 buf[written] = n as u8;
97 written + 1
98}
99
100#[inline(always)]
101fn offset(off: usize) -> u32 {
102 ((off as u32) << 2) | 3
103}
104
105#[inline(always)]
106fn copy_inline(body: &mut [u32], body_index: &mut usize, pos: &mut usize, field: &Unit) {
107 let len = field.inline_len;
108 body[*body_index..*body_index + len].copy_from_slice(field.inline_words());
109 *body_index += len;
110 *pos -= len;
111}
112
113#[inline(always)]
114fn unit_words<'a>(unit: &'a Unit, buffer: &'a Buffer) -> Option<&'a [u32]> {
115 if unit.inline_len != 0 {
116 return Some(unit.inline_words());
117 }
118 if unit.segment.len == 0 {
119 return Some(&[]);
120 }
121 let start = buffer.len().checked_sub(unit.segment.pos)?;
122 buffer.view().get(start..start + unit.segment.len)
123}
124
125#[inline(always)]
126fn pick_unit(unit: &mut Unit, buffer: &mut Buffer, tail: &mut usize, width: usize) {
127 if unit.inline_len != 0 {
128 return;
129 }
130
131 let seg = unit.segment;
132 if seg.len <= width {
133 let start = buffer.len() - seg.pos;
134 let words = &buffer.head()[start..start + seg.len];
135 unit.inline_len = seg.len;
136 unit.inline_data[..seg.len].copy_from_slice(words);
137 return;
138 }
139
140 let start = buffer.len() - seg.pos;
141 let end = start + seg.len;
142 if *tail > end {
143 let new_start = *tail - seg.len;
144 buffer.head_mut().copy_within(start..end, new_start);
145 unit.segment.pos -= new_start - start;
146 *tail = new_start;
147 } else {
148 debug_assert!(*tail >= seg.len);
149 *tail -= seg.len;
150 }
151}
152
153#[inline(always)]
154fn mark_unit(unit: &Unit, buffer: &mut Buffer, width: usize) {
155 let expanded_len = buffer.len() + width;
156 let cell = buffer.expand(width);
157 if unit.inline_len != 0 {
158 cell[..unit.inline_len].copy_from_slice(unit.inline_words());
159 for word in &mut cell[unit.inline_len..] {
160 *word = 0;
161 }
162 } else {
163 cell[0] = offset(expanded_len - unit.segment.pos);
164 for word in &mut cell[1..] {
165 *word = 0;
166 }
167 }
168}
169
170#[inline(always)]
171fn best_array_size(elements: &[Unit]) -> (usize, usize) {
172 let mut sizes = [0usize; 3];
173 for element in elements {
174 sizes[0] += 1;
175 sizes[1] += 2;
176 sizes[2] += 3;
177 let len = element.size();
178 if len <= 1 {
179 continue;
180 }
181 sizes[0] += len;
182 if len <= 2 {
183 continue;
184 }
185 sizes[1] += len;
186 if len <= 3 {
187 continue;
188 }
189 sizes[2] += len;
190 }
191
192 let mut mode = 0usize;
193 for idx in 1..3 {
194 if sizes[idx] < sizes[mode] {
195 mode = idx;
196 }
197 }
198 (sizes[mode], mode + 1)
199}
200
201#[inline(always)]
202fn best_array_size_pairs(elements: &[(Unit, Unit)]) -> ((usize, usize), (usize, usize)) {
203 let mut key_sizes = [0usize; 3];
204 let mut value_sizes = [0usize; 3];
205 for (key, value) in elements {
206 for sizes in [&mut key_sizes, &mut value_sizes] {
207 sizes[0] += 1;
208 sizes[1] += 2;
209 sizes[2] += 3;
210 }
211
212 let key_len = key.size();
213 if key_len > 1 {
214 key_sizes[0] += key_len;
215 if key_len > 2 {
216 key_sizes[1] += key_len;
217 if key_len > 3 {
218 key_sizes[2] += key_len;
219 }
220 }
221 }
222
223 let value_len = value.size();
224 if value_len > 1 {
225 value_sizes[0] += value_len;
226 if value_len > 2 {
227 value_sizes[1] += value_len;
228 if value_len > 3 {
229 value_sizes[2] += value_len;
230 }
231 }
232 }
233 }
234
235 let mut key_mode = 0usize;
236 let mut value_mode = 0usize;
237 for idx in 1..3 {
238 if key_sizes[idx] < key_sizes[key_mode] {
239 key_mode = idx;
240 }
241 if value_sizes[idx] < value_sizes[value_mode] {
242 value_mode = idx;
243 }
244 }
245
246 (
247 (key_sizes[key_mode], key_mode + 1),
248 (value_sizes[value_mode], value_mode + 1),
249 )
250}
251
252#[inline(always)]
253fn perfect_hash_section(size: usize) -> usize {
254 ((size * 105).saturating_add(255) / 256).max(10)
255}
256
257#[inline(always)]
258fn perfect_hash_bitmap_size(section: usize) -> usize {
259 ((section * 3 + 31) & !31) / 4
260}
261
262#[inline(always)]
263fn set_bit2(vec: &mut [u8], pos: usize, val: u8) {
264 let shift = ((pos & 3) << 1) as u8;
265 let idx = pos >> 2;
266 vec[idx] &= !(3u8 << shift);
267 vec[idx] |= (val & 3) << shift;
268}
269
270#[inline(always)]
271fn get_bit2(vec: &[u8], pos: usize) -> u8 {
272 (vec[pos >> 2] >> ((pos & 3) << 1)) & 3
273}
274
275#[derive(Clone, Copy)]
276struct Edge {
277 slots: [usize; 3],
278}
279
280#[inline(always)]
281fn peel_graph(edges: &[Edge], slot_cnt: usize) -> Option<Vec<usize>> {
282 const NONE: usize = usize::MAX;
283
284 #[derive(Clone, Copy)]
285 struct Vertex {
286 slot: usize,
287 prev: usize,
288 next: usize,
289 }
290
291 let mut heads = vec![NONE; slot_cnt];
292 let mut vertices = vec![
293 Vertex {
294 slot: NONE,
295 prev: NONE,
296 next: NONE,
297 };
298 edges.len() * 3
299 ];
300
301 for (edge_idx, edge) in edges.iter().enumerate() {
302 for (slot_index, &slot) in edge.slots.iter().enumerate() {
303 let node = edge_idx * 3 + slot_index;
304 let head = heads[slot];
305 vertices[node] = Vertex {
306 slot,
307 prev: NONE,
308 next: head,
309 };
310 if head != NONE {
311 vertices[head].prev = node;
312 }
313 heads[slot] = node;
314 }
315 }
316
317 let mut queue = Vec::with_capacity(slot_cnt);
318 for (slot, &head) in heads.iter().enumerate() {
319 if head != NONE && vertices[head].next == NONE {
320 queue.push(slot);
321 }
322 }
323 let mut queue_head = 0usize;
324
325 let mut order = Vec::with_capacity(edges.len());
326
327 while let Some(&slot) = queue.get(queue_head) {
328 queue_head += 1;
329 let head = heads[slot];
330 if head == NONE || vertices[head].next != NONE {
331 continue;
332 }
333 let edge_idx = head / 3;
334 order.push(edge_idx);
335
336 for offset in 0..3 {
337 let node = edge_idx * 3 + offset;
338 let vertex = vertices[node];
339 if vertex.slot == NONE {
340 continue;
341 }
342
343 if vertex.prev != NONE {
344 vertices[vertex.prev].next = vertex.next;
345 } else {
346 heads[vertex.slot] = vertex.next;
347 }
348 if vertex.next != NONE {
349 vertices[vertex.next].prev = vertex.prev;
350 }
351
352 let head = heads[vertex.slot];
353 if head != NONE && vertices[head].next == NONE {
354 queue.push(vertex.slot);
355 }
356 vertices[node].slot = NONE;
357 }
358 }
359
360 if order.len() == edges.len() {
361 Some(order)
362 } else {
363 None
364 }
365}
366
367#[inline(always)]
368fn count_valid_slots(bitmap: &[u8], block: usize) -> usize {
369 let start = block * 8;
370 let bits = u64::from_le_bytes(
371 bitmap[start..start + 8]
372 .try_into()
373 .expect("bitmap block must fit"),
374 );
375 count_valid_slots_in_word(bits)
376}
377
378#[inline(always)]
379fn locate_in_perfect_hash(index: &[u8], key: &[u8]) -> Option<usize> {
380 let size = u32::from_le_bytes(index.get(..4)?.try_into().ok()?) as usize & 0x0fff_ffff;
381 if size < 2 {
382 return Some(0);
383 }
384 let section = perfect_hash_section(size);
385 let section_u32 = section as u32;
386 let section_magic = fast_mod_magic(section_u32);
387 let bitmap_size = perfect_hash_bitmap_size(section);
388 let bitmap = index.get(8..8 + bitmap_size)?;
389 let table = index.get(8 + bitmap_size..)?;
390 let seed = u32::from_le_bytes(index.get(4..8)?.try_into().ok()?) as u64;
391 let code = hash128(key, seed);
392 let slots = [
393 fast_mod_u32(code[0], section_u32, section_magic) as usize,
394 fast_mod_u32(code[1], section_u32, section_magic) as usize + section,
395 fast_mod_u32(code[2], section_u32, section_magic) as usize + section * 2,
396 ];
397 let m = get_bit2(bitmap, slots[0]) as usize
398 + get_bit2(bitmap, slots[1]) as usize
399 + get_bit2(bitmap, slots[2]) as usize;
400 let slot = slots[m % 3];
401 let block = slot >> 5;
402 let bit = slot & 31;
403
404 let off = if size > u16::MAX as usize {
405 u32::from_le_bytes(table.get(block * 4..block * 4 + 4)?.try_into().ok()?) as usize
406 } else if size > u8::MAX as usize {
407 u16::from_le_bytes(table.get(block * 2..block * 2 + 2)?.try_into().ok()?) as usize
408 } else if size > 24 {
409 *table.get(block)? as usize
410 } else {
411 0
412 };
413
414 let word_start = block * 8;
415 let bits = u64::from_le_bytes(bitmap.get(word_start..word_start + 8)?.try_into().ok()?);
416 let masked = bits | (u64::MAX << (bit << 1));
417 Some(off + count_valid_slots_in_word(masked))
418}
419
420#[inline(always)]
421fn count_valid_slots_in_word(bits: u64) -> usize {
422 let invalid = ((bits & 0x5555_5555_5555_5555) & (bits >> 1)).count_ones() as usize;
423 32 - invalid
424}
425
426#[inline(always)]
427fn fast_mod_magic(divisor: u32) -> u64 {
428 u64::MAX / divisor as u64 + 1
429}
430
431#[inline(always)]
432fn fast_mod_u32(value: u32, divisor: u32, magic: u64) -> u32 {
433 let low = magic.wrapping_mul(value as u64);
434 (((low as u128) * divisor as u128) >> 64) as u32
435}
436
437#[inline(always)]
438pub fn build_perfect_hash_index<K: AsRef<[u8]>>(keys: &[K]) -> Option<Vec<u8>> {
439 Some(build_perfect_hash_index_with_positions(keys)?.0)
440}
441
442#[inline(always)]
443pub fn build_perfect_hash_index_with_positions<K: AsRef<[u8]>>(
444 keys: &[K],
445) -> Option<(Vec<u8>, Vec<usize>)> {
446 let total = keys.len();
447 if total >= (1usize << 28) {
448 return None;
449 }
450 if total <= 1 {
451 return Some(((total as u32).to_le_bytes().to_vec(), vec![0; total]));
452 }
453
454 let section = perfect_hash_section(total);
455 let section_u32 = section as u32;
456 let section_magic = fast_mod_magic(section_u32);
457 let slot_cnt = section * 3;
458 let bitmap_size = perfect_hash_bitmap_size(section);
459
460 let mut seed = 0u32;
461 let (edges, order) = loop {
462 let edges: Vec<_> = keys
463 .iter()
464 .map(|key| {
465 let code = hash128(key.as_ref(), seed as u64);
466 Edge {
467 slots: [
468 fast_mod_u32(code[0], section_u32, section_magic) as usize,
469 fast_mod_u32(code[1], section_u32, section_magic) as usize + section,
470 fast_mod_u32(code[2], section_u32, section_magic) as usize + section * 2,
471 ],
472 }
473 })
474 .collect();
475 if let Some(order) = peel_graph(&edges, slot_cnt) {
476 break (edges, order);
477 }
478 seed = seed.wrapping_add(1);
479 if seed == 0 {
480 return None;
481 }
482 };
483
484 let mut bitmap = vec![0xffu8; bitmap_size];
485 let mut taken = vec![false; slot_cnt];
486 for &edge_idx in order.iter().rev() {
487 let [a, b, c] = edges[edge_idx].slots;
488 let (chosen, target) = if !taken[a] {
489 taken[a] = true;
490 taken[b] = true;
491 taken[c] = true;
492 (a, 0u8)
493 } else if !taken[b] {
494 taken[b] = true;
495 taken[c] = true;
496 (b, 1u8)
497 } else {
498 taken[c] = true;
499 (c, 2u8)
500 };
501
502 let sum = match chosen {
503 x if x == a => get_bit2(&bitmap, b) as u16 + get_bit2(&bitmap, c) as u16,
504 x if x == b => get_bit2(&bitmap, a) as u16 + get_bit2(&bitmap, c) as u16,
505 _ => get_bit2(&bitmap, a) as u16 + get_bit2(&bitmap, b) as u16,
506 };
507 let chosen_val = ((target as i16 - (sum % 3) as i16 + 3) % 3) as u8;
508 set_bit2(&mut bitmap, chosen, chosen_val);
509 }
510
511 let mut out = Vec::with_capacity(8 + bitmap_size + bitmap_size / 2);
512 out.extend_from_slice(&(total as u32).to_le_bytes());
513 out.extend_from_slice(&seed.to_le_bytes());
514 out.extend_from_slice(&bitmap);
515
516 if total > u16::MAX as usize {
517 let mut cnt = 0u32;
518 for block in 0..(bitmap_size / 8) {
519 out.extend_from_slice(&cnt.to_le_bytes());
520 cnt += count_valid_slots(&bitmap, block) as u32;
521 }
522 } else if total > u8::MAX as usize {
523 let mut cnt = 0u16;
524 for block in 0..(bitmap_size / 8) {
525 out.extend_from_slice(&cnt.to_le_bytes());
526 cnt += count_valid_slots(&bitmap, block) as u16;
527 }
528 } else if total > 24 {
529 let mut cnt = 0u8;
530 for block in 0..(bitmap_size / 8) {
531 out.push(cnt);
532 cnt += count_valid_slots(&bitmap, block) as u8;
533 }
534 }
535
536 let mut positions = Vec::with_capacity(keys.len());
537 for key in keys.iter() {
538 positions.push(locate_in_perfect_hash(&out, key.as_ref())?);
539 }
540
541 Some((out, positions))
542}
543
544#[inline(always)]
545pub fn fold_field(buffer: &mut Buffer, unit: &mut Unit) {
546 if !unit.is_segment() || unit.segment.len >= 4 || unit.segment.pos != buffer.len() {
547 return;
548 }
549 let seg = unit.segment;
550 let head = buffer.view();
551 unit.inline_len = seg.len;
552 unit.inline_data[..seg.len].copy_from_slice(&head[..seg.len]);
553 unit.segment = Segment::default();
554 buffer.shrink(seg.len);
555}
556
557#[inline(always)]
558pub fn serialize_scalar<T: Scalar>(value: T) -> Unit {
559 let mut words = [0u32; 3];
560 let word_len = T::WIDTH;
561 value
562 .write_words(&mut words[..word_len])
563 .expect("scalar width must match");
564 Unit {
565 inline_len: word_len,
566 inline_data: words,
567 segment: Segment::default(),
568 }
569}
570
571#[inline(always)]
572pub fn serialize_bool(value: bool) -> Unit {
573 Unit::inline(&[u32::from(value)])
574}
575
576#[inline(always)]
577pub fn serialize_bytes(bytes: &[u8], buffer: &mut Buffer) -> Option<Unit> {
578 if bytes.len() >= (1usize << 30) {
579 return None;
580 }
581 let mark = (bytes.len() as u32) << 2;
582 let mut header = [0u8; 5];
583 let header_size = write_varint(&mut header, mark);
584 let total_words = (header_size + bytes.len()).div_ceil(4);
585
586 let last = buffer.len();
587 let mut inline = [0u32; 3];
588 if total_words == 1 {
589 let raw = unsafe { core::slice::from_raw_parts_mut(inline.as_mut_ptr().cast::<u8>(), 4) };
590 raw.fill(0);
591 raw[..header_size].copy_from_slice(&header[..header_size]);
592 raw[header_size..header_size + bytes.len()].copy_from_slice(bytes);
593 Some(Unit {
594 inline_len: 1,
595 inline_data: inline,
596 segment: Segment::default(),
597 })
598 } else {
599 let words = buffer.expand(total_words);
600 words[total_words - 1] = 0;
601 let raw = unsafe {
602 core::slice::from_raw_parts_mut(words.as_mut_ptr().cast::<u8>(), total_words * 4)
603 };
604 raw[..header_size].copy_from_slice(&header[..header_size]);
605 raw[header_size..header_size + bytes.len()].copy_from_slice(bytes);
606 Some(Unit::segment(last, buffer.len()))
607 }
608}
609
610#[inline(always)]
611pub fn serialize_str(value: &str, buffer: &mut Buffer) -> Option<Unit> {
612 serialize_bytes(value.as_bytes(), buffer)
613}
614
615#[inline(always)]
616pub fn serialize_message_at(fields: &mut [Unit], buffer: &mut Buffer, last: usize) -> Option<Unit> {
617 if fields.is_empty() {
618 return None;
619 }
620 let used_len = fields
621 .iter()
622 .rposition(|unit| !unit.is_empty())
623 .map(|index| index + 1)
624 .unwrap_or(0);
625 if used_len == 0 {
626 let last = buffer.len();
627 buffer.put(0);
628 return Some(Unit::segment(last, buffer.len()));
629 }
630 let fields = &mut fields[..used_len];
631
632 let mut body_size = 0usize;
633 let mut size = 0usize;
634 for field in fields.iter().rev() {
635 if field.inline_len != 0 {
636 body_size += field.inline_len;
637 size += field.inline_len;
638 } else if field.segment.len != 0 {
639 body_size += 1;
640 size += field.segment.len;
641 }
642 }
643 if size >= (1usize << 30) {
644 return None;
645 }
646
647 let section = (fields.len() + 12) / 25;
648 if section > 0xff {
649 return None;
650 }
651
652 let head_size = 1 + section * 2;
653 let current_size = buffer.len();
654 let total_size = current_size + head_size + body_size;
655 let block = buffer.expand(head_size + body_size);
656 let (head, body) = block.split_at_mut(head_size);
657 let mut body_index = 0usize;
658 let mut pos = total_size - head_size;
659 head.fill(0);
660 head[0] = section as u32;
661
662 let mut cnt = 0u32;
663 for (i, field) in fields.iter().take(12).enumerate() {
664 if field.inline_len != 0 {
665 head[0] |= (field.inline_len as u32) << (8 + i * 2);
666 cnt += field.inline_len as u32;
667 copy_inline(body, &mut body_index, &mut pos, field);
668 } else if field.segment.len != 0 {
669 head[0] |= 1u32 << (8 + i * 2);
670 cnt += 1;
671 body[body_index] = offset(pos - field.segment.pos);
672 body_index += 1;
673 pos -= 1;
674 }
675 }
676
677 for sec in 0..section {
678 let start = 12 + sec * 25;
679 let end = fields.len().min(start + 25);
680 let mut mark = (cnt as u64) << 50;
681 let mut shift = 0usize;
682 for field in &fields[start..end] {
683 if field.inline_len != 0 {
684 mark |= (field.inline_len as u64) << shift;
685 cnt += field.inline_len as u32;
686 copy_inline(body, &mut body_index, &mut pos, field);
687 } else if field.segment.len != 0 {
688 mark |= 1u64 << shift;
689 cnt += 1;
690 body[body_index] = offset(pos - field.segment.pos);
691 body_index += 1;
692 pos -= 1;
693 }
694 shift += 2;
695 }
696 head[1 + sec * 2] = mark as u32;
697 head[1 + sec * 2 + 1] = (mark >> 32) as u32;
698 }
699
700 Some(Unit::segment(last, buffer.len()))
701}
702
703#[inline(always)]
704pub fn serialize_message(fields: &mut [Unit], buffer: &mut Buffer) -> Option<Unit> {
705 serialize_message_at(fields, buffer, buffer.len())
706}
707
708#[inline(always)]
709pub fn serialize_array_at_mut(
710 elements: &mut [Unit],
711 buffer: &mut Buffer,
712 last: usize,
713) -> Option<Unit> {
714 if elements.is_empty() {
715 return Some(Unit::inline(&[1]));
716 }
717
718 let (size, width) = best_array_size(elements);
719 if size >= (1usize << 30) {
720 return None;
721 }
722
723 let mut tail = buffer.len().checked_sub(last)?;
724 for unit in elements.iter_mut().rev() {
725 pick_unit(unit, buffer, &mut tail, width);
726 }
727 buffer.shrink(tail);
728 for unit in elements.iter().rev() {
729 mark_unit(unit, buffer, width);
730 }
731 buffer.put(((elements.len() as u32) << 2) | width as u32);
732 Some(Unit::segment(last, buffer.len()))
733}
734
735#[inline(always)]
736pub fn serialize_array_at(elements: &[Unit], buffer: &mut Buffer, last: usize) -> Option<Unit> {
737 if elements.is_empty() {
738 return Some(Unit::inline(&[1]));
739 }
740
741 let (size, width) = best_array_size(elements);
742 if size >= (1usize << 30) {
743 return None;
744 }
745
746 let mut payloads = Vec::with_capacity(size.saturating_sub(elements.len() * width));
747 let mut cells = vec![0u32; elements.len() * width];
748 let cells_len = cells.len();
749 for (index, unit) in elements.iter().enumerate() {
750 let words = unit_words(unit, buffer)?;
751 let cell = &mut cells[index * width..(index + 1) * width];
752 if words.len() <= width {
753 cell[..words.len()].copy_from_slice(words);
754 } else {
755 let payload_start = cells_len.checked_add(payloads.len())?;
756 let cell_start = index.checked_mul(width)?;
757 cell[0] = offset(payload_start.checked_sub(cell_start)?);
758 payloads.extend_from_slice(words);
759 }
760 }
761 buffer.shrink(buffer.len().checked_sub(last)?);
762 buffer.put_words(&payloads);
763 buffer.put_words(&cells);
764 buffer.put(((elements.len() as u32) << 2) | width as u32);
765 Some(Unit::segment(last, buffer.len()))
766}
767
768#[inline(always)]
769pub fn serialize_array(elements: &[Unit], buffer: &mut Buffer) -> Option<Unit> {
770 serialize_array_at(elements, buffer, buffer.len())
771}
772
773#[inline(always)]
774pub fn serialize_map_at_mut(
775 index: &[u8],
776 keys: &mut [Unit],
777 values: &mut [Unit],
778 buffer: &mut Buffer,
779 last: usize,
780) -> Option<Unit> {
781 if keys.len() != values.len() {
782 return None;
783 }
784 if keys.is_empty() {
785 return Some(Unit::inline(&[5u32 << 28]));
786 }
787
788 let (key_size, key_width) = best_array_size(keys);
789 let (value_size, value_width) = best_array_size(values);
790 let index_words = index.len().div_ceil(4);
791 let size = index_words + key_size + value_size;
792 if size >= (1usize << 30) {
793 return None;
794 }
795
796 let mut tail = buffer.len().checked_sub(last)?;
797 for index in (0..keys.len()).rev() {
798 pick_unit(&mut values[index], buffer, &mut tail, value_width);
799 pick_unit(&mut keys[index], buffer, &mut tail, key_width);
800 }
801 buffer.shrink(tail);
802 for index in (0..keys.len()).rev() {
803 mark_unit(&values[index], buffer, value_width);
804 mark_unit(&keys[index], buffer, key_width);
805 }
806
807 let head = buffer.expand(index_words);
808 head.fill(0);
809 let raw =
810 unsafe { core::slice::from_raw_parts_mut(head.as_mut_ptr().cast::<u8>(), index_words * 4) };
811 raw[..index.len()].copy_from_slice(index);
812 head[0] |= (key_width as u32) << 30 | (value_width as u32) << 28;
813 Some(Unit::segment(last, buffer.len()))
814}
815
816#[inline(always)]
817pub(crate) fn serialize_map_pairs_at_mut(
818 index: &[u8],
819 pairs: &mut [(Unit, Unit)],
820 buffer: &mut Buffer,
821 last: usize,
822) -> Option<Unit> {
823 if pairs.is_empty() {
824 return Some(Unit::inline(&[5u32 << 28]));
825 }
826
827 let ((key_size, key_width), (value_size, value_width)) = best_array_size_pairs(pairs);
828 let index_words = index.len().div_ceil(4);
829 let size = index_words + key_size + value_size;
830 if size >= (1usize << 30) {
831 return None;
832 }
833
834 let mut tail = buffer.len().checked_sub(last)?;
835 for (key, value) in pairs.iter_mut().rev() {
836 pick_unit(value, buffer, &mut tail, value_width);
837 pick_unit(key, buffer, &mut tail, key_width);
838 }
839 buffer.shrink(tail);
840 for (key, value) in pairs.iter().rev() {
841 mark_unit(value, buffer, value_width);
842 mark_unit(key, buffer, key_width);
843 }
844
845 let head = buffer.expand(index_words);
846 head.fill(0);
847 let raw =
848 unsafe { core::slice::from_raw_parts_mut(head.as_mut_ptr().cast::<u8>(), index_words * 4) };
849 raw[..index.len()].copy_from_slice(index);
850 head[0] |= (key_width as u32) << 30 | (value_width as u32) << 28;
851 Some(Unit::segment(last, buffer.len()))
852}
853
854#[inline(always)]
855pub fn serialize_map_at(
856 index: &[u8],
857 keys: &[Unit],
858 values: &[Unit],
859 buffer: &mut Buffer,
860 last: usize,
861) -> Option<Unit> {
862 if keys.len() != values.len() {
863 return None;
864 }
865 if keys.is_empty() {
866 return Some(Unit::inline(&[5u32 << 28]));
867 }
868
869 let (key_size, key_width) = best_array_size(keys);
870 let (value_size, value_width) = best_array_size(values);
871 let index_words = index.len().div_ceil(4);
872 let size = index_words + key_size + value_size;
873 if size >= (1usize << 30) {
874 return None;
875 }
876
877 let pair_width = key_width + value_width;
878 let mut payloads = Vec::with_capacity(size.saturating_sub(keys.len() * pair_width));
879 let mut cells = vec![0u32; keys.len() * pair_width];
880 let cells_len = cells.len();
881 for index in 0..keys.len() {
882 let key_words = unit_words(&keys[index], buffer)?;
883 let value_words = unit_words(&values[index], buffer)?;
884 let cell_start = index.checked_mul(pair_width)?;
885 let (key_cell, value_cell) =
886 cells[cell_start..cell_start + pair_width].split_at_mut(key_width);
887
888 if key_words.len() <= key_width {
889 key_cell[..key_words.len()].copy_from_slice(key_words);
890 } else {
891 let payload_start = cells_len.checked_add(payloads.len())?;
892 key_cell[0] = offset(payload_start.checked_sub(cell_start)?);
893 payloads.extend_from_slice(key_words);
894 }
895
896 let value_cell_start = cell_start + key_width;
897 if value_words.len() <= value_width {
898 value_cell[..value_words.len()].copy_from_slice(value_words);
899 } else {
900 let payload_start = cells_len.checked_add(payloads.len())?;
901 value_cell[0] = offset(payload_start.checked_sub(value_cell_start)?);
902 payloads.extend_from_slice(value_words);
903 }
904 }
905 buffer.shrink(buffer.len().checked_sub(last)?);
906 buffer.put_words(&payloads);
907 buffer.put_words(&cells);
908
909 let head = buffer.expand(index_words);
910 head.fill(0);
911 let raw =
912 unsafe { core::slice::from_raw_parts_mut(head.as_mut_ptr().cast::<u8>(), index_words * 4) };
913 raw[..index.len()].copy_from_slice(index);
914 head[0] |= (key_width as u32) << 30 | (value_width as u32) << 28;
915 Some(Unit::segment(last, buffer.len()))
916}
917
918#[inline(always)]
919pub fn serialize_map(
920 index: &[u8],
921 keys: &[Unit],
922 values: &[Unit],
923 buffer: &mut Buffer,
924) -> Option<Unit> {
925 serialize_map_at(index, keys, values, buffer, buffer.len())
926}
927
928#[cfg(test)]
929mod tests {
930 use super::{
931 Unit, build_perfect_hash_index, build_perfect_hash_index_with_positions, fold_field,
932 serialize_array, serialize_array_at, serialize_bool, serialize_map, serialize_message,
933 serialize_scalar, serialize_str,
934 };
935 use crate::{ArrayView, Buffer, MapView, MessageView, StringView, ViewArray};
936
937 #[test]
938 fn serializes_inline_string() {
939 let mut buffer = Buffer::new();
940 let unit = serialize_str("hi", &mut buffer).unwrap();
941 assert_eq!(unit.inline_words().len(), 1);
942 assert!(buffer.is_empty());
943 }
944
945 #[test]
946 fn folds_segmented_field_when_small() {
947 let mut buffer = Buffer::new();
948 let mut unit = serialize_str("hello", &mut buffer).unwrap();
949 assert!(unit.is_segment());
950 fold_field(&mut buffer, &mut unit);
951 assert_eq!(unit.inline_words().len(), 2);
952 assert!(buffer.is_empty());
953
954 let mut small = serialize_str("abc", &mut buffer).unwrap();
955 assert_eq!(small.inline_words().len(), 1);
956 fold_field(&mut buffer, &mut small);
957 assert_eq!(small.inline_words().len(), 1);
958 }
959
960 #[test]
961 fn serializes_simple_message_roundtrip() {
962 let mut buffer = Buffer::new();
963 let field0 = serialize_scalar::<i32>(42);
964 let field1 = serialize_bool(true);
965 let field3 = serialize_str("hi", &mut buffer).unwrap();
966 let mut fields = vec![field0, field1, Unit::empty(), field3];
967 let _message = serialize_message(&mut fields, &mut buffer).unwrap();
968
969 let view = MessageView::new(buffer.view()).unwrap();
970 assert_eq!(view.scalar::<i32>(0), Some(42));
971 assert_eq!(view.scalar::<bool>(1), Some(true));
972 assert_eq!(view.string(3).unwrap().as_str(), Some("hi"));
973 assert!(view.scalar::<i32>(2).is_none());
974 }
975
976 #[test]
977 fn serializes_all_empty_fields_as_empty_message() {
978 let mut buffer = Buffer::new();
979 let mut fields = vec![Unit::empty(), Unit::empty()];
980 let _message = serialize_message(&mut fields, &mut buffer).unwrap();
981 let view = MessageView::new(buffer.view()).unwrap();
982 assert!(!view.has_field(0));
983 assert!(!view.has_field(1));
984 }
985
986 #[test]
987 fn serializes_scalar_array_roundtrip() {
988 let mut buffer = Buffer::new();
989 let elements = vec![serialize_scalar::<i32>(1), serialize_scalar::<i32>(2)];
990 let _array = serialize_array(&elements, &mut buffer).unwrap();
991 let view = ArrayView::new(buffer.view()).unwrap();
992 let scalars = view.scalars::<i32>().unwrap();
993 assert_eq!(scalars.get(0), Some(1));
994 assert_eq!(scalars.get(1), Some(2));
995 }
996
997 #[test]
998 fn serializes_string_array_roundtrip() {
999 let mut buffer = Buffer::new();
1000 let a = serialize_str("abc", &mut buffer).unwrap();
1001 let b = serialize_str("apple", &mut buffer).unwrap();
1002 let elements = vec![a, b];
1003 let _array = serialize_array(&elements, &mut buffer).unwrap();
1004 let view = ArrayView::new(buffer.view()).unwrap();
1005 let strings = ViewArray::<StringView<'_>>::new(view);
1006 assert_eq!(strings.get(0).unwrap().as_str(), Some("abc"));
1007 assert_eq!(strings.get(1).unwrap().as_str(), Some("apple"));
1008 }
1009
1010 #[test]
1011 fn builds_index_and_serializes_string_int_map_roundtrip() {
1012 let keys_bytes = vec![b"abc-1".to_vec(), b"abc-2".to_vec()];
1013 let (index, positions) = build_perfect_hash_index_with_positions(&keys_bytes).unwrap();
1014
1015 let mut buffer = Buffer::new();
1016 let key0 = serialize_str("abc-1", &mut buffer).unwrap();
1017 let key1 = serialize_str("abc-2", &mut buffer).unwrap();
1018 let mut keys = vec![Unit::empty(); 2];
1019 let mut values = vec![Unit::empty(); 2];
1020 keys[positions[0]] = key0;
1021 keys[positions[1]] = key1;
1022 values[positions[0]] = serialize_scalar::<i32>(1);
1023 values[positions[1]] = serialize_scalar::<i32>(2);
1024 let _map = serialize_map(&index, &keys, &values, &mut buffer).unwrap();
1025
1026 let view = MapView::new(buffer.view()).unwrap();
1027 assert_eq!(
1028 view.find_str("abc-1").unwrap().value().scalar::<i32>(),
1029 Some(1)
1030 );
1031 assert_eq!(
1032 view.find_str("abc-2").unwrap().value().scalar::<i32>(),
1033 Some(2)
1034 );
1035 assert!(view.find_str("abc-3").is_none());
1036 }
1037
1038 #[test]
1039 fn index_builder_matches_reader_expectations() {
1040 let keys = vec![b"abc-1".to_vec(), b"abc-2".to_vec(), b"abc-4".to_vec()];
1041 let index = build_perfect_hash_index(&keys).unwrap();
1042 let mut seen = std::collections::BTreeSet::new();
1043 for key in &keys {
1044 seen.insert(super::locate_in_perfect_hash(&index, key).unwrap());
1045 }
1046 assert_eq!(seen.len(), keys.len());
1047 }
1048
1049 #[test]
1050 fn serializes_short_string_key_float_array_map_roundtrip() {
1051 let keys_bytes = vec![b"lv5".to_vec(), b"lv9".to_vec()];
1052 let (index, positions) = build_perfect_hash_index_with_positions(&keys_bytes).unwrap();
1053
1054 let mut buffer = Buffer::new();
1055 let key0 = serialize_str("lv5", &mut buffer).unwrap();
1056 let key1 = serialize_str("lv9", &mut buffer).unwrap();
1057
1058 let last = buffer.len();
1059 let value0 = serialize_array_at(
1060 &[
1061 serialize_scalar::<f32>(51.0),
1062 serialize_scalar::<f32>(52.0),
1063 serialize_scalar::<f32>(53.0),
1064 ],
1065 &mut buffer,
1066 last,
1067 )
1068 .unwrap();
1069 let last = buffer.len();
1070 let value1 = serialize_array_at(
1071 &[serialize_scalar::<f32>(91.0), serialize_scalar::<f32>(92.0)],
1072 &mut buffer,
1073 last,
1074 )
1075 .unwrap();
1076
1077 let mut keys = vec![Unit::empty(); 2];
1078 let mut values = vec![Unit::empty(); 2];
1079 keys[positions[0]] = key0;
1080 keys[positions[1]] = key1;
1081 values[positions[0]] = value0;
1082 values[positions[1]] = value1;
1083 let _map = serialize_map(&index, &keys, &values, &mut buffer).unwrap();
1084
1085 let view = MapView::new(buffer.view()).unwrap();
1086 let lv5 = view.find_str("lv5").unwrap().value().array().unwrap();
1087 assert_eq!(
1088 lv5.scalars::<f32>().unwrap().iter().collect::<Vec<_>>(),
1089 vec![51.0, 52.0, 53.0]
1090 );
1091 let lv9 = view.find_str("lv9").unwrap().value().array().unwrap();
1092 assert_eq!(
1093 lv9.scalars::<f32>().unwrap().iter().collect::<Vec<_>>(),
1094 vec![91.0, 92.0]
1095 );
1096 }
1097
1098 #[test]
1099 fn serializes_multi_entry_short_string_key_float_array_map_roundtrip() {
1100 let keys = ["lv1", "lv2", "lv3", "lv4", "lv5", "lv9"];
1101 let key_bytes = keys
1102 .iter()
1103 .map(|key| key.as_bytes().to_vec())
1104 .collect::<Vec<_>>();
1105 let (index, positions) = build_perfect_hash_index_with_positions(&key_bytes).unwrap();
1106
1107 let values_src = [
1108 vec![11.0f32, 12.0],
1109 vec![21.0, 22.0],
1110 vec![31.0, 32.0],
1111 vec![41.0, 42.0],
1112 vec![51.0, 52.0, 53.0],
1113 vec![91.0, 92.0],
1114 ];
1115
1116 let mut buffer = Buffer::new();
1117 let encoded_keys = keys
1118 .iter()
1119 .map(|key| serialize_str(key, &mut buffer).unwrap())
1120 .collect::<Vec<_>>();
1121 let encoded_values = values_src
1122 .iter()
1123 .map(|values| {
1124 let units = values
1125 .iter()
1126 .map(|value| serialize_scalar::<f32>(*value))
1127 .collect::<Vec<_>>();
1128 serialize_array(&units, &mut buffer).unwrap()
1129 })
1130 .collect::<Vec<_>>();
1131
1132 let mut keys = vec![Unit::empty(); positions.len()];
1133 let mut values = vec![Unit::empty(); positions.len()];
1134 for (idx, pos) in positions.iter().copied().enumerate() {
1135 keys[pos] = encoded_keys[idx];
1136 values[pos] = encoded_values[idx];
1137 }
1138
1139 let _map = serialize_map(&index, &keys, &values, &mut buffer).unwrap();
1140 let view = MapView::new(buffer.view()).unwrap();
1141 for (key, expected) in ["lv1", "lv2", "lv3", "lv4", "lv5", "lv9"]
1142 .into_iter()
1143 .zip(values_src.iter())
1144 {
1145 let array = view.find_str(key).unwrap().value().array().unwrap();
1146 assert_eq!(
1147 array.scalars::<f32>().unwrap().iter().collect::<Vec<_>>(),
1148 expected.clone()
1149 );
1150 }
1151 }
1152}