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;