async_proto/impls/
mod.rs

1//! [`Protocol`] implementations for primitive and [`std`] types.
2
3#![allow(missing_docs)]
4
5use {
6    std::{
7        collections::{
8            BTreeMap,
9            BTreeSet,
10            HashMap,
11            HashSet,
12        },
13        convert::{
14            TryFrom as _,
15            TryInto as _,
16        },
17        future::Future,
18        hash::Hash,
19        io::prelude::*,
20        ops::{
21            Range,
22            RangeFrom,
23            RangeInclusive,
24            RangeTo,
25            RangeToInclusive,
26        },
27        pin::Pin,
28    },
29    byteorder::{
30        NetworkEndian,
31        ReadBytesExt as _,
32        WriteBytesExt as _,
33    },
34    fallible_collections::{
35        FallibleBox,
36        FallibleVec,
37    },
38    tokio::io::{
39        AsyncRead,
40        AsyncReadExt as _,
41        AsyncWrite,
42        AsyncWriteExt as _,
43    },
44    async_proto_derive::impl_protocol_for,
45    crate::{
46        ErrorContext,
47        Protocol,
48        ReadError,
49        ReadErrorKind,
50        WriteError,
51    },
52};
53
54#[cfg(feature = "bytes")] mod bytes;
55#[cfg(feature = "chrono")] mod chrono;
56#[cfg(feature = "chrono-tz")] mod chrono_tz;
57#[cfg(feature = "either")] mod either;
58#[cfg(feature = "enumset")] mod enumset;
59#[cfg(feature = "git2")] mod git2;
60#[cfg(feature = "gix-hash")] mod gix_hash;
61#[cfg(feature = "noisy_float")] mod noisy_float;
62#[cfg(feature = "semver")] mod semver;
63#[cfg(feature = "serde_json")] mod serde_json;
64#[cfg(feature = "serenity")] mod serenity;
65#[cfg(feature = "uuid")] mod uuid;
66
67macro_rules! impl_protocol_primitive {
68    ($ty:ty, $read:ident, $write:ident$(, $endian:ty)?) => {
69        /// Primitive number types are encoded in [big-endian](https://en.wikipedia.org/wiki/Big-endian) format.
70        impl Protocol for $ty {
71            fn read<'a, R: AsyncRead + Unpin + Send + 'a>(stream: &'a mut R) -> Pin<Box<dyn Future<Output = Result<Self, ReadError>> + Send + 'a>> {
72                Box::pin(async move {
73                    Ok(stream.$read().await.map_err(|e| ReadError {
74                        context: ErrorContext::BuiltIn { for_type: stringify!($ty) },
75                        kind: e.into(),
76                    })?)
77                })
78            }
79
80            fn write<'a, W: AsyncWrite + Unpin + Send + 'a>(&'a self, sink: &'a mut W) -> Pin<Box<dyn Future<Output = Result<(), WriteError>> + Send + 'a>> {
81                Box::pin(async move {
82                    Ok(sink.$write(*self).await.map_err(|e| WriteError {
83                        context: ErrorContext::BuiltIn { for_type: stringify!($ty) },
84                        kind: e.into(),
85                    })?)
86                })
87            }
88
89            fn read_sync(stream: &mut impl Read) -> Result<Self, ReadError> {
90                Ok(stream.$read$(::<$endian>)?().map_err(|e| ReadError {
91                    context: ErrorContext::BuiltIn { for_type: stringify!($ty) },
92                    kind: e.into(),
93                })?)
94            }
95
96            fn write_sync(&self, sink: &mut impl Write) -> Result<(), WriteError> {
97                Ok(sink.$write$(::<$endian>)?(*self).map_err(|e| WriteError {
98                    context: ErrorContext::BuiltIn { for_type: stringify!($ty) },
99                    kind: e.into(),
100                })?)
101            }
102        }
103    };
104}
105
106impl_protocol_primitive!(u8, read_u8, write_u8);
107impl_protocol_primitive!(i8, read_i8, write_i8);
108impl_protocol_primitive!(u16, read_u16, write_u16, NetworkEndian);
109impl_protocol_primitive!(i16, read_i16, write_i16, NetworkEndian);
110impl_protocol_primitive!(u32, read_u32, write_u32, NetworkEndian);
111impl_protocol_primitive!(i32, read_i32, write_i32, NetworkEndian);
112impl_protocol_primitive!(u64, read_u64, write_u64, NetworkEndian);
113impl_protocol_primitive!(i64, read_i64, write_i64, NetworkEndian);
114impl_protocol_primitive!(u128, read_u128, write_u128, NetworkEndian);
115impl_protocol_primitive!(i128, read_i128, write_i128, NetworkEndian);
116
117impl<Idx: Protocol + Send + Sync> Protocol for RangeInclusive<Idx> { //TODO derive
118    fn read<'a, R: AsyncRead + Unpin + Send + 'a>(stream: &'a mut R) -> Pin<Box<dyn Future<Output = Result<Self, ReadError>> + Send + 'a>> {
119        Box::pin(async move {
120            Ok(Idx::read(stream).await?..=Idx::read(stream).await?)
121        })
122    }
123
124    fn write<'a, W: AsyncWrite + Unpin + Send + 'a>(&'a self, sink: &'a mut W) -> Pin<Box<dyn Future<Output = Result<(), WriteError>> + Send + 'a>> {
125        Box::pin(async move {
126            self.start().write(sink).await?;
127            self.end().write(sink).await?;
128            Ok(())
129        })
130    }
131
132    fn read_sync(stream: &mut impl Read) -> Result<Self, ReadError> {
133        Ok(Idx::read_sync(stream)?..=Idx::read_sync(stream)?)
134    }
135
136    fn write_sync(&self, sink: &mut impl Write) -> Result<(), WriteError> {
137        self.start().write_sync(sink)?;
138        self.end().write_sync(sink)?;
139        Ok(())
140    }
141}
142
143macro_rules! impl_protocol_tuple {
144    ($($ty:ident),*) => {
145        #[allow(unused)]
146        impl<$($ty: Protocol + Send + Sync),*> Protocol for ($($ty,)*) {
147            fn read<'a, R: AsyncRead + Unpin + Send + 'a>(stream: &'a mut R) -> Pin<Box<dyn Future<Output = Result<Self, ReadError>> + Send + 'a>> {
148                Box::pin(async move {
149                    Ok((
150                        $($ty::read(stream).await?,)*
151                    ))
152                })
153            }
154
155            #[allow(non_snake_case)]
156            fn write<'a, W: AsyncWrite + Unpin + Send + 'a>(&'a self, sink: &'a mut W) -> Pin<Box<dyn Future<Output = Result<(), WriteError>> + Send + 'a>> {
157                Box::pin(async move {
158                    let ($($ty,)*) = self;
159                    $(
160                        $ty.write(sink).await?;
161                    )*
162                    Ok(())
163                })
164            }
165
166            fn read_sync(stream: &mut impl Read) -> Result<Self, ReadError> {
167                Ok((
168                    $($ty::read_sync(stream)?,)*
169                ))
170            }
171
172            #[allow(non_snake_case)]
173            fn write_sync(&self, sink: &mut impl Write) -> Result<(), WriteError> {
174                let ($($ty,)*) = self;
175                $(
176                    $ty.write_sync(sink)?;
177                )*
178                Ok(())
179            }
180        }
181    };
182}
183
184impl_protocol_tuple!();
185impl_protocol_tuple!(A);
186impl_protocol_tuple!(A, B);
187impl_protocol_tuple!(A, B, C);
188impl_protocol_tuple!(A, B, C, D);
189impl_protocol_tuple!(A, B, C, D, E);
190impl_protocol_tuple!(A, B, C, D, E, F);
191impl_protocol_tuple!(A, B, C, D, E, F, G);
192impl_protocol_tuple!(A, B, C, D, E, F, G, H);
193impl_protocol_tuple!(A, B, C, D, E, F, G, H, I);
194impl_protocol_tuple!(A, B, C, D, E, F, G, H, I, J);
195impl_protocol_tuple!(A, B, C, D, E, F, G, H, I, J, K);
196impl_protocol_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
197
198impl<T: Protocol + Send + Sync, const N: usize> Protocol for [T; N] {
199    fn read<'a, R: AsyncRead + Unpin + Send + 'a>(stream: &'a mut R) -> Pin<Box<dyn Future<Output = Result<Self, ReadError>> + Send + 'a>> {
200        Box::pin(async move {
201            let mut vec = <Vec<_> as FallibleVec<_>>::try_with_capacity(N).map_err(|e| ReadError {
202                context: ErrorContext::BuiltIn { for_type: "[T; N]" },
203                kind: e.into(),
204            })?;
205            for _ in 0..N {
206                vec.push(T::read(stream).await?);
207            }
208            Ok(match vec.try_into() {
209                Ok(array) => array,
210                Err(_) => panic!("wrong array length"),
211            })
212        })
213    }
214
215    fn write<'a, W: AsyncWrite + Unpin + Send + 'a>(&'a self, sink: &'a mut W) -> Pin<Box<dyn Future<Output = Result<(), WriteError>> + Send + 'a>> {
216        Box::pin(async move {
217            for elt in self {
218                elt.write(sink).await?;
219            }
220            Ok(())
221        })
222    }
223
224    fn read_sync(stream: &mut impl Read) -> Result<Self, ReadError> {
225        let mut vec = <Vec<_> as FallibleVec<_>>::try_with_capacity(N).map_err(|e| ReadError {
226            context: ErrorContext::BuiltIn { for_type: "[T; N]" },
227            kind: e.into(),
228        })?;
229        for _ in 0..N {
230            vec.push(T::read_sync(stream)?);
231        }
232        Ok(match vec.try_into() {
233            Ok(array) => array,
234            Err(_) => panic!("wrong array length"),
235        })
236    }
237
238    fn write_sync(&self, sink: &mut impl Write) -> Result<(), WriteError> {
239        for elt in self {
240            elt.write_sync(sink)?;
241        }
242        Ok(())
243    }
244}
245
246/// Represented as one byte, with `0` for `false` and `1` for `true`.
247impl Protocol for bool {
248    fn read<'a, R: AsyncRead + Unpin + Send + 'a>(stream: &'a mut R) -> Pin<Box<dyn Future<Output = Result<Self, ReadError>> + Send + 'a>> {
249        Box::pin(async move {
250            Ok(match u8::read(stream).await? {
251                0 => false,
252                1 => true,
253                n => return Err(ReadError {
254                    context: ErrorContext::BuiltIn { for_type: "bool" },
255                    kind: ReadErrorKind::UnknownVariant8(n),
256                }),
257            })
258        })
259    }
260
261    fn write<'a, W: AsyncWrite + Unpin + Send + 'a>(&'a self, sink: &'a mut W) -> Pin<Box<dyn Future<Output = Result<(), WriteError>> + Send + 'a>> {
262        Box::pin(async move {
263            if *self { 1u8 } else { 0 }.write(sink).await
264        })
265    }
266
267    fn read_sync(stream: &mut impl Read) -> Result<Self, ReadError> {
268        Ok(match u8::read_sync(stream)? {
269            0 => false,
270            1 => true,
271            n => return Err(ReadError {
272                context: ErrorContext::BuiltIn { for_type: "bool" },
273                kind: ReadErrorKind::UnknownVariant8(n),
274            }),
275        })
276    }
277
278    fn write_sync(&self, sink: &mut impl Write) -> Result<(), WriteError> {
279        if *self { 1u8 } else { 0 }.write_sync(sink)
280    }
281}
282
283impl<T: Protocol> Protocol for Box<T> {
284    fn read<'a, R: AsyncRead + Unpin + Send + 'a>(stream: &'a mut R) -> Pin<Box<dyn Future<Output = Result<Self, ReadError>> + Send + 'a>> {
285        Box::pin(async move {
286            Ok(<Box<_> as FallibleBox<_>>::try_new(T::read(stream).await?).map_err(|e| ReadError {
287                context: ErrorContext::BuiltIn { for_type: "Box" },
288                kind: e.into(),
289            })?)
290        })
291    }
292
293    fn write<'a, W: AsyncWrite + Unpin + Send + 'a>(&'a self, sink: &'a mut W) -> Pin<Box<dyn Future<Output = Result<(), WriteError>> + Send + 'a>> {
294        (**self).write(sink)
295    }
296
297    fn read_sync(stream: &mut impl Read) -> Result<Self, ReadError> {
298        Ok(<Box<_> as FallibleBox<_>>::try_new(T::read_sync(stream)?).map_err(|e| ReadError {
299            context: ErrorContext::BuiltIn { for_type: "Box" },
300            kind: e.into(),
301        })?)
302    }
303
304    fn write_sync(&self, sink: &mut impl Write) -> Result<(), WriteError> {
305        (**self).write_sync(sink)
306    }
307}
308
309/// A vector is prefixed with the length as a [`u64`].
310///
311/// Note that due to Rust's lack of [specialization](https://github.com/rust-lang/rust/issues/31844), this implementation is inefficient for `Vec<u8>`.
312/// Prefer [`Bytes`](https://docs.rs/bytes/latest/bytes/struct.Bytes.html) if possible.
313impl<T: Protocol + Send + Sync> Protocol for Vec<T> {
314    fn read<'a, R: AsyncRead + Unpin + Send + 'a>(stream: &'a mut R) -> Pin<Box<dyn Future<Output = Result<Self, ReadError>> + Send + 'a>> {
315        Box::pin(async move {
316            let len = u64::read(stream).await?;
317            let mut buf = <Self as FallibleVec<_>>::try_with_capacity(usize::try_from(len).map_err(|e| ReadError {
318                context: ErrorContext::BuiltIn { for_type: "Vec" },
319                kind: e.into(),
320            })?).map_err(|e| ReadError {
321                context: ErrorContext::BuiltIn { for_type: "Vec" },
322                kind: e.into(),
323            })?;
324            for _ in 0..len {
325                buf.push(T::read(stream).await?);
326            }
327            Ok(buf)
328        })
329    }
330
331    fn write<'a, W: AsyncWrite + Unpin + Send + 'a>(&'a self, sink: &'a mut W) -> Pin<Box<dyn Future<Output = Result<(), WriteError>> + Send + 'a>> {
332        Box::pin(async move {
333            u64::try_from(self.len()).map_err(|e| WriteError {
334                context: ErrorContext::BuiltIn { for_type: "Vec" },
335                kind: e.into(),
336            })?.write(sink).await?;
337            for elt in self {
338                elt.write(sink).await?;
339            }
340            Ok(())
341        })
342    }
343
344    fn read_sync(stream: &mut impl Read) -> Result<Self, ReadError> {
345        let len = u64::read_sync(stream)?;
346        let mut buf = <Self as FallibleVec<_>>::try_with_capacity(usize::try_from(len).map_err(|e| ReadError {
347            context: ErrorContext::BuiltIn { for_type: "Vec" },
348            kind: e.into(),
349        })?).map_err(|e| ReadError {
350            context: ErrorContext::BuiltIn { for_type: "Vec" },
351            kind: e.into(),
352        })?;
353        for _ in 0..len {
354            buf.push(T::read_sync(stream)?);
355        }
356        Ok(buf)
357    }
358
359    fn write_sync(&self, sink: &mut impl Write) -> Result<(), WriteError> {
360        u64::try_from(self.len()).map_err(|e| WriteError {
361            context: ErrorContext::BuiltIn { for_type: "Vec" },
362            kind: e.into(),
363        })?.write_sync(sink)?;
364        for elt in self {
365            elt.write_sync(sink)?;
366        }
367        Ok(())
368    }
369}
370
371/// A set is prefixed with the length as a [`u64`].
372impl<T: Protocol + Ord + Send + Sync + 'static> Protocol for BTreeSet<T> {
373    fn read<'a, R: AsyncRead + Unpin + Send + 'a>(stream: &'a mut R) -> Pin<Box<dyn Future<Output = Result<Self, ReadError>> + Send + 'a>> {
374        Box::pin(async move {
375            let len = u64::read(stream).await?;
376            usize::try_from(len).map_err(|e| ReadError {
377                context: ErrorContext::BuiltIn { for_type: "BTreeSet" },
378                kind: e.into(),
379            })?; // error here rather than panicking in the insert loop
380            let mut set = Self::default();
381            for _ in 0..len {
382                set.insert(T::read(stream).await?); //TODO use fallible allocation once available
383            }
384            Ok(set)
385        })
386    }
387
388    fn write<'a, W: AsyncWrite + Unpin + Send + 'a>(&'a self, sink: &'a mut W) -> Pin<Box<dyn Future<Output = Result<(), WriteError>> + Send + 'a>> {
389        Box::pin(async move {
390            u64::try_from(self.len()).map_err(|e| WriteError {
391                context: ErrorContext::BuiltIn { for_type: "BTreeSet" },
392                kind: e.into(),
393            })?.write(sink).await?;
394            for elt in self {
395                elt.write(sink).await?;
396            }
397            Ok(())
398        })
399    }
400
401    fn read_sync(stream: &mut impl Read) -> Result<Self, ReadError> {
402        let len = u64::read_sync(stream)?;
403        usize::try_from(len).map_err(|e| ReadError {
404            context: ErrorContext::BuiltIn { for_type: "BTreeSet" },
405            kind: e.into(),
406        })?; // error here rather than panicking in the insert loop
407        let mut set = Self::default();
408        for _ in 0..len {
409            set.insert(T::read_sync(stream)?); //TODO use fallible allocation once available
410        }
411        Ok(set)
412    }
413
414    fn write_sync(&self, sink: &mut impl Write) -> Result<(), WriteError> {
415        u64::try_from(self.len()).map_err(|e| WriteError {
416            context: ErrorContext::BuiltIn { for_type: "BTreeSet" },
417            kind: e.into(),
418        })?.write_sync(sink)?;
419        for elt in self {
420            elt.write_sync(sink)?;
421        }
422        Ok(())
423    }
424}
425
426/// A set is prefixed with the length as a [`u64`].
427impl<T: Protocol + Eq + Hash + Send + Sync> Protocol for HashSet<T> {
428    fn read<'a, R: AsyncRead + Unpin + Send + 'a>(stream: &'a mut R) -> Pin<Box<dyn Future<Output = Result<Self, ReadError>> + Send + 'a>> {
429        Box::pin(async move {
430            let len = u64::read(stream).await?;
431            let mut set = Self::with_capacity(usize::try_from(len).map_err(|e| ReadError {
432                context: ErrorContext::BuiltIn { for_type: "HashSet" },
433                kind: e.into(),
434            })?); //TODO use fallible allocation once available
435            for _ in 0..len {
436                set.insert(T::read(stream).await?);
437            }
438            Ok(set)
439        })
440    }
441
442    fn write<'a, W: AsyncWrite + Unpin + Send + 'a>(&'a self, sink: &'a mut W) -> Pin<Box<dyn Future<Output = Result<(), WriteError>> + Send + 'a>> {
443        Box::pin(async move {
444            u64::try_from(self.len()).map_err(|e| WriteError {
445                context: ErrorContext::BuiltIn { for_type: "HashSet" },
446                kind: e.into(),
447            })?.write(sink).await?;
448            for elt in self {
449                elt.write(sink).await?;
450            }
451            Ok(())
452        })
453    }
454
455    fn read_sync(stream: &mut impl Read) -> Result<Self, ReadError> {
456        let len = u64::read_sync(stream)?;
457        let mut set = Self::with_capacity(usize::try_from(len).map_err(|e| ReadError {
458            context: ErrorContext::BuiltIn { for_type: "HashSet" },
459            kind: e.into(),
460        })?); //TODO use fallible allocation once available
461        for _ in 0..len {
462            set.insert(T::read_sync(stream)?);
463        }
464        Ok(set)
465    }
466
467    fn write_sync(&self, sink: &mut impl Write) -> Result<(), WriteError> {
468        u64::try_from(self.len()).map_err(|e| WriteError {
469            context: ErrorContext::BuiltIn { for_type: "HashSet" },
470            kind: e.into(),
471        })?.write_sync(sink)?;
472        for elt in self {
473            elt.write_sync(sink)?;
474        }
475        Ok(())
476    }
477}
478
479/// A string is encoded in UTF-8 and prefixed with the length in bytes as a [`u64`].
480impl Protocol for String {
481    fn read<'a, R: AsyncRead + Unpin + Send + 'a>(stream: &'a mut R) -> Pin<Box<dyn Future<Output = Result<Self, ReadError>> + Send + 'a>> {
482        Box::pin(async move {
483            let len = u64::read(stream).await?;
484            let mut buf = Vec::default();
485            buf.try_resize(usize::try_from(len).map_err(|e| ReadError {
486                context: ErrorContext::BuiltIn { for_type: "String" },
487                kind: e.into(),
488            })?, 0).map_err(|e| ReadError {
489                context: ErrorContext::BuiltIn { for_type: "String" },
490                kind: e.into(),
491            })?;
492            stream.read_exact(&mut buf).await.map_err(|e| ReadError {
493                context: ErrorContext::BuiltIn { for_type: "String" },
494                kind: e.into(),
495            })?;
496            Ok(Self::from_utf8(buf).map_err(|e| ReadError {
497                context: ErrorContext::BuiltIn { for_type: "String" },
498                kind: e.into(),
499            })?)
500        })
501    }
502
503    fn write<'a, W: AsyncWrite + Unpin + Send + 'a>(&'a self, sink: &'a mut W) -> Pin<Box<dyn Future<Output = Result<(), WriteError>> + Send + 'a>> {
504        Box::pin(async move {
505            u64::try_from(self.len()).map_err(|e| WriteError {
506                context: ErrorContext::BuiltIn { for_type: "String" },
507                kind: e.into(),
508            })?.write(sink).await?;
509            sink.write(self.as_bytes()).await.map_err(|e| WriteError {
510                context: ErrorContext::BuiltIn { for_type: "String" },
511                kind: e.into(),
512            })?;
513            Ok(())
514        })
515    }
516
517    fn read_sync(stream: &mut impl Read) -> Result<Self, ReadError> {
518        let len = u64::read_sync(stream)?;
519        let mut buf = Vec::default();
520        buf.try_resize(usize::try_from(len).map_err(|e| ReadError {
521            context: ErrorContext::BuiltIn { for_type: "String" },
522            kind: e.into(),
523        })?, 0).map_err(|e| ReadError {
524            context: ErrorContext::BuiltIn { for_type: "String" },
525            kind: e.into(),
526        })?;
527        stream.read_exact(&mut buf).map_err(|e| ReadError {
528            context: ErrorContext::BuiltIn { for_type: "String" },
529            kind: e.into(),
530        })?;
531        Ok(Self::from_utf8(buf).map_err(|e| ReadError {
532            context: ErrorContext::BuiltIn { for_type: "String" },
533            kind: e.into(),
534        })?)
535    }
536
537    fn write_sync(&self, sink: &mut impl Write) -> Result<(), WriteError> {
538        u64::try_from(self.len()).map_err(|e| WriteError {
539            context: ErrorContext::BuiltIn { for_type: "String" },
540            kind: e.into(),
541        })?.write_sync(sink)?;
542        sink.write(self.as_bytes()).map_err(|e| WriteError {
543            context: ErrorContext::BuiltIn { for_type: "String" },
544            kind: e.into(),
545        })?;
546        Ok(())
547    }
548}
549
550/// A map is prefixed with the length as a [`u64`].
551impl<K: Protocol + Ord + Send + Sync + 'static, V: Protocol + Send + Sync + 'static> Protocol for BTreeMap<K, V> {
552    fn read<'a, R: AsyncRead + Unpin + Send + 'a>(stream: &'a mut R) -> Pin<Box<dyn Future<Output = Result<Self, ReadError>> + Send + 'a>> {
553        Box::pin(async move {
554            let len = u64::read(stream).await?;
555            usize::try_from(len).map_err(|e| ReadError {
556                context: ErrorContext::BuiltIn { for_type: "BTreeMap" },
557                kind: e.into(),
558            })?; // error here rather than panicking in the insert loop
559            let mut map = Self::default();
560            for _ in 0..len {
561                map.insert(K::read(stream).await?, V::read(stream).await?); //TODO use fallible allocation once available
562            }
563            Ok(map)
564        })
565    }
566
567    fn write<'a, W: AsyncWrite + Unpin + Send + 'a>(&'a self, sink: &'a mut W) -> Pin<Box<dyn Future<Output = Result<(), WriteError>> + Send + 'a>> {
568        Box::pin(async move {
569            u64::try_from(self.len()).map_err(|e| WriteError {
570                context: ErrorContext::BuiltIn { for_type: "BTreeMap" },
571                kind: e.into(),
572            })?.write(sink).await?;
573            for (k, v) in self {
574                k.write(sink).await?;
575                v.write(sink).await?;
576            }
577            Ok(())
578        })
579    }
580
581    fn read_sync(stream: &mut impl Read) -> Result<Self, ReadError> {
582        let len = u64::read_sync(stream)?;
583        usize::try_from(len).map_err(|e| ReadError {
584            context: ErrorContext::BuiltIn { for_type: "BTreeMap" },
585            kind: e.into(),
586        })?; // error here rather than panicking in the insert loop
587        let mut map = Self::default();
588        for _ in 0..len {
589            map.insert(K::read_sync(stream)?, V::read_sync(stream)?); //TODO use fallible allocation once available
590        }
591        Ok(map)
592    }
593
594    fn write_sync(&self, sink: &mut impl Write) -> Result<(), WriteError> {
595        u64::try_from(self.len()).map_err(|e| WriteError {
596            context: ErrorContext::BuiltIn { for_type: "BTreeMap" },
597            kind: e.into(),
598        })?.write_sync(sink)?;
599        for (k, v) in self {
600            k.write_sync(sink)?;
601            v.write_sync(sink)?;
602        }
603        Ok(())
604    }
605}
606
607/// A map is prefixed with the length as a [`u64`].
608impl<K: Protocol + Eq + Hash + Send + Sync, V: Protocol + Send + Sync> Protocol for HashMap<K, V> {
609    fn read<'a, R: AsyncRead + Unpin + Send + 'a>(stream: &'a mut R) -> Pin<Box<dyn Future<Output = Result<Self, ReadError>> + Send + 'a>> {
610        Box::pin(async move {
611            let len = u64::read(stream).await?;
612            let mut map = Self::with_capacity(usize::try_from(len).map_err(|e| ReadError {
613                context: ErrorContext::BuiltIn { for_type: "HashMap" },
614                kind: e.into(),
615            })?); //TODO use fallible allocation once available
616            for _ in 0..len {
617                map.insert(K::read(stream).await?, V::read(stream).await?);
618            }
619            Ok(map)
620        })
621    }
622
623    fn write<'a, W: AsyncWrite + Unpin + Send + 'a>(&'a self, sink: &'a mut W) -> Pin<Box<dyn Future<Output = Result<(), WriteError>> + Send + 'a>> {
624        Box::pin(async move {
625            u64::try_from(self.len()).map_err(|e| WriteError {
626                context: ErrorContext::BuiltIn { for_type: "HashMap" },
627                kind: e.into(),
628            })?.write(sink).await?;
629            for (k, v) in self {
630                k.write(sink).await?;
631                v.write(sink).await?;
632            }
633            Ok(())
634        })
635    }
636
637    fn read_sync(stream: &mut impl Read) -> Result<Self, ReadError> {
638        let len = u64::read_sync(stream)?;
639        let mut map = Self::with_capacity(usize::try_from(len).map_err(|e| ReadError {
640            context: ErrorContext::BuiltIn { for_type: "HashMap" },
641            kind: e.into(),
642        })?); //TODO use fallible allocation once available
643        for _ in 0..len {
644            map.insert(K::read_sync(stream)?, V::read_sync(stream)?);
645        }
646        Ok(map)
647    }
648
649    fn write_sync(&self, sink: &mut impl Write) -> Result<(), WriteError> {
650        u64::try_from(self.len()).map_err(|e| WriteError {
651            context: ErrorContext::BuiltIn { for_type: "HashMap" },
652            kind: e.into(),
653        })?.write_sync(sink)?;
654        for (k, v) in self {
655            k.write_sync(sink)?;
656            v.write_sync(sink)?;
657        }
658        Ok(())
659    }
660}
661
662/// A cow is represented like its owned variant.
663///
664/// Note that due to a restriction in the type system, writing a borrowed cow requires cloning it.
665impl<'cow, B: ToOwned + Sync + ?Sized> Protocol for std::borrow::Cow<'cow, B>
666where B::Owned: Protocol + Send + Sync {
667    fn read<'a, R: AsyncRead + Unpin + Send + 'a>(stream: &'a mut R) -> Pin<Box<dyn Future<Output = Result<Self, ReadError>> + Send + 'a>> {
668        Box::pin(async move {
669            Ok(Self::Owned(B::Owned::read(stream).await?))
670        })
671    }
672
673    fn write<'a, W: AsyncWrite + Unpin + Send + 'a>(&'a self, sink: &'a mut W) -> Pin<Box<dyn Future<Output = Result<(), WriteError>> + Send + 'a>> {
674        Box::pin(async move {
675            match self {
676                Self::Borrowed(borrowed) => (*borrowed).to_owned().write(sink).await?,
677                Self::Owned(owned) => owned.write(sink).await?,
678            }
679            Ok(())
680        })
681    }
682
683    fn read_sync(stream: &mut impl Read) -> Result<Self, ReadError> {
684        Ok(Self::Owned(B::Owned::read_sync(stream)?))
685    }
686
687    fn write_sync(&self, sink: &mut impl Write) -> Result<(), WriteError> {
688        match self {
689            Self::Borrowed(borrowed) => (*borrowed).to_owned().write_sync(sink)?,
690            Self::Owned(owned) => owned.write_sync(sink)?,
691        }
692        Ok(())
693    }
694}
695
696#[derive(Protocol)]
697#[async_proto(internal)]
698struct F32Proxy([u8; 4]);
699
700impl From<F32Proxy> for f32 {
701    fn from(F32Proxy(bytes): F32Proxy) -> Self {
702        Self::from_be_bytes(bytes)
703    }
704}
705
706impl<'a> From<&'a f32> for F32Proxy {
707    fn from(val: &f32) -> Self {
708        Self(val.to_be_bytes())
709    }
710}
711
712#[derive(Protocol)]
713#[async_proto(internal)]
714struct F64Proxy([u8; 8]);
715
716impl From<F64Proxy> for f64 {
717    fn from(F64Proxy(bytes): F64Proxy) -> Self {
718        Self::from_be_bytes(bytes)
719    }
720}
721
722impl<'a> From<&'a f64> for F64Proxy {
723    fn from(val: &f64) -> Self {
724        Self(val.to_be_bytes())
725    }
726}
727
728#[derive(Protocol)]
729#[async_proto(internal)]
730struct DurationProxy {
731    secs: u64,
732    subsec_nanos: u32,
733}
734
735impl From<DurationProxy> for std::time::Duration {
736    fn from(DurationProxy { secs, subsec_nanos }: DurationProxy) -> Self {
737        Self::new(secs, subsec_nanos)
738    }
739}
740
741impl<'a> From<&'a std::time::Duration> for DurationProxy {
742    fn from(duration: &std::time::Duration) -> Self {
743        Self {
744            secs: duration.as_secs(),
745            subsec_nanos: duration.subsec_nanos(),
746        }
747    }
748}
749
750impl_protocol_for! {
751    #[async_proto(attr(doc = "A nonzero integer is represented like its value."))]
752    #[async_proto(via = u8, clone, map_err = |_| ReadErrorKind::UnknownVariant8(0))]
753    type std::num::NonZeroU8;
754
755    #[async_proto(attr(doc = "A nonzero integer is represented like its value."))]
756    #[async_proto(via = i8, clone, map_err = |_| ReadErrorKind::UnknownVariant8(0))]
757    type std::num::NonZeroI8;
758
759    #[async_proto(attr(doc = "A nonzero integer is represented like its value."))]
760    #[async_proto(via = u16, clone, map_err = |_| ReadErrorKind::UnknownVariant16(0))]
761    type std::num::NonZeroU16;
762
763    #[async_proto(attr(doc = "A nonzero integer is represented like its value."))]
764    #[async_proto(via = i16, clone, map_err = |_| ReadErrorKind::UnknownVariant16(0))]
765    type std::num::NonZeroI16;
766
767    #[async_proto(attr(doc = "A nonzero integer is represented like its value."))]
768    #[async_proto(via = u32, clone, map_err = |_| ReadErrorKind::UnknownVariant32(0))]
769    type std::num::NonZeroU32;
770
771    #[async_proto(attr(doc = "A nonzero integer is represented like its value."))]
772    #[async_proto(via = i32, clone, map_err = |_| ReadErrorKind::UnknownVariant32(0))]
773    type std::num::NonZeroI32;
774
775    #[async_proto(attr(doc = "A nonzero integer is represented like its value."))]
776    #[async_proto(via = u64, clone, map_err = |_| ReadErrorKind::UnknownVariant64(0))]
777    type std::num::NonZeroU64;
778
779    #[async_proto(attr(doc = "A nonzero integer is represented like its value."))]
780    #[async_proto(via = i64, clone, map_err = |_| ReadErrorKind::UnknownVariant64(0))]
781    type std::num::NonZeroI64;
782
783    #[async_proto(attr(doc = "A nonzero integer is represented like its value."))]
784    #[async_proto(via = u128, clone, map_err = |_| ReadErrorKind::UnknownVariant128(0))]
785    type std::num::NonZeroU128;
786
787    #[async_proto(attr(doc = "A nonzero integer is represented like its value."))]
788    #[async_proto(via = i128, clone, map_err = |_| ReadErrorKind::UnknownVariant128(0))]
789    type std::num::NonZeroI128;
790
791    #[async_proto(attr(doc = "Primitive number types are encoded in [big-endian](https://en.wikipedia.org/wiki/Big-endian) format."))]
792    #[async_proto(via = F32Proxy)]
793    type f32;
794
795    #[async_proto(attr(doc = "Primitive number types are encoded in [big-endian](https://en.wikipedia.org/wiki/Big-endian) format."))]
796    #[async_proto(via = F64Proxy)]
797    type f64;
798
799    #[async_proto(where(Idx: Protocol + Send + Sync))]
800    struct Range<Idx> {
801        start: Idx,
802        end: Idx,
803    }
804
805    #[async_proto(where(Idx: Protocol + Sync))]
806    struct RangeFrom<Idx> {
807        start: Idx,
808    }
809
810    #[async_proto(where(Idx: Protocol + Sync))]
811    struct RangeTo<Idx> {
812        end: Idx,
813    }
814
815    #[async_proto(where(Idx: Protocol + Sync))]
816    struct RangeToInclusive<Idx> {
817        end: Idx,
818    }
819
820    #[async_proto(where(T: Protocol + Sync))]
821    enum Option<T> {
822        None,
823        Some(T),
824    }
825
826    #[async_proto(where(T: Protocol + Sync, E: Protocol + Sync))]
827    enum Result<T, E> {
828        Ok(T),
829        Err(E),
830    }
831
832    enum std::convert::Infallible {}
833
834    #[async_proto(where(T: Sync))]
835    struct std::marker::PhantomData<T>;
836
837    struct std::ops::RangeFull;
838
839    #[async_proto(attr(doc = "A duration is represented as the number of whole seconds as a [`u64`] followed by the number of subsecond nanoseconds as a [`u32`]."))]
840    #[async_proto(via = DurationProxy)]
841    type std::time::Duration;
842}