serde_lexpr/lib.rs
1#![deny(missing_docs)]
2#![warn(rust_2018_idioms)]
3
4//! This crate provides [Serde]-based serialization and deserialization from
5//! statically-typed Rust data structures to S-expressions, both using the
6//! [`lexpr::Value`] type and to S-expression textual representation.
7//!
8//! # About representations
9//!
10//! The guiding principle for choosing the S-expression representation of Rust
11//! types is that it should look "natural" (or ideomatic) to a Lisp programmer,
12//! without introducing ambiguities.
13//!
14//! ## Sequences
15//!
16//! The serializer will represent serde sequences as lists. Note that `Vec` is
17//! considered a sequence, so it will be, perhaps counterintuitevely, be
18//! represented by an S-expression list, instead of an S-expression
19//! vector. While it would be possible to serialize all sequences as
20//! S-expression vectors instead, this would lead to unideomatic (noisy)
21//! S-expressions. When deserializing, both vectors and (proper) lists are
22//! accepted when a Serde sequence is expected.
23//!
24//! ```
25//! use serde_lexpr::{from_str, to_string};
26//!
27//! let v1: Vec<u32> = from_str("(1 2 3)").unwrap();
28//! assert_eq!(v1, vec![1, 2, 3]);
29//! assert_eq!(to_string(&v1).unwrap(), "(1 2 3)".to_string());
30//! let v2: Vec<u32> = from_str("#(1 2 3)").unwrap();
31//! assert_eq!(v1, v2);
32//! assert_eq!(to_string(&v2).unwrap(), "(1 2 3)".to_string());
33//! ```
34//!
35//! # Option
36//!
37//! The two variants of the `Option` type are represented as empty list
38//! (representing `None`) or a single-element list (representing
39//! `Some(x)`). This representation is chosen for unambiguity over using a
40//! special "missing" value (such as `#nil`) for `None` and a plain value for
41//! `Some`. It also combines nicely with struct fields containing option values.
42//!
43//! ```
44//! use serde_lexpr::{from_str, to_string};
45//!
46//! let answer: Option<u32> = from_str("(42)").unwrap();
47//! assert_eq!(answer, Some(42));
48//! let no_answer: Option<u32> = from_str("()").unwrap();
49//! assert_eq!(no_answer, None);
50//! ```
51//!
52//! ## Tuples and tuple structs
53//!
54//! Tuples and tuple structs are serialized as S-expression vectors.
55//!
56//! ```
57//! use serde_lexpr::{from_str, to_string};
58//! use serde_derive::{Serialize, Deserialize};
59//!
60//! assert_eq!(to_string(&(1, "two", 3)).unwrap(), "#(1 \"two\" 3)".to_string());
61//! let tuple: (u8, String, u64) = from_str("(1 \"two\" 3)").unwrap();
62//! assert_eq!(tuple, (1, "two".to_string(), 3));
63//!
64//! #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
65//! struct Person(String, u8);
66//!
67//! assert_eq!(to_string(&Person("Billy".into(), 42)).unwrap(), "#(\"Billy\" 42)".to_string());
68//! let joanne: Person = from_str("#(\"Joanne\" 23)").unwrap();
69//! assert_eq!(joanne, Person("Joanne".into(), 23));
70//! ```
71//!
72//! ## Structs
73//!
74//! Structs are serialized as association lists, i.e. a list consisting of cons
75//! cells, where each cell's `car` is the name of the struct field (as a
76//! symbol), and the `cdr` containing the field's value.
77//!
78//! ```
79//! use serde_lexpr::{from_str, to_string};
80//! use serde_derive::{Serialize, Deserialize};
81//!
82//! #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
83//! struct Person {
84//! name: String,
85//! age: u8,
86//! };
87//!
88//! let billy = Person { name: "Billy".into(), age: 42 };
89//! assert_eq!(to_string(&billy).unwrap(), "((name . \"Billy\") (age . 42))".to_string());
90//! let joanne: Person = from_str("((name . \"Joanne\") (age . 23))").unwrap();
91//! assert_eq!(joanne, Person { name: "Joanne".into(), age: 23 });
92//! ```
93//!
94//! ## Enums
95//!
96//! Enum variants without data are serialized as plain symbols. Tuple variants
97//! are serialized as a list starting with the variant name as a symbol,
98//! followed by the values. This representation is chosen over using a vector to
99//! keep the emitted S-expressions less noisy and hopefully a bit more
100//! ideomatic. Struct variants are serialized like structs (i.e. as association
101//! lists), but have the variant name prepended as a symbol.
102//!
103//! ```
104//! use serde_lexpr::{from_str, to_string};
105//! use serde_derive::{Serialize, Deserialize};
106//!
107//! #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
108//! #[serde(rename_all = "kebab-case")]
109//! enum Choice {
110//! Yes,
111//! No,
112//! Other(String),
113//! }
114//!
115//! let choices: Vec<Choice> = from_str("(yes no (other . \"foo\"))").unwrap();
116//! assert_eq!(choices, vec![Choice::Yes, Choice::No, Choice::Other("foo".into())]);
117//!
118//! #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
119//! #[serde(rename_all = "kebab-case")]
120//! enum Example {
121//! Unit,
122//! Newtype(u32),
123//! NewtypeOption(Option<u32>),
124//! Tuple(u32, u32),
125//! Struct { foo: bool, bar: u32 },
126//! }
127//!
128//! let unit: Example = from_str("unit").unwrap();
129//! assert_eq!(unit, Example::Unit);
130//!
131//! let newtype: Example = from_str("(newtype . 42)").unwrap();
132//! assert_eq!(newtype, Example::Newtype(42));
133//!
134//! let newtype_some: Example = from_str("(newtype-option 23)").unwrap();
135//! assert_eq!(newtype_some, Example::NewtypeOption(Some(23)));
136//!
137//! let newtype_none: Example = from_str("(newtype-option)").unwrap();
138//! assert_eq!(newtype_none, Example::NewtypeOption(None));
139//!
140//! let tuple: Example = from_str("(tuple 1 2)").unwrap();
141//! assert_eq!(tuple, Example::Tuple(1, 2));
142//!
143//! let struct_variant: Example = from_str("(struct (foo . #t) (bar . 3))").unwrap();
144//! assert_eq!(struct_variant, Example::Struct { foo: true, bar: 3 });
145//! ```
146//!
147//! [Serde]: https://crates.io/crates/serde
148//! [`lexpr::Value`]: https://docs.rs/lexpr/*/lexpr/enum.Value.html
149
150mod de;
151mod ser;
152mod value;
153
154pub mod error;
155pub use de::{
156 from_reader, from_reader_custom, from_slice, from_slice_custom, from_str, from_str_custom,
157};
158pub use error::{Error, Result};
159pub use ser::{to_string, to_string_custom, to_vec, to_vec_custom, to_writer, to_writer_custom};
160pub use value::{from_value, to_value, Cons, Value};
161
162// This is exposed for convenience (allowing importing via `serde_lexpr`) and so
163// that links from the `Value` documentation work.
164pub use lexpr::{parse, print};