scale_value/scale_impls/tracing_decoder/
visitor.rs

1// Copyright (C) 2022-2024 Parity Technologies (UK) Ltd. (admin@parity.io)
2// This file is a part of the scale-value crate.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//         http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use crate::prelude::*;
17
18use super::error::TraceDecodingError;
19use super::path::Path;
20use crate::{Composite, Primitive, Value, ValueDef, Variant};
21use core::marker::PhantomData;
22use scale_decode::visitor::TypeIdFor;
23use scale_type_resolver::TypeResolver;
24
25/// A visitor that will attempt to decode some bytes into a [`crate::Value`],
26/// returning a detailed error of where the decoding fails if it does.
27pub struct TraceDecodingVisitor<Resolver> {
28    path: Path,
29    marker: PhantomData<Resolver>,
30}
31
32impl<Resolver> TraceDecodingVisitor<Resolver> {
33    fn at_path(&self, path: Path) -> Self {
34        TraceDecodingVisitor { path, marker: PhantomData }
35    }
36    fn at_idx(&self, idx: usize) -> Self {
37        self.at_path(self.path.at_idx(idx))
38    }
39    fn at_field(&self, field: String) -> Self {
40        self.at_path(self.path.at_field(field))
41    }
42}
43
44impl<Resolver> Default for TraceDecodingVisitor<Resolver> {
45    fn default() -> Self {
46        Self::new()
47    }
48}
49
50impl<Resolver> TraceDecodingVisitor<Resolver> {
51    /// Construct a new [`TraceDecodingVisitor`].
52    pub fn new() -> Self {
53        TraceDecodingVisitor { path: Path::new(), marker: PhantomData }
54    }
55}
56
57macro_rules! to_unnamed_composite {
58    ($self:ident, $value:ident) => {{
59        let mut f = move || {
60            let mut idx = 0;
61            let mut vals = Vec::with_capacity($value.remaining());
62
63            while let Some(val) = $value.decode_item($self.at_idx(idx)) {
64                match val {
65                    Err(e) => {
66                        let merged_error = e.with_outer_context(
67                            || $self.path.at_idx(idx),
68                            || Composite::Unnamed(vals.clone()),
69                            |inner_value| {
70                                let mut vals = vals.clone();
71                                vals.push(inner_value);
72                                Composite::Unnamed(vals)
73                            },
74                        );
75                        return Err(merged_error);
76                    }
77                    Ok(v) => {
78                        vals.push(v);
79                    }
80                }
81
82                idx += 1;
83            }
84
85            Ok::<_, TraceDecodingError<_>>(Composite::Unnamed(vals))
86        };
87
88        f()
89    }};
90}
91
92macro_rules! to_unnamed_composite_value {
93    ($self:ident, $value:ident, $type_id:ident) => {{
94        let composite = to_unnamed_composite!($self, $value).map_err(|e| {
95            e.map_decoded_so_far(|c| Value {
96                value: ValueDef::Composite(c),
97                context: $type_id.clone(),
98            })
99        })?;
100
101        Ok(Value { value: ValueDef::Composite(composite), context: $type_id })
102    }};
103}
104
105impl<Resolver> scale_decode::Visitor for TraceDecodingVisitor<Resolver>
106where
107    Resolver: TypeResolver,
108{
109    type Value<'scale, 'resolver> = Value<TypeIdFor<Self>>;
110    type Error = TraceDecodingError<Value<TypeIdFor<Self>>>;
111    type TypeResolver = Resolver;
112
113    fn visit_bool<'scale, 'resolver>(
114        self,
115        value: bool,
116        type_id: TypeIdFor<Self>,
117    ) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
118        Ok(Value::with_context(ValueDef::Primitive(Primitive::Bool(value)), type_id))
119    }
120
121    fn visit_char<'scale, 'resolver>(
122        self,
123        value: char,
124        type_id: TypeIdFor<Self>,
125    ) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
126        Ok(Value::with_context(ValueDef::Primitive(Primitive::Char(value)), type_id))
127    }
128
129    fn visit_u8<'scale, 'resolver>(
130        self,
131        value: u8,
132        type_id: TypeIdFor<Self>,
133    ) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
134        self.visit_u128(value as u128, type_id)
135    }
136
137    fn visit_u16<'scale, 'resolver>(
138        self,
139        value: u16,
140        type_id: TypeIdFor<Self>,
141    ) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
142        self.visit_u128(value as u128, type_id)
143    }
144
145    fn visit_u32<'scale, 'resolver>(
146        self,
147        value: u32,
148        type_id: TypeIdFor<Self>,
149    ) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
150        self.visit_u128(value as u128, type_id)
151    }
152
153    fn visit_u64<'scale, 'resolver>(
154        self,
155        value: u64,
156        type_id: TypeIdFor<Self>,
157    ) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
158        self.visit_u128(value as u128, type_id)
159    }
160
161    fn visit_u128<'scale, 'resolver>(
162        self,
163        value: u128,
164        type_id: TypeIdFor<Self>,
165    ) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
166        Ok(Value::with_context(ValueDef::Primitive(Primitive::U128(value)), type_id))
167    }
168
169    fn visit_u256<'info>(
170        self,
171        value: &[u8; 32],
172        type_id: TypeIdFor<Self>,
173    ) -> Result<Self::Value<'_, 'info>, Self::Error> {
174        Ok(Value::with_context(ValueDef::Primitive(Primitive::U256(*value)), type_id))
175    }
176
177    fn visit_i8<'scale, 'resolver>(
178        self,
179        value: i8,
180        type_id: TypeIdFor<Self>,
181    ) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
182        self.visit_i128(value as i128, type_id)
183    }
184
185    fn visit_i16<'scale, 'resolver>(
186        self,
187        value: i16,
188        type_id: TypeIdFor<Self>,
189    ) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
190        self.visit_i128(value as i128, type_id)
191    }
192
193    fn visit_i32<'scale, 'resolver>(
194        self,
195        value: i32,
196        type_id: TypeIdFor<Self>,
197    ) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
198        self.visit_i128(value as i128, type_id)
199    }
200
201    fn visit_i64<'scale, 'resolver>(
202        self,
203        value: i64,
204        type_id: TypeIdFor<Self>,
205    ) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
206        self.visit_i128(value as i128, type_id)
207    }
208
209    fn visit_i128<'scale, 'resolver>(
210        self,
211        value: i128,
212        type_id: TypeIdFor<Self>,
213    ) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
214        Ok(Value::with_context(ValueDef::Primitive(Primitive::I128(value)), type_id))
215    }
216
217    fn visit_i256<'info>(
218        self,
219        value: &[u8; 32],
220        type_id: TypeIdFor<Self>,
221    ) -> Result<Self::Value<'_, 'info>, Self::Error> {
222        Ok(Value::with_context(ValueDef::Primitive(Primitive::I256(*value)), type_id))
223    }
224
225    fn visit_bitsequence<'scale, 'info>(
226        self,
227        value: &mut scale_decode::visitor::types::BitSequence<'scale>,
228        type_id: TypeIdFor<Self>,
229    ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
230        let bits: Result<_, _> = value.decode()?.collect();
231        Ok(Value::with_context(ValueDef::BitSequence(bits?), type_id))
232    }
233
234    fn visit_str<'scale, 'info>(
235        self,
236        value: &mut scale_decode::visitor::types::Str<'scale>,
237        type_id: TypeIdFor<Self>,
238    ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
239        Ok(Value::with_context(
240            ValueDef::Primitive(Primitive::String(value.as_str()?.to_owned())),
241            type_id,
242        ))
243    }
244
245    fn visit_sequence<'scale, 'resolver>(
246        self,
247        value: &mut scale_decode::visitor::types::Sequence<'scale, 'resolver, Self::TypeResolver>,
248        type_id: TypeIdFor<Self>,
249    ) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
250        to_unnamed_composite_value!(self, value, type_id)
251    }
252
253    fn visit_array<'scale, 'resolver>(
254        self,
255        value: &mut scale_decode::visitor::types::Array<'scale, 'resolver, Self::TypeResolver>,
256        type_id: scale_decode::visitor::TypeIdFor<Self>,
257    ) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
258        to_unnamed_composite_value!(self, value, type_id)
259    }
260
261    fn visit_tuple<'scale, 'resolver>(
262        self,
263        value: &mut scale_decode::visitor::types::Tuple<'scale, 'resolver, Self::TypeResolver>,
264        type_id: TypeIdFor<Self>,
265    ) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
266        to_unnamed_composite_value!(self, value, type_id)
267    }
268
269    fn visit_variant<'scale, 'resolver>(
270        self,
271        value: &mut scale_decode::visitor::types::Variant<'scale, 'resolver, Self::TypeResolver>,
272        type_id: TypeIdFor<Self>,
273    ) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
274        let variant_name = value.name();
275        let path = self.path.at_variant(variant_name.to_owned());
276        let values = visit_composite(&self, value.fields());
277        match values {
278            Err(e) => {
279                let merged_error = e.with_outer_context(
280                    || path.clone(),
281                    || Value {
282                        value: ValueDef::Variant(Variant {
283                            name: variant_name.to_owned(),
284                            values: Composite::Unnamed(vec![]),
285                        }),
286                        context: type_id.clone(),
287                    },
288                    |inner_value| Value {
289                        value: ValueDef::Variant(Variant {
290                            name: variant_name.to_owned(),
291                            values: inner_value,
292                        }),
293                        context: type_id.clone(),
294                    },
295                );
296                Err(merged_error)
297            }
298            Ok(values) => Ok(Value {
299                value: ValueDef::Variant(Variant { name: variant_name.to_owned(), values }),
300                context: type_id,
301            }),
302        }
303    }
304
305    fn visit_composite<'scale, 'resolver>(
306        self,
307        value: &mut scale_decode::visitor::types::Composite<'scale, 'resolver, Self::TypeResolver>,
308        type_id: TypeIdFor<Self>,
309    ) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
310        let composite_vals = visit_composite(&self, value).map_err(|e| {
311            e.map_decoded_so_far(|c| Value {
312                value: ValueDef::Composite(c),
313                context: type_id.clone(),
314            })
315        })?;
316
317        Ok(Value { value: ValueDef::Composite(composite_vals), context: type_id })
318    }
319}
320
321fn visit_composite<R>(
322    this: &TraceDecodingVisitor<R>,
323    value: &mut scale_decode::visitor::types::Composite<'_, '_, R>,
324) -> Result<Composite<R::TypeId>, TraceDecodingError<Composite<R::TypeId>>>
325where
326    R: TypeResolver,
327{
328    let len = value.remaining();
329
330    // if no fields, we'll always assume unnamed.
331    let named = len > 0 && !value.has_unnamed_fields();
332
333    // if unnamed, treat like array/tuple/sequence.
334    if !named {
335        return to_unnamed_composite!(this, value);
336    }
337
338    // otherwise, treat as a named struct.
339    let mut vals = Vec::with_capacity(len);
340    let mut name = value.peek_name().unwrap_or("<unnamed>");
341
342    while let Some(val) = value.decode_item(this.at_field(name.to_owned())) {
343        match val {
344            Err(e) => {
345                let merged_error = e.with_outer_context(
346                    || this.path.at_field(name.to_owned()),
347                    || Composite::Named(vals.clone()),
348                    |inner_value| {
349                        let mut vals = vals.clone();
350                        vals.push((name.to_owned(), inner_value));
351                        Composite::Named(vals)
352                    },
353                );
354                return Err(merged_error);
355            }
356            Ok(v) => {
357                vals.push((name.to_owned(), v));
358            }
359        }
360
361        name = value.peek_name().unwrap_or("<unnamed>");
362    }
363
364    Ok(Composite::Named(vals))
365}