Skip to content

Commit 76fef58

Browse files
moved constructors to constants, implemented decode for ulong
1 parent 33a4b3e commit 76fef58

File tree

3 files changed

+127
-12
lines changed

3 files changed

+127
-12
lines changed

amqp-type/src/fixed_width/uint.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,27 @@ use crate::serde::decode::Decode;
33
use crate::serde::encode::{Encode, Encoded};
44
use crate::verify::verify_bytes_read_eq;
55

6+
7+
const DEFAULT_CONSTR: u8 = 0x70;
8+
const SMALL_UINT_CONSTR: u8 = 0x52;
9+
const UINT_0_CONSTR: u8 = 0x43;
10+
611
impl Encode for u32 {
712
fn encode(&self) -> Encoded {
813
match self {
9-
0 => Encoded::new_empty(0x43),
10-
x if x > &0 && x <= &255 => Encoded::new_fixed(0x52, x.to_be_bytes().to_vec()),
11-
_ => Encoded::new_fixed(0x70, self.to_be_bytes().to_vec()),
14+
0 => Encoded::new_empty(UINT_0_CONSTR),
15+
x if x > &0 && x <= &255 => Encoded::new_fixed(SMALL_UINT_CONSTR, x.to_be_bytes().to_vec()),
16+
_ => Encoded::new_fixed(DEFAULT_CONSTR, self.to_be_bytes().to_vec()),
1217
}
1318
}
1419
}
1520

