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}