Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(spanned): Expose SpannedDeserializer #635

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading