//! Serde support for serializing Rust data as Preserves symbols. //! //! Serde doesn't include symbols in its data model, so we do some somewhat awful tricks to //! force things to come out the way we want them. //! //! # Example //! //! Either use [Symbol] directly in your data types, or annotate [String]-valued fields that //! you want to (en|de)code as Preserves `Symbol`s with `#[serde(with = "preserves::symbol")]`: //! //! ```rust //! #[derive(serde::Serialize, serde::Deserialize)] //! struct Example { //! sym1: preserves::symbol::Symbol, //! #[serde(with = "preserves::symbol")] //! sym2: String, //! } //! ``` use crate::value::{IOValue, NestedValue}; /// Wrapper for a string to coerce its Preserves-serialization to `Symbol`. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] pub struct Symbol(pub String); impl serde::Serialize for Symbol { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { IOValue::symbol(&self.0).serialize(serializer) } } impl<'de> serde::Deserialize<'de> for Symbol { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { let v = IOValue::deserialize(deserializer)?; let s = v .value() .as_symbol() .ok_or_else(|| serde::de::Error::custom("Expected symbol"))?; Ok(Symbol(s.clone())) } } #[doc(hidden)] pub fn serialize(s: &str, serializer: S) -> Result where S: serde::Serializer, { use serde::Serialize; Symbol(s.to_string()).serialize(serializer) } #[doc(hidden)] pub fn deserialize<'de, D>(deserializer: D) -> Result where D: serde::Deserializer<'de>, { use serde::Deserialize; Symbol::deserialize(deserializer).map(|v| v.0) }