singlefile_formats/data/
bincode.rs

1#![cfg_attr(docsrs, doc(cfg(feature = "bincode")))]
2#![cfg(feature = "bincode")]
3
4//! Defines a [`FileFormat`] using the Bincode binary data format.
5
6pub extern crate bincode as original;
7
8use bincode::{Decode, Encode};
9use bincode::config::{Configuration, Config, BigEndian, LittleEndian, Varint, Fixint, Limit, NoLimit};
10use bincode::error::{DecodeError, EncodeError};
11#[cfg(feature = "bincode-serde")]
12use serde::ser::Serialize;
13#[cfg(feature = "bincode-serde")]
14use serde::de::DeserializeOwned;
15use singlefile::FileFormat;
16use thiserror::Error;
17
18use std::io::{Read, Write};
19
20/// An error that can occur while using [`Bincode`].
21#[derive(Debug, Error)]
22pub enum BincodeError {
23  /// An error occurred while encoding.
24  #[error(transparent)]
25  EncodeError(#[from] EncodeError),
26  /// An error occurred while decoding.
27  #[error(transparent)]
28  DecodeError(#[from] DecodeError)
29}
30
31/// A [`FileFormat`] corresponding to the CBOR binary data format.
32/// Implemented using the [`ciborium`] crate, only compatible with types that implement
33/// [`Decode`] and [`Encode`].
34#[derive(Debug, Clone, Copy, Default)]
35pub struct Bincode<E = LittleEndian, I = Varint, L = NoLimit> {
36  /// The internal [`Configuration`].
37  pub configuration: Configuration<E, I, L>
38}
39
40impl<T, E, I, L> FileFormat<T> for Bincode<E, I, L>
41where T: Decode<()> + Encode, Configuration<E, I, L>: Config {
42  type FormatError = BincodeError;
43
44  #[inline]
45  fn from_reader<R: Read>(&self, mut reader: R) -> Result<T, Self::FormatError> {
46    Ok(bincode::decode_from_std_read(&mut reader, self.configuration)?)
47  }
48
49  #[inline]
50  fn from_buffer(&self, buf: &[u8]) -> Result<T, Self::FormatError> {
51    Ok(bincode::decode_from_slice(buf, self.configuration)?.0)
52  }
53
54  #[inline]
55  fn to_writer<W: Write>(&self, mut writer: W, value: &T) -> Result<(), Self::FormatError> {
56    bincode::encode_into_std_write(value, &mut writer, self.configuration)?;
57    Ok(())
58  }
59
60  #[inline]
61  fn to_buffer(&self, value: &T) -> Result<Vec<u8>, Self::FormatError> {
62    Ok(bincode::encode_to_vec(value, self.configuration)?)
63  }
64}
65
66impl<E, I, L> Bincode<E, I, L> {
67  /// Creates a new [`Bincode`] given a [`Configuration`].
68  #[inline]
69  pub const fn new(configuration: Configuration<E, I, L>) -> Self {
70    Bincode { configuration }
71  }
72
73  /// Makes bincode encode all integer types in big endian.
74  ///
75  /// Applies [`with_big_endian`][Configuration::with_big_endian] to the wrapped [`Configuration`].
76  #[inline]
77  pub const fn with_big_endian(self) -> Bincode<BigEndian, I, L> {
78    Bincode { configuration: self.configuration.with_big_endian() }
79  }
80
81  /// Makes bincode encode all integer types in little endian.
82  ///
83  /// Applies [`with_little_endian`][Configuration::with_little_endian] to the wrapped [`Configuration`].
84  #[inline]
85  pub const fn with_little_endian(self) -> Bincode<LittleEndian, I, L> {
86    Bincode { configuration: self.configuration.with_little_endian() }
87  }
88
89  /// Makes bincode encode all integer types with a variable integer encoding.
90  ///
91  /// Applies [`with_variable_int_encoding`][Configuration::with_variable_int_encoding] to the wrapped [`Configuration`].
92  #[inline]
93  pub const fn with_variable_int_encoding(self) -> Bincode<E, Varint, L> {
94    Bincode { configuration: self.configuration.with_variable_int_encoding() }
95  }
96
97  /// Fixed-size integer encoding.
98  ///
99  /// Applies [`with_fixed_int_encoding`][Configuration::with_fixed_int_encoding] to the wrapped [`Configuration`].
100  #[inline]
101  pub const fn with_fixed_int_encoding(self) -> Bincode<E, Fixint, L> {
102    Bincode { configuration: self.configuration.with_fixed_int_encoding() }
103  }
104
105  /// Sets the byte limit to `limit`.
106  ///
107  /// Applies [`with_limit`][Configuration::with_limit] to the wrapped [`Configuration`].
108  #[inline]
109  pub const fn with_limit<const N: usize>(self) -> Bincode<E, I, Limit<N>> {
110    Bincode { configuration: self.configuration.with_limit() }
111  }
112
113  /// Clear the byte limit.
114  ///
115  /// Applies [`with_no_limit`][Configuration::with_no_limit] to the wrapped [`Configuration`].
116  #[inline]
117  pub const fn with_no_limit(self) -> Bincode<E, I, NoLimit> {
118    Bincode { configuration: self.configuration.with_no_limit() }
119  }
120}
121
122/// A [`FileFormat`] corresponding to the CBOR binary data format.
123/// Implemented using the [`ciborium`] crate, only compatible with types that implement
124/// [`Decode`] and [`Encode`].
125#[cfg(feature = "bincode-serde")]
126#[derive(Debug, Clone, Copy, Default)]
127pub struct BincodeSerde<E = LittleEndian, I = Varint, L = NoLimit> {
128  /// The internal [`Configuration`].
129  pub configuration: Configuration<E, I, L>
130}
131
132#[cfg(feature = "bincode-serde")]
133impl<T, E, I, L> FileFormat<T> for BincodeSerde<E, I, L>
134where T: DeserializeOwned + Serialize, Configuration<E, I, L>: Config {
135  type FormatError = BincodeError;
136
137  #[inline]
138  fn from_reader<R: Read>(&self, mut reader: R) -> Result<T, Self::FormatError> {
139    Ok(bincode::serde::decode_from_std_read(&mut reader, self.configuration)?)
140  }
141
142  #[inline]
143  fn from_buffer(&self, buf: &[u8]) -> Result<T, Self::FormatError> {
144    Ok(bincode::serde::decode_from_slice(buf, self.configuration)?.0)
145  }
146
147  #[inline]
148  fn to_writer<W: Write>(&self, mut writer: W, value: &T) -> Result<(), Self::FormatError> {
149    bincode::serde::encode_into_std_write(value, &mut writer, self.configuration)?;
150    Ok(())
151  }
152
153  #[inline]
154  fn to_buffer(&self, value: &T) -> Result<Vec<u8>, Self::FormatError> {
155    Ok(bincode::serde::encode_to_vec(value, self.configuration)?)
156  }
157}
158
159#[cfg(feature = "bincode-serde")]
160impl<E, I, L> BincodeSerde<E, I, L> {
161  /// Creates a new [`Bincode`] given a [`Configuration`].
162  #[inline]
163  pub const fn new(configuration: Configuration<E, I, L>) -> Self {
164    BincodeSerde { configuration }
165  }
166
167  /// Makes bincode encode all integer types in big endian.
168  ///
169  /// Applies [`with_big_endian`][Configuration::with_big_endian] to the wrapped [`Configuration`].
170  #[inline]
171  pub const fn with_big_endian(self) -> BincodeSerde<BigEndian, I, L> {
172    BincodeSerde { configuration: self.configuration.with_big_endian() }
173  }
174
175  /// Makes bincode encode all integer types in little endian.
176  ///
177  /// Applies [`with_little_endian`][Configuration::with_little_endian] to the wrapped [`Configuration`].
178  #[inline]
179  pub const fn with_little_endian(self) -> BincodeSerde<LittleEndian, I, L> {
180    BincodeSerde { configuration: self.configuration.with_little_endian() }
181  }
182
183  /// Makes bincode encode all integer types with a variable integer encoding.
184  ///
185  /// Applies [`with_variable_int_encoding`][Configuration::with_variable_int_encoding] to the wrapped [`Configuration`].
186  #[inline]
187  pub const fn with_variable_int_encoding(self) -> BincodeSerde<E, Varint, L> {
188    BincodeSerde { configuration: self.configuration.with_variable_int_encoding() }
189  }
190
191  /// Fixed-size integer encoding.
192  ///
193  /// Applies [`with_fixed_int_encoding`][Configuration::with_fixed_int_encoding] to the wrapped [`Configuration`].
194  #[inline]
195  pub const fn with_fixed_int_encoding(self) -> BincodeSerde<E, Fixint, L> {
196    BincodeSerde { configuration: self.configuration.with_fixed_int_encoding() }
197  }
198
199  /// Sets the byte limit to `limit`.
200  ///
201  /// Applies [`with_limit`][Configuration::with_limit] to the wrapped [`Configuration`].
202  #[inline]
203  pub const fn with_limit<const N: usize>(self) -> BincodeSerde<E, I, Limit<N>> {
204    BincodeSerde { configuration: self.configuration.with_limit() }
205  }
206
207  /// Clear the byte limit.
208  ///
209  /// Applies [`with_no_limit`][Configuration::with_no_limit] to the wrapped [`Configuration`].
210  #[inline]
211  pub const fn with_no_limit(self) -> BincodeSerde<E, I, NoLimit> {
212    BincodeSerde { configuration: self.configuration.with_no_limit() }
213  }
214}
215
216/// A shortcut type to a [`Compressed`][crate::compression::Compressed] [`Bincode`].
217/// Provides a single parameter for compression format.
218#[cfg_attr(docsrs, doc(cfg(feature = "compression")))]
219#[cfg(feature = "compression")]
220pub type CompressedBincode<C, E = LittleEndian, I = Varint, L = NoLimit>
221  = crate::compression::Compressed<C, Bincode<E, I, L>>;
222
223/// A shortcut type to a [`Compressed`][crate::compression::Compressed] [`BincodeSerde`].
224/// Provides a single parameter for compression format.
225#[cfg_attr(docsrs, doc(cfg(all(feature = "compression", feature = "bincode-serde"))))]
226#[cfg(all(feature = "compression", feature = "bincode-serde"))]
227pub type CompressedBincodeSerde<C, E = LittleEndian, I = Varint, L = NoLimit>
228  = crate::compression::Compressed<C, Bincode<E, I, L>>;