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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
pub use nom::IResult;
pub use cookie_factory::GenError;
use nom::number::streaming::{le_u8, le_u16};
use nom::{named, map, count};
use cookie_factory::{do_gen, gen_be_u8, gen_le_u16};
use std::net::{
IpAddr,
Ipv4Addr,
Ipv6Addr,
};
#[cfg(feature = "sodiumoxide")]
pub use sodium::*;
#[cfg(feature = "sodiumoxide")]
mod sodium;
pub trait FromBytes: Sized {
fn from_bytes(i: &[u8]) -> IResult<&[u8], Self>;
}
pub trait ToBytes: Sized {
fn to_bytes<'a>(&self, buf: (&'a mut [u8], usize)) -> Result<(&'a mut [u8], usize), GenError>;
}
impl ToBytes for IpAddr {
fn to_bytes<'a>(&self, buf: (&'a mut [u8], usize)) -> Result<(&'a mut [u8], usize), GenError> {
match *self {
IpAddr::V4(ref p) => p.to_bytes(buf),
IpAddr::V6(ref p) => p.to_bytes(buf),
}
}
}
impl FromBytes for Ipv4Addr {
named!(from_bytes<Ipv4Addr>, map!(count!(le_u8, 4),
|v| Ipv4Addr::new(v[0], v[1], v[2], v[3])
));
}
impl ToBytes for Ipv4Addr {
fn to_bytes<'a>(&self, buf: (&'a mut [u8], usize)) -> Result<(&'a mut [u8], usize), GenError> {
let o = self.octets();
do_gen!(buf,
gen_be_u8!(o[0]) >>
gen_be_u8!(o[1]) >>
gen_be_u8!(o[2]) >>
gen_be_u8!(o[3])
)
}
}
impl FromBytes for Ipv6Addr {
named!(from_bytes<Ipv6Addr>, map!(count!(le_u16, 8),
|v| Ipv6Addr::new(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7])
));
}
impl ToBytes for Ipv6Addr {
fn to_bytes<'a>(&self, buf: (&'a mut [u8], usize)) -> Result<(&'a mut [u8], usize), GenError> {
let s = self.segments();
do_gen!(buf,
gen_le_u16!(s[0]) >>
gen_le_u16!(s[1]) >>
gen_le_u16!(s[2]) >>
gen_le_u16!(s[3]) >>
gen_le_u16!(s[4]) >>
gen_le_u16!(s[5]) >>
gen_le_u16!(s[6]) >>
gen_le_u16!(s[7])
)
}
}
pub fn gen_len_limit(buf: (&mut [u8], usize), limit: usize) -> Result<(&mut [u8], usize), GenError> {
if buf.1 <= limit {
Ok(buf)
} else {
Err(GenError::BufferTooSmall(buf.1))
}
}
#[allow(clippy::needless_pass_by_value)]
pub fn gen_error(_buf: (&mut [u8], usize), error: u32) -> Result<(&mut [u8], usize), GenError> {
Err(GenError::CustomError(error))
}
#[macro_export]
macro_rules! encode_decode_test (
($init:expr, $test:ident, $value:expr) => (
#[test]
fn $test() {
$init;
let value = $value;
let mut buf = [0; 1024 * 1024];
let (_, size) = value.to_bytes((&mut buf, 0)).unwrap();
assert!(size <= 1024 * 1024);
let (rest, decoded_value) = FromBytes::from_bytes(&buf[..size]).unwrap();
fn infer<T>(_: &T, _: &T) { }
infer(&decoded_value, &value);
assert!(rest.is_empty());
assert_eq!(decoded_value, value);
}
)
);
#[macro_export]
macro_rules! unpack {
($variable:expr, $variant:path, $name:ident) => (
unpack!($variable, $variant { $name })
);
($variable:expr, $variant:path) => {
unpack!($variable, $variant[inner])
};
($variable:expr, $variant:path [ $($inner:ident),* ]) => (
match $variable {
$variant( $($inner),* ) => ( $($inner),* ),
other => panic!("Expected {} but got {:?}", stringify!($variant), other),
}
);
($variable:expr, $variant:path { $($inner:ident),* }) => (
match $variable {
$variant { $($inner,)* .. } => ( $($inner),* ),
other => panic!("Expected {} but got {:?}", stringify!($variant), other),
}
);
}