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