Skip to content

Commit

Permalink
Merge pull request #481 from CraftSpider/serde
Browse files Browse the repository at this point in the history
Add serde feature and support
  • Loading branch information
zesterer authored Jul 17, 2023
2 parents 6cd79f9 + 7df3def commit 10dad10
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 4 deletions.
17 changes: 14 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ exclude = [
default = ["std", "spill-stack"]

# Integrate with the standard library.
std = []
std = [
"regex-automata?/std",
"serde?/std"
]

# Enable nightly-only features like better compiler diagnostics and a Parser impl for ! (the never type).
nightly = []

# Allows deeper recursion by dynamically spilling stack state on to the heap.
spill-stack = ["stacker", "std"]
spill-stack = ["dep:stacker", "std"]

# Allows parser memoization, speeding up heavily back-tracking parsers and allowing left recursion.
memoization = []
Expand Down Expand Up @@ -52,6 +55,9 @@ either = ["dep:either"]
# Enables regex combinators
regex = ["dep:regex-automata"]

# Enable serde serialization support
serde = ["dep:serde"]

# An alias of all features that work with the stable compiler.
# Do not use this feature, its removal is not considered a breaking change and its behaviour may change.
# If you're working on chumsky and you're adding a feature that does not require nightly support, please add it to this list.
Expand All @@ -64,10 +70,11 @@ rustdoc-args = ["--cfg", "docsrs"]
[dependencies]
hashbrown = "0.14"
stacker = { version = "0.1", optional = true }
regex-automata = { version = "0.3", optional = true }
regex-automata = { version = "0.3", default-features = false, optional = true, features = ["alloc", "meta", "perf", "unicode", "nfa", "dfa", "hybrid"] }
spin = { version = "0.9", features = ["once"], default-features = false, optional = true }
lexical = { version = "6.1.1", default-features = false, features = ["parse-integers", "parse-floats", "format"], optional = true }
either = { version = "1.8.1", optional = true }
serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] }
unicode-ident = "1.0.10"

[dev-dependencies]
Expand Down Expand Up @@ -119,3 +126,7 @@ required-features = ["label"]
[[example]]
name = "json"
required-features = ["std"]

[[example]]
name = "io"
required-features = ["std"]
5 changes: 5 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ pub trait Error<'a, I: Input<'a>>: Sized {

/// A ZST error type that tracks only whether a parse error occurred at all. This type is for when
/// you want maximum parse speed, at the cost of all error reporting.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Copy, Clone, Default)]
pub struct EmptyErr(());

Expand All @@ -132,6 +133,7 @@ impl fmt::Display for EmptyErr {

/// A very cheap error type that tracks only the error span. This type is most useful when you want fast parsing but do
/// not particularly care about the quality of error messages.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Cheap<S = SimpleSpan<usize>> {
span: S,
Expand Down Expand Up @@ -169,6 +171,7 @@ where

/// A simple error type that tracks the error span and found token. This type is most useful when you want fast parsing
/// but do not particularly care about the quality of error messages.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Simple<'a, T, S = SimpleSpan<usize>> {
span: S,
Expand Down Expand Up @@ -226,6 +229,7 @@ where
}

/// An expected pattern for a [`Rich`] error.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum RichPattern<'a, T, L = &'static str> {
/// A specific token was expected.
Expand Down Expand Up @@ -312,6 +316,7 @@ where

// TODO: Maybe should make ExpectedFound encapsulated a bit more
/// The reason for a [`Rich`] error.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum RichReason<'a, T, L = &'static str> {
/// An unexpected input was found
Expand Down
1 change: 1 addition & 0 deletions src/extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ mod current {
///
/// If you're writing an extension crate for chumsky, you can make things less confusing for your users by putting your
/// parser behind a type alias.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct Ext<T: ?Sized>(pub T);
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// TODO: Talk about `.map` and purity assumptions

extern crate alloc;
extern crate core;

macro_rules! go_extra {
( $O :ty ) => {
Expand Down Expand Up @@ -117,6 +118,8 @@ use core::{
str::FromStr,
};
use hashbrown::HashMap;
#[cfg(feature = "serde")]
use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer};

#[cfg(feature = "label")]
use self::label::{LabelError, Labelled};
Expand Down
3 changes: 2 additions & 1 deletion src/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ pub trait Span {

/// The most basic implementor of `Span` - akin to `Range`, but `Copy` since it's not also
/// an iterator. Also has a `Display` implementation
#[derive(Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct SimpleSpan<T = usize, C = ()> {
/// The start offset of the span.
pub start: T,
Expand Down
37 changes: 37 additions & 0 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,40 @@ impl<'a, T> From<&'a mut T> for Maybe<T, &'a mut T> {
Self::Ref(x)
}
}

#[cfg(feature = "serde")]
impl<T: Serialize, R: Deref<Target = T>> Serialize for Maybe<T, R> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_newtype_struct("Maybe", &**self)
}
}

#[cfg(feature = "serde")]
impl<'de, T: Deserialize<'de>, R: Deref<Target = T>> Deserialize<'de> for Maybe<T, R> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct MaybeVisitor<T, R>(PhantomData<(T, R)>);

impl<'de2, T: Deserialize<'de2>, R: Deref<Target = T>> Visitor<'de2> for MaybeVisitor<T, R> {
type Value = Maybe<T, R>;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a Maybe")
}

fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de2>,
{
T::deserialize(deserializer).map(Maybe::Val)
}
}

deserializer.deserialize_newtype_struct("Maybe", MaybeVisitor(PhantomData))
}
}

0 comments on commit 10dad10

Please sign in to comment.