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