scale_value/
lib.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
16/*!
17This crate exposes the [`Value`] type and related subtypes, which are used as the runtime
18representations of SCALE encoded data (much like `serde_json::Value` is a runtime representation
19of JSON data).
20
21[`Value`]'s can be:
22
23- Encoded and decoded from SCALE bytes via [`::scale_encode::EncodeAsType`] and [`::scale_decode::DecodeAsType`]
24  traits (or by calling [`crate::scale::decode_as_type`] and [`crate::scale::encode_as_type`]).
25- Parsed to and from strings by calling [`crate::stringify::from_str`] and [`crate::stringify::to_string`]).
26  Parsing from strings requires the `from_string` feature to be enabled.
27- Serialized and deserialized via `serde` traits (for example, to and from JSON). They can also be serialized
28  from and to other types with the relevant serde derives on. These require the `serde` feature to be enabled.
29- Accessed ergonomically via the [`At`] trait.
30*/
31#![deny(missing_docs)]
32#![no_std]
33
34extern crate alloc;
35
36#[cfg(feature = "__std")]
37extern crate std;
38
39mod at;
40mod macros;
41mod prelude;
42mod scale_impls;
43#[cfg(feature = "serde")]
44mod serde_impls;
45mod string_impls;
46mod value_type;
47
48// Traits to allow indexing into values.
49pub use at::{At, Location};
50
51// The value definition.
52pub use value_type::{BitSequence, Composite, Primitive, Value, ValueDef, Variant};
53
54/// Serializing and deserializing a [`crate::Value`] into/from other types via serde.
55#[cfg(feature = "serde")]
56pub mod serde {
57    use crate::prelude::*;
58    pub use crate::serde_impls::{DeserializerError, SerializerError, ValueSerializer};
59
60    /// Attempt to convert a [`crate::Value`] into another type via serde.
61    ///
62    /// # Examples
63    ///
64    /// Use serde to convert a value into a built-in type:
65    ///
66    /// ```rust
67    /// use scale_value::Value;
68    ///
69    /// let value = Value::unnamed_composite(vec![
70    ///     Value::u128(1),
71    ///     Value::u128(2),
72    ///     Value::u128(3),
73    /// ]);
74    ///
75    /// let arr: [u8; 3] = scale_value::serde::from_value(value).unwrap();
76    /// ```
77    ///
78    /// Converting values to a custom type:
79    ///
80    /// ```rust
81    /// use scale_value::Value;
82    /// use serde::{ Serialize, Deserialize };
83    ///
84    /// #[derive(Serialize, Deserialize, PartialEq, Debug)]
85    /// enum Foo {
86    ///     A { is_valid: bool, name: String },
87    ///     B(u8, bool)
88    /// }
89    ///
90    /// let value1 = Value::named_variant("A", [
91    ///     ("name", Value::string("James")),
92    ///     ("is_valid", Value::bool(true)),
93    /// ]);
94    /// let foo1: Foo = scale_value::serde::from_value(value1).unwrap();
95    /// assert_eq!(foo1, Foo::A { is_valid: true, name: "James".into() });
96    ///
97    /// let value2 = Value::unnamed_variant("B", [
98    ///     Value::u128(123),
99    ///     Value::bool(true),
100    /// ]);
101    /// let foo2: Foo = scale_value::serde::from_value(value2).unwrap();
102    /// assert_eq!(foo2, Foo::B(123, true));
103    /// ```
104    pub fn from_value<'de, Ctx, T: serde::Deserialize<'de>>(
105        value: crate::Value<Ctx>,
106    ) -> Result<T, DeserializerError> {
107        T::deserialize(value)
108    }
109
110    /// Attempt to convert some type into a [`crate::Value`] via serde.
111    ///
112    /// # Examples
113    ///
114    /// Convert a built-in array of values into a [`crate::Value`]:
115    ///
116    /// ```rust
117    /// use scale_value::Value;
118    ///
119    /// let arr = [1u8, 2u8, 3u8];
120    ///
121    /// let val = scale_value::serde::to_value(arr).unwrap();
122    /// assert_eq!(val, Value::unnamed_composite([
123    ///     Value::u128(1),
124    ///     Value::u128(2),
125    ///     Value::u128(3),
126    /// ]));
127    /// ```
128    ///
129    /// Converting some custom type to a [`crate::Value`]:
130    ///
131    /// ```rust
132    /// use scale_value::Value;
133    /// use serde::{ Serialize, Deserialize };
134    ///
135    /// #[derive(Serialize, Deserialize, PartialEq, Debug)]
136    /// enum Foo {
137    ///     A { is_valid: bool, name: String },
138    ///     B(u8, bool)
139    /// }
140    ///
141    /// let foo = Foo::A { is_valid: true, name: "James".into() };
142    ///
143    /// let value = scale_value::serde::to_value(foo).unwrap();
144    /// assert_eq!(value, Value::named_variant("A", [
145    ///     ("is_valid", Value::bool(true)),
146    ///     ("name", Value::string("James")),
147    /// ]));
148    /// ```
149    pub fn to_value<T: serde::Serialize>(ty: T) -> Result<crate::Value<()>, SerializerError> {
150        ty.serialize(ValueSerializer)
151    }
152}
153
154/// Encoding and decoding SCALE bytes into a [`crate::Value`].
155///
156/// # Exmaple
157///
158/// Given some known metadata type ID, encode and decode some [`crate::Value`]
159/// to SCALE bytes.
160///
161/// ```rust
162/// # fn make_type<T: scale_info::TypeInfo + 'static>() -> (u32, scale_info::PortableRegistry) {
163/// #     let m = scale_info::MetaType::new::<T>();
164/// #     let mut types = scale_info::Registry::new();
165/// #     let id = types.register_type(&m);
166/// #     let portable_registry: scale_info::PortableRegistry = types.into();
167/// #     (id.id(), portable_registry)
168/// # }
169/// # let (type_id, registry) = make_type::<Foo>();
170/// use scale_value::Value;
171///
172/// // Imagine we have a `registry` (of type [`scale_info::PortableRegistry`]) containing this type,
173/// // and a `type_id` (a `u32`) pointing to it in the registry.
174/// #[derive(scale_info::TypeInfo)]
175/// enum Foo {
176///     A { is_valid: bool, name: String }
177/// }
178///
179/// // Given that, we can encode/decode something with that shape to/from SCALE bytes:
180/// let value = Value::named_variant("A", [
181///     ("is_valid", Value::bool(true)),
182///     ("name", Value::string("James")),
183/// ]);
184///
185/// // Encode the Value to bytes:
186/// let mut bytes = Vec::new();
187/// scale_value::scale::encode_as_type(&value, type_id, &registry, &mut bytes).unwrap();
188///
189/// // Decode the bytes back into a matching Value.
190/// // This value contains contextual information about which type was used
191/// // to decode each part of it, which we can throw away with `.remove_context()`.
192/// let new_value = scale_value::scale::decode_as_type(&mut &*bytes, type_id, &registry).unwrap();
193///
194/// assert_eq!(value, new_value.remove_context());
195/// ```
196pub mod scale {
197    use crate::prelude::*;
198    use scale_decode::FieldIter;
199    use scale_encode::EncodeAsType;
200
201    pub use crate::scale_impls::{DecodeError, ValueVisitor};
202    pub use scale_encode::Error as EncodeError;
203    pub use scale_type_resolver::TypeResolver;
204
205    /// Attempt to decode some SCALE encoded bytes into a value, by providing a pointer
206    /// to the bytes (which will be moved forwards as bytes are used in the decoding),
207    /// a type ID, and a type registry from which we'll look up the relevant type information.
208    pub fn decode_as_type<R>(
209        data: &mut &[u8],
210        ty_id: R::TypeId,
211        types: &R,
212    ) -> Result<crate::Value<R::TypeId>, DecodeError>
213    where
214        R: TypeResolver,
215        R::TypeId: Clone,
216    {
217        crate::scale_impls::decode_value_as_type(data, ty_id, types)
218    }
219
220    /// Attempt to decode some SCALE encoded bytes into multiple values, by providing a pointer
221    /// to the bytes (which will be moved forwards as bytes are used in the decoding),
222    /// and an iterator of fields, where each field contains a type ID and optionally a field name.
223    pub fn decode_as_fields<'resolver, R>(
224        input: &mut &[u8],
225        fields: &mut dyn FieldIter<'resolver, R::TypeId>,
226        types: &'resolver R,
227    ) -> Result<crate::Composite<R::TypeId>, DecodeError>
228    where
229        R: TypeResolver,
230        R::TypeId: Clone,
231    {
232        crate::scale_impls::decode_composite_as_fields(input, fields, types)
233    }
234
235    /// Attempt to encode some [`crate::Value<T>`] into SCALE bytes, by providing a pointer to the
236    /// type ID that we'd like to encode it as, a type registry from which we'll look
237    /// up the relevant type information, and a buffer to encode the bytes to.
238    pub fn encode_as_type<R: TypeResolver, T>(
239        value: &crate::Value<T>,
240        ty_id: R::TypeId,
241        types: &R,
242        buf: &mut Vec<u8>,
243    ) -> Result<(), EncodeError> {
244        value.encode_as_type_to(ty_id, types, buf)
245    }
246
247    /// A visitor and function to decode some bytes into a [`crate::Value`] while tracing the current
248    /// decoding state so that a more detailed error can be returned in the event of a failure.
249    pub mod tracing {
250        pub use crate::scale_impls::{TraceDecodingError, TraceDecodingVisitor};
251
252        /// Decode a value using the [`TraceDecodingVisitor`], which internally keeps track of the current decoding state, and as
253        /// a result hands back a much more detailed error than [`crate::scale::decode_as_type()`] if decoding fails.
254        ///
255        /// One approach is to use the standard visitor for decoding on the "happy path", and if you need more information about
256        /// the decode error, to try decoding the same bytes again using this function to obtain more information about what failed.
257        pub fn decode_as_type<R>(
258            data: &mut &[u8],
259            ty_id: R::TypeId,
260            types: &R,
261        ) -> Result<crate::Value<R::TypeId>, TraceDecodingError<crate::Value<R::TypeId>>>
262        where
263            R: scale_type_resolver::TypeResolver,
264        {
265            scale_decode::visitor::decode_with_visitor(
266                data,
267                ty_id,
268                types,
269                TraceDecodingVisitor::new(),
270            )
271        }
272    }
273}
274
275/// Converting a [`crate::Value`] to or from strings.
276pub mod stringify {
277    use crate::prelude::*;
278
279    pub use crate::string_impls::ToWriterBuilder;
280    #[cfg(feature = "from-string")]
281    pub use crate::string_impls::{
282        FromStrBuilder, ParseBitSequenceError, ParseCharError, ParseComplexError, ParseError,
283        ParseErrorKind, ParseNumberError, ParseStringError,
284    };
285
286    /// This module provides custom parsers that work alongside [`crate::stringify::from_str_custom`]
287    /// and extend the syntax to support parsing common formats into [`crate::Value`]'s. See
288    /// [`crate::stringify::from_str_custom`] for a usage example.
289    #[cfg(feature = "from-string")]
290    pub mod custom_parsers {
291        #[cfg(feature = "parser-ss58")]
292        pub use crate::string_impls::parse_ss58;
293        pub use crate::string_impls::{parse_hex, ParseHexError};
294    }
295
296    /// This module provides custom formatters that work alongside [`crate::stringify::to_writer_custom`]
297    /// and allow for the output to be formatted in various ways.
298    pub mod custom_formatters {
299        pub use crate::string_impls::format_hex;
300    }
301
302    /// Attempt to parse a string into a [`crate::Value<()>`], returning a tuple
303    /// consisting of a result (either the value or a [`ParseError`] containing
304    /// location and error information) and the remainder of the string that wasn't
305    /// parsed.
306    ///
307    /// # Examples
308    ///
309    /// ```rust
310    /// use scale_value::Value;
311    ///
312    /// fn to_value(str: &str) -> Value {
313    ///     scale_value::stringify::from_str(str).0.unwrap()
314    /// }
315    ///
316    /// // Primitive values:
317    /// assert_eq!(to_value("1"), Value::u128(1));
318    /// assert_eq!(to_value("-1"), Value::i128(-1));
319    /// assert_eq!(to_value("true"), Value::bool(true));
320    /// assert_eq!(to_value("'a'"), Value::char('a'));
321    /// assert_eq!(to_value("\"hi\""), Value::string("hi"));
322    ///
323    /// // Named composite values look a bit like rust structs:
324    /// let value = to_value("{ a: true, b: \"hello\" }");
325    /// assert_eq!(
326    ///     value,
327    ///     Value::named_composite(vec![
328    ///         ("a", Value::bool(true)),
329    ///         ("b", Value::string("hello"))
330    ///     ])
331    /// );
332    ///
333    /// // Unnamed composite values look a bit like rust tuples:
334    /// let value = to_value("(true, \"hello\")");
335    /// assert_eq!(
336    ///     value,
337    ///     Value::unnamed_composite(vec![
338    ///         Value::bool(true),
339    ///         Value::string("hello")
340    ///     ])
341    /// );
342    ///
343    /// // Variant values (named or unnamed) are just the above with a variant name
344    /// // prefixed:
345    /// let value = to_value("MyVariant { a: true, b: \"hello\" }");
346    /// assert_eq!(
347    ///     value,
348    ///     Value::named_variant(
349    ///         "MyVariant",
350    ///         vec![
351    ///             ("a", Value::bool(true)),
352    ///             ("b", Value::string("hello"))
353    ///         ]
354    ///     )
355    /// );
356    ///
357    /// // Bit sequences can be encoded from unnamed composites, but we have a
358    /// // compact syntax for them too:
359    /// assert_eq!(
360    ///     to_value("<0101>"),
361    ///     Value::bit_sequence(scale_bits::Bits::from_iter([false, true, false, true]))
362    /// );
363    /// ```
364    #[cfg(feature = "from-string")]
365    pub fn from_str(s: &str) -> (Result<crate::Value<()>, ParseError>, &str) {
366        crate::string_impls::FromStrBuilder::new().parse(s)
367    }
368
369    /// This is similar to [`from_str`], except that it returns a [`FromStrBuilder`],
370    /// which allows for some additional configuration in how strings are parsed.
371    ///
372    /// # Example
373    ///
374    /// ```rust
375    /// # // Example only runs when parser-ss58 feature is enabled:
376    /// # #[cfg(not(feature = "parser-ss58"))]
377    /// # fn main() {}
378    /// # #[cfg(feature = "parser-ss58")]
379    /// # fn main() {
380    /// #
381    /// use scale_value::Value;
382    /// use scale_value::stringify::custom_parsers;
383    ///
384    /// fn to_value(str: &str) -> Value {
385    ///     scale_value::stringify::from_str_custom()
386    ///         // You can write your own custom parser, but for
387    ///         // this example, we just use some provided ones.
388    ///         .add_custom_parser(custom_parsers::parse_hex)
389    ///         // Requires the parser-ss58 feature:
390    ///         .add_custom_parser(custom_parsers::parse_ss58)
391    ///         .parse(str)
392    ///         .0
393    ///         .unwrap()
394    /// }
395    ///
396    /// // Hex strings will now be parsed into unnamed composite types
397    /// let value = to_value("(1,2,0x030405)");
398    /// assert_eq!(
399    ///     value,
400    ///     Value::unnamed_composite(vec![
401    ///         Value::u128(1),
402    ///         Value::u128(2),
403    ///         Value::unnamed_composite(vec![
404    ///             Value::u128(3),
405    ///             Value::u128(4),
406    ///             Value::u128(5),
407    ///         ])
408    ///     ])
409    /// );
410    ///
411    /// // ss58 addresses will also become unnamed composite types
412    /// let value = to_value(r#"{
413    ///     name: "Alice",
414    ///     address: 5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty
415    /// }"#);
416    ///
417    /// // Manually obtain and decode the hex value for the address:
418    /// let addr: Vec<_> = hex::decode("8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48")
419    ///     .unwrap()
420    ///     .into_iter()
421    ///     .map(|b| Value::u128(b as u128))
422    ///     .collect();
423    ///
424    /// assert_eq!(
425    ///     value,
426    ///     Value::named_composite(vec![
427    ///         ("name", Value::string("Alice")),
428    ///         ("address", Value::unnamed_composite(addr))
429    ///     ])
430    /// )
431    /// #
432    /// # }
433    /// ```
434    #[cfg(feature = "from-string")]
435    pub fn from_str_custom() -> FromStrBuilder {
436        crate::string_impls::FromStrBuilder::new()
437    }
438
439    /// Identical to calling `to_string()` on the [`crate::Value`], but here just
440    /// to make it a little more obvious that this is the inverse of [`from_str`].
441    ///
442    /// # Panics
443    ///
444    /// Panics if a `Primitive::U256`/`Primitive::I256` are a part of the value,
445    /// since we cannot properly format and parse those at the moment.
446    pub fn to_string<T>(value: &crate::Value<T>) -> String {
447        value.to_string()
448    }
449
450    /// Format a [`crate::Value`] to a string, writing it to the provided writer.
451    ///
452    /// # Example
453    ///
454    /// ```rust
455    /// use scale_value::{Value, value};
456    ///
457    /// let value = value!({
458    ///     foo: true,
459    ///     bar: "hello"
460    /// });
461    ///
462    /// // Write the ourput to a string or any other writer.
463    /// let mut s = String::new();
464    /// scale_value::stringify::to_writer(&value, &mut s).unwrap();
465    ///
466    /// assert_eq!(s, r#"{ foo: true, bar: "hello" }"#)
467    /// ```
468    pub fn to_writer<T, W: core::fmt::Write>(
469        value: &crate::Value<T>,
470        writer: W,
471    ) -> core::fmt::Result {
472        crate::string_impls::ToWriterBuilder::new().write(value, writer)
473    }
474
475    /// Format a [`crate::Value`] to a string. Several options can be configured in the
476    /// process, such as the indentation, custom formatters, printing of context, and
477    /// style (compact or spaced).
478    ///
479    /// # Example
480    ///
481    /// ```rust
482    /// use scale_value::{Value, ValueDef, Primitive, value};
483    /// use scale_value::stringify::custom_formatters::format_hex;
484    /// use core::fmt::Write;
485    ///
486    /// let value = value!({
487    ///     foo: true,
488    ///     bar: (1u8,2u8,3u8,4u8)
489    /// });
490    ///
491    /// let mut s = String::new();
492    ///
493    /// fn capitalise_bools<T, W: Write>(v: &Value<T>, w: &mut W) -> Option<core::fmt::Result> {
494    ///     if let ValueDef::Primitive(Primitive::Bool(b)) = &v.value {
495    ///         match b {
496    ///             true => Some(write!(w, "TRUE")),
497    ///             false => Some(write!(w, "FALSE"))
498    ///         }
499    ///     } else {
500    ///         None
501    ///     }
502    /// }
503    ///
504    /// scale_value::stringify::to_writer_custom()
505    ///     .compact()
506    ///     .add_custom_formatter(|v, w| format_hex(v, w))
507    ///     .add_custom_formatter(|v, w| capitalise_bools(v, w))
508    ///     .write(&value, &mut s);
509    ///
510    /// assert_eq!(s, r#"{foo:TRUE,bar:0x01020304}"#)
511    /// ```
512    pub fn to_writer_custom<T, W: core::fmt::Write>() -> ToWriterBuilder<T, W> {
513        crate::string_impls::ToWriterBuilder::new()
514    }
515}