rkyv/api/high/checked.rs
1//! High-level checked APIs.
2//!
3//! These APIs have default writers, automatically manage allocators, and
4//! support shared pointers.
5
6use bytecheck::CheckBytes;
7use rancor::{Source, Strategy};
8
9use crate::{
10 api::{
11 access_pos_unchecked_mut, access_pos_with_context, access_with_context,
12 check_pos_with_context, deserialize_using, root_position,
13 },
14 de::pooling::Pool,
15 seal::Seal,
16 validation::{
17 archive::ArchiveValidator, shared::SharedValidator, Validator,
18 },
19 Archive, Deserialize, Portable,
20};
21
22/// A high-level validator.
23///
24/// This is part of the [high-level API](crate::api::high).
25pub type HighValidator<'a, E> =
26 Strategy<Validator<ArchiveValidator<'a>, SharedValidator>, E>;
27
28fn validator(bytes: &[u8]) -> Validator<ArchiveValidator<'_>, SharedValidator> {
29 Validator::new(ArchiveValidator::new(bytes), SharedValidator::new())
30}
31
32/// Access a byte slice with a given root position.
33///
34/// This is a safe alternative to [`access_pos_unchecked`] and is part of the
35/// [high-level API](crate::api::high).
36///
37/// [`access_pos_unchecked`]: crate::api::access_pos_unchecked
38///
39/// # Example
40///
41/// ```
42/// use rkyv::{
43/// api::{high::access_pos, root_position},
44/// bytecheck::CheckBytes,
45/// rancor::Error,
46/// to_bytes, Archive, Archived, Serialize,
47/// };
48///
49/// #[derive(Archive, Serialize)]
50/// struct Example {
51/// name: String,
52/// value: i32,
53/// }
54///
55/// let value = Example {
56/// name: "pi".to_string(),
57/// value: 31415926,
58/// };
59///
60/// let bytes = to_bytes::<Error>(&value).unwrap();
61/// let archived = access_pos::<ArchivedExample, Error>(
62/// &bytes,
63/// root_position::<ArchivedExample>(bytes.len()),
64/// )
65/// .unwrap();
66///
67/// assert_eq!(archived.name, "pi");
68/// assert_eq!(archived.value, 31415926);
69/// ```
70pub fn access_pos<T, E>(bytes: &[u8], pos: usize) -> Result<&T, E>
71where
72 T: Portable + for<'a> CheckBytes<HighValidator<'a, E>>,
73 E: Source,
74{
75 access_pos_with_context::<_, _, E>(bytes, pos, &mut validator(bytes))
76}
77
78/// Access a byte slice.
79///
80/// This is a safe alternative to [`access_unchecked`] and is part of the
81/// [high-level API](crate::api::high).
82///
83/// [`access_unchecked`]: crate::access_unchecked
84///
85/// # Example
86///
87/// ```
88/// use rkyv::{
89/// access, bytecheck::CheckBytes, rancor::Error, to_bytes, Archive,
90/// Archived, Serialize,
91/// };
92///
93/// #[derive(Archive, Serialize)]
94/// struct Example {
95/// name: String,
96/// value: i32,
97/// }
98///
99/// let value = Example {
100/// name: "pi".to_string(),
101/// value: 31415926,
102/// };
103///
104/// let bytes = to_bytes::<Error>(&value).unwrap();
105/// let archived = access::<ArchivedExample, Error>(&bytes).unwrap();
106///
107/// assert_eq!(archived.name, "pi");
108/// assert_eq!(archived.value, 31415926);
109/// ```
110pub fn access<T, E>(bytes: &[u8]) -> Result<&T, E>
111where
112 T: Portable + for<'a> CheckBytes<HighValidator<'a, E>>,
113 E: Source,
114{
115 access_with_context::<_, _, E>(bytes, &mut validator(bytes))
116}
117
118/// Mutably access a byte slice with a given root position.
119///
120/// This is a safe alternative to [`access_pos_unchecked_mut`] and is part of
121/// the [high-level API](crate::api::high).
122///
123/// # Example
124///
125/// ```
126/// use rkyv::{
127/// api::{high::access_pos_mut, root_position},
128/// bytecheck::CheckBytes,
129/// rancor::Error, munge::munge,
130/// to_bytes, Archive, Archived, Serialize,
131/// };
132///
133/// #[derive(Archive, Serialize)]
134/// struct Example {
135/// name: String,
136/// value: i32,
137/// }
138///
139/// let value = Example {
140/// name: "pi".to_string(),
141/// value: 31415926,
142/// };
143///
144/// let mut bytes = to_bytes::<Error>(&value).unwrap();
145/// let root_pos = root_position::<ArchivedExample>(bytes.len());
146///
147/// let mut archived =
148/// access_pos_mut::<ArchivedExample, Error>(&mut bytes, root_pos).unwrap();
149///
150/// // Because the access is mutable, we can mutate the archived data
151/// munge!(let ArchivedExample { mut value, .. } = archived);
152/// assert_eq!(*value, 31415926);
153/// *value = 12345.into();
154/// assert_eq!(*value, 12345);
155/// ```
156pub fn access_pos_mut<T, E>(
157 bytes: &mut [u8],
158 pos: usize,
159) -> Result<Seal<'_, T>, E>
160where
161 T: Portable + for<'a> CheckBytes<HighValidator<'a, E>>,
162 E: Source,
163{
164 let mut context = validator(bytes);
165 check_pos_with_context::<T, _, E>(bytes, pos, &mut context)?;
166 unsafe { Ok(access_pos_unchecked_mut::<T>(bytes, pos)) }
167}
168
169/// Mutably access a byte slice.
170///
171/// This is a safe alternative to [`access_unchecked_mut`] and is part of the
172/// [high-level API](crate::api::high).
173///
174/// [`access_unchecked_mut`]: crate::api::access_unchecked_mut
175///
176/// # Example
177///
178/// ```
179/// use rkyv::{
180/// access_mut,
181/// bytecheck::CheckBytes,
182/// rancor::Error, munge::munge,
183/// to_bytes, Archive, Archived, Serialize,
184/// };
185///
186/// #[derive(Archive, Serialize)]
187/// struct Example {
188/// name: String,
189/// value: i32,
190/// }
191///
192/// let value = Example {
193/// name: "pi".to_string(),
194/// value: 31415926,
195/// };
196///
197/// let mut bytes = to_bytes::<Error>(&value).unwrap();
198///
199/// let mut archived = access_mut::<ArchivedExample, Error>(&mut bytes)
200/// .unwrap();
201///
202/// // Because the access is mutable, we can mutate the archived data
203/// munge!(let ArchivedExample { mut value, .. } = archived);
204/// assert_eq!(*value, 31415926);
205/// *value = 12345.into();
206/// assert_eq!(*value, 12345);
207/// ```
208pub fn access_mut<T, E>(bytes: &mut [u8]) -> Result<Seal<'_, T>, E>
209where
210 T: Portable + for<'a> CheckBytes<HighValidator<'a, E>>,
211 E: Source,
212{
213 let mut context = validator(bytes);
214 let pos = root_position::<T>(bytes.len());
215 check_pos_with_context::<T, _, E>(bytes, pos, &mut context)?;
216 unsafe { Ok(access_pos_unchecked_mut::<T>(bytes, pos)) }
217}
218
219/// Deserialize a value from the given bytes.
220///
221/// This is a safe alternative to [`from_bytes_unchecked`] and is part of the
222/// [high-level API](crate::api::high).
223///
224/// [`from_bytes_unchecked`]: crate::api::high::from_bytes_unchecked
225///
226/// # Example
227///
228/// ```
229/// use rkyv::{
230/// from_bytes, rancor::Error, to_bytes, Archive, Deserialize, Serialize,
231/// };
232///
233/// #[derive(Archive, Serialize, Deserialize, Debug, PartialEq)]
234/// struct Example {
235/// name: String,
236/// value: i32,
237/// }
238///
239/// let value = Example {
240/// name: "pi".to_string(),
241/// value: 31415926,
242/// };
243///
244/// let bytes = to_bytes::<Error>(&value).unwrap();
245/// let deserialized = from_bytes::<Example, Error>(&bytes).unwrap();
246///
247/// assert_eq!(deserialized, value);
248/// ```
249pub fn from_bytes<T, E>(bytes: &[u8]) -> Result<T, E>
250where
251 T: Archive,
252 T::Archived: for<'a> CheckBytes<HighValidator<'a, E>>
253 + Deserialize<T, Strategy<Pool, E>>,
254 E: Source,
255{
256 let mut deserializer = Pool::default();
257 deserialize_using(access::<T::Archived, E>(bytes)?, &mut deserializer)
258}