Skip to main content

rkyv/api/high/
mod.rs

1//! APIs for environments where allocations can be made.
2//!
3//! These APIs have default writers, automatically manage allocators, and
4//! support shared pointers.
5
6#[cfg(feature = "bytecheck")]
7mod checked;
8
9use rancor::Strategy;
10
11#[cfg(feature = "bytecheck")]
12pub use self::checked::*;
13use crate::{
14    access_unchecked,
15    api::{deserialize_using, serialize_using},
16    de::Pool,
17    ser::{
18        allocator::ArenaHandle, sharing::Share, Allocator, Serializer, Writer,
19    },
20    util::{with_arena, AlignedVec},
21    Archive, Deserialize, Serialize,
22};
23
24/// A high-level serializer.
25///
26/// This is part of the [high-level API](crate::api::high).
27pub type HighSerializer<W, A, E> = Strategy<Serializer<W, A, Share>, E>;
28
29/// A high-level deserializer.
30///
31/// This is part of the [high-level API](crate::api::high).
32pub type HighDeserializer<E> = Strategy<Pool, E>;
33
34/// Serialize a value to bytes.
35///
36/// Returns the serialized bytes in an [`AlignedVec`].
37///
38/// This is part of the [high-level API](crate::api::high).
39///
40/// # Example
41///
42/// ```
43/// use rkyv::{
44///     from_bytes, rancor::Error, to_bytes, Archive, Deserialize, Serialize,
45/// };
46///
47/// #[derive(Archive, Serialize, Deserialize, Debug, PartialEq)]
48/// struct Example {
49///     name: String,
50///     value: i32,
51/// }
52///
53/// let value = Example {
54///     name: "pi".to_string(),
55///     value: 31415926,
56/// };
57///
58/// let bytes = to_bytes::<Error>(&value).unwrap();
59/// let deserialized = from_bytes::<Example, Error>(&bytes).unwrap();
60///
61/// assert_eq!(deserialized, value);
62/// ```
63pub fn to_bytes<E>(
64    // rustfmt insists on inlining this parameter even though it exceeds the
65    // max line length
66    #[rustfmt::skip] value: &impl for<'a> Serialize<
67        HighSerializer<AlignedVec, ArenaHandle<'a>, E>,
68    >,
69) -> Result<AlignedVec, E>
70where
71    E: rancor::Source,
72{
73    to_bytes_in(value, AlignedVec::new())
74}
75
76/// Serialize a value and write the bytes to the given writer.
77///
78/// This is part of the [high-level API](crate::api::high).
79///
80/// # Example
81///
82/// ```
83/// use rkyv::{
84///     api::high::to_bytes_in, from_bytes, rancor::Error, util::AlignedVec,
85///     Archive, Deserialize, Serialize,
86/// };
87///
88/// #[derive(Archive, Serialize, Deserialize, Debug, PartialEq)]
89/// struct Example {
90///     name: String,
91///     value: i32,
92/// }
93///
94/// let value = Example {
95///     name: "pi".to_string(),
96///     value: 31415926,
97/// };
98///
99/// let bytes =
100///     to_bytes_in::<_, Error>(&value, AlignedVec::<8>::new()).unwrap();
101/// let deserialized = from_bytes::<Example, Error>(&bytes).unwrap();
102///
103/// assert_eq!(deserialized, value);
104/// ```
105pub fn to_bytes_in<W, E>(
106    value: &impl for<'a> Serialize<HighSerializer<W, ArenaHandle<'a>, E>>,
107    writer: W,
108) -> Result<W, E>
109where
110    W: Writer<E>,
111    E: rancor::Source,
112{
113    with_arena(|arena| to_bytes_in_with_alloc(value, writer, arena.acquire()))
114}
115
116/// Serialize a value using the given allocator.
117///
118/// This is part of the [high-level API](crate::api::high).
119///
120/// # Example
121///
122/// ```
123/// use rkyv::{
124///     api::high::to_bytes_with_alloc, from_bytes, rancor::Error,
125///     util::with_arena, Archive, Deserialize, Serialize,
126/// };
127///
128/// #[derive(Archive, Serialize, Deserialize, Debug, PartialEq)]
129/// struct Example {
130///     name: String,
131///     value: i32,
132/// }
133///
134/// let value = Example {
135///     name: "pi".to_string(),
136///     value: 31415926,
137/// };
138///
139/// with_arena(|arena| {
140///     let bytes =
141///         to_bytes_with_alloc::<_, Error>(&value, arena.acquire()).unwrap();
142///     let deserialized = from_bytes::<Example, Error>(&bytes).unwrap();
143///
144///     assert_eq!(deserialized, value);
145/// });
146/// ```
147pub fn to_bytes_with_alloc<A, E>(
148    value: &impl Serialize<HighSerializer<AlignedVec, A, E>>,
149    alloc: A,
150) -> Result<AlignedVec, E>
151where
152    A: Allocator<E>,
153    E: rancor::Source,
154{
155    to_bytes_in_with_alloc(value, AlignedVec::new(), alloc)
156}
157
158/// Serialize a value using the given allocator and write the bytes to the given
159/// writer.
160///
161/// This is part of the [high-level API](crate::api::high).
162///
163/// # Example
164///
165/// ```
166/// use rkyv::{
167///     api::high::to_bytes_in_with_alloc,
168///     from_bytes,
169///     rancor::Error,
170///     util::{with_arena, AlignedVec},
171///     Archive, Deserialize, Serialize,
172/// };
173///
174/// #[derive(Archive, Serialize, Deserialize, Debug, PartialEq)]
175/// struct Example {
176///     name: String,
177///     value: i32,
178/// }
179///
180/// let value = Example {
181///     name: "pi".to_string(),
182///     value: 31415926,
183/// };
184///
185/// with_arena(|arena| {
186///     let bytes = to_bytes_in_with_alloc::<_, _, Error>(
187///         &value,
188///         AlignedVec::<8>::new(),
189///         arena.acquire(),
190///     )
191///     .expect("failed to serialize vec");
192///
193///     let deserialized = from_bytes::<Example, Error>(&bytes)
194///         .expect("failed to deserialize vec");
195///
196///     assert_eq!(deserialized, value);
197/// });
198/// ```
199pub fn to_bytes_in_with_alloc<W, A, E>(
200    value: &impl Serialize<HighSerializer<W, A, E>>,
201    writer: W,
202    alloc: A,
203) -> Result<W, E>
204where
205    W: Writer<E>,
206    A: Allocator<E>,
207    E: rancor::Source,
208{
209    let mut serializer = Serializer::new(writer, alloc, Share::new());
210    serialize_using(value, &mut serializer)?;
211    Ok(serializer.into_writer())
212}
213
214/// Deserialize a value from the given bytes.
215///
216/// This function does not check that the data is valid. Use [`from_bytes`] to
217/// validate the data instead.
218///
219/// This is part of the [high-level API](crate::api::high).
220///
221/// # Safety
222///
223/// The byte slice must represent a valid archived type when accessed at the
224/// default root position. See the [module docs](crate::api) for more
225/// information.
226///
227/// # Example
228///
229/// ```
230/// use rkyv::{
231///     from_bytes_unchecked, rancor::Error, to_bytes, Archive, Deserialize,
232///     Serialize,
233/// };
234///
235/// #[derive(Archive, Serialize, Deserialize, Debug, PartialEq)]
236/// struct Example {
237///     name: String,
238///     value: i32,
239/// }
240///
241/// let value = Example {
242///     name: "pi".to_string(),
243///     value: 31415926,
244/// };
245///
246/// let bytes = to_bytes::<Error>(&value).unwrap();
247/// let deserialized =
248///     unsafe { from_bytes_unchecked::<Example, Error>(&bytes).unwrap() };
249///
250/// assert_eq!(deserialized, value);
251/// ```
252pub unsafe fn from_bytes_unchecked<T, E>(bytes: &[u8]) -> Result<T, E>
253where
254    T: Archive,
255    T::Archived: Deserialize<T, HighDeserializer<E>>,
256{
257    // SAFETY: The caller has guaranteed that a valid `T` is located at the root
258    // position in the byte slice.
259    let archived = unsafe { access_unchecked::<T::Archived>(bytes) };
260    deserialize(archived)
261}
262
263/// Deserialize a value from the given archived value.
264///
265/// This is part of the [high-level API](crate::api::high).
266///
267/// # Example
268///
269/// ```
270/// use rkyv::{
271///     access, deserialize, rancor::Error, to_bytes, Archive, Deserialize,
272///     Serialize,
273/// };
274///
275/// #[derive(Archive, Serialize, Deserialize, Debug, PartialEq)]
276/// struct Example {
277///     name: String,
278///     value: i32,
279/// }
280///
281/// let value = Example {
282///     name: "pi".to_string(),
283///     value: 31415926,
284/// };
285///
286/// let bytes = to_bytes::<Error>(&value).unwrap();
287/// let archived = access::<ArchivedExample, Error>(&*bytes).unwrap();
288/// let deserialized = deserialize::<Example, Error>(archived).unwrap();
289///
290/// assert_eq!(deserialized, value);
291/// ```
292pub fn deserialize<T, E>(
293    value: &impl Deserialize<T, HighDeserializer<E>>,
294) -> Result<T, E> {
295    deserialize_using(value, &mut Pool::new())
296}
297
298#[cfg(test)]
299mod tests {
300    use rancor::Panic;
301
302    use crate::{
303        alloc::{string::ToString, vec::Vec},
304        api::high::to_bytes_in,
305    };
306
307    #[test]
308    fn to_bytes_in_vec() {
309        let value = "hello world".to_string();
310        let bytes = to_bytes_in::<_, Panic>(&value, Vec::new()).unwrap();
311        assert!(!bytes.is_empty());
312    }
313}