pot/
lib.rs

1#![doc = include_str!("../crate-docs.md")]
2#![forbid(unsafe_code)]
3#![warn(
4    clippy::cargo,
5    missing_docs,
6    // clippy::missing_docs_in_private_items,
7    clippy::pedantic,
8    future_incompatible,
9    rust_2018_idioms,
10)]
11#![allow(
12    clippy::missing_errors_doc, // TODO clippy::missing_errors_doc
13    clippy::option_if_let_else,
14    clippy::used_underscore_binding, // false positive with tracing
15    clippy::module_name_repetitions,
16)]
17
18/// Types for deserializing pots.
19pub mod de;
20mod error;
21/// Low-level interface for reading and writing the pot format.
22pub mod format;
23/// Types for reading data.
24pub mod reader;
25/// Types for serializing pots.
26pub mod ser;
27mod value;
28use std::io::Read;
29
30use byteorder::WriteBytesExt;
31
32pub use self::error::Error;
33pub use self::value::{OwnedValue, Value, ValueError, ValueIter};
34/// A result alias that returns [`Error`].
35pub type Result<T, E = Error> = std::result::Result<T, E>;
36use serde::de::DeserializeOwned;
37use serde::{Deserialize, Serialize};
38
39use crate::de::SymbolMapRef;
40use crate::reader::IoReader;
41
42/// Serialize `value` using Pot into a `Vec<u8>`.
43///
44/// ```rust
45/// let serialized = pot::to_vec(&"hello world").unwrap();
46/// let deserialized = pot::from_slice::<String>(&serialized).unwrap();
47/// assert_eq!(deserialized, "hello world");
48/// ```
49#[inline]
50pub fn to_vec<T>(value: &T) -> Result<Vec<u8>>
51where
52    T: Serialize,
53{
54    Config::default().serialize(value)
55}
56
57/// Serialize `value` using Pot into `writer`.
58///
59/// ```rust
60/// let mut serialized = Vec::new();
61/// pot::to_writer(&"hello world", &mut serialized).unwrap();
62/// let deserialized = pot::from_reader::<String, _>(&serialized[..]).unwrap();
63/// assert_eq!(deserialized, "hello world");
64/// ```
65#[inline]
66pub fn to_writer<T, W>(value: &T, writer: W) -> Result<()>
67where
68    T: Serialize,
69    W: WriteBytesExt,
70{
71    Config::default().serialize_into(value, writer)
72}
73
74/// Restores a previously Pot-serialized value from a slice.
75///
76/// ```rust
77/// let serialized = pot::to_vec(&"hello world").unwrap();
78/// let deserialized = pot::from_slice::<String>(&serialized).unwrap();
79/// assert_eq!(deserialized, "hello world");
80/// ```
81#[inline]
82pub fn from_slice<'a, T>(serialized: &'a [u8]) -> Result<T>
83where
84    T: Deserialize<'a>,
85{
86    Config::default().deserialize(serialized)
87}
88
89/// Restores a previously Pot-serialized value from a [`Read`] implementer.
90///
91/// ```rust
92/// let mut serialized = Vec::new();
93/// pot::to_writer(&"hello world", &mut serialized).unwrap();
94/// let deserialized = pot::from_reader::<String, _>(&serialized[..]).unwrap();
95/// assert_eq!(deserialized, "hello world");
96/// ```
97#[inline]
98pub fn from_reader<T, R>(reader: R) -> Result<T>
99where
100    T: DeserializeOwned,
101    R: Read,
102{
103    Config::default().deserialize_from(reader)
104}
105
106/// Serialization and deserialization configuration.
107#[must_use]
108#[derive(Clone, Debug)]
109pub struct Config {
110    allocation_budget: usize,
111    compatibility: Compatibility,
112}
113
114impl Default for Config {
115    #[inline]
116    fn default() -> Self {
117        Self::new()
118    }
119}
120
121impl Config {
122    /// Returns the default configuration.
123    pub const fn new() -> Self {
124        Self {
125            allocation_budget: usize::MAX,
126            compatibility: Compatibility::const_default(),
127        }
128    }
129    /// Sets the maximum number of bytes able to be allocated. This is not
130    /// guaranteed to be perfectly accurate, due to the limitations of serde
131    /// deserializers. Pot can keep track of how many bytes it thinks its
132    /// allocating, but a deserializer can always allocate more memory than Pot
133    /// can be aware of.
134    ///
135    /// The default allocation budget is [`usize::MAX`].
136    #[inline]
137    pub const fn allocation_budget(mut self, budget: usize) -> Self {
138        self.allocation_budget = budget;
139        self
140    }
141
142    /// Sets the compatibility mode for serializing and returns self.
143    pub const fn compatibility(mut self, compatibilty: Compatibility) -> Self {
144        self.compatibility = compatibilty;
145        self
146    }
147
148    /// Deserializes a value from a slice using the configured options.
149    #[inline]
150    pub fn deserialize<'de, T>(&self, serialized: &'de [u8]) -> Result<T>
151    where
152        T: Deserialize<'de>,
153    {
154        let mut deserializer = de::Deserializer::from_slice(serialized, self.allocation_budget)?;
155        let t = T::deserialize(&mut deserializer)?;
156        if deserializer.end_of_input() {
157            Ok(t)
158        } else {
159            Err(Error::TrailingBytes)
160        }
161    }
162
163    /// Deserializes a value from a [`Read`] implementer using the configured
164    /// options.
165    #[inline]
166    pub fn deserialize_from<T, R: Read>(&self, reader: R) -> Result<T>
167    where
168        T: DeserializeOwned,
169    {
170        let mut deserializer = de::Deserializer::from_read(
171            IoReader::new(reader),
172            SymbolMapRef::temporary(),
173            self.allocation_budget,
174        )?;
175        T::deserialize(&mut deserializer)
176    }
177
178    /// Serializes a value to a `Vec` using the configured options.
179    #[inline]
180    pub fn serialize<T: Serialize>(&self, value: &T) -> Result<Vec<u8>> {
181        let mut output = Vec::new();
182        self.serialize_into(value, &mut output)?;
183        Ok(output)
184    }
185
186    /// Serializes a value to a writer using the configured options.
187    #[allow(clippy::unused_self)]
188    #[inline]
189    pub fn serialize_into<T, W>(&self, value: &T, writer: W) -> Result<()>
190    where
191        T: Serialize,
192        W: WriteBytesExt,
193    {
194        let mut serializer = ser::Serializer::new_with_compatibility(writer, self.compatibility)?;
195        value.serialize(&mut serializer)
196    }
197}
198
199/// Compatibility settings for Pot.
200#[derive(Debug, Eq, PartialEq, Clone, Copy)]
201#[non_exhaustive]
202pub enum Compatibility {
203    /// Serializes data that is compatible with all versions of Pot
204    /// deserializers.
205    ///
206    /// This format does not support [`Value`](crate::Value) deserialization of
207    /// enum variants without associated data. See [`V5`](Self::V5) for more
208    /// information.
209    Full,
210    /// Serializes data in the default format
211    ///
212    /// This format has a single change in how enum variants without associated
213    /// data are serialized. This change allows `deserialize_any` to
214    /// unambiguously distinguish between variants with associated data and
215    /// variants without associated data.
216    ///
217    /// This will be the default compatibility setting in `v4.0` and later. All
218    /// versions after `v3.0.1` are able to read this updated format.
219    V4,
220}
221
222impl Compatibility {
223    const fn const_default() -> Self {
224        Self::Full
225    }
226}
227
228impl Default for Compatibility {
229    fn default() -> Self {
230        Self::const_default()
231    }
232}
233
234#[cfg(test)]
235mod tests;