decoder/lib.rs
1//! A decoder library for your types.
2//!
3//! When using [`serde`], your types become entangled with serialization logic due to the [`Serialize`] and [`Deserialize`] traits.
4//!
5//! This crate lets you decouple serialization logic by leveraging simple functions, at some performance cost:
6//!
7//! ```rust,no_run
8//! use decoder::{Map, Result, Value};
9//!
10//! struct Person {
11//! name: String,
12//! projects: Vec<Project>
13//! }
14//!
15//! struct Project {
16//! name: String,
17//! url: String,
18//! }
19//!
20//! impl Person {
21//! fn decode(value: Value) -> Result<Self> {
22//! use decoder::decode::{map, sequence, string};
23//!
24//! let mut person = map(value)?;
25//!
26//! Ok(Self {
27//! name: person.required("name", string)?,
28//! projects: person.required("projects", sequence(Project::decode))?,
29//! })
30//! }
31//!
32//! fn encode(&self) -> Value {
33//! use decoder::encode::{map, sequence, string};
34//!
35//! map([
36//! ("name", string(&self.name)),
37//! ("projects", sequence(Project::encode, &self.projects)),
38//! ])
39//! .into()
40//! }
41//! }
42//!
43//! impl Project {
44//! fn decode(value: Value) -> Result<Self> {
45//! use decoder::decode::{map, string};
46//!
47//! let mut project = map(value)?;
48//!
49//! Ok(Project {
50//! name: project.required("name", string)?,
51//! url: project.required("url", string)?
52//! })
53//! }
54//!
55//! fn encode(&self) -> Value {
56//! use decoder::encode::{map, string};
57//!
58//! map([
59//! ("name", string(&self.name)),
60//! ("url", string(&self.url)),
61//! ])
62//! .into()
63//! }
64//! }
65//!
66//! let person =
67//! decoder::run(serde_json::from_str, Person::decode, "{ ... }").expect("Decode person");
68//!
69//! let _ = serde_json::to_string(&person.encode());
70//! ```
71//!
72//! You can try this crate if the [`serde`] way™ has become painful or it does not resonate with you.
73//!
74//! [`serde`]: https://serde.rs
75//! [`Serialize`]: https://docs.rs/serde/latest/serde/trait.Serialize.html
76//! [`Deserialize`]: https://docs.rs/serde/latest/serde/trait.Deserialize.html
77pub mod decode;
78pub mod encode;
79
80mod error;
81mod value;
82
83pub use error::Error;
84pub use value::{Map, Value};
85
86/// A decoding result.
87pub type Result<T> = std::result::Result<T, Error>;
88
89/// Some logic that turns a [`Value`] into some [`Output`](Self::Output).
90pub trait Decoder {
91 /// The output of the [`Decoder`].
92 type Output;
93
94 /// Runs the [`Decoder`].
95 fn run(&self, value: Value) -> Result<Self::Output>;
96}
97
98impl<F, T> Decoder for F
99where
100 F: Fn(Value) -> Result<T>,
101{
102 type Output = T;
103
104 fn run(&self, value: Value) -> Result<T> {
105 self(value)
106 }
107}
108
109/// Runs a [`Decoder`] using the given function to deserialize a [`Value`]
110/// from the given input.
111pub fn run<T, I, E>(
112 deserialize: impl Fn(I) -> std::result::Result<Value, E>,
113 decoder: impl Decoder<Output = T>,
114 input: I,
115) -> Result<T>
116where
117 E: std::error::Error + Send + Sync + 'static,
118{
119 decoder.run(deserialize(input).map_err(Error::deserializer)?)
120}