-
Notifications
You must be signed in to change notification settings - Fork 53
Expand file tree
/
Copy pathtry_convert.rs
More file actions
74 lines (64 loc) · 2.19 KB
/
try_convert.rs
File metadata and controls
74 lines (64 loc) · 2.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use crate::{
coder::{Decoder, View},
derive::Decode,
fast::{CowSlice, NextUnchecked, PushUnchecked, SliceImpl, Unaligned},
};
#[allow(unused)]
macro_rules! impl_try_convert {
($want: path, $have: ty) => {
impl_try_convert!($want, $have, $have);
};
($want: path, $have_encode: ty, $have_decode: ty) => {
impl crate::derive::Encode for $want {
type Encoder = crate::derive::convert::ConvertIntoEncoder<$have_encode>;
}
impl<'a> crate::derive::Decode<'a> for $want {
type Decoder =
crate::derive::try_convert::TryConvertFromDecoder<'a, $have_decode, $want>;
}
};
}
#[allow(unused)]
pub(crate) use impl_try_convert;
// Like [`TryFrom`] but we can implement it ourselves.
pub trait TryConvertFrom<T>: Sized {
fn try_convert_from(value: T) -> Result<Self, crate::Error>;
}
/// Decodes a `T` and then converts it with [`TryConvertFrom`].
pub struct TryConvertFromDecoder<'a, T: Decode<'a>, F: TryConvertFrom<T>> {
data: CowSlice<'a, F>,
decoder: T::Decoder,
}
// Can't derive since it would bound T: Default.
impl<'a, T: Decode<'a>, F: TryConvertFrom<T>> Default for TryConvertFromDecoder<'a, T, F> {
fn default() -> Self {
Self {
data: CowSlice::with_allocation(Vec::new()),
decoder: Default::default(),
}
}
}
impl<'a, T: Decode<'a>, F: TryConvertFrom<T>> View<'a> for TryConvertFromDecoder<'a, T, F> {
fn populate(&mut self, input: &mut &'a [u8], length: usize) -> Result<(), crate::Error> {
self.decoder.populate(input, length)?;
let out: &mut Vec<F> = &mut self.data.set_owned();
out.reserve(length);
for _ in 0..length {
let value = F::try_convert_from(self.decoder.decode())?;
unsafe { out.push_unchecked(value) };
}
Ok(())
}
}
impl<'a, T: Decode<'a>, F: TryConvertFrom<T> + Send + Sync + Copy> Decoder<'a, F>
for TryConvertFromDecoder<'a, T, F>
{
#[inline(always)]
fn as_primitive(&mut self) -> Option<&mut SliceImpl<'_, Unaligned<F>>> {
None
}
#[inline(always)]
fn decode(&mut self) -> F {
unsafe { self.data.mut_slice().next_unchecked() }
}
}