async_proto/impls/
serde_json.rs

1use {
2    std::{
3        future::Future,
4        io::prelude::*,
5        pin::Pin,
6    },
7    tokio::io::{
8        AsyncRead,
9        AsyncWrite,
10    },
11    async_proto_derive::impl_protocol_for,
12    crate::{
13        ErrorContext,
14        LengthPrefixed,
15        Protocol,
16        ReadError,
17        ReadErrorKind,
18        WriteError,
19    },
20};
21
22#[cfg_attr(docsrs, doc(cfg(feature = "serde_json")))]
23impl Protocol for serde_json::Map<String, serde_json::Value> {
24    fn read<'a, R: AsyncRead + Unpin + Send + 'a>(stream: &'a mut R) -> Pin<Box<dyn Future<Output = Result<Self, ReadError>> + Send + 'a>> {
25        Self::read_length_prefixed(stream, u64::MAX)
26    }
27
28    fn write<'a, W: AsyncWrite + Unpin + Send + 'a>(&'a self, sink: &'a mut W) -> Pin<Box<dyn Future<Output = Result<(), WriteError>> + Send + 'a>> {
29        self.write_length_prefixed(sink, u64::MAX)
30    }
31
32    fn read_sync(stream: &mut impl Read) -> Result<Self, ReadError> {
33        Self::read_length_prefixed_sync(stream, u64::MAX)
34    }
35
36    fn write_sync(&self, sink: &mut impl Write) -> Result<(), WriteError> {
37        self.write_length_prefixed_sync(sink, u64::MAX)
38    }
39}
40
41#[cfg_attr(docsrs, doc(cfg(feature = "serde_json")))]
42impl LengthPrefixed for serde_json::Map<String, serde_json::Value> {
43    fn read_length_prefixed<'a, R: AsyncRead + Unpin + Send + 'a>(stream: &'a mut R, max_len: u64) -> Pin<Box<dyn Future<Output = Result<Self, ReadError>> + Send + 'a>> {
44        Box::pin(async move {
45            let len = super::read_len(stream, max_len, || ErrorContext::BuiltIn { for_type: "serde_json::Map" }).await?;
46            let mut map = Self::with_capacity(len); //TODO fallible allocation?
47            for _ in 0..len {
48                map.insert(String::read(stream).await?, serde_json::Value::read(stream).await?);
49            }
50            Ok(map)
51        })
52    }
53
54    fn write_length_prefixed<'a, W: AsyncWrite + Unpin + Send + 'a>(&'a self, sink: &'a mut W, max_len: u64) -> Pin<Box<dyn Future<Output = Result<(), WriteError>> + Send + 'a>> {
55        Box::pin(async move {
56            super::write_len(sink, self.len(), max_len, || ErrorContext::BuiltIn { for_type: "serde_json::Map" }).await?;
57            for (k, v) in self {
58                k.write(sink).await?;
59                v.write(sink).await?;
60            }
61            Ok(())
62        })
63    }
64
65    fn read_length_prefixed_sync(stream: &mut impl Read, max_len: u64) -> Result<Self, ReadError> {
66        let len = super::read_len_sync(stream, max_len, || ErrorContext::BuiltIn { for_type: "serde_json::Map" })?;
67        let mut map = Self::with_capacity(len); //TODO fallible allocation?
68        for _ in 0..len {
69            map.insert(String::read_sync(stream)?, serde_json::Value::read_sync(stream)?);
70        }
71        Ok(map)
72    }
73
74    fn write_length_prefixed_sync(&self, sink: &mut impl Write, max_len: u64) -> Result<(), WriteError> {
75        super::write_len_sync(sink, self.len(), max_len, || ErrorContext::BuiltIn { for_type: "serde_json::Map" })?;
76        for (k, v) in self {
77            k.write_sync(sink)?;
78            v.write_sync(sink)?;
79        }
80        Ok(())
81    }
82}
83
84#[derive(Protocol)]
85#[async_proto(internal)]
86enum NumberProxy {
87    U64(u64),
88    I64(i64),
89    F64(f64),
90}
91
92impl TryFrom<NumberProxy> for serde_json::Number {
93    type Error = ReadErrorKind;
94
95    fn try_from(number: NumberProxy) -> Result<Self, ReadErrorKind> {
96        match number {
97            NumberProxy::U64(n) => Ok(Self::from(n)),
98            NumberProxy::I64(n) => Ok(Self::from(n)),
99            NumberProxy::F64(n) => Self::from_f64(n).ok_or(ReadErrorKind::FloatNotFinite),
100        }
101    }
102}
103
104impl<'a> From<&'a serde_json::Number> for NumberProxy {
105    fn from(number: &serde_json::Number) -> Self {
106        if let Some(value) = number.as_u64() {
107            Self::U64(value)
108        } else if let Some(value) = number.as_i64() {
109            Self::I64(value)
110        } else if let Some(value) = number.as_f64() {
111            Self::F64(value)
112        } else {
113            unreachable!("serde_json::Number is neither u64 nor i64 nor f64")
114        }
115    }
116}
117
118impl_protocol_for! {
119    #[async_proto(attr(cfg_attr(docsrs, doc(cfg(feature = "serde_json")))))]
120    enum serde_json::Value {
121        Null,
122        Bool(bool),
123        Number(serde_json::Number),
124        String(String),
125        Array(Vec<serde_json::Value>),
126        Object(serde_json::Map<String, serde_json::Value>),
127    }
128
129    #[async_proto(attr(cfg_attr(docsrs, doc(cfg(feature = "serde_json")))))]
130    #[async_proto(via = NumberProxy)]
131    type serde_json::Number;
132}