Skip to content

Commit

Permalink
Expose to_tokio_writer
Browse files Browse the repository at this point in the history
  • Loading branch information
fasterthanlime committed Nov 29, 2024
1 parent c5eaa29 commit 094df70
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 10 deletions.
44 changes: 44 additions & 0 deletions Cargo.lock

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

17 changes: 7 additions & 10 deletions merde_core/src/deserialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::{
any::TypeId,
borrow::Cow,
collections::HashMap,
future::Future,
hash::{BuildHasher, Hash},
marker::PhantomData,
};
Expand All @@ -16,23 +17,20 @@ pub trait Deserializer<'s>: std::fmt::Debug {

/// Get the next event from the deserializer.
#[doc(hidden)]
#[allow(async_fn_in_trait)]
async fn next(&mut self) -> Result<Event<'s>, Self::Error<'s>>;
fn next(&mut self) -> impl Future<Output = Result<Event<'s>, Self::Error<'s>>>;

/// Deserialize a value of type `T`.
#[doc(hidden)]
#[allow(async_fn_in_trait)]
async fn t<T: Deserialize<'s>>(&mut self) -> Result<T, Self::Error<'s>> {
self.t_starting_with(None).await
fn t<T: Deserialize<'s>>(&mut self) -> impl Future<Output = Result<T, Self::Error<'s>>> {
self.t_starting_with(None)
}

/// Deserialize a value of type `T`, using the given event as the first event.
#[doc(hidden)]
#[allow(async_fn_in_trait)]
async fn t_starting_with<T: Deserialize<'s>>(
fn t_starting_with<T: Deserialize<'s>>(
&mut self,
starter: Option<Event<'s>>,
) -> Result<T, Self::Error<'s>>;
) -> impl Future<Output = Result<T, Self::Error<'s>>>;

/// Deserialize a value of type `T`, with infinite stack support.
fn deserialize_sync<T: Deserialize<'s>>(&mut self) -> Result<T, Self::Error<'s>> {
Expand Down Expand Up @@ -205,8 +203,7 @@ impl DeserOpinions for DefaultDeserOpinions {
}

pub trait Deserialize<'s>: Sized {
#[allow(async_fn_in_trait)]
async fn deserialize<D>(de: &mut D) -> Result<Self, D::Error<'s>>
fn deserialize<D>(de: &mut D) -> impl Future<Output = Result<Self, D::Error<'s>>>
where
D: Deserializer<'s> + ?Sized;

Expand Down
1 change: 1 addition & 0 deletions merde_json/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ tokio = ["dep:tokio"]

[dev-dependencies]
merde_loggingserializer = { path = "../merde_loggingserializer" }
tokio = { version = "1", features = ["macros", "rt", "net"] }
37 changes: 37 additions & 0 deletions merde_json/src/deserialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,4 +344,41 @@ mod tests {
let s = "indeed not";
assert_eq!(cowify(src.as_bytes(), s), CowStr::Owned(s.into()));
}

// Actually trying to use Send stuff, we run into <https://github.com/rust-lang/rust/issues/100013>
// so this test is a no-go for now

// #[tokio::test]
// async fn test_cowify_async() {
// let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap();
// let port = listener.local_addr().unwrap().port();
// println!("Listening on: localhost:{port}");

// let accepted = tokio::spawn(async move {
// let (mut stream, _) = listener.accept().await.unwrap();

// let mut buf = Vec::new();
// stream.read_to_end(&mut buf).await.unwrap();
// let json_str = String::from_utf8(buf).unwrap();
// let mut deserializer = JsonDeserializer::new(&json_str);
// let deserialized: Value = Value::deserialize(&mut deserializer).await.unwrap();
// println!("Deserialized value: {:?}", deserialized);

// deserialized.into_static()
// });

// let mut arr = Array::new();
// for _ in 0..10 {
// arr.push(Map::new().with("foo", 24).with("bar", "hiya").into());
// }
// let v = Value::from(arr);

// let mut stream = tokio::net::TcpStream::connect(format!("127.0.0.1:{port}"))
// .await
// .unwrap();
// crate::to_tokio_writer(&mut stream, &v).await.unwrap();

// let deserialized = accepted.await.unwrap();
// assert_eq!(deserialized, v);
// }
}
33 changes: 33 additions & 0 deletions merde_json/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,25 @@ where
T::deserialize_owned(&mut deser)
}

/// Deserialize an instance of type `T` from a byte slice of JSON text.
pub fn from_bytes<'s, T>(b: &'s [u8]) -> Result<T, MerdeJsonError<'s>>
where
T: Deserialize<'s>,
{
let s = std::str::from_utf8(b)?;
from_str(s)
}

/// Deserialize an instance of type `T` from a byte slice of JSON text,
/// and return its static variant e.g. (CowStr<'static>, etc.)
pub fn from_bytes_owned<T>(b: &[u8]) -> Result<T, MerdeJsonError<'_>>
where
T: DeserializeOwned,
{
let s = std::str::from_utf8(b)?;
from_str_owned(s)
}

/// Serialize the given data structure as a String of JSON.
pub fn to_string<T: Serialize>(value: &T) -> Result<String, MerdeJsonError<'static>> {
// SAFETY: This is safe because we know that the JSON serialization
Expand Down Expand Up @@ -188,3 +207,17 @@ where
s.serialize_sync(value)?;
Ok(())
}

#[cfg(feature = "tokio")]
/// Serialize the given data structure as JSON into the Tokio I/O stream.
pub async fn to_tokio_writer<W, T>(writer: &mut W, value: &T) -> Result<(), MerdeJsonError<'static>>
where
W: tokio::io::AsyncWrite + Unpin,
T: Serialize,
{
use std::pin::Pin;

let mut s = JsonSerializer::from_tokio_writer(Pin::new(writer));
s.serialize(value).await?;
Ok(())
}

0 comments on commit 094df70

Please sign in to comment.