Skip to content

Commit

Permalink
Merge pull request #698 from epage/im
Browse files Browse the repository at this point in the history
feat(edit): Expose `ImDocument`, an Immutable Document
  • Loading branch information
epage committed Mar 9, 2024
2 parents 2056161 + 6c11613 commit 8b6f77e
Show file tree
Hide file tree
Showing 10 changed files with 264 additions and 160 deletions.
25 changes: 5 additions & 20 deletions crates/toml/src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,7 @@ impl<'de, 'a> serde::Deserializer<'de> for Deserializer<'a> {
where
V: serde::de::Visitor<'de>,
{
let inner = self
.input
.parse::<toml_edit::de::Deserializer>()
.map_err(Error::new)?;
let inner = toml_edit::de::Deserializer::parse(self.input).map_err(Error::new)?;
inner.deserialize_any(visitor).map_err(Error::new)
}

Expand All @@ -126,10 +123,7 @@ impl<'de, 'a> serde::Deserializer<'de> for Deserializer<'a> {
where
V: serde::de::Visitor<'de>,
{
let inner = self
.input
.parse::<toml_edit::de::Deserializer>()
.map_err(Error::new)?;
let inner = toml_edit::de::Deserializer::parse(self.input).map_err(Error::new)?;
inner.deserialize_option(visitor).map_err(Error::new)
}

Expand All @@ -141,10 +135,7 @@ impl<'de, 'a> serde::Deserializer<'de> for Deserializer<'a> {
where
V: serde::de::Visitor<'de>,
{
let inner = self
.input
.parse::<toml_edit::de::Deserializer>()
.map_err(Error::new)?;
let inner = toml_edit::de::Deserializer::parse(self.input).map_err(Error::new)?;
inner
.deserialize_newtype_struct(name, visitor)
.map_err(Error::new)
Expand All @@ -159,10 +150,7 @@ impl<'de, 'a> serde::Deserializer<'de> for Deserializer<'a> {
where
V: serde::de::Visitor<'de>,
{
let inner = self
.input
.parse::<toml_edit::de::Deserializer>()
.map_err(Error::new)?;
let inner = toml_edit::de::Deserializer::parse(self.input).map_err(Error::new)?;
inner
.deserialize_struct(name, fields, visitor)
.map_err(Error::new)
Expand All @@ -178,10 +166,7 @@ impl<'de, 'a> serde::Deserializer<'de> for Deserializer<'a> {
where
V: serde::de::Visitor<'de>,
{
let inner = self
.input
.parse::<toml_edit::de::Deserializer>()
.map_err(Error::new)?;
let inner = toml_edit::de::Deserializer::parse(self.input).map_err(Error::new)?;
inner
.deserialize_enum(name, variants, visitor)
.map_err(Error::new)
Expand Down
96 changes: 63 additions & 33 deletions crates/toml_edit/src/de/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,17 @@ impl From<Error> for crate::TomlError {

impl std::error::Error for Error {}

/// Convert a value into `T`.
/// Convert a TOML [documents][crate::Document] into `T`.
#[cfg(feature = "parse")]
pub fn from_str<T>(s: &'_ str) -> Result<T, Error>
where
T: DeserializeOwned,
{
let de = s.parse::<Deserializer>()?;
let de = Deserializer::parse(s)?;
T::deserialize(de)
}

/// Convert a value into `T`.
/// Convert a TOML [documents][crate::Document] into `T`.
#[cfg(feature = "parse")]
pub fn from_slice<T>(s: &'_ [u8]) -> Result<T, Error>
where
Expand All @@ -106,24 +106,51 @@ where
from_str(s)
}

/// Convert a document into `T`.
pub fn from_document<T>(d: crate::Document) -> Result<T, Error>
/// Convert a [Document][crate::Document] into `T`.
pub fn from_document<T>(d: impl Into<Deserializer>) -> Result<T, Error>
where
T: DeserializeOwned,
{
let deserializer = Deserializer::new(d);
let deserializer = d.into();
T::deserialize(deserializer)
}

/// Deserialization for TOML [documents][crate::Document].
pub struct Deserializer {
input: crate::Document,
pub struct Deserializer<S = String> {
root: crate::Item,
raw: Option<S>,
}

impl Deserializer {
/// Deserialization implementation for TOML.
#[deprecated(since = "0.22.6", note = "Replaced with `Deserializer::from`")]
pub fn new(input: crate::Document) -> Self {
Self { input }
Self::from(input)
}
}

#[cfg(feature = "parse")]
impl<S: AsRef<str>> Deserializer<S> {
/// Parse a TOML document
pub fn parse(raw: S) -> Result<Self, Error> {
crate::ImDocument::parse(raw)
.map(Self::from)
.map_err(Into::into)
}
}

impl From<crate::Document> for Deserializer {
fn from(doc: crate::Document) -> Self {
let crate::Document { root, raw, .. } = doc;
Self { root, raw }
}
}

impl<S> From<crate::ImDocument<S>> for Deserializer<S> {
fn from(doc: crate::ImDocument<S>) -> Self {
let crate::ImDocument { root, raw, .. } = doc;
let raw = Some(raw);
Self { root, raw }
}
}

Expand All @@ -133,27 +160,26 @@ impl std::str::FromStr for Deserializer {

/// Parses a document from a &str
fn from_str(s: &str) -> Result<Self, Self::Err> {
let d = crate::parser::parse_document(s).map_err(Error::from)?;
Ok(Self::new(d))
let doc: crate::ImDocument<_> = s.parse().map_err(Error::from)?;
Ok(Deserializer::from(doc))
}
}

// Note: this is wrapped by `toml::de::Deserializer` and any trait methods
// implemented here need to be wrapped there
impl<'de> serde::Deserializer<'de> for Deserializer {
impl<'de, S: Into<String>> serde::Deserializer<'de> for Deserializer<S> {
type Error = Error;

fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
let original = self.input.original;
self.input
.root
let raw = self.raw;
self.root
.into_deserializer()
.deserialize_any(visitor)
.map_err(|mut e: Self::Error| {
e.inner.set_original(original);
e.inner.set_raw(raw.map(|r| r.into()));
e
})
}
Expand All @@ -164,13 +190,12 @@ impl<'de> serde::Deserializer<'de> for Deserializer {
where
V: serde::de::Visitor<'de>,
{
let original = self.input.original;
self.input
.root
let raw = self.raw;
self.root
.into_deserializer()
.deserialize_option(visitor)
.map_err(|mut e: Self::Error| {
e.inner.set_original(original);
e.inner.set_raw(raw.map(|r| r.into()));
e
})
}
Expand All @@ -183,13 +208,12 @@ impl<'de> serde::Deserializer<'de> for Deserializer {
where
V: serde::de::Visitor<'de>,
{
let original = self.input.original;
self.input
.root
let raw = self.raw;
self.root
.into_deserializer()
.deserialize_newtype_struct(name, visitor)
.map_err(|mut e: Self::Error| {
e.inner.set_original(original);
e.inner.set_raw(raw.map(|r| r.into()));
e
})
}
Expand All @@ -203,13 +227,12 @@ impl<'de> serde::Deserializer<'de> for Deserializer {
where
V: serde::de::Visitor<'de>,
{
let original = self.input.original;
self.input
.root
let raw = self.raw;
self.root
.into_deserializer()
.deserialize_struct(name, fields, visitor)
.map_err(|mut e: Self::Error| {
e.inner.set_original(original);
e.inner.set_raw(raw.map(|r| r.into()));
e
})
}
Expand All @@ -224,13 +247,12 @@ impl<'de> serde::Deserializer<'de> for Deserializer {
where
V: serde::de::Visitor<'de>,
{
let original = self.input.original;
self.input
.root
let raw = self.raw;
self.root
.into_deserializer()
.deserialize_enum(name, variants, visitor)
.map_err(|mut e: Self::Error| {
e.inner.set_original(original);
e.inner.set_raw(raw.map(|r| r.into()));
e
})
}
Expand All @@ -254,7 +276,15 @@ impl<'de> serde::de::IntoDeserializer<'de, crate::de::Error> for crate::Document
type Deserializer = Deserializer;

fn into_deserializer(self) -> Self::Deserializer {
Deserializer::new(self)
Deserializer::from(self)
}
}

impl<'de> serde::de::IntoDeserializer<'de, crate::de::Error> for crate::ImDocument<String> {
type Deserializer = Deserializer;

fn into_deserializer(self) -> Self::Deserializer {
Deserializer::from(self)
}
}

Expand Down
Loading

0 comments on commit 8b6f77e

Please sign in to comment.