risc0_zeroio/
deserialize.rs

1// Copyright 2023 RISC Zero, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use alloc::{boxed::Box, vec::Vec};
16use core::marker::PhantomData;
17
18use impl_trait_for_tuples::impl_for_tuples;
19
20use super::align_bytes_to_words;
21
22pub trait Deserialize<'a> {
23    type RefType;
24
25    const FIXED_WORDS: usize;
26
27    fn deserialize_from(words: &'a [u32]) -> Self::RefType;
28
29    fn from_ref(val: &Self::RefType) -> Self;
30}
31
32pub trait DeserializeOwned: for<'a> Deserialize<'a> {}
33impl<T> DeserializeOwned for T where T: for<'a> Deserialize<'a> {}
34
35impl<'a> Deserialize<'a> for u32 {
36    type RefType = u32;
37
38    const FIXED_WORDS: usize = 1;
39
40    fn deserialize_from(words: &[u32]) -> Self::RefType {
41        words[0]
42    }
43
44    fn from_ref(val: &Self::RefType) -> Self {
45        *val
46    }
47}
48
49impl<'a> Deserialize<'a> for alloc::string::String {
50    type RefType = &'a str;
51
52    const FIXED_WORDS: usize = 2;
53
54    fn deserialize_from(words: &'a [u32]) -> Self::RefType {
55        let (len, ptr) = (words[0], words[1]);
56
57        core::str::from_utf8(&bytemuck::cast_slice(&words[ptr as usize..])[..len as usize]).unwrap()
58    }
59
60    fn from_ref(val: &Self::RefType) -> Self {
61        (*val).into()
62    }
63}
64
65impl<'a> Deserialize<'a> for Vec<u8> {
66    type RefType = &'a [u8];
67
68    const FIXED_WORDS: usize = 2;
69
70    fn deserialize_from(words: &'a [u32]) -> Self::RefType {
71        let (len, ptr) = (words[0], words[1]);
72
73        &bytemuck::cast_slice(&words[ptr as usize..])[..len as usize]
74    }
75
76    fn from_ref(val: &Self::RefType) -> Self {
77        (*val).into()
78    }
79}
80
81impl<'a, T: Deserialize<'a>> Deserialize<'a> for Option<T> {
82    type RefType = Option<T::RefType>;
83
84    const FIXED_WORDS: usize = 1;
85
86    fn deserialize_from(words: &'a [u32]) -> Self::RefType {
87        let ptr = words[0];
88
89        if ptr == 0 {
90            None
91        } else {
92            Some(T::deserialize_from(&words[ptr as usize..]))
93        }
94    }
95
96    fn from_ref(val: &Self::RefType) -> Self {
97        val.as_ref().map(|v| T::from_ref(&v))
98    }
99}
100
101impl<'a, T: Deserialize<'a>> Deserialize<'a> for Box<T> {
102    type RefType = T::RefType;
103
104    const FIXED_WORDS: usize = T::FIXED_WORDS;
105
106    fn deserialize_from(words: &'a [u32]) -> T::RefType {
107        T::deserialize_from(words)
108    }
109
110    fn from_ref(val: &Self::RefType) -> Self {
111        Box::new(T::from_ref(&val))
112    }
113}
114
115pub struct VecRef<'a, T> {
116    len: usize,
117    words: &'a [u32],
118    phantom: PhantomData<T>,
119}
120
121impl<'a, T: Deserialize<'a>> VecRef<'a, T> {
122    pub fn len(&self) -> usize {
123        self.len
124    }
125
126    pub fn index(&self, index: usize) -> T::RefType {
127        T::deserialize_from(&self.words[T::FIXED_WORDS * index..])
128    }
129
130    pub fn as_u32s(&self) -> &'a [u32] {
131        &self.words[..T::FIXED_WORDS * self.len]
132    }
133}
134
135pub struct VecRefIter<'a, T> {
136    words: &'a [u32],
137    items_left: usize,
138    phantom: PhantomData<T>,
139}
140
141impl<'a, T: Deserialize<'a>> VecRef<'a, T> {
142    pub fn iter(&self) -> VecRefIter<'a, T> {
143        VecRefIter {
144            words: self.words,
145            items_left: self.len,
146            phantom: PhantomData,
147        }
148    }
149}
150
151impl<'a, T: Deserialize<'a>> IntoIterator for VecRef<'a, T> {
152    type Item = T::RefType;
153    type IntoIter = VecRefIter<'a, T>;
154
155    fn into_iter(self) -> Self::IntoIter {
156        self.iter()
157    }
158}
159
160impl<'a, T: Deserialize<'a>> Iterator for VecRefIter<'a, T> {
161    type Item = T::RefType;
162    fn next(&mut self) -> Option<T::RefType> {
163        if self.items_left > 0 {
164            let val = T::deserialize_from(self.words);
165            self.items_left -= 1;
166            self.words = &self.words[T::FIXED_WORDS..];
167            Some(val)
168        } else {
169            None
170        }
171    }
172}
173
174impl<'a, T: Deserialize<'a>> Deserialize<'a> for Vec<T> {
175    type RefType = VecRef<'a, T>;
176
177    const FIXED_WORDS: usize = 2;
178
179    fn deserialize_from(words: &'a [u32]) -> Self::RefType {
180        VecRef {
181            len: words[0] as usize,
182            words: &words[words[1] as usize..],
183            phantom: PhantomData,
184        }
185    }
186
187    fn from_ref(val: &Self::RefType) -> Self {
188        let mut v = Vec::with_capacity(val.len());
189        v.extend(val.iter().map(|v| T::from_ref(&v)));
190        v
191    }
192}
193
194impl<'a, T: Deserialize<'a>, const N: usize> Deserialize<'a> for [T; N] {
195    type RefType = VecRef<'a, T>;
196
197    const FIXED_WORDS: usize = N * T::FIXED_WORDS;
198
199    fn deserialize_from(words: &'a [u32]) -> Self::RefType {
200        VecRef {
201            len: N,
202            words,
203            phantom: PhantomData,
204        }
205    }
206
207    fn from_ref(val: &Self::RefType) -> Self {
208        match Vec::from_iter(val.iter().map(|x| T::from_ref(&x))).try_into() {
209            Ok(result) => result,
210            _ => panic!("VecRef iterator didn't return the proper number of elements"),
211        }
212    }
213}
214
215impl<'a, const N: usize> Deserialize<'a> for [u8; N] {
216    type RefType = &'a [u8; N];
217
218    const FIXED_WORDS: usize = align_bytes_to_words(N);
219
220    fn deserialize_from(words: &'a [u32]) -> Self::RefType {
221        let slice = &bytemuck::cast_slice(words)[..N];
222        slice.try_into().unwrap()
223    }
224
225    fn from_ref(val: &Self::RefType) -> Self {
226        **val
227    }
228}
229
230#[impl_for_tuples(1, 5)]
231impl<'a> Deserialize<'a> for Tuple {
232    for_tuples!(type RefType = (#(Tuple::RefType),*););
233    for_tuples!(const FIXED_WORDS: usize = #(Tuple::FIXED_WORDS)+*; );
234
235    fn deserialize_from(words: &'a [u32]) -> Self::RefType {
236        let mut pos = 0;
237        let mut inc_pos = |n| {
238            let old_pos = pos;
239            pos += n;
240            old_pos
241        };
242        for_tuples!(
243            (#(
244                Tuple::deserialize_from(&words[inc_pos(Tuple::FIXED_WORDS)..])
245            ),*));
246    }
247
248    fn from_ref(val: &Self::RefType) -> Self {
249        for_tuples!(
250            (#(
251                Tuple::from_ref(&val.Tuple)
252            ),*));
253    }
254}
255
256impl<'a> Deserialize<'a> for () {
257    type RefType = ();
258    const FIXED_WORDS: usize = 0;
259
260    fn deserialize_from(_words: &'a [u32]) -> Self::RefType {
261        ()
262    }
263
264    fn from_ref(_val: &Self::RefType) -> Self {
265        ()
266    }
267}