1 unstable release
0.1.0 | Sep 26, 2022 |
---|
#380 in #deserialize
31KB
727 lines
Async Serde
This is a crate for async fn
serde. It's not necessarily more efficient,
merely different. It allows using serde to interact with data formats (like
JSON, etc) directly instead of going through deserialization.
Its main feature is the ability to trivially apply non-deterministic (in the automaton sense) transformations directly onto the deserialization process. This is particularly useful if you happen to be making a jq clone that operates directly on the data stream instead of loading the whole data stream into an in-memory data structure first.
Note
Note that the types Instructor
and Step
can be passed around freely in
a Run
impl. While not unsound, this can lead to hard-to-debug errors.
It's recommended to only use these as indicated in these examples, to avoid
the hard-to-debug runtime errors.
Examples
use std::borrow::Cow;
use async_serde::Deserialize;
use async_serde::Inspect;
use async_serde::Instructor;
use async_serde::Run;
use async_serde::Visit;
use async_trait::async_trait;
struct Foo;
#[async_trait(?Send)]
impl<'de, E: serde::de::Error> Run<'de, E> for Foo {
type Output = Cow<'de, str>;
async fn run(
self,
instructor: Instructor<'_, 'de>
) -> Result<Self::Output, E> {
let step = instructor.ask(Deserialize::String).unwrap().await;
match step.kind() {
Visit::Str => {
step.inspect_string(|s| {
match s {
Inspect::Borrowed(s) => Cow::from(s),
Inspect::Owned(s) => Cow::from(String::from(s)),
Inspect::Buffered(s) => Cow::from(s.to_owned()),
}
}).ok_or_else(|| E::custom("wrong type"))
},
_ => Err(E::custom("wrong type")),
}
}
}
fn main() {
let mut json = serde_json::Deserializer::from_str("\"hello\"");
let exec = async_serde::Executor::new(&mut json);
// this is returning an Result<Option<Cow<'de, str>>, Error>
let res = exec.run::<_, serde_json::Error>(Foo);
assert_eq!(res.unwrap(), "hello");
}
use std::borrow::Cow;
use async_serde::Deserialize;
use async_serde::Inspect;
use async_serde::Instructor;
use async_serde::Run;
use async_serde::Visit;
use async_trait::async_trait;
struct Foo;
#[async_trait(?Send)]
impl<'de, E: serde::de::Error> Run<'de, E> for Foo {
type Output = [Vec<Cow<'de, str>>; 2];
async fn run(
self,
instructor: Instructor<'_, 'de>
) -> Result<Self::Output, E> {
let mut step = instructor.ask(Deserialize::Seq).unwrap().await;
match step.kind() {
Visit::Seq => {
let step2 = step.cloned();
match futures::join!(
step.inspect_seq(|s| async move {
// TODO
Ok(Vec::new())
}).ok_or_else(|| E::custom("wrong type"))?,
step2.inspect_seq(|s| async move {
// TODO
Ok(Vec::new())
}).ok_or_else(|| E::custom("wrong type"))?
) {
(a, b) => Ok([a?, b?])
}
},
_ => Err(E::custom("wrong type")),
}
}
}
fn main() {
let mut json = serde_json::Deserializer::from_str("[\"a\", \"b\"]");
let exec = async_serde::Executor::new(&mut json);
// this is returning an Result<Option<Cow<'de, str>>, Error>
let res = exec.run::<_, serde_json::Error>(Foo).unwrap();
assert_eq!(res[0], &[Cow::from("a"), "b".into()][..]);
assert_eq!(res[1], &[Cow::from("a"), "b".into()][..]);
}
Dependencies
~1–1.8MB
~37K SLoC