Skip to content

Commit

Permalink
feat(spanned): Expose SpannedDeserializer
Browse files Browse the repository at this point in the history
Fixes #634
  • Loading branch information
epage committed Oct 24, 2023
1 parent 7ba37bb commit 126767e
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 80 deletions.
81 changes: 81 additions & 0 deletions crates/serde_spanned/src/de.rs
Original file line number Diff line number Diff line change
@@ -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<usize>,
end: Option<usize>,
value: Option<T>,
_lifetime: std::marker::PhantomData<&'de ()>,
_error: std::marker::PhantomData<E>,
}

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<usize>) -> 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::<T>::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<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
where
K: serde::de::DeserializeSeed<'de>,
{
if self.start.is_some() {
seed.deserialize(BorrowedStrDeserializer::new(Spanned::<T>::START_FIELD))
.map(Some)
} else if self.end.is_some() {
seed.deserialize(BorrowedStrDeserializer::new(Spanned::<T>::END_FIELD))
.map(Some)
} else if self.value.is_some() {
seed.deserialize(BorrowedStrDeserializer::new(Spanned::<T>::VALUE_FIELD))
.map(Some)
} else {
Ok(None)
}
}

fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
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")
}
}
}
2 changes: 2 additions & 0 deletions crates/serde_spanned/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

mod spanned;
pub use crate::spanned::Spanned;
#[cfg(feature = "serde")]
pub mod de;

#[doc(hidden)]
#[cfg(feature = "serde")]
Expand Down
10 changes: 10 additions & 0 deletions crates/serde_spanned/src/spanned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ impl<T> Spanned<T> {
}
}

#[cfg(feature = "serde")]
impl<T> Spanned<T> {
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<str> for Spanned<String> {
fn borrow(&self) -> &str {
self.get_ref()
Expand Down
6 changes: 4 additions & 2 deletions crates/toml_edit/src/de/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Self, Error>::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::<Self, Error>::new(self, span),
);
}
}

Expand Down
9 changes: 7 additions & 2 deletions crates/toml_edit/src/de/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 0 additions & 2 deletions crates/toml_edit/src/de/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@ use serde::de::DeserializeOwned;
mod array;
mod datetime;
mod key;
mod spanned;
mod table;
mod table_enum;
mod value;

use array::ArrayDeserializer;
use datetime::DatetimeDeserializer;
use key::KeyDeserializer;
use spanned::SpannedDeserializer;
use table::TableMapAccess;
use table_enum::TableEnumDeserializer;

Expand Down
70 changes: 0 additions & 70 deletions crates/toml_edit/src/de/spanned.rs

This file was deleted.

6 changes: 4 additions & 2 deletions crates/toml_edit/src/de/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Self, Error>::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::<Self, Error>::new(self, span),
);
}
}

Expand Down
6 changes: 4 additions & 2 deletions crates/toml_edit/src/de/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Self, Error>::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::<Self, Error>::new(self, span),
);
}
}

Expand Down

0 comments on commit 126767e

Please sign in to comment.