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);
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 {
Ok(Vec::new())
}).ok_or_else(|| E::custom("wrong type"))?,
step2.inspect_seq(|s| async move {
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);
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()][..]);
}