Skip to content

Commit

Permalink
Introduce a _lot_ of Serialize impls, re-use metastack properly on bo…
Browse files Browse the repository at this point in the history
…th sides for async recursion
  • Loading branch information
fasterthanlime committed Oct 22, 2024
1 parent 6c5a54f commit bee8068
Show file tree
Hide file tree
Showing 10 changed files with 442 additions and 72 deletions.
60 changes: 59 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 8 additions & 8 deletions merde/examples/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@ fn main() {
use merde::json::JsonSerialize;

let events = vec![
Event::MouseUp(MouseUp { x: 10, y: 20 }),
Event::MouseDown(MouseDown { x: 30, y: 40 }),
Event::TextInput(TextInput {
ExampleEvent::MouseUp(MouseUp { x: 10, y: 20 }),
ExampleEvent::MouseDown(MouseDown { x: 30, y: 40 }),
ExampleEvent::TextInput(TextInput {
text: "Hello".into(),
}),
Event::StringStuff(StringStuff("Some string".into())),
Event::Emergency(Emergency::NoPizzaLeft),
ExampleEvent::StringStuff(StringStuff("Some string".into())),
ExampleEvent::Emergency(Emergency::NoPizzaLeft),
];

for event in events {
let json = event.to_json_string();
println!("JSON: {}", json);
let deserialized: Event = merde::json::from_str(&json).unwrap();
let deserialized: ExampleEvent = merde::json::from_str(&json).unwrap();
println!("Deserialized: {:?}", deserialized);
assert_eq!(event, deserialized);
}
Expand All @@ -25,7 +25,7 @@ fn main() {
}

#[derive(Debug, PartialEq, Eq)]
enum Event<'s> {
enum ExampleEvent<'s> {
MouseUp(MouseUp),
MouseDown(MouseDown),
TextInput(TextInput<'s>),
Expand All @@ -34,7 +34,7 @@ enum Event<'s> {
}

merde::derive! {
impl (JsonSerialize, Deserialize) for enum Event<'s>
impl (JsonSerialize, Deserialize) for enum ExampleEvent<'s>
externally_tagged {
"mouseup" => MouseUp,
"mousedown" => MouseDown,
Expand Down
1 change: 1 addition & 0 deletions merde_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ serde = ["dep:serde", "compact_str/serde"]
rusqlite = ["dep:rusqlite"]

[dev-dependencies]
insta = "1.40.0"
trybuild = "1.0.101"
26 changes: 8 additions & 18 deletions merde_core/src/deserialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ use std::{
any::TypeId,
borrow::Cow,
collections::HashMap,
future::Future,
hash::{BuildHasher, Hash},
marker::PhantomData,
pin::Pin,
};

use crate::{
Expand Down Expand Up @@ -35,20 +33,6 @@ pub trait Deserializer<'s>: std::fmt::Debug {
starter: Option<Event<'s>>,
) -> Result<T, Self::Error<'s>>;

/// Return a boxed version of `Self::t_starting_with`, useful to avoid
/// future sizes becoming infinite, for example when deserializing Value,
/// etc.
#[doc(hidden)]
fn t_starting_with_boxed<'d, T: Deserialize<'s> + 'd>(
&'d mut self,
starter: Option<Event<'s>>,
) -> Pin<Box<dyn Future<Output = Result<T, Self::Error<'s>>> + 'd>>
where
's: 'd,
{
self.t_starting_with(starter).with_metastack_resume_point()
}

/// Deserialize a value of type `T`, with infinite stack support.
fn deserialize<T: Deserialize<'s>>(&mut self) -> Result<T, Self::Error<'s>> {
self.t_starting_with(None)
Expand Down Expand Up @@ -587,7 +571,10 @@ impl<'s> Deserialize<'s> for Value<'s> {
match de.next()? {
Event::MapEnd => break,
Event::Str(key) => {
let value: Value = de.t_starting_with_boxed(None).await?;
let value: Value = de
.t_starting_with(None)
.with_metastack_resume_point()
.await?;
map.insert(key, value);
}
ev => {
Expand All @@ -607,7 +594,10 @@ impl<'s> Deserialize<'s> for Value<'s> {
match de.next()? {
Event::ArrayEnd => break,
ev => {
let item: Value = de.t_starting_with_boxed(Some(ev)).await?;
let item: Value = de
.t_starting_with(Some(ev))
.with_metastack_resume_point()
.await?;
vec.push(item);
}
}
Expand Down
51 changes: 35 additions & 16 deletions merde_core/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,52 @@ pub enum Event<'s> {
}

macro_rules! impl_from_for_event {
($ty:ty => $variant:ident, $($rest:tt)*) => {
impl_from_for_event!($ty => $variant);
impl_from_for_event!($($rest)*);
};

($ty:ty => $variant:ident) => {
impl From<$ty> for Event<'_> {
fn from(v: $ty) -> Self {
Event::$variant(v.into())
}
}
};

(,) => {};
() => {};
}

impl_from_for_event!(i8 => I64);
impl_from_for_event!(i16 => I64);
impl_from_for_event!(i32 => I64);
impl_from_for_event!(i64 => I64);
impl_from_for_event! {
// signed
i8 => I64,
i16 => I64,
i32 => I64,
i64 => I64,
// unsigned
u8 => U64,
u16 => U64,
u32 => U64,
u64 => U64,
// floats
f32 => Float,
f64 => Float,
// misc.
bool => Bool,
}

impl_from_for_event!(u8 => U64);
impl_from_for_event!(u16 => U64);
impl_from_for_event!(u32 => U64);
impl_from_for_event!(u64 => U64);
impl From<isize> for Event<'_> {
fn from(v: isize) -> Self {
Event::I64(i64::try_from(v).unwrap())
}
}

impl_from_for_event!(f32 => Float);
impl_from_for_event!(f64 => Float);
impl From<usize> for Event<'_> {
fn from(v: usize) -> Self {
Event::U64(u64::try_from(v).unwrap())
}
}

impl<'s> From<&'s str> for Event<'s> {
fn from(v: &'s str) -> Self {
Expand Down Expand Up @@ -76,12 +101,6 @@ impl<'s> From<CowBytes<'s>> for Event<'s> {
}
}

impl<'s> From<bool> for Event<'s> {
fn from(v: bool) -> Self {
Event::Bool(v)
}
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum EventType {
I64,
Expand Down
22 changes: 22 additions & 0 deletions merde_core/src/into_static.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use std::collections::VecDeque;
use std::hash::BuildHasher;
use std::hash::Hash;

use crate::Event;

/// Allow turning a value into an "owned" variant, which can then be
/// returned, moved, etc.
///
Expand Down Expand Up @@ -49,6 +51,26 @@ where
}
}

impl<'s> IntoStatic for Event<'s> {
type Output = Event<'static>;

fn into_static(self) -> Self::Output {
match self {
Event::I64(v) => Event::I64(v),
Event::U64(v) => Event::U64(v),
Event::Float(v) => Event::Float(v),
Event::Str(v) => Event::Str(v.into_static()),
Event::Bytes(v) => Event::Bytes(v.into_static()),
Event::Bool(v) => Event::Bool(v),
Event::Null => Event::Null,
Event::MapStart(v) => Event::MapStart(v),
Event::MapEnd => Event::MapEnd,
Event::ArrayStart(v) => Event::ArrayStart(v),
Event::ArrayEnd => Event::ArrayEnd,
}
}
}

macro_rules! impl_into_static_passthru {
($($ty:ty),+) => {
$(
Expand Down
Loading

0 comments on commit bee8068

Please sign in to comment.