[][src]Crate serde_lexpr

This crate provides Serde-based serialization and deserialization from statically-typed Rust data structures to S-expressions, both using the lexpr::Value type and to S-expression textual representation.

About representations

The guiding principle for choosing the S-expression representation of Rust types is that it should look "natural" (or ideomatic) to a Lisp programmer, without introducing ambiguities.

Sequences

The serializer will represent serde sequences as lists. Note that Vec is considered a sequence, so it will be, perhaps counterintuitevely, be represented by an S-expression list, instead of an S-expression vector. While it would be possible to serialize all sequences as S-expression vectors instead, this would lead to unideomatic (noisy) S-expressions. When deserializing, both vectors and (proper) lists are accepted when a Serde sequence is expected.

use serde_lexpr::{from_str, to_string};

let v1: Vec<u32> = from_str("(1 2 3)").unwrap();
assert_eq!(v1, vec![1, 2, 3]);
assert_eq!(to_string(&v1).unwrap(), "(1 2 3)".to_string());
let v2: Vec<u32> = from_str("#(1 2 3)").unwrap();
assert_eq!(v1, v2);
assert_eq!(to_string(&v2).unwrap(), "(1 2 3)".to_string());

Option

The two variants of the Option type are represented as empty list (representing None) or a single-element list (representing Some(x)). This representation is chosen for unambiguity over using a special "missing" value (such as #nil) for None and a plain value for Some. It also combines nicely with struct fields containing option values.

use serde_lexpr::{from_str, to_string};

let answer: Option<u32> = from_str("(42)").unwrap();
assert_eq!(answer, Some(42));
let no_answer: Option<u32> = from_str("()").unwrap();
assert_eq!(no_answer, None);

Tuples and tuple structs

Tuples and tuple structs are serialized as S-expression vectors.

use serde_lexpr::{from_str, to_string};
use serde_derive::{Serialize, Deserialize};

assert_eq!(to_string(&(1, "two", 3)).unwrap(), "#(1 \"two\" 3)".to_string());
let tuple: (u8, String, u64) = from_str("(1 \"two\" 3)").unwrap();
assert_eq!(tuple, (1, "two".to_string(), 3));

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
struct Person(String, u8);

assert_eq!(to_string(&Person("Billy".into(), 42)).unwrap(), "#(\"Billy\" 42)".to_string());
let joanne: Person = from_str("#(\"Joanne\" 23)").unwrap();
assert_eq!(joanne, Person("Joanne".into(), 23));

Structs

Structs are serialized as association lists, i.e. a list consisting of cons cells, where each cell's car is the name of the struct field (as a symbol), and the cdr containing the field's value.

use serde_lexpr::{from_str, to_string};
use serde_derive::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
struct Person {
  name: String,
  age: u8,
};

let billy = Person { name: "Billy".into(), age: 42 };
assert_eq!(to_string(&billy).unwrap(), "((name . \"Billy\") (age . 42))".to_string());
let joanne: Person = from_str("((name . \"Joanne\") (age . 23))").unwrap();
assert_eq!(joanne, Person { name: "Joanne".into(), age: 23 });

Enums

Enum variants without data are serialized as plain symbols. Tuple variants are serialized as a list starting with the variant name as a symbol, followed by the values. This representation is chosen over using a vector to keep the emitted S-expressions less noisy and hopefully a bit more ideomatic. Struct variants are serialized like structs (i.e. as association lists), but have the variant name prepended as a symbol.

use serde_lexpr::{from_str, to_string};
use serde_derive::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
enum Choice {
  Yes,
  No,
  Other(String),
}

let choices: Vec<Choice> = from_str("(yes no (other . \"foo\"))").unwrap();
assert_eq!(choices, vec![Choice::Yes, Choice::No, Choice::Other("foo".into())]);

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
enum Example {
  Unit,
  Newtype(u32),
  NewtypeOption(Option<u32>),
  Tuple(u32, u32),
  Struct { foo: bool, bar: u32 },
}

let unit: Example = from_str("unit").unwrap();
assert_eq!(unit, Example::Unit);

let newtype: Example = from_str("(newtype . 42)").unwrap();
assert_eq!(newtype, Example::Newtype(42));

let newtype_some: Example = from_str("(newtype-option 23)").unwrap();
assert_eq!(newtype_some, Example::NewtypeOption(Some(23)));

let newtype_none: Example = from_str("(newtype-option)").unwrap();
assert_eq!(newtype_none, Example::NewtypeOption(None));

let tuple: Example = from_str("(tuple 1 2)").unwrap();
assert_eq!(tuple, Example::Tuple(1, 2));

let struct_variant: Example = from_str("(struct (foo . #t) (bar . 3))").unwrap();
assert_eq!(struct_variant, Example::Struct { foo: true, bar: 3 });

Re-exports

pub use error::Error;
pub use error::Result;

Modules

error

When serializing or deserializing S-expressions goes wrong.

parse

S-expression parser and options.

print

Converting S-expression values into text.

Structs

Cons

A Lisp "cons cell".

Enums

Value

Represents an S-expression value.

Functions

from_reader

Parse a value from an input stream of S-expressions, using the default parser options.

from_reader_custom

Parse a value from an input stream of S-expressions, using the default parser options.

from_slice

Deserialize an instance of type T from an S-expression byte slice, using the default parser options.

from_slice_custom

Deserialize an instance of type T from an S-expression byte slice, using the default parser options.

from_str

Deserialize an instance of type T from an S-expression string, using the default parser options.

from_str_custom

Deserialize an instance of type T from an S-expression string.

from_value

Interpret a lexpr::Value as an instance of type T.

to_string

Serialize an instance of type T into an S-expression string, using the default printer options.

to_string_custom

Serialize an instance of type T into an S-expression string.

to_value

Convert a T into lexpr::Value which is an enum that can represent any valid S-expression data.

to_vec

Serialize an instance of type T into an S-expression byte vector, using the default printer options.

to_vec_custom

Serialize an instance of type T into an S-expression byte vector.

to_writer

Serialize an instance of type T into an S-expression byte vector, using the default printer options.

to_writer_custom

Serialize an instance of type T into an S-expression byte vector.