From 126767e184ec2a30f36e4025cdaa19579f982e15 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 24 Oct 2023 13:43:38 -0500 Subject: [PATCH] feat(spanned): Expose SpannedDeserializer Fixes #634 --- crates/serde_spanned/src/de.rs | 81 +++++++++++++++++++++++++++++ crates/serde_spanned/src/lib.rs | 2 + crates/serde_spanned/src/spanned.rs | 10 ++++ crates/toml_edit/src/de/array.rs | 6 ++- crates/toml_edit/src/de/key.rs | 9 +++- crates/toml_edit/src/de/mod.rs | 2 - crates/toml_edit/src/de/spanned.rs | 70 ------------------------- crates/toml_edit/src/de/table.rs | 6 ++- crates/toml_edit/src/de/value.rs | 6 ++- 9 files changed, 112 insertions(+), 80 deletions(-) create mode 100644 crates/serde_spanned/src/de.rs delete mode 100644 crates/toml_edit/src/de/spanned.rs diff --git a/crates/serde_spanned/src/de.rs b/crates/serde_spanned/src/de.rs new file mode 100644 index 00000000..aa0fb344 --- /dev/null +++ b/crates/serde_spanned/src/de.rs @@ -0,0 +1,81 @@ +//! Deserialzation support for [`Spanned`] + +use serde::de::value::BorrowedStrDeserializer; +use serde::de::IntoDeserializer as _; + +use crate::Spanned; + +/// Deserializer / format support for emitting [`Spanned`] +pub struct SpannedDeserializer<'de, T, E> +where + T: serde::de::IntoDeserializer<'de, E>, + E: serde::de::Error, +{ + start: Option, + end: Option, + value: Option, + _lifetime: std::marker::PhantomData<&'de ()>, + _error: std::marker::PhantomData, +} + +impl<'de, T, E> SpannedDeserializer<'de, T, E> +where + T: serde::de::IntoDeserializer<'de, E>, + E: serde::de::Error, +{ + /// Create a deserializer to emit [`Spanned`] + pub fn new(value: T, span: std::ops::Range) -> Self { + Self { + start: Some(span.start), + end: Some(span.end), + value: Some(value), + _lifetime: Default::default(), + _error: Default::default(), + } + } + + /// Check if deserializing a [`Spanned`] + pub fn is_spanned(name: &'static str, fields: &'static [&'static str]) -> bool { + Spanned::::is_spanned(name, fields) + } +} + +impl<'de, T, E> serde::de::MapAccess<'de> for SpannedDeserializer<'de, T, E> +where + T: serde::de::IntoDeserializer<'de, E>, + E: serde::de::Error, +{ + type Error = E; + fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> + where + K: serde::de::DeserializeSeed<'de>, + { + if self.start.is_some() { + seed.deserialize(BorrowedStrDeserializer::new(Spanned::::START_FIELD)) + .map(Some) + } else if self.end.is_some() { + seed.deserialize(BorrowedStrDeserializer::new(Spanned::::END_FIELD)) + .map(Some) + } else if self.value.is_some() { + seed.deserialize(BorrowedStrDeserializer::new(Spanned::::VALUE_FIELD)) + .map(Some) + } else { + Ok(None) + } + } + + fn next_value_seed(&mut self, seed: V) -> Result + where + V: serde::de::DeserializeSeed<'de>, + { + if let Some(start) = self.start.take() { + seed.deserialize(start.into_deserializer()) + } else if let Some(end) = self.end.take() { + seed.deserialize(end.into_deserializer()) + } else if let Some(value) = self.value.take() { + seed.deserialize(value.into_deserializer()) + } else { + panic!("next_value_seed called before next_key_seed") + } + } +} diff --git a/crates/serde_spanned/src/lib.rs b/crates/serde_spanned/src/lib.rs index 8ff723f4..3b0adbac 100644 --- a/crates/serde_spanned/src/lib.rs +++ b/crates/serde_spanned/src/lib.rs @@ -16,6 +16,8 @@ mod spanned; pub use crate::spanned::Spanned; +#[cfg(feature = "serde")] +pub mod de; #[doc(hidden)] #[cfg(feature = "serde")] diff --git a/crates/serde_spanned/src/spanned.rs b/crates/serde_spanned/src/spanned.rs index ac351ca8..30639452 100644 --- a/crates/serde_spanned/src/spanned.rs +++ b/crates/serde_spanned/src/spanned.rs @@ -56,6 +56,16 @@ impl Spanned { } } +#[cfg(feature = "serde")] +impl Spanned { + pub(crate) const START_FIELD: &str = START_FIELD; + pub(crate) const END_FIELD: &str = END_FIELD; + pub(crate) const VALUE_FIELD: &str = VALUE_FIELD; + pub(crate) fn is_spanned(name: &'static str, fields: &'static [&'static str]) -> bool { + is_spanned(name, fields) + } +} + impl std::borrow::Borrow for Spanned { fn borrow(&self) -> &str { self.get_ref() diff --git a/crates/toml_edit/src/de/array.rs b/crates/toml_edit/src/de/array.rs index adc54016..5b3321f9 100644 --- a/crates/toml_edit/src/de/array.rs +++ b/crates/toml_edit/src/de/array.rs @@ -32,9 +32,11 @@ impl<'de> serde::Deserializer<'de> for ArrayDeserializer { where V: serde::de::Visitor<'de>, { - if serde_spanned::__unstable::is_spanned(name, fields) { + if serde_spanned::de::SpannedDeserializer::::is_spanned(name, fields) { if let Some(span) = self.span.clone() { - return visitor.visit_map(super::SpannedDeserializer::new(self, span)); + return visitor.visit_map( + serde_spanned::de::SpannedDeserializer::::new(self, span), + ); } } diff --git a/crates/toml_edit/src/de/key.rs b/crates/toml_edit/src/de/key.rs index a3b28256..38af5fb4 100644 --- a/crates/toml_edit/src/de/key.rs +++ b/crates/toml_edit/src/de/key.rs @@ -54,9 +54,14 @@ impl<'de> serde::de::Deserializer<'de> for KeyDeserializer { where V: serde::de::Visitor<'de>, { - if serde_spanned::__unstable::is_spanned(name, fields) { + if serde_spanned::de::SpannedDeserializer::<&str, Error>::is_spanned(name, fields) { if let Some(span) = self.span.clone() { - return visitor.visit_map(super::SpannedDeserializer::new(self.key.as_str(), span)); + return visitor.visit_map( + serde_spanned::de::SpannedDeserializer::<&str, Error>::new( + self.key.as_str(), + span, + ), + ); } } self.deserialize_any(visitor) diff --git a/crates/toml_edit/src/de/mod.rs b/crates/toml_edit/src/de/mod.rs index 09ea1209..1a7e03e4 100644 --- a/crates/toml_edit/src/de/mod.rs +++ b/crates/toml_edit/src/de/mod.rs @@ -7,7 +7,6 @@ use serde::de::DeserializeOwned; mod array; mod datetime; mod key; -mod spanned; mod table; mod table_enum; mod value; @@ -15,7 +14,6 @@ mod value; use array::ArrayDeserializer; use datetime::DatetimeDeserializer; use key::KeyDeserializer; -use spanned::SpannedDeserializer; use table::TableMapAccess; use table_enum::TableEnumDeserializer; diff --git a/crates/toml_edit/src/de/spanned.rs b/crates/toml_edit/src/de/spanned.rs deleted file mode 100644 index 7ce58640..00000000 --- a/crates/toml_edit/src/de/spanned.rs +++ /dev/null @@ -1,70 +0,0 @@ -use serde::de::value::BorrowedStrDeserializer; -use serde::de::IntoDeserializer as _; - -use super::Error; - -pub(crate) struct SpannedDeserializer<'de, T: serde::de::IntoDeserializer<'de, Error>> { - phantom_data: std::marker::PhantomData<&'de ()>, - start: Option, - end: Option, - value: Option, -} - -impl<'de, T> SpannedDeserializer<'de, T> -where - T: serde::de::IntoDeserializer<'de, Error>, -{ - pub(crate) fn new(value: T, span: std::ops::Range) -> Self { - Self { - phantom_data: Default::default(), - start: Some(span.start), - end: Some(span.end), - value: Some(value), - } - } -} - -impl<'de, T> serde::de::MapAccess<'de> for SpannedDeserializer<'de, T> -where - T: serde::de::IntoDeserializer<'de, Error>, -{ - type Error = Error; - fn next_key_seed(&mut self, seed: K) -> Result, Error> - where - K: serde::de::DeserializeSeed<'de>, - { - if self.start.is_some() { - seed.deserialize(BorrowedStrDeserializer::new( - serde_spanned::__unstable::START_FIELD, - )) - .map(Some) - } else if self.end.is_some() { - seed.deserialize(BorrowedStrDeserializer::new( - serde_spanned::__unstable::END_FIELD, - )) - .map(Some) - } else if self.value.is_some() { - seed.deserialize(BorrowedStrDeserializer::new( - serde_spanned::__unstable::VALUE_FIELD, - )) - .map(Some) - } else { - Ok(None) - } - } - - fn next_value_seed(&mut self, seed: V) -> Result - where - V: serde::de::DeserializeSeed<'de>, - { - if let Some(start) = self.start.take() { - seed.deserialize(start.into_deserializer()) - } else if let Some(end) = self.end.take() { - seed.deserialize(end.into_deserializer()) - } else if let Some(value) = self.value.take() { - seed.deserialize(value.into_deserializer()) - } else { - panic!("next_value_seed called before next_key_seed") - } - } -} diff --git a/crates/toml_edit/src/de/table.rs b/crates/toml_edit/src/de/table.rs index 0b6183e0..f90078d7 100644 --- a/crates/toml_edit/src/de/table.rs +++ b/crates/toml_edit/src/de/table.rs @@ -48,9 +48,11 @@ impl<'de> serde::Deserializer<'de> for TableDeserializer { where V: serde::de::Visitor<'de>, { - if serde_spanned::__unstable::is_spanned(name, fields) { + if serde_spanned::de::SpannedDeserializer::::is_spanned(name, fields) { if let Some(span) = self.span.clone() { - return visitor.visit_map(super::SpannedDeserializer::new(self, span)); + return visitor.visit_map( + serde_spanned::de::SpannedDeserializer::::new(self, span), + ); } } diff --git a/crates/toml_edit/src/de/value.rs b/crates/toml_edit/src/de/value.rs index d3cf87fc..57e9ba50 100644 --- a/crates/toml_edit/src/de/value.rs +++ b/crates/toml_edit/src/de/value.rs @@ -128,9 +128,11 @@ impl<'de> serde::Deserializer<'de> for ValueDeserializer { where V: serde::de::Visitor<'de>, { - if serde_spanned::__unstable::is_spanned(name, fields) { + if serde_spanned::de::SpannedDeserializer::::is_spanned(name, fields) { if let Some(span) = self.input.span() { - return visitor.visit_map(super::SpannedDeserializer::new(self, span)); + return visitor.visit_map( + serde_spanned::de::SpannedDeserializer::::new(self, span), + ); } }