1621
impl Decode for u32 {
1722
fn can_decode(iter: impl Iterator<Item = u8>) -> bool {
1823
match iter.peekable().peek() {
19-
Some(0x70) => true,
20-
Some(0x52) => true,
21-
Some(0x43) => true,
24+
Some(&DEFAULT_CONSTR) => true,
25+
Some(&SMALL_UINT_CONSTR) => true,
26+
Some(&UINT_0_CONSTR) => true,
2227
_ => false,
2328
}
2429
}
@@ -28,9 +33,9 @@ impl Decode for u32 {
2833
Self: Sized,
2934
{
3035
match iter.next() {
31-
Some(0x70) => Ok(parse_uint(iter)?),
32-
Some(0x52) => Ok(parse_small_uint(iter)?),
33-
Some(0x43) => Ok(0u32),
36+
Some(DEFAULT_CONSTR) => Ok(parse_uint(iter)?),
37+
Some(SMALL_UINT_CONSTR) => Ok(parse_small_uint(iter)?),
38+
Some(UINT_0_CONSTR) => Ok(0u32),
3439
Some(c) => Err(AppError::DeserializationIllegalConstructorError(c)),
3540
None => Err(AppError::IteratorEmptyOrTooShortError),
3641
}

amqp-type/src/fixed_width/ulong.rs

Lines changed: 106 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,66 @@
1+
use crate::error::AppError;
12
use crate::serde::encode::{Encode, Encoded};
3+
use crate::serde::decode::Decode;
4+
use crate::verify::verify_bytes_read_eq;
5+
6+
7+
const DEFAULT_CONSTR: u8 = 0x80;
8+
const SMALL_ULONG_CONSTR: u8 = 0x53;
9+
const ULONG_0_CONSTR: u8 = 0x44;
210

311
impl Encode for u64 {
412
fn encode(&self) -> Encoded {
513
match self {
6-
0 => Encoded::new_empty(0x44),
7-
x if x > &&0 && x <= &255 => Encoded::new_fixed(0x53, x.to_be_bytes().to_vec()),
8-
_ => Encoded::new_fixed(0x80, self.to_be_bytes().to_vec()),
14+
0 => Encoded::new_empty(ULONG_0_CONSTR),
15+
x if x > &&0 && x <= &255 => Encoded::new_fixed(SMALL_ULONG_CONSTR, x.to_be_bytes().to_vec()),
16+
_ => Encoded::new_fixed(DEFAULT_CONSTR, self.to_be_bytes().to_vec()),
17+
}
18+
}
19+
}
20+
21+
impl Decode for u64 {
22+
23+
fn can_decode(iter: impl Iterator<Item = u8>) -> bool {
24+
match iter.peekable().peek() {
25+
Some(&DEFAULT_CONSTR) => true,
26+
Some(&SMALL_ULONG_CONSTR) => true,
27+
Some(&ULONG_0_CONSTR) => true,
28+
_ => false
29+
}
30+
}
31+
32+
fn try_decode(mut iter: impl Iterator<Item = u8>) -> Result<Self, crate::error::AppError>
33+
where
34+
Self: Sized {
35+
match iter.next() {
36+
Some(DEFAULT_CONSTR) => Ok(parse_ulong(iter)?),
37+
Some(SMALL_ULONG_CONSTR) => Ok(parse_small_ulong(iter)?),
38+
Some(ULONG_0_CONSTR) => Ok(0),
39+
Some(c) => Err(AppError::DeserializationIllegalConstructorError(c)),
40+
None => Err(AppError::IteratorEmptyOrTooShortError),
941
}
1042
}
1143
}
1244

45+
fn parse_ulong(mut iter: impl Iterator<Item = u8>) -> Result<u64, AppError> {
46+
let mut byte_vals = [0; 8];
47+
let mut index = 0;
48+
for b in iter.take(8) {
49+
byte_vals[index] = b;
50+
index += 1;
51+
}
52+
verify_bytes_read_eq(index, 8)?;
53+
Ok(u64::from_be_bytes(byte_vals))
54+
}
55+
56+
fn parse_small_ulong(mut iter: impl Iterator<Item = u8>) -> Result<u64, AppError> {
57+
if let Some(val) = iter.next() {
58+
Ok(val as u64)
59+
} else {
60+
Err(AppError::IteratorEmptyOrTooShortError)
61+
}
62+
}
63+
1364
#[cfg(test)]
1465
mod test {
1566

@@ -32,4 +83,56 @@ mod test {
3283
let val: u64 = 0;
3384
assert_eq!(val.encode().constructor(), 0x44);
3485
}
86+
87+
#[test]
88+
fn can_deocde_returns_true_if_constructor_is_valid() {
89+
let val_norm = vec![0x80];
90+
let val_small = vec![0x53];
91+
let val_zero = vec![0x44];
92+
assert_eq!(u64::can_decode(val_norm.into_iter()), true);
93+
assert_eq!(u64::can_decode(val_small.into_iter()), true);
94+
assert_eq!(u64::can_decode(val_zero.into_iter()), true);
95+
}
96+
97+
#[test]
98+
fn can_decode_return_false_if_constructor_is_invalid() {
99+
let val = vec![0x71];
100+
assert_eq!(u64::can_decode(val.into_iter()), false);
101+
}
102+
103+
#[test]
104+
fn try_decode_returns_correct_value() {
105+
let val = vec![0x80, 0x01, 0x01,0x11, 0x10, 0x10, 0x00, 0x00, 0x10];
106+
assert_eq!(u64::try_decode(val.into_iter()).unwrap(), 72357829700222992);
107+
}
108+
109+
#[test]
110+
fn decode_returns_error_when_value_bytes_are_invalid() {
111+
let val = vec![0x66, 0x44];
112+
assert!(u64::try_decode(val.into_iter()).is_err());
113+
}
114+
115+
#[test]
116+
fn decode_returns_error_when_bytes_are_missing() {
117+
let val = vec![0x70, 0x00, 0x00, 0x01];
118+
assert!(u64::try_decode(val.into_iter()).is_err());
119+
}
120+
121+
#[test]
122+
fn try_decode_can_decode_zero_length_value_zero() {
123+
let val = vec![0x44];
124+
assert_eq!(u64::try_decode(val.into_iter()).unwrap(), 0);
125+
}
126+
127+
#[test]
128+
fn try_decode_can_decode_smallulong_values() {
129+
let val = vec![0x53, 0xff];
130+
assert_eq!(u64::try_decode(val.into_iter()).unwrap(), 255);
131+
}
132+
133+
#[test]
134+
fn try_decode_returns_error_when_parsing_small_ulong_and_bytes_are_missing() {
135+
let val = vec![0x53];
136+
assert!(u64::try_decode(val.into_iter()).is_err());
137+
}
35138
}

amqp-type/src/serde/decode.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,14 @@ use crate::error::AppError;
44
pub struct Constructor(u8);
55

66
pub trait Decode {
7+
/// This function determines if an implementor can decode itself from the current position in the iterator
8+
/// by checking whether the next byte in the iterator is a valid constructor for this type.
9+
/// TODO: make this function async
710
fn can_decode(iter: impl Iterator<Item = u8>) -> bool;
11+
12+
/// Tries to decode the implementing type from the byte iterator. this advances the iterator until the
13+
/// type and its value are completely decoded.
14+
/// TODO: Make this function async
815
fn try_decode(iter: impl Iterator<Item = u8>) -> Result<Self, AppError>
916
where
1017
Self: Sized;

0 commit comments

Comments
 (0)