1#[doc(hidden)]
2pub mod macro_helpers;
3pub mod serde_self_describing;
4
5use std::{any::Any, ptr::copy_nonoverlapping};
6
7use ::smallvec::SmallVec;
8use bincode::{
9 BorrowDecode, Decode, Encode,
10 de::{BorrowDecoder, Decoder, DecoderImpl, read::Reader},
11 enc::{Encoder, EncoderImpl, write::Writer},
12 error::{DecodeError, EncodeError},
13};
14use turbo_tasks_hash::DeterministicHasher;
15
16pub const TURBO_BINCODE_CONFIG: bincode::config::Configuration = bincode::config::standard();
17pub const TURBO_BINCODE_HASH_CONFIG: bincode::config::Configuration<
20 bincode::config::LittleEndian,
21 bincode::config::Fixint,
22 bincode::config::NoLimit,
23> = TURBO_BINCODE_CONFIG.with_fixed_int_encoding();
24pub type TurboBincodeBuffer = SmallVec<[u8; 16]>;
25pub type TurboBincodeEncoder<'a> =
26 EncoderImpl<TurboBincodeWriter<'a>, bincode::config::Configuration>;
27pub type TurboBincodeDecoder<'a> =
28 DecoderImpl<TurboBincodeReader<'a>, bincode::config::Configuration, ()>;
29pub type AnyEncodeFn = fn(&dyn Any, &mut TurboBincodeEncoder<'_>) -> Result<(), EncodeError>;
30pub type AnyDecodeFn<T> = fn(&mut TurboBincodeDecoder<'_>) -> Result<T, DecodeError>;
31
32pub fn new_turbo_bincode_encoder(buf: &mut TurboBincodeBuffer) -> TurboBincodeEncoder<'_> {
33 EncoderImpl::new(TurboBincodeWriter::new(buf), TURBO_BINCODE_CONFIG)
34}
35
36pub fn new_turbo_bincode_decoder(buffer: &[u8]) -> TurboBincodeDecoder<'_> {
37 DecoderImpl::new(TurboBincodeReader::new(buffer), TURBO_BINCODE_CONFIG, ())
38}
39
40pub fn turbo_bincode_encode<T: Encode>(value: &T) -> Result<TurboBincodeBuffer, EncodeError> {
45 let mut buffer = TurboBincodeBuffer::new();
46 turbo_bincode_encode_into(value, &mut buffer)?;
47 Ok(buffer)
48}
49
50pub fn turbo_bincode_encode_into<T: Encode>(
51 value: &T,
52 buffer: &mut TurboBincodeBuffer,
53) -> Result<(), EncodeError> {
54 let mut encoder = new_turbo_bincode_encoder(buffer);
55 value.encode(&mut encoder)?;
56 Ok(())
57}
58
59pub fn turbo_bincode_decode<T: Decode<()>>(buf: &[u8]) -> Result<T, DecodeError> {
62 let mut decoder = new_turbo_bincode_decoder(buf);
63 let val = T::decode(&mut decoder)?;
64 let remaining_buf = decoder.reader().buffer;
65 if !remaining_buf.is_empty() {
66 return Err(DecodeError::ArrayLengthMismatch {
67 required: buf.len() - remaining_buf.len(),
68 found: buf.len(),
69 });
70 }
71 Ok(val)
72}
73
74pub struct TurboBincodeWriter<'a> {
75 pub buffer: &'a mut TurboBincodeBuffer,
76}
77
78impl<'a> TurboBincodeWriter<'a> {
79 pub fn new(buffer: &'a mut TurboBincodeBuffer) -> Self {
80 Self { buffer }
81 }
82}
83
84impl Writer for TurboBincodeWriter<'_> {
85 fn write(&mut self, bytes: &[u8]) -> Result<(), EncodeError> {
86 self.buffer.extend_from_slice(bytes);
87 Ok(())
88 }
89}
90
91pub struct TurboBincodeReader<'a> {
94 pub buffer: &'a [u8],
95}
96
97impl<'a> TurboBincodeReader<'a> {
98 pub fn new(buffer: &'a [u8]) -> Self {
99 Self { buffer }
100 }
101}
102
103impl Reader for TurboBincodeReader<'_> {
104 fn read(&mut self, target_buffer: &mut [u8]) -> Result<(), DecodeError> {
105 let len = target_buffer.len();
106 let (head, rest) =
107 self.buffer
108 .split_at_checked(len)
109 .ok_or_else(|| DecodeError::UnexpectedEnd {
110 additional: len - self.buffer.len(),
111 })?;
112 unsafe {
117 copy_nonoverlapping(head.as_ptr(), target_buffer.as_mut_ptr(), len);
118 }
119 self.buffer = rest;
120 Ok(())
121 }
122
123 fn peek_read(&mut self, n: usize) -> Option<&[u8]> {
124 self.buffer.get(..n)
125 }
126
127 fn consume(&mut self, n: usize) {
128 self.buffer = &self.buffer[n..];
129 }
130}
131
132pub struct HashWriter<'a, H: DeterministicHasher + ?Sized> {
136 hasher: &'a mut H,
137}
138
139impl<'a, H: DeterministicHasher + ?Sized> HashWriter<'a, H> {
140 pub fn new(hasher: &'a mut H) -> Self {
142 Self { hasher }
143 }
144}
145
146impl<H: DeterministicHasher + ?Sized> Writer for HashWriter<'_, H> {
147 fn write(&mut self, bytes: &[u8]) -> Result<(), EncodeError> {
148 self.hasher.write_bytes(bytes);
149 Ok(())
150 }
151}
152
153pub type HashEncoder<'a, H> = EncoderImpl<
155 HashWriter<'a, H>,
156 bincode::config::Configuration<
157 bincode::config::LittleEndian,
158 bincode::config::Fixint,
159 bincode::config::NoLimit,
160 >,
161>;
162
163pub fn new_hash_encoder<H: DeterministicHasher + ?Sized>(hasher: &mut H) -> HashEncoder<'_, H> {
167 EncoderImpl::new(HashWriter::new(hasher), TURBO_BINCODE_HASH_CONFIG)
168}
169
170pub trait TurboBincodeEncode: Encode {
178 fn encode(&self, encoder: &mut TurboBincodeEncoder) -> Result<(), EncodeError>;
179}
180
181pub trait TurboBincodeDecode<Context>: Decode<Context> {
190 fn decode(decoder: &mut TurboBincodeDecoder) -> Result<Self, DecodeError>;
191}
192
193#[macro_export]
194macro_rules! impl_encode_for_turbo_bincode_encode {
195 ($ty:ty) => {
196 impl $crate::macro_helpers::bincode::Encode for $ty {
197 fn encode<'a, E: $crate::macro_helpers::bincode::enc::Encoder>(
198 &self,
199 encoder: &'a mut E,
200 ) -> ::std::result::Result<(), $crate::macro_helpers::bincode::error::EncodeError> {
201 $crate::macro_helpers::encode_for_turbo_bincode_encode_impl(self, encoder)
202 }
203 }
204 };
205}
206
207#[macro_export]
208macro_rules! impl_decode_for_turbo_bincode_decode {
209 ($ty:ty) => {
210 impl<Context> $crate::macro_helpers::bincode::Decode<Context> for $ty {
211 fn decode<D: $crate::macro_helpers::bincode::de::Decoder<Context = Context>>(
212 decoder: &mut D,
213 ) -> ::std::result::Result<Self, $crate::macro_helpers::bincode::error::DecodeError>
214 {
215 $crate::macro_helpers::decode_for_turbo_bincode_decode_impl(decoder)
216 }
217 }
218 };
219}
220
221pub mod indexmap {
222 use std::hash::{BuildHasher, Hash};
223
224 use ::indexmap::IndexMap;
225
226 use super::*;
227
228 pub fn encode<E, K, V, S>(map: &IndexMap<K, V, S>, encoder: &mut E) -> Result<(), EncodeError>
229 where
230 E: Encoder,
231 K: Encode,
232 V: Encode,
233 {
234 usize::encode(&map.len(), encoder)?;
235 for (k, v) in map {
236 K::encode(k, encoder)?;
237 V::encode(v, encoder)?;
238 }
239 Ok(())
240 }
241
242 pub fn decode<Context, D, K, V, S>(decoder: &mut D) -> Result<IndexMap<K, V, S>, DecodeError>
243 where
244 D: Decoder<Context = Context>,
245 K: Decode<Context> + Eq + Hash,
246 V: Decode<Context>,
247 S: BuildHasher + Default,
248 {
249 let len = usize::decode(decoder)?;
250 let mut map = IndexMap::with_capacity_and_hasher(len, Default::default());
251 for _i in 0..len {
252 map.insert(K::decode(decoder)?, V::decode(decoder)?);
253 }
254 Ok(map)
255 }
256
257 pub fn borrow_decode<'de, Context, D, K, V, S>(
258 decoder: &mut D,
259 ) -> Result<IndexMap<K, V, S>, DecodeError>
260 where
261 D: BorrowDecoder<'de, Context = Context>,
262 K: BorrowDecode<'de, Context> + Eq + Hash,
263 V: BorrowDecode<'de, Context>,
264 S: BuildHasher + Default,
265 {
266 let len = usize::decode(decoder)?;
267 let mut map = IndexMap::with_capacity_and_hasher(len, Default::default());
268 for _i in 0..len {
269 map.insert(K::borrow_decode(decoder)?, V::borrow_decode(decoder)?);
270 }
271 Ok(map)
272 }
273
274 #[cfg(test)]
275 mod tests {
276 use bincode::{decode_from_slice, encode_to_vec};
277
278 use super::*;
279
280 #[test]
281 fn test_roundtrip() {
282 let cfg = bincode::config::standard();
283
284 #[derive(Encode, Decode)]
285 struct Wrapper(#[bincode(with = "crate::indexmap")] IndexMap<String, u32>);
286
287 let map1 = Wrapper(IndexMap::from([
288 ("key1".to_string(), 12345u32),
289 ("key2".to_string(), 23456u32),
290 ]));
291
292 let map2: Wrapper = decode_from_slice(&encode_to_vec(&map1, cfg).unwrap(), cfg)
293 .unwrap()
294 .0;
295
296 assert_eq!(map1.0, map2.0);
297 }
298 }
299}
300
301pub mod indexset {
302 use std::hash::{BuildHasher, Hash};
303
304 use ::indexmap::IndexSet;
305
306 use super::*;
307
308 pub fn encode<E, T, S>(set: &IndexSet<T, S>, encoder: &mut E) -> Result<(), EncodeError>
309 where
310 E: Encoder,
311 T: Encode,
312 {
313 usize::encode(&set.len(), encoder)?;
314 for item in set {
315 T::encode(item, encoder)?;
316 }
317 Ok(())
318 }
319
320 pub fn decode<Context, D, T, S>(decoder: &mut D) -> Result<IndexSet<T, S>, DecodeError>
321 where
322 D: Decoder<Context = Context>,
323 T: Decode<Context> + Eq + Hash,
324 S: BuildHasher + Default,
325 {
326 let len = usize::decode(decoder)?;
327 let mut set = IndexSet::with_capacity_and_hasher(len, Default::default());
328 for _i in 0..len {
329 set.insert(T::decode(decoder)?);
330 }
331 Ok(set)
332 }
333
334 pub fn borrow_decode<'de, Context, D, T, S>(
335 decoder: &mut D,
336 ) -> Result<IndexSet<T, S>, DecodeError>
337 where
338 D: BorrowDecoder<'de, Context = Context>,
339 T: BorrowDecode<'de, Context> + Eq + Hash,
340 S: BuildHasher + Default,
341 {
342 let len = usize::decode(decoder)?;
343 let mut set = IndexSet::with_capacity_and_hasher(len, Default::default());
344 for _i in 0..len {
345 set.insert(T::borrow_decode(decoder)?);
346 }
347 Ok(set)
348 }
349
350 #[cfg(test)]
351 mod tests {
352 use bincode::{decode_from_slice, encode_to_vec};
353
354 use super::*;
355
356 #[test]
357 fn test_roundtrip() {
358 let cfg = bincode::config::standard();
359
360 #[derive(Encode, Decode)]
361 struct Wrapper(#[bincode(with = "crate::indexset")] IndexSet<String>);
362
363 let set1 = Wrapper(IndexSet::from([
364 "value1".to_string(),
365 "value2".to_string(),
366 "value3".to_string(),
367 ]));
368
369 let set2: Wrapper = decode_from_slice(&encode_to_vec(&set1, cfg).unwrap(), cfg)
370 .unwrap()
371 .0;
372
373 assert_eq!(set1.0, set2.0);
374 }
375 }
376}
377
378pub mod mime_option {
379 use std::str::FromStr;
380
381 use mime::Mime;
382
383 use super::*;
384
385 pub fn encode<E: Encoder>(mime: &Option<Mime>, encoder: &mut E) -> Result<(), EncodeError> {
386 let mime_str: Option<&str> = mime.as_ref().map(AsRef::as_ref);
387 Encode::encode(&mime_str, encoder)
388 }
389
390 pub fn decode<Context, D: Decoder<Context = Context>>(
391 decoder: &mut D,
392 ) -> Result<Option<Mime>, DecodeError> {
393 if let Some(mime_str) = <Option<String> as Decode<Context>>::decode(decoder)? {
394 Ok(Some(
395 Mime::from_str(&mime_str).map_err(|e| DecodeError::OtherString(e.to_string()))?,
396 ))
397 } else {
398 Ok(None)
399 }
400 }
401
402 pub fn borrow_decode<'de, Context, D: BorrowDecoder<'de, Context = Context>>(
403 decoder: &mut D,
404 ) -> Result<Option<Mime>, DecodeError> {
405 decode(decoder)
406 }
407
408 #[cfg(test)]
409 mod tests {
410 use bincode::{decode_from_slice, encode_to_vec};
411
412 use super::*;
413
414 #[derive(Encode, Decode)]
415 struct Wrapper(#[bincode(with = "crate::mime_option")] Option<Mime>);
416
417 #[test]
418 fn test_roundtrip() {
419 let cfg = bincode::config::standard();
420
421 let mime1 = Wrapper(Some("text/html; charset=utf-8".parse().unwrap()));
422
423 let mime2: Wrapper = decode_from_slice(&encode_to_vec(&mime1, cfg).unwrap(), cfg)
424 .unwrap()
425 .0;
426
427 assert_eq!(mime1.0, mime2.0);
428 }
429
430 #[test]
431 fn test_roundtrip_none() {
432 let cfg = bincode::config::standard();
433
434 let mime1 = Wrapper(None);
435
436 let mime2: Wrapper = decode_from_slice(&encode_to_vec(&mime1, cfg).unwrap(), cfg)
437 .unwrap()
438 .0;
439
440 assert_eq!(mime1.0, mime2.0);
441 }
442 }
443}
444
445pub mod either {
446 use ::either::Either;
447
448 use super::*;
449
450 pub fn encode<E: Encoder, L: Encode, R: Encode>(
451 value: &Either<L, R>,
452 encoder: &mut E,
453 ) -> Result<(), EncodeError> {
454 value.is_left().encode(encoder)?;
455 ::either::for_both!(value, v => Encode::encode(v, encoder))
456 }
457
458 pub fn decode<
459 Context,
460 D: Decoder<Context = Context>,
461 L: Decode<Context>,
462 R: Decode<Context>,
463 >(
464 decoder: &mut D,
465 ) -> Result<Either<L, R>, DecodeError> {
466 let is_left = bool::decode(decoder)?;
467 Ok(if is_left {
468 Either::Left(L::decode(decoder)?)
469 } else {
470 Either::Right(R::decode(decoder)?)
471 })
472 }
473
474 pub fn borrow_decode<
475 'de,
476 Context,
477 D: BorrowDecoder<'de, Context = Context>,
478 L: BorrowDecode<'de, Context>,
479 R: BorrowDecode<'de, Context>,
480 >(
481 decoder: &mut D,
482 ) -> Result<Either<L, R>, DecodeError> {
483 let is_left = bool::borrow_decode(decoder)?;
484 Ok(if is_left {
485 Either::Left(L::borrow_decode(decoder)?)
486 } else {
487 Either::Right(R::borrow_decode(decoder)?)
488 })
489 }
490
491 #[cfg(test)]
492 mod tests {
493 use bincode::{decode_from_slice, encode_to_vec};
494
495 use super::*;
496
497 #[derive(Encode, Decode)]
498 struct Wrapper(#[bincode(with = "crate::either")] Either<String, u32>);
499
500 #[test]
501 fn test_roundtrip_left() {
502 let cfg = bincode::config::standard();
503
504 let either1 = Wrapper(Either::Left("hello".to_string()));
505
506 let either2: Wrapper = decode_from_slice(&encode_to_vec(&either1, cfg).unwrap(), cfg)
507 .unwrap()
508 .0;
509
510 assert_eq!(either1.0, either2.0);
511 }
512
513 #[test]
514 fn test_roundtrip_right() {
515 let cfg = bincode::config::standard();
516
517 let either1 = Wrapper(Either::Right(42u32));
518
519 let either2: Wrapper = decode_from_slice(&encode_to_vec(&either1, cfg).unwrap(), cfg)
520 .unwrap()
521 .0;
522
523 assert_eq!(either1.0, either2.0);
524 }
525 }
526}
527
528pub mod smallvec {
529 use ::smallvec::Array;
530
531 use super::*;
532
533 pub fn encode<E: Encoder, A: Array<Item = impl Encode>>(
534 vec: &SmallVec<A>,
535 encoder: &mut E,
536 ) -> Result<(), EncodeError> {
537 usize::encode(&vec.len(), encoder)?;
538 for item in vec {
539 Encode::encode(item, encoder)?;
540 }
541 Ok(())
542 }
543
544 pub fn decode<Context, D: Decoder<Context = Context>, A: Array<Item = impl Decode<Context>>>(
545 decoder: &mut D,
546 ) -> Result<SmallVec<A>, DecodeError> {
547 let len = usize::decode(decoder)?;
548 let mut vec = SmallVec::with_capacity(len);
549 for _ in 0..len {
550 vec.push(Decode::decode(decoder)?);
551 }
552 Ok(vec)
553 }
554
555 pub fn borrow_decode<
556 'de,
557 Context,
558 D: BorrowDecoder<'de, Context = Context>,
559 A: Array<Item = impl BorrowDecode<'de, Context>>,
560 >(
561 decoder: &mut D,
562 ) -> Result<SmallVec<A>, DecodeError> {
563 let len = usize::decode(decoder)?;
564 let mut vec = SmallVec::with_capacity(len);
565 for _ in 0..len {
566 vec.push(BorrowDecode::borrow_decode(decoder)?);
567 }
568 Ok(vec)
569 }
570
571 #[cfg(test)]
572 mod tests {
573 use bincode::{decode_from_slice, encode_to_vec};
574
575 use super::*;
576
577 #[test]
578 fn test_roundtrip() {
579 let cfg = bincode::config::standard();
580
581 #[derive(Encode, Decode)]
582 struct Wrapper(#[bincode(with = "crate::smallvec")] SmallVec<[u32; 4]>);
583
584 let vec1 = Wrapper(SmallVec::from_slice(&[1u32, 2, 3, 4, 5]));
585
586 let vec2: Wrapper = decode_from_slice(&encode_to_vec(&vec1, cfg).unwrap(), cfg)
587 .unwrap()
588 .0;
589
590 assert_eq!(vec1.0, vec2.0);
591 }
592 }
593}
594
595pub mod owned_cow {
596 use std::borrow::Cow;
601
602 use super::*;
603
604 #[allow(clippy::ptr_arg)]
605 pub fn encode<E, T>(cow: &Cow<'_, T>, encoder: &mut E) -> Result<(), EncodeError>
606 where
607 E: Encoder,
608 T: ToOwned + ?Sized,
609 for<'a> &'a T: Encode,
610 {
611 cow.encode(encoder)
612 }
613
614 pub fn decode<'cow, Context, D, T>(decoder: &mut D) -> Result<Cow<'cow, T>, DecodeError>
615 where
616 D: Decoder<Context = Context>,
617 T: ToOwned + ?Sized,
618 <T as ToOwned>::Owned: Decode<Context>,
619 {
620 Decode::decode(decoder)
621 }
622
623 pub fn borrow_decode<'de, 'cow, Context, D, T>(
624 decoder: &mut D,
625 ) -> Result<Cow<'cow, T>, DecodeError>
626 where
627 D: BorrowDecoder<'de, Context = Context>,
628 T: ToOwned + ?Sized,
629 <T as ToOwned>::Owned: Decode<Context>,
630 {
631 Decode::decode(decoder)
632 }
633}