gadget_blueprint_serde/
lib.rs

1//! Compatibility crate for using the [Serde](https://docs.rs/serde) serialization frame with data from [`tangle_subxt`](https://docs.rs/tangle_subxt)
2//!
3//! This crate provides two primary functions:
4//!
5//! * [`to_field`] - Convert a [`Serialize`] type to a [`Field`]
6//! * [`from_field`] - Convert a [`Field`] to a [`DeserializeOwned`] type
7//!
8//! # Examples
9//!
10//! ```rust
11//! use gadget_blueprint_serde::{new_bounded_string, BoundedVec, Field};
12//! use serde::{Deserialize, Serialize};
13//!
14//! #[derive(PartialEq, Debug, Serialize, Deserialize)]
15//! struct Person {
16//!     name: String,
17//!     age: u8,
18//! }
19//!
20//! let person = Person {
21//!     name: String::from("John"),
22//!     age: 40,
23//! };
24//!
25//! let expected = Field::Struct(
26//!     new_bounded_string("Person"),
27//!     Box::new(BoundedVec(vec![
28//!         (
29//!             new_bounded_string("name"),
30//!             Field::String(new_bounded_string("John")),
31//!         ),
32//!         (new_bounded_string("age"), Field::Uint8(40)),
33//!     ])),
34//! );
35//!
36//! // Convert our `Serialize` type to a `tangle_subxt::Field`
37//! let field = gadget_blueprint_serde::to_field(&person).unwrap();
38//! assert_eq!(expected, field);
39//!
40//! // Convert our `tangle_subxt::Field` back to a `Person`
41//! let person_deserialized: Person = gadget_blueprint_serde::from_field(field).unwrap();
42//! assert_eq!(person, person_deserialized);
43//! ```
44
45#![cfg_attr(feature = "std", no_std)]
46
47mod de;
48pub mod error;
49mod ser;
50#[cfg(test)]
51mod tests;
52
53extern crate alloc;
54
55use serde::Serialize;
56use serde::de::DeserializeOwned;
57use tangle_subxt::subxt_core::utils::AccountId32;
58pub use tangle_subxt::tangle_testnet_runtime::api::runtime_types::tangle_primitives::services::field::Field;
59pub use tangle_subxt::tangle_testnet_runtime::api::runtime_types::bounded_collections::bounded_vec::BoundedVec;
60pub use ser::new_bounded_string;
61pub use serde_bytes::ByteBuf;
62use error::Result;
63
64/// Derive a [`Field`] from an instance of type `S`
65///
66/// # Errors
67///
68/// * Attempting to serialize an [`UnsupportedType`](error::UnsupportedType)
69///
70/// # Examples
71///
72/// ```rust
73/// use gadget_blueprint_serde::{new_bounded_string, BoundedVec, Field};
74/// use serde::Serialize;
75///
76/// #[derive(Serialize)]
77/// struct Person {
78///     name: String,
79///     age: u8,
80/// }
81///
82/// let person = Person {
83///     name: String::from("John"),
84///     age: 40,
85/// };
86///
87/// let expected = Field::Struct(
88///     new_bounded_string("Person"),
89///     Box::new(BoundedVec(vec![
90///         (
91///             new_bounded_string("name"),
92///             Field::String(new_bounded_string("John")),
93///         ),
94///         (new_bounded_string("age"), Field::Uint8(40)),
95///     ])),
96/// );
97///
98/// let field = gadget_blueprint_serde::to_field(person).unwrap();
99/// assert_eq!(expected, field);
100/// ```
101pub fn to_field<S>(value: S) -> Result<Field<AccountId32>>
102where
103    S: Serialize,
104{
105    let mut ser = ser::Serializer;
106    value.serialize(&mut ser)
107}
108
109/// Derive an instance of type `D` from a [`Field`]
110///
111/// # Errors
112///
113/// * Attempting to deserialize an [`UnsupportedType`](error::UnsupportedType)
114/// * Attempting to deserialize non UTF-8 bytes into a [`String`](alloc::string::String)
115/// * Any type mismatch (e.g. attempting to deserialize [`Field::Int8`] into a [`char`]).
116///
117/// # Examples
118///
119/// ```rust
120/// use gadget_blueprint_serde::{new_bounded_string, BoundedVec, Field};
121/// use serde::Deserialize;
122///
123/// #[derive(Deserialize, Debug)]
124/// struct Person {
125///     name: String,
126///     age: u8,
127/// }
128///
129/// let field = Field::Struct(
130///     new_bounded_string("Person"),
131///     Box::new(BoundedVec(vec![
132///         (
133///             new_bounded_string("name"),
134///             Field::String(new_bounded_string("John")),
135///         ),
136///         (new_bounded_string("age"), Field::Uint8(40)),
137///     ])),
138/// );
139///
140/// let person: Person = gadget_blueprint_serde::from_field(field).unwrap();
141/// println!("{:#?}", person);
142/// ```
143pub fn from_field<D>(field: Field<AccountId32>) -> Result<D>
144where
145    D: DeserializeOwned,
146{
147    let de = de::Deserializer(field);
148    D::deserialize(de)
149}