1pub mod floats;
42pub mod lanes;
43mod shaped;
44mod view;
45
46pub use shaped::{read_shaped, unpack_shaped};
47pub use view::{Floats, FromF64, Ints, List, ListIter, View, list, read_view};
48
49use yog_sync::Arc;
50
51use bumpalo::Bump;
52
53use crate::binary::interner::Interner;
54use crate::binary::writer::START_BYTES;
55use crate::binary::{
56 Decoder, MAX_DEPTH, VARINT_BITS, VARINT_MAX_SHIFT, VARINT_MORE, VARINT_SHIFT, Writer,
57 read_varint, unzigzag, varint, zigzag,
58};
59use crate::schema::{Schema, read_ref_value};
60
61const F64_BYTES: usize = 8;
63const F32_BYTES: usize = 4;
64const LENGTH_RESERVED: usize = 1;
67const ONE_BYTE_MAX: usize = 0x7F;
69const INLINE_STRINGS: usize = 16;
71
72pub fn to_frame<T: Schema>(v: &T) -> Vec<u8> {
74 let mut p = Packer::new();
75 v.pack(&mut p);
76 p.finish()
77}
78
79thread_local! {
80 static PACKER: std::cell::RefCell<Packer> = std::cell::RefCell::new(Packer::new());
83}
84
85pub fn with_frame<T: Schema, R>(v: &T, f: impl FnOnce(&[u8]) -> R) -> R {
88 PACKER.with(|cell| match cell.try_borrow_mut() {
89 Ok(mut p) => {
90 p.clear();
91 v.pack(&mut p);
92 let p = &mut *p;
93 p.seal();
94 let out = f(&p.out);
95 p.out.clear();
96 out
97 }
98 Err(_) => f(&to_frame(v)),
99 })
100}
101
102pub fn read_frame<T: Schema>(bytes: &[u8]) -> Option<T> {
104 let mut u = Unpacker::open(bytes)?;
105 let v = T::unpack(&mut u)?;
106 u.at_end().then_some(v)
107}
108
109pub struct Packer {
111 out: Vec<u8>,
112 table: Vec<u8>,
113 strings: Interner,
114}
115
116impl Default for Packer {
117 fn default() -> Self {
118 Self::new()
119 }
120}
121
122impl Packer {
123 pub fn new() -> Self {
124 Packer {
125 out: Vec::with_capacity(START_BYTES),
126 table: Vec::new(),
127 strings: Interner::new(),
128 }
129 }
130
131 pub fn put_u(&mut self, n: u64) {
133 varint(&mut self.out, n);
134 }
135
136 pub fn put_i(&mut self, n: i64) {
137 varint(&mut self.out, zigzag(n));
138 }
139
140 pub fn put_bool(&mut self, b: bool) {
141 self.out.push(u8::from(b));
142 }
143
144 pub fn put_f64(&mut self, f: f64) {
145 self.out.extend_from_slice(&f.to_le_bytes());
146 }
147
148 pub fn put_f32(&mut self, f: f32) {
149 self.out.extend_from_slice(&f.to_le_bytes());
150 }
151
152 pub fn put_f64s(&mut self, items: &[f64]) {
155 self.put_u(items.len() as u64);
156 let narrow = floats::fits_f32(items);
157 self.put_bool(narrow);
158 if narrow {
159 floats::put_narrow(&mut self.out, items);
160 } else {
161 floats::put_wide(&mut self.out, items);
162 }
163 }
164
165 pub fn put_uints(&mut self, len: usize, items: impl Iterator<Item = u64> + Clone) {
168 self.put_u(len as u64);
169 let max = items.clone().fold(0, u64::max);
170 let bits = (u64::BITS - max.leading_zeros()).max(1);
171 self.out.push(bits as u8);
172 lanes::pack(&mut self.out, len, bits, items);
173 }
174
175 pub fn put_f32s(&mut self, items: &[f32]) {
176 self.put_u(items.len() as u64);
177 floats::put_f32s(&mut self.out, items);
178 }
179
180 pub fn put_str(&mut self, s: &str) {
182 let i = match self.strings.find(&self.table, s) {
183 Some(i) => i,
184 None => {
185 varint(&mut self.table, s.len() as u64);
186 let at = self.table.len();
187 self.table.extend_from_slice(s.as_bytes());
188 self.strings.add(&self.table, s, at)
189 }
190 };
191 self.put_u(i as u64);
192 }
193
194 pub fn put_bytes(&mut self, b: &[u8]) {
195 self.put_u(b.len() as u64);
196 self.out.extend_from_slice(b);
197 }
198
199 pub fn put_tagged<T: Schema>(&mut self, v: &T) {
202 let mut w = Writer::body();
203 v.encode(&mut w);
204 self.put_bytes(&w.finish());
205 }
206
207 pub fn begin(&mut self) -> usize {
209 let at = self.out.len();
210 self.out.extend_from_slice(&[0; LENGTH_RESERVED]);
211 at
212 }
213
214 pub fn begin_list(&mut self, len: usize) -> usize {
218 self.put_u(len as u64);
219 self.begin()
220 }
221
222 pub fn end(&mut self, at: usize) {
224 let len = self.out.len() - at - LENGTH_RESERVED;
225 if len <= ONE_BYTE_MAX {
226 self.out[at] = len as u8;
227 return;
228 }
229 let mut length = Vec::new();
230 varint(&mut length, len as u64);
231 self.out.splice(at..at + LENGTH_RESERVED, length);
232 }
233
234 pub fn finish(mut self) -> Vec<u8> {
236 self.seal();
237 self.out
238 }
239
240 fn seal(&mut self) {
242 let table_len = self.table.len();
243 self.out.extend_from_slice(&self.table);
244 let at = self.out.len();
246 varint(&mut self.out, table_len as u64);
247 self.out[at..].reverse();
248 }
249
250 fn clear(&mut self) {
252 self.out.clear();
253 self.table.clear();
254 self.strings.clear();
255 }
256}
257
258pub struct Unpacker<'b> {
261 body: &'b [u8],
262 i: usize,
263 table: &'b [u8],
264 table_at: usize,
266 strings: Strings<'b>,
267 shared: Vec<Option<Arc<str>>>,
270 depth: usize,
271}
272
273struct Strings<'b> {
275 inline: [&'b str; INLINE_STRINGS],
276 len: usize,
277 spill: Vec<&'b str>,
278}
279
280impl<'b> Strings<'b> {
281 fn new() -> Self {
282 Strings {
283 inline: [""; INLINE_STRINGS],
284 len: 0,
285 spill: Vec::new(),
286 }
287 }
288
289 fn len(&self) -> usize {
290 self.len
291 }
292
293 fn push(&mut self, s: &'b str) {
294 match self.inline.get_mut(self.len) {
295 Some(slot) => *slot = s,
296 None => self.spill.push(s),
297 }
298 self.len += 1;
299 }
300
301 fn get(&self, i: usize) -> Option<&'b str> {
302 if i >= self.len {
303 return None;
304 }
305 Some(if i < INLINE_STRINGS {
306 self.inline[i]
307 } else {
308 self.spill[i - INLINE_STRINGS]
309 })
310 }
311}
312
313impl<'b> Unpacker<'b> {
314 pub fn open(bytes: &'b [u8]) -> Option<Self> {
316 let (table_len, trailer) = read_varint_back(bytes)?;
317 let body_end = bytes.len().checked_sub(trailer)?.checked_sub(table_len)?;
318 Some(Unpacker {
319 body: &bytes[..body_end],
320 i: 0,
321 table: &bytes[body_end..bytes.len() - trailer],
322 table_at: 0,
323 strings: Strings::new(),
324 shared: Vec::new(),
325 depth: 0,
326 })
327 }
328
329 pub fn at_end(&self) -> bool {
331 self.i == self.body.len()
332 }
333
334 fn take(&mut self, len: usize) -> Option<&'b [u8]> {
335 let end = self.i.checked_add(len).filter(|&e| e <= self.body.len())?;
336 let out = &self.body[self.i..end];
337 self.i = end;
338 Some(out)
339 }
340
341 pub fn get_u(&mut self) -> Option<u64> {
342 read_varint(self.body, &mut self.i)
343 }
344
345 pub fn get_i(&mut self) -> Option<i64> {
346 self.get_u().map(unzigzag)
347 }
348
349 pub fn get_bool(&mut self) -> Option<bool> {
350 match self.take(1)? {
351 [0] => Some(false),
352 [1] => Some(true),
353 _ => None,
354 }
355 }
356
357 pub fn get_f64(&mut self) -> Option<f64> {
358 Some(f64::from_le_bytes(self.take(F64_BYTES)?.try_into().ok()?))
359 }
360
361 pub fn get_f32(&mut self) -> Option<f32> {
362 Some(f32::from_le_bytes(self.take(F32_BYTES)?.try_into().ok()?))
363 }
364
365 fn count_of(&mut self, min: usize) -> Option<usize> {
367 let n = usize::try_from(self.get_u()?).ok()?;
368 (n <= (self.body.len() - self.i) / min.max(1)).then_some(n)
369 }
370
371 pub fn count(&mut self) -> Option<usize> {
373 self.count_of(1)
374 }
375
376 pub fn get_f64s(&mut self) -> Option<Vec<f64>> {
377 let (_, narrow, raw) = self.packed_floats(true)?;
378 Some(if narrow {
379 floats::widen(raw)
380 } else {
381 raw.as_chunks::<F64_BYTES>()
382 .0
383 .iter()
384 .map(|b| f64::from_le_bytes(*b))
385 .collect()
386 })
387 }
388
389 pub fn get_uints<T>(&mut self, of: impl Fn(u64) -> Option<T>) -> Option<Vec<T>> {
391 let (n, bits, raw) = self.packed_ints()?;
392 let mut out = Vec::with_capacity(n);
393 let mut ok = true;
394 lanes::unpack(raw, n, bits, |v| match of(v) {
395 Some(t) if ok => out.push(t),
396 _ => ok = false,
397 });
398 ok.then_some(out)
399 }
400
401 pub fn get_f32s(&mut self) -> Option<Vec<f32>> {
402 let (_, _, raw) = self.packed_floats(false)?;
403 Some(
404 raw.as_chunks::<F32_BYTES>()
405 .0
406 .iter()
407 .map(|b| f32::from_le_bytes(*b))
408 .collect(),
409 )
410 }
411
412 pub fn packed_ints(&mut self) -> Option<(usize, u32, &'b [u8])> {
414 let n = usize::try_from(self.get_u()?).ok()?;
415 let bits = u32::from(*self.take(1)?.first()?);
416 if !(1..=u64::BITS).contains(&bits)
417 || n > (self.body.len() - self.i) * u8::BITS as usize / bits as usize
418 {
419 return None;
420 }
421 let bytes = self.take(lanes::packed_bytes(n, bits)?)?;
422 Some((n, bits, bytes))
423 }
424
425 pub fn packed_floats(&mut self, wide: bool) -> Option<(usize, bool, &'b [u8])> {
429 let n = self.count()?;
430 let narrow = if wide { self.get_bool()? } else { true };
431 let width = if narrow { F32_BYTES } else { F64_BYTES };
432 Some((n, narrow, self.take(n.checked_mul(width)?)?))
433 }
434
435 pub fn get_str(&mut self) -> Option<&'b str> {
437 let i = self.string_index()?;
438 self.strings.get(i)
439 }
440
441 pub fn get_shared_str(&mut self) -> Option<Arc<str>> {
443 let i = self.string_index()?;
444 if self.shared.len() <= i {
445 self.shared.resize(i + 1, None);
446 }
447 let s = self.strings.get(i)?;
448 Some(self.shared[i].get_or_insert_with(|| s.into()).clone())
449 }
450
451 fn string_index(&mut self) -> Option<usize> {
453 let i = usize::try_from(self.get_u()?).ok()?;
454 while self.strings.len() <= i {
455 let len = usize::try_from(read_varint(self.table, &mut self.table_at)?).ok()?;
456 let end = self
457 .table_at
458 .checked_add(len)
459 .filter(|&e| e <= self.table.len())?;
460 let s = std::str::from_utf8(&self.table[self.table_at..end]).ok()?;
461 self.table_at = end;
462 self.strings.push(s);
463 }
464 Some(i)
465 }
466
467 pub fn get_bytes(&mut self) -> Option<&'b [u8]> {
468 let len = self.count()?;
469 self.take(len)
470 }
471
472 pub fn get_tagged<T: Schema>(&mut self) -> Option<T> {
474 let bytes = self.get_bytes()?;
475 let mut d = Decoder::body(bytes);
476 if let Some(v) = T::decode(&mut d)
477 && d.at_end()
478 {
479 return Some(v);
480 }
481 let arena = Bump::new();
482 let mut d = Decoder::body(bytes);
483 let v = d.value_ref(&arena).ok()?;
484 d.at_end().then_some(())?;
485 read_ref_value(&v).ok()
486 }
487
488 pub fn begin(&mut self) -> Option<usize> {
490 let len = self.count()?;
491 self.depth += 1;
492 (self.depth <= MAX_DEPTH).then_some(self.i + len)
493 }
494
495 pub fn list(&mut self) -> Option<(usize, usize)> {
497 let n = self.count()?;
498 let len = self.count()?;
499 Some((n, self.i + len))
500 }
501
502 pub fn skip_to(&mut self, end: usize) -> Option<()> {
504 (self.i <= end && end <= self.body.len()).then(|| self.i = end)
505 }
506
507 pub fn position(&self) -> usize {
509 self.i
510 }
511
512 pub fn fork(&self, at: usize) -> Unpacker<'b> {
514 Unpacker {
515 body: self.body,
516 i: at,
517 table: self.table,
518 table_at: 0,
519 strings: Strings::new(),
520 shared: Vec::new(),
521 depth: self.depth,
522 }
523 }
524
525 pub fn more(&self, end: usize) -> bool {
527 self.i < end
528 }
529
530 pub fn leave(&mut self, end: usize) -> Option<()> {
532 self.depth -= 1;
533 (self.i <= end).then(|| self.i = end)
534 }
535}
536
537fn read_varint_back(bytes: &[u8]) -> Option<(usize, usize)> {
540 let mut n = 0u64;
541 let mut shift = 0;
542 for (taken, b) in bytes.iter().rev().enumerate() {
543 if shift >= VARINT_MAX_SHIFT {
544 return None;
545 }
546 n |= (u64::from(*b) & VARINT_BITS) << shift;
547 if b & VARINT_MORE == 0 {
548 return Some((usize::try_from(n).ok()?, taken + 1));
549 }
550 shift += VARINT_SHIFT;
551 }
552 None
553}