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