scale_value/
value_type.rs

1// Copyright (C) 2022-2023 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::*;
17use either::Either;
18
19// We use this to represent BitSequence values, so expose it here.
20pub use scale_bits::Bits as BitSequence;
21
22/// [`Value`] holds a representation of some value that has been decoded, as well as some arbitrary context.
23///
24/// Not all SCALE encoded types have an similar-named value; for instance, the values corresponding to
25/// sequence, array and composite types can all be represented with [`Composite`]. Only enough information
26/// is preserved here to to be able to encode and decode SCALE bytes with a known type to and from [`Value`]s
27/// losslessly.
28#[derive(Debug, Clone, PartialEq, Eq)]
29pub struct Value<T = ()> {
30    /// The shape and associated data for this Value
31    pub value: ValueDef<T>,
32    /// Some additional arbitrary context that can be associated with a value.
33    pub context: T,
34}
35
36impl Value<()> {
37    /// Construct a named composite type from any type which produces a tuple of keys and values
38    /// when iterated over.
39    pub fn named_composite<S, Vals>(vals: Vals) -> Self
40    where
41        S: Into<String>,
42        Vals: IntoIterator<Item = (S, Value<()>)>,
43    {
44        Value { value: ValueDef::Composite(Composite::named(vals)), context: () }
45    }
46    /// Construct an unnamed composite type from any type which produces values
47    /// when iterated over.
48    pub fn unnamed_composite<Vals>(vals: Vals) -> Self
49    where
50        Vals: IntoIterator<Item = Value<()>>,
51    {
52        Value { value: ValueDef::Composite(Composite::unnamed(vals)), context: () }
53    }
54    /// Create a new variant value without additional context.
55    pub fn variant<S: Into<String>>(name: S, values: Composite<()>) -> Value<()> {
56        Value { value: ValueDef::Variant(Variant { name: name.into(), values }), context: () }
57    }
58    /// Create a new variant value with named fields and without additional context.
59    pub fn named_variant<S, F, Vals>(name: S, fields: Vals) -> Value<()>
60    where
61        S: Into<String>,
62        F: Into<String>,
63        Vals: IntoIterator<Item = (F, Value<()>)>,
64    {
65        Value { value: ValueDef::Variant(Variant::named_fields(name, fields)), context: () }
66    }
67    /// Create a new variant value with tuple-like fields and without additional context.
68    pub fn unnamed_variant<S, Vals>(name: S, fields: Vals) -> Value<()>
69    where
70        S: Into<String>,
71        Vals: IntoIterator<Item = Value<()>>,
72    {
73        Value { value: ValueDef::Variant(Variant::unnamed_fields(name, fields)), context: () }
74    }
75    /// Create a new bit sequence value without additional context.
76    pub fn bit_sequence(bits: BitSequence) -> Value<()> {
77        Value { value: ValueDef::BitSequence(bits), context: () }
78    }
79    /// Create a new primitive value without additional context.
80    pub fn primitive(primitive: Primitive) -> Value<()> {
81        Value { value: ValueDef::Primitive(primitive), context: () }
82    }
83    /// Create a new string value without additional context.
84    pub fn string<S: Into<String>>(val: S) -> Value<()> {
85        Value { value: ValueDef::Primitive(Primitive::String(val.into())), context: () }
86    }
87    /// Create a new boolean value without additional context.
88    pub fn bool(val: bool) -> Value<()> {
89        Value { value: ValueDef::Primitive(Primitive::Bool(val)), context: () }
90    }
91    /// Create a new char without additional context.
92    pub fn char(val: char) -> Value<()> {
93        Value { value: ValueDef::Primitive(Primitive::Char(val)), context: () }
94    }
95    /// Create a new unsigned integer without additional context.
96    pub fn u128(val: u128) -> Value<()> {
97        Value { value: ValueDef::Primitive(Primitive::u128(val)), context: () }
98    }
99    /// Create a new signed integer without additional context.
100    pub fn i128(val: i128) -> Value<()> {
101        Value { value: ValueDef::Primitive(Primitive::i128(val)), context: () }
102    }
103    /// Create a new Value from a set of bytes; useful for converting things like AccountIds.
104    pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Value<()> {
105        let vals: Vec<_> = bytes.as_ref().iter().map(|&b| Value::u128(b as u128)).collect();
106        Value::unnamed_composite(vals)
107    }
108}
109
110impl Value<()> {
111    /// Create a new value with no associated context.
112    pub fn without_context(value: ValueDef<()>) -> Value<()> {
113        Value { value, context: () }
114    }
115}
116
117impl<T> Value<T> {
118    /// Create a new value with some associated context.
119    pub fn with_context(value: ValueDef<T>, context: T) -> Value<T> {
120        Value { value, context }
121    }
122    /// Remove the context.
123    pub fn remove_context(self) -> Value<()> {
124        self.map_context(|_| ())
125    }
126    /// Map the context to some different type.
127    pub fn map_context<F, U>(self, mut f: F) -> Value<U>
128    where
129        F: Clone + FnMut(T) -> U,
130    {
131        Value { context: f(self.context), value: self.value.map_context(f) }
132    }
133    /// If the value is a boolean value, return it.
134    pub fn as_bool(&self) -> Option<bool> {
135        match &self.value {
136            ValueDef::Primitive(p) => p.as_bool(),
137            _ => None,
138        }
139    }
140    /// If the value is a char, return it.
141    pub fn as_char(&self) -> Option<char> {
142        match &self.value {
143            ValueDef::Primitive(p) => p.as_char(),
144            _ => None,
145        }
146    }
147    /// If the value is a u128, return it.
148    pub fn as_u128(&self) -> Option<u128> {
149        match &self.value {
150            ValueDef::Primitive(p) => p.as_u128(),
151            _ => None,
152        }
153    }
154    /// If the value is an i128, return it.
155    pub fn as_i128(&self) -> Option<i128> {
156        match &self.value {
157            ValueDef::Primitive(p) => p.as_i128(),
158            _ => None,
159        }
160    }
161    /// If the value is a string, return it.
162    pub fn as_str(&self) -> Option<&str> {
163        match &self.value {
164            ValueDef::Primitive(p) => p.as_str(),
165            _ => None,
166        }
167    }
168}
169
170/// The underlying shape of a given value.
171#[derive(Clone, Debug, PartialEq, Eq)]
172pub enum ValueDef<T> {
173    /// A named or unnamed struct-like, array-like or tuple-like set of values.
174    Composite(Composite<T>),
175    /// An enum variant.
176    Variant(Variant<T>),
177    /// A sequence of bits.
178    BitSequence(BitSequence),
179    /// Any of the primitive values we can have.
180    Primitive(Primitive),
181}
182
183impl<T> ValueDef<T> {
184    /// Map the context to some different type.
185    pub fn map_context<F, U>(self, f: F) -> ValueDef<U>
186    where
187        F: Clone + FnMut(T) -> U,
188    {
189        match self {
190            ValueDef::Composite(val) => ValueDef::Composite(val.map_context(f)),
191            ValueDef::Variant(val) => ValueDef::Variant(val.map_context(f)),
192            ValueDef::BitSequence(val) => ValueDef::BitSequence(val),
193            ValueDef::Primitive(val) => ValueDef::Primitive(val),
194        }
195    }
196}
197
198impl<T> From<BitSequence> for ValueDef<T> {
199    fn from(val: BitSequence) -> Self {
200        ValueDef::BitSequence(val)
201    }
202}
203
204impl From<BitSequence> for Value<()> {
205    fn from(val: BitSequence) -> Self {
206        Value::without_context(val.into())
207    }
208}
209
210/// A named or unnamed struct-like, array-like or tuple-like set of values.
211/// This is used to represent a range of composite values on their own, or
212/// as values for a specific [`Variant`].
213#[derive(Clone, Debug, PartialEq, Eq)]
214pub enum Composite<T> {
215    /// Eg `{ foo: 2, bar: false }`
216    Named(Vec<(String, Value<T>)>),
217    /// Eg `(2, false)`
218    Unnamed(Vec<Value<T>>),
219}
220
221impl<T> Composite<T> {
222    /// Construct a named composite type from any type which produces a tuple of keys and values
223    /// when iterated over.
224    pub fn named<S: Into<String>, Vals: IntoIterator<Item = (S, Value<T>)>>(vals: Vals) -> Self {
225        Composite::Named(vals.into_iter().map(|(n, v)| (n.into(), v)).collect())
226    }
227    /// Construct an unnamed composite type from any type which produces values
228    /// when iterated over.
229    pub fn unnamed<Vals: IntoIterator<Item = Value<T>>>(vals: Vals) -> Self {
230        Composite::Unnamed(vals.into_iter().collect())
231    }
232    /// Return the number of values stored in this composite type.
233    pub fn len(&self) -> usize {
234        match self {
235            Composite::Named(values) => values.len(),
236            Composite::Unnamed(values) => values.len(),
237        }
238    }
239
240    /// Is the composite type empty?
241    pub fn is_empty(&self) -> bool {
242        match self {
243            Composite::Named(values) => values.is_empty(),
244            Composite::Unnamed(values) => values.is_empty(),
245        }
246    }
247
248    /// Iterate over the values stored in this composite type.
249    pub fn values(&self) -> impl ExactSizeIterator<Item = &Value<T>> {
250        match self {
251            Composite::Named(values) => Either::Left(values.iter().map(|(_k, v)| v)),
252            Composite::Unnamed(values) => Either::Right(values.iter()),
253        }
254    }
255
256    /// Iterate over the values stored in this composite type.
257    pub fn into_values(self) -> impl ExactSizeIterator<Item = Value<T>> {
258        match self {
259            Composite::Named(values) => Either::Left(values.into_iter().map(|(_k, v)| v)),
260            Composite::Unnamed(values) => Either::Right(values.into_iter()),
261        }
262    }
263
264    /// Map the context to some different type.
265    pub fn map_context<F, U>(self, f: F) -> Composite<U>
266    where
267        F: Clone + FnMut(T) -> U,
268    {
269        match self {
270            Composite::Named(values) => {
271                // Note: Optimally I'd pass `&mut f` into each iteration to avoid cloning,
272                // but this leads to a type recusion error because F becomes `&mut F`, which can
273                // (at type level) recurse here again and become `&mut &mut F` and so on. Since
274                // that's no good; just require `Clone` to avoid altering the type.
275                let vals =
276                    values.into_iter().map(move |(k, v)| (k, v.map_context(f.clone()))).collect();
277                Composite::Named(vals)
278            }
279            Composite::Unnamed(values) => {
280                let vals = values.into_iter().map(move |v| v.map_context(f.clone())).collect();
281                Composite::Unnamed(vals)
282            }
283        }
284    }
285}
286
287impl<V: Into<Value<()>>> From<Vec<V>> for Composite<()> {
288    fn from(vals: Vec<V>) -> Self {
289        let vals = vals.into_iter().map(|v| v.into()).collect();
290        Composite::Unnamed(vals)
291    }
292}
293
294impl<V: Into<Value<()>>> From<Vec<V>> for ValueDef<()> {
295    fn from(vals: Vec<V>) -> Self {
296        ValueDef::Composite(vals.into())
297    }
298}
299
300impl<V: Into<Value<()>>> From<Vec<V>> for Value<()> {
301    fn from(vals: Vec<V>) -> Self {
302        Value::without_context(vals.into())
303    }
304}
305
306impl<K: Into<String>, V: Into<Value<()>>> From<Vec<(K, V)>> for Composite<()> {
307    fn from(vals: Vec<(K, V)>) -> Self {
308        let vals = vals.into_iter().map(|(k, v)| (k.into(), v.into())).collect();
309        Composite::Named(vals)
310    }
311}
312
313impl<K: Into<String>, V: Into<Value<()>>> From<Vec<(K, V)>> for ValueDef<()> {
314    fn from(vals: Vec<(K, V)>) -> Self {
315        ValueDef::Composite(vals.into())
316    }
317}
318
319impl<K: Into<String>, V: Into<Value<()>>> From<Vec<(K, V)>> for Value<()> {
320    fn from(vals: Vec<(K, V)>) -> Self {
321        Value::without_context(vals.into())
322    }
323}
324
325impl<T> From<Composite<T>> for ValueDef<T> {
326    fn from(val: Composite<T>) -> Self {
327        ValueDef::Composite(val)
328    }
329}
330
331impl From<Composite<()>> for Value<()> {
332    fn from(val: Composite<()>) -> Self {
333        Value::without_context(ValueDef::Composite(val))
334    }
335}
336
337/// This represents the value of a specific variant from an enum, and contains
338/// the name of the variant, and the named/unnamed values associated with it.
339#[derive(Clone, Debug, PartialEq, Eq)]
340pub struct Variant<T> {
341    /// The name of the variant.
342    pub name: String,
343    /// Values for each of the named or unnamed fields associated with this variant.
344    pub values: Composite<T>,
345}
346
347impl<T> Variant<T> {
348    /// Construct a variant with named fields.
349    pub fn named_fields<S, K, Vals>(name: S, fields: Vals) -> Variant<T>
350    where
351        S: Into<String>,
352        K: Into<String>,
353        Vals: IntoIterator<Item = (K, Value<T>)>,
354    {
355        Variant { name: name.into(), values: Composite::named(fields) }
356    }
357    /// Construct a variant with tuple-like fields.
358    pub fn unnamed_fields<S, Vals>(name: S, fields: Vals) -> Variant<T>
359    where
360        S: Into<String>,
361        Vals: IntoIterator<Item = Value<T>>,
362    {
363        Variant { name: name.into(), values: Composite::unnamed(fields) }
364    }
365    /// Map the context to some different type.
366    pub fn map_context<F, U>(self, f: F) -> Variant<U>
367    where
368        F: Clone + FnMut(T) -> U,
369    {
370        Variant { name: self.name, values: self.values.map_context(f) }
371    }
372}
373
374impl<T> From<Variant<T>> for ValueDef<T> {
375    fn from(val: Variant<T>) -> Self {
376        ValueDef::Variant(val)
377    }
378}
379
380impl From<Variant<()>> for Value<()> {
381    fn from(val: Variant<()>) -> Self {
382        Value::without_context(ValueDef::Variant(val))
383    }
384}
385
386/// A "primitive" value (this includes strings).
387#[derive(Debug, Clone, PartialEq, Eq)]
388pub enum Primitive {
389    /// A boolean value.
390    Bool(bool),
391    /// A single character.
392    Char(char),
393    /// A string.
394    String(String),
395    /// A u128 value.
396    U128(u128),
397    /// An i128 value.
398    I128(i128),
399    /// An unsigned 256 bit number (internally represented as a 32 byte array).
400    U256([u8; 32]),
401    /// A signed 256 bit number (internally represented as a 32 byte array).
402    I256([u8; 32]),
403}
404
405impl Primitive {
406    /// Create a new unsigned integer without additional context.
407    pub fn u128(val: u128) -> Primitive {
408        Primitive::U128(val)
409    }
410    /// Create a new signed integer without additional context.
411    pub fn i128(val: i128) -> Primitive {
412        Primitive::I128(val)
413    }
414    /// If the primitive type is a boolean value, return it.
415    pub fn as_bool(&self) -> Option<bool> {
416        match self {
417            Primitive::Bool(b) => Some(*b),
418            _ => None,
419        }
420    }
421    /// If the primitive type is a char, return it.
422    pub fn as_char(&self) -> Option<char> {
423        match self {
424            Primitive::Char(c) => Some(*c),
425            _ => None,
426        }
427    }
428    /// If the primitive type is a u128, return it.
429    pub fn as_u128(&self) -> Option<u128> {
430        match self {
431            Primitive::U128(n) => Some(*n),
432            _ => None,
433        }
434    }
435    /// If the primitive type is an i128, return it.
436    pub fn as_i128(&self) -> Option<i128> {
437        match self {
438            Primitive::I128(n) => Some(*n),
439            _ => None,
440        }
441    }
442    /// If the primitive type is a string, return it.
443    pub fn as_str(&self) -> Option<&str> {
444        match self {
445            Primitive::String(s) => Some(&**s),
446            _ => None,
447        }
448    }
449}
450
451impl<T> From<Primitive> for ValueDef<T> {
452    fn from(val: Primitive) -> Self {
453        ValueDef::Primitive(val)
454    }
455}
456
457macro_rules! impl_primitive_type {
458    ($($variant:ident($ty:ty as $castty:ty),)*) => {$(
459        impl From<$ty> for Primitive {
460            fn from(val: $ty) -> Self {
461                Primitive::$variant(val as $castty)
462            }
463        }
464
465        impl<T> From<$ty> for ValueDef<T> {
466            fn from(val: $ty) -> Self {
467                ValueDef::Primitive(val.into())
468            }
469        }
470
471        impl From<$ty> for Value<()> {
472            fn from(val: $ty) -> Self {
473                Value::without_context(val.into())
474            }
475        }
476    )*}
477}
478
479impl_primitive_type!(
480    Bool(bool as bool),
481    Char(char as char),
482    String(String as String),
483    U128(u128 as u128),
484    U128(u64 as u128),
485    U128(usize as u128),
486    U128(u32 as u128),
487    U128(u16 as u128),
488    U128(u8 as u128),
489    I128(i128 as i128),
490    I128(i64 as i128),
491    I128(isize as i128),
492    I128(i32 as i128),
493    I128(i16 as i128),
494    I128(i8 as i128),
495);
496
497// note regarding impl From<AsRef<str>>:
498// a nicer generic `impl<K: Into<String>> From<K>` or `impl<K: AsRef<str>> From<K>` verson is not possible because it conflicts with the From<Bits> implementation above.
499
500impl From<&str> for Primitive {
501    fn from(val: &str) -> Self {
502        Primitive::String(val.to_string())
503    }
504}
505
506impl<T> From<&str> for ValueDef<T> {
507    fn from(val: &str) -> Self {
508        ValueDef::Primitive(val.into())
509    }
510}
511
512impl From<&str> for Value<()> {
513    fn from(val: &str) -> Self {
514        Value::without_context(val.into())
515    }
516}