1#[cfg(feature = "alloc")]
2use alloc::{borrow::Cow, string::String, vec::Vec};
3
4use crate::{BitReader, BitWriter, Config, Error, Result, TrailingBytes};
5
6const RAW_UTF8: u8 = 0;
7const ASCII7: u8 = 1;
8const RAW_INTEGERS: u8 = 0;
9const DELTA_INTEGERS: u8 = 1;
10const RLE_INTEGERS: u8 = 2;
11
12#[derive(Clone, Copy, Debug, Eq, PartialEq)]
14pub enum StringStrategy {
15 RawUtf8,
17 Ascii7,
19}
20
21#[derive(Clone, Copy, Debug, Eq, PartialEq)]
23pub enum CollectionStrategy {
24 Raw,
26 Delta,
28 RunLength,
30}
31
32#[derive(Clone, Copy, Debug, Eq, PartialEq)]
34pub struct AdaptiveConfig {
35 base: Config,
36}
37
38impl AdaptiveConfig {
39 pub(crate) const fn new(base: Config) -> Self {
40 Self { base }
41 }
42
43 pub const fn base_config(self) -> Config {
45 self.base
46 }
47
48 #[cfg(feature = "alloc")]
50 pub fn serialize<T: nextjson::NsonSerialize + ?Sized>(self, value: &T) -> Result<Vec<u8>> {
51 self.base.serialize(value)
52 }
53
54 pub fn deserialize<'de, T: nextjson::NsonDeserialize<'de>>(
56 self,
57 input: &'de [u8],
58 ) -> Result<T> {
59 self.base.deserialize(input)
60 }
61
62 #[cfg(feature = "alloc")]
64 pub fn encode_string(self, value: &str) -> Result<Vec<u8>> {
65 let required = self.encoded_string_size(value)?;
66 let mut output = Vec::new();
67 output
68 .try_reserve_exact(required)
69 .map_err(|_| Error::SizeLimit { limit: u64::MAX })?;
70 output.resize(required, 0);
71 self.encode_string_into_slice(&mut output, value)?;
72 Ok(output)
73 }
74
75 pub fn encoded_string_size(self, value: &str) -> Result<usize> {
77 let (_, _, required) = string_layout(value)?;
78 self.enforce_byte_limit(required)?;
79 Ok(required)
80 }
81
82 pub fn encode_string_into_slice(self, output: &mut [u8], value: &str) -> Result<usize> {
86 let (strategy, payload_size, required) = string_layout(value)?;
87 self.enforce_byte_limit(required)?;
88 if output.len() < required {
89 return Err(Error::BufferTooSmall {
90 required,
91 available: output.len(),
92 });
93 }
94 let mut cursor = OutputCursor::new(&mut output[..required]);
95 cursor.byte(match strategy {
96 StringStrategy::RawUtf8 => RAW_UTF8,
97 StringStrategy::Ascii7 => ASCII7,
98 });
99 cursor.varint(value.len() as u128);
100 match strategy {
101 StringStrategy::RawUtf8 => cursor.bytes(value.as_bytes()),
102 StringStrategy::Ascii7 => {
103 let packed = cursor.take_mut(payload_size);
104 let mut writer = BitWriter::new(packed);
105 for byte in value.bytes() {
106 writer.write(byte as u128, 7)?;
107 }
108 }
109 }
110 Ok(required)
111 }
112
113 pub fn string_strategy(self, input: &[u8]) -> Result<StringStrategy> {
115 match input.first().copied().ok_or(Error::UnexpectedEnd)? {
116 RAW_UTF8 => Ok(StringStrategy::RawUtf8),
117 ASCII7 => Ok(StringStrategy::Ascii7),
118 _ => Err(Error::Adaptive("unknown string strategy")),
119 }
120 }
121
122 #[cfg(feature = "alloc")]
124 pub fn decode_string(self, input: &[u8]) -> Result<String> {
125 Ok(self.decode_string_borrowed(input)?.into_owned())
126 }
127
128 pub fn decode_string_into_slice<'output>(
135 self,
136 output: &'output mut [u8],
137 input: &[u8],
138 ) -> Result<&'output str> {
139 self.enforce_byte_limit(input.len())?;
140 let mut cursor = Cursor::new(input);
141 let strategy = cursor.byte()?;
142 if !matches!(strategy, RAW_UTF8 | ASCII7) {
143 return Err(Error::Adaptive("unknown string strategy"));
144 }
145 let length = cursor.usize_varint()?;
146 if output.len() < length {
147 return Err(Error::BufferTooSmall {
148 required: length,
149 available: output.len(),
150 });
151 }
152
153 match strategy {
154 RAW_UTF8 => {
155 let bytes = cursor.take(length)?;
156 core::str::from_utf8(bytes).map_err(Error::InvalidUtf8)?;
157 output[..length].copy_from_slice(bytes);
158 }
159 ASCII7 => {
160 let meaningful_bits = length
161 .checked_mul(7)
162 .ok_or(Error::Adaptive("ASCII7 length overflow"))?;
163 let packed = meaningful_bits
164 .checked_add(7)
165 .ok_or(Error::Adaptive("ASCII7 length overflow"))?
166 / 8;
167 let bytes = cursor.take(packed)?;
168 let mut reader = BitReader::new(bytes);
169 for slot in &mut output[..length] {
170 *slot = reader.read(7)? as u8;
171 }
172 validate_ascii_padding(bytes, meaningful_bits)?;
173 }
174 _ => return Err(Error::Adaptive("unknown string strategy")),
175 }
176 cursor.finish(self.base.trailing)?;
177 core::str::from_utf8(&output[..length]).map_err(Error::InvalidUtf8)
178 }
179
180 #[cfg(feature = "alloc")]
185 pub fn decode_string_borrowed<'a>(self, input: &'a [u8]) -> Result<Cow<'a, str>> {
186 self.enforce_byte_limit(input.len())?;
187 let mut cursor = Cursor::new(input);
188 let strategy = cursor.byte()?;
189 let length = cursor.usize_varint()?;
190 let value = match strategy {
191 RAW_UTF8 => {
192 let bytes = cursor.take(length)?;
193 Cow::Borrowed(core::str::from_utf8(bytes).map_err(Error::InvalidUtf8)?)
194 }
195 ASCII7 => {
196 let meaningful_bits = length
197 .checked_mul(7)
198 .ok_or(Error::Adaptive("ASCII7 length overflow"))?;
199 let packed = meaningful_bits
200 .checked_add(7)
201 .ok_or(Error::Adaptive("ASCII7 length overflow"))?
202 / 8;
203 let bytes = cursor.take(packed)?;
204 let mut reader = BitReader::new(bytes);
205 let mut value = String::new();
206 value
207 .try_reserve_exact(length)
208 .map_err(|_| Error::SizeLimit { limit: u64::MAX })?;
209 for _ in 0..length {
210 value.push(reader.read(7)? as u8 as char);
213 }
214 validate_ascii_padding(bytes, meaningful_bits)?;
215 Cow::Owned(value)
216 }
217 _ => return Err(Error::Adaptive("unknown string strategy")),
218 };
219 cursor.finish(self.base.trailing)?;
220 Ok(value)
221 }
222
223 #[cfg(feature = "alloc")]
225 pub fn encode_i64_slice(self, values: &[i64]) -> Result<Vec<u8>> {
226 let required = self.encoded_i64_slice_size(values)?;
227 let mut output = Vec::new();
228 output
229 .try_reserve_exact(required)
230 .map_err(|_| Error::SizeLimit { limit: u64::MAX })?;
231 output.resize(required, 0);
232 self.encode_i64_slice_into_slice(&mut output, values)?;
233 Ok(output)
234 }
235
236 pub fn encoded_i64_slice_size(self, values: &[i64]) -> Result<usize> {
238 self.enforce_collection_limit(values.len())?;
239 let (_, _, required) = collection_layout(values)?;
240 self.enforce_byte_limit(required)?;
241 Ok(required)
242 }
243
244 pub fn encode_i64_slice_into_slice(self, output: &mut [u8], values: &[i64]) -> Result<usize> {
248 self.enforce_collection_limit(values.len())?;
249 let (strategy, _, required) = collection_layout(values)?;
250 self.enforce_byte_limit(required)?;
251 if output.len() < required {
252 return Err(Error::BufferTooSmall {
253 required,
254 available: output.len(),
255 });
256 }
257 let mut cursor = OutputCursor::new(&mut output[..required]);
258 cursor.byte(match strategy {
259 CollectionStrategy::Raw => RAW_INTEGERS,
260 CollectionStrategy::Delta => DELTA_INTEGERS,
261 CollectionStrategy::RunLength => RLE_INTEGERS,
262 });
263 cursor.varint(values.len() as u128);
264 match strategy {
265 CollectionStrategy::Raw => {
266 for value in values {
267 cursor.varint(zigzag_i64(*value));
268 }
269 }
270 CollectionStrategy::Delta => {
271 if let Some(first) = values.first() {
272 cursor.varint(zigzag_i64(*first));
273 for pair in values.windows(2) {
274 cursor.varint(zigzag_i128(pair[1] as i128 - pair[0] as i128));
275 }
276 }
277 }
278 CollectionStrategy::RunLength => {
279 let mut start = 0;
280 while start < values.len() {
281 let mut end = start + 1;
282 while end < values.len() && values[end] == values[start] {
283 end += 1;
284 }
285 cursor.varint(zigzag_i64(values[start]));
286 cursor.varint((end - start) as u128);
287 start = end;
288 }
289 }
290 }
291 Ok(required)
292 }
293
294 pub fn collection_strategy(self, input: &[u8]) -> Result<CollectionStrategy> {
296 match input.first().copied().ok_or(Error::UnexpectedEnd)? {
297 RAW_INTEGERS => Ok(CollectionStrategy::Raw),
298 DELTA_INTEGERS => Ok(CollectionStrategy::Delta),
299 RLE_INTEGERS => Ok(CollectionStrategy::RunLength),
300 _ => Err(Error::Adaptive("unknown collection strategy")),
301 }
302 }
303
304 #[cfg(feature = "alloc")]
306 pub fn decode_i64_vec(self, input: &[u8]) -> Result<Vec<i64>> {
307 let length = self.decoded_i64_slice_len(input)?;
308 let mut values = Vec::new();
309 values
310 .try_reserve_exact(length)
311 .map_err(|_| Error::SizeLimit { limit: u64::MAX })?;
312 values.resize(length, 0);
313 self.decode_i64_slice_into(&mut values, input)?;
314 Ok(values)
315 }
316
317 pub fn decoded_i64_slice_len(self, input: &[u8]) -> Result<usize> {
319 self.enforce_byte_limit(input.len())?;
320 let mut cursor = Cursor::new(input);
321 let strategy = cursor.byte()?;
322 if !matches!(strategy, RAW_INTEGERS | DELTA_INTEGERS | RLE_INTEGERS) {
323 return Err(Error::Adaptive("unknown collection strategy"));
324 }
325 let length = cursor.usize_varint()?;
326 self.enforce_collection_limit(length)?;
327 Ok(length)
328 }
329
330 pub fn decode_i64_slice_into(self, output: &mut [i64], input: &[u8]) -> Result<usize> {
335 self.enforce_byte_limit(input.len())?;
336 let mut cursor = Cursor::new(input);
337 let strategy = cursor.byte()?;
338 if !matches!(strategy, RAW_INTEGERS | DELTA_INTEGERS | RLE_INTEGERS) {
339 return Err(Error::Adaptive("unknown collection strategy"));
340 }
341 let length = cursor.usize_varint()?;
342 self.enforce_collection_limit(length)?;
343 if output.len() < length {
344 return Err(Error::BufferTooSmall {
345 required: length,
346 available: output.len(),
347 });
348 }
349 let mut written = 0usize;
350 match strategy {
351 RAW_INTEGERS => {
352 while written < length {
353 let remaining_values = length - written;
354 let plain = plain_varint_prefix(cursor.remaining_slice()).min(remaining_values);
355 for byte in cursor.take(plain)? {
356 output[written] = decode_i128(*byte as u128) as i64;
357 written += 1;
358 }
359 if written < length {
360 output[written] = decode_i64(cursor.varint()?)?;
361 written += 1;
362 }
363 }
364 }
365 DELTA_INTEGERS => {
366 if length != 0 {
367 output[0] = decode_i64(cursor.varint()?)?;
368 written = 1;
369 while written < length {
370 let delta = decode_i128(cursor.varint()?);
371 let next = (output[written - 1] as i128)
372 .checked_add(delta)
373 .and_then(|value| i64::try_from(value).ok())
374 .ok_or(Error::Adaptive("delta reconstruction overflow"))?;
375 output[written] = next;
376 written += 1;
377 }
378 }
379 }
380 RLE_INTEGERS => {
381 while written < length {
382 let value = decode_i64(cursor.varint()?)?;
383 let run = cursor.usize_varint()?;
384 if run == 0 || run > length - written {
385 return Err(Error::Adaptive("invalid run length"));
386 }
387 output[written..written + run].fill(value);
388 written += run;
389 }
390 }
391 _ => unreachable!("strategy was validated above"),
392 }
393 cursor.finish(self.base.trailing)?;
394 Ok(written)
395 }
396
397 fn enforce_byte_limit(self, length: usize) -> Result<()> {
398 if let Some(limit) = self.base.limit {
399 if length as u64 > limit {
400 return Err(Error::SizeLimit { limit });
401 }
402 }
403 Ok(())
404 }
405
406 fn enforce_collection_limit(self, length: usize) -> Result<()> {
407 if let Some(limit) = self.base.collection_limit {
408 if length as u64 > limit {
409 return Err(Error::CollectionLimit { limit });
410 }
411 }
412 Ok(())
413 }
414}
415
416fn validate_ascii_padding(bytes: &[u8], meaningful_bits: usize) -> Result<()> {
417 if !meaningful_bits.is_multiple_of(8)
418 && bytes
419 .last()
420 .is_some_and(|last| last >> (meaningful_bits % 8) != 0)
421 {
422 return Err(Error::Adaptive("non-zero ASCII7 padding"));
423 }
424 Ok(())
425}
426
427fn string_layout(value: &str) -> Result<(StringStrategy, usize, usize)> {
428 let raw_size = value.len();
429 let packed_size = if is_ascii(value.as_bytes()) {
430 Some(
431 value
432 .len()
433 .checked_mul(7)
434 .and_then(|bits| bits.checked_add(7))
435 .ok_or(Error::Adaptive("encoded size overflow"))?
436 / 8,
437 )
438 } else {
439 None
440 };
441 let (strategy, payload_size) = match packed_size {
442 Some(size) if size < raw_size => (StringStrategy::Ascii7, size),
443 _ => (StringStrategy::RawUtf8, raw_size),
444 };
445 let required = 1usize
446 .checked_add(varint_size(value.len() as u128))
447 .and_then(|size| size.checked_add(payload_size))
448 .ok_or(Error::Adaptive("encoded size overflow"))?;
449 Ok((strategy, payload_size, required))
450}
451
452fn is_ascii(input: &[u8]) -> bool {
453 #[cfg(feature = "simd")]
454 return crate::simd::is_ascii(input);
455 #[cfg(not(feature = "simd"))]
456 input.is_ascii()
457}
458
459fn plain_varint_prefix(input: &[u8]) -> usize {
460 #[cfg(feature = "simd")]
461 return crate::simd::plain_varint_prefix(input);
462 #[cfg(not(feature = "simd"))]
463 input.iter().take_while(|&&byte| byte <= 250).count()
464}
465
466fn collection_layout(values: &[i64]) -> Result<(CollectionStrategy, usize, usize)> {
467 let raw_size = values.iter().try_fold(0usize, |size, value| {
468 size.checked_add(varint_size(zigzag_i64(*value)))
469 .ok_or(Error::Adaptive("encoded size overflow"))
470 })?;
471 let delta_size = delta_size(values)?;
472 let rle_size = rle_size(values)?;
473 let strategy = if delta_size < raw_size && delta_size <= rle_size {
474 CollectionStrategy::Delta
475 } else if rle_size < raw_size {
476 CollectionStrategy::RunLength
477 } else {
478 CollectionStrategy::Raw
479 };
480 let payload_size = match strategy {
481 CollectionStrategy::Raw => raw_size,
482 CollectionStrategy::Delta => delta_size,
483 CollectionStrategy::RunLength => rle_size,
484 };
485 let required = 1usize
486 .checked_add(varint_size(values.len() as u128))
487 .and_then(|size| size.checked_add(payload_size))
488 .ok_or(Error::Adaptive("encoded size overflow"))?;
489 Ok((strategy, payload_size, required))
490}
491
492fn delta_size(values: &[i64]) -> Result<usize> {
493 let Some(first) = values.first() else {
494 return Ok(0);
495 };
496 values
497 .windows(2)
498 .try_fold(varint_size(zigzag_i64(*first)), |size, pair| {
499 size.checked_add(varint_size(zigzag_i128(pair[1] as i128 - pair[0] as i128)))
500 .ok_or(Error::Adaptive("encoded size overflow"))
501 })
502}
503
504fn rle_size(values: &[i64]) -> Result<usize> {
505 let mut size = 0usize;
506 let mut start = 0;
507 while start < values.len() {
508 let mut end = start + 1;
509 while end < values.len() && values[end] == values[start] {
510 end += 1;
511 }
512 size = size
513 .checked_add(varint_size(zigzag_i64(values[start])))
514 .and_then(|size| size.checked_add(varint_size((end - start) as u128)))
515 .ok_or(Error::Adaptive("encoded size overflow"))?;
516 start = end;
517 }
518 Ok(size)
519}
520
521const fn zigzag_i64(value: i64) -> u128 {
522 ((value << 1) ^ (value >> 63)) as u64 as u128
523}
524
525const fn zigzag_i128(value: i128) -> u128 {
526 ((value << 1) ^ (value >> 127)) as u128
527}
528
529fn decode_i64(value: u128) -> Result<i64> {
530 i64::try_from(decode_i128(value)).map_err(|_| Error::IntegerOverflow { target: "i64" })
531}
532
533const fn decode_i128(value: u128) -> i128 {
534 ((value >> 1) as i128) ^ -((value & 1) as i128)
535}
536
537const fn varint_size(value: u128) -> usize {
538 match value {
539 0..=250 => 1,
540 251..=0xffff => 3,
541 0x1_0000..=0xffff_ffff => 5,
542 0x1_0000_0000..=0xffff_ffff_ffff_ffff => 9,
543 _ => 17,
544 }
545}
546
547struct OutputCursor<'a> {
548 output: &'a mut [u8],
549 position: usize,
550}
551
552impl<'a> OutputCursor<'a> {
553 const fn new(output: &'a mut [u8]) -> Self {
554 Self {
555 output,
556 position: 0,
557 }
558 }
559
560 fn byte(&mut self, value: u8) {
561 self.output[self.position] = value;
562 self.position += 1;
563 }
564
565 fn bytes(&mut self, value: &[u8]) {
566 self.take_mut(value.len()).copy_from_slice(value);
567 }
568
569 fn take_mut(&mut self, length: usize) -> &mut [u8] {
570 let start = self.position;
571 self.position += length;
572 &mut self.output[start..self.position]
573 }
574
575 fn varint(&mut self, value: u128) {
576 match value {
577 0..=250 => self.byte(value as u8),
578 251..=0xffff => {
579 self.byte(251);
580 self.bytes(&(value as u16).to_le_bytes());
581 }
582 0x1_0000..=0xffff_ffff => {
583 self.byte(252);
584 self.bytes(&(value as u32).to_le_bytes());
585 }
586 0x1_0000_0000..=0xffff_ffff_ffff_ffff => {
587 self.byte(253);
588 self.bytes(&(value as u64).to_le_bytes());
589 }
590 _ => {
591 self.byte(254);
592 self.bytes(&value.to_le_bytes());
593 }
594 }
595 }
596}
597
598struct Cursor<'a> {
599 input: &'a [u8],
600 position: usize,
601}
602
603impl<'a> Cursor<'a> {
604 const fn new(input: &'a [u8]) -> Self {
605 Self { input, position: 0 }
606 }
607
608 fn byte(&mut self) -> Result<u8> {
609 Ok(self.take(1)?[0])
610 }
611
612 fn take(&mut self, length: usize) -> Result<&'a [u8]> {
613 let end = self
614 .position
615 .checked_add(length)
616 .ok_or(Error::UnexpectedEnd)?;
617 let bytes = self
618 .input
619 .get(self.position..end)
620 .ok_or(Error::UnexpectedEnd)?;
621 self.position = end;
622 Ok(bytes)
623 }
624
625 fn remaining_slice(&self) -> &'a [u8] {
626 &self.input[self.position..]
627 }
628
629 fn take_array<const N: usize>(&mut self) -> Result<[u8; N]> {
630 self.take(N)?.try_into().map_err(|_| Error::UnexpectedEnd)
631 }
632
633 fn varint(&mut self) -> Result<u128> {
634 let marker = self.byte()?;
635 let (value, minimum) = match marker {
636 0..=250 => return Ok(marker as u128),
637 251 => (u16::from_le_bytes(self.take_array()?) as u128, 251),
638 252 => (u32::from_le_bytes(self.take_array()?) as u128, 0x1_0000),
639 253 => (
640 u64::from_le_bytes(self.take_array()?) as u128,
641 0x1_0000_0000,
642 ),
643 254 => (
644 u128::from_le_bytes(self.take_array()?),
645 0x1_0000_0000_0000_0000,
646 ),
647 marker => return Err(Error::InvalidVarintMarker(marker)),
648 };
649 if value < minimum {
650 Err(Error::NonCanonicalVarint)
651 } else {
652 Ok(value)
653 }
654 }
655
656 fn usize_varint(&mut self) -> Result<usize> {
657 usize::try_from(self.varint()?).map_err(|_| Error::IntegerOverflow { target: "usize" })
658 }
659
660 fn finish(self, trailing: TrailingBytes) -> Result<()> {
661 if trailing == TrailingBytes::Reject && self.position != self.input.len() {
662 return Err(Error::TrailingBytes {
663 remaining: self.input.len() - self.position,
664 });
665 }
666 Ok(())
667 }
668}