Skip to content

Commit 3966f79

Browse files
implemented decode for long, float and double, some refactoring
1 parent 4af58ce commit 3966f79

File tree

4 files changed

+253
-8
lines changed

4 files changed

+253
-8
lines changed

amqp-type/src/fixed_width/double.rs

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
use crate::serde::encode::{Encode, Encoded};
22
use std::hash::Hash;
33

4+
use crate::serde::decode::Decode;
5+
use crate::verify::verify_bytes_read_eq;
6+
use crate::error::AppError;
7+
8+
49
/// Crate assumes nothing about the values being passed to it.
5-
/// Any kind of f32 value is handled as is.
10+
/// Any kind of f64 value is handled as is.
611
/// This means that the hash function considers only the bytes of a float.
7-
/// Two f32 or f64 values are considered Equal if and only if, the entirety of their by sequences match.
12+
/// Two f64 or f64 values are considered Equal if and only if, the entirety of their by sequences match.
813
/// This ensures that no information is lost.
914
/// regardless of whether they mean Nan or similar things.
1015
/// As a result, Nan == Nan if and only if the two numbers have the exact same byte sequence.
1116
pub struct Double(f64);
1217

18+
const DEFAULT_CONSTR: u8 = 0x82;
19+
1320
impl Hash for Double {
1421
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1522
self.0.to_bits().hash(state)
@@ -39,13 +46,81 @@ impl From<f64> for Double {
3946
}
4047
}
4148

49+
50+
impl Decode for f64 {
51+
52+
fn can_decode(iter: impl Iterator<Item = u8>) -> bool {
53+
match iter.peekable().peek() {
54+
Some(&DEFAULT_CONSTR) => true,
55+
_ => false
56+
}
57+
}
58+
59+
fn try_decode(mut iter: impl Iterator<Item = u8>) -> Result<Self, crate::error::AppError>
60+
where
61+
Self: Sized {
62+
match iter.next() {
63+
Some(DEFAULT_CONSTR) => Ok(parse_f64(iter)?),
64+
Some(c) => Err(AppError::DeserializationIllegalConstructorError(c)),
65+
None => Err(AppError::IteratorEmptyOrTooShortError),
66+
}
67+
}
68+
}
69+
70+
fn parse_f64(iter: impl Iterator<Item = u8>) -> Result<f64, AppError> {
71+
let mut byte_vals = [0; 8];
72+
let mut index = 0;
73+
for b in iter.take(8) {
74+
byte_vals[index] = b;
75+
index += 1;
76+
}
77+
verify_bytes_read_eq(index, 8)?;
78+
Ok(f64::from_be_bytes(byte_vals))
79+
}
80+
81+
4282
#[cfg(test)]
4383
mod test {
4484

4585
use super::*;
86+
87+
4688
#[test]
4789
fn construct_double() {
4890
let val: Double = 64.0.into();
4991
assert_eq!(val.encode().constructor(), 0x82);
5092
}
51-
}
93+
94+
95+
#[test]
96+
fn can_deocde_returns_true_if_constructor_is_valid() {
97+
let val_norm = vec![0x82];
98+
assert_eq!(f64::can_decode(val_norm.into_iter()), true);
99+
}
100+
101+
#[test]
102+
fn can_decode_return_false_if_constructor_is_invalid() {
103+
let val = vec![0x75];
104+
assert_eq!(f64::can_decode(val.into_iter()), false);
105+
}
106+
107+
#[test]
108+
fn try_decode_returns_correct_value() {
109+
let val = vec![0x82, 0x40, 0x20, 0x00, 0x00, 0x41, 0x70,0x00, 0x10];
110+
assert_eq!(f64::try_decode(val.into_iter()).unwrap(), 8.0000019501895) ;
111+
}
112+
113+
#[test]
114+
fn try_decode_returns_error_when_value_bytes_are_invalid() {
115+
let val = vec![0x66, 0x44];
116+
assert!(f64::try_decode(val.into_iter()).is_err());
117+
}
118+
119+
#[test]
120+
fn try_decode_returns_error_when_bytes_are_missing() {
121+
let val = vec![0x82, 0x00, 0x01];
122+
assert!(f64::try_decode(val.into_iter()).is_err());
123+
}
124+
125+
126+
}

amqp-type/src/fixed_width/float.rs

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1-
use crate::serde::encode::{Encode, Encoded};
21
use std::hash::Hash;
2+
use crate::serde::encode::{Encode, Encoded};
3+
use crate::serde::decode::Decode;
4+
use crate::verify::verify_bytes_read_eq;
5+
use crate::error::AppError;
6+
7+
const DEFAULT_CONSTR: u8 = 0x72;
38

49
pub struct Float(f32);
510

11+
12+
613
impl Hash for Float {
714
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
815
self.0.to_bits().hash(state)
@@ -23,7 +30,7 @@ impl Eq for Float {}
2330

2431
impl Encode for Float {
2532
fn encode(&self) -> Encoded {
26-
Encoded::new_fixed(0x72, self.0.to_be_bytes().to_vec())
33+
Encoded::new_fixed(DEFAULT_CONSTR, self.0.to_be_bytes().to_vec())
2734
}
2835
}
2936

@@ -33,6 +40,38 @@ impl From<f32> for Float {
3340
}
3441
}
3542

43+
impl Decode for f32 {
44+
45+
fn can_decode(iter: impl Iterator<Item = u8>) -> bool {
46+
match iter.peekable().peek() {
47+
Some(&DEFAULT_CONSTR) => true,
48+
_ => false
49+
}
50+
}
51+
52+
fn try_decode(mut iter: impl Iterator<Item = u8>) -> Result<Self, crate::error::AppError>
53+
where
54+
Self: Sized {
55+
match iter.next() {
56+
Some(DEFAULT_CONSTR) => Ok(parse_f32(iter)?),
57+
Some(c) => Err(AppError::DeserializationIllegalConstructorError(c)),
58+
None => Err(AppError::IteratorEmptyOrTooShortError),
59+
}
60+
}
61+
}
62+
63+
fn parse_f32(iter: impl Iterator<Item = u8>) -> Result<f32, AppError> {
64+
let mut byte_vals = [0; 4];
65+
let mut index = 0;
66+
for b in iter.take(4) {
67+
byte_vals[index] = b;
68+
index += 1;
69+
}
70+
verify_bytes_read_eq(index, 4)?;
71+
Ok(f32::from_be_bytes(byte_vals))
72+
}
73+
74+
3675
#[cfg(test)]
3776
mod test {
3877

@@ -43,4 +82,37 @@ mod test {
4382
let val: Float = 32.0.into();
4483
assert_eq!(val.encode().constructor(), 0x72);
4584
}
46-
}
85+
86+
87+
#[test]
88+
fn can_deocde_returns_true_if_constructor_is_valid() {
89+
let val_norm = vec![0x72];
90+
assert_eq!(f32::can_decode(val_norm.into_iter()), true);
91+
}
92+
93+
#[test]
94+
fn can_decode_return_false_if_constructor_is_invalid() {
95+
let val = vec![0x75];
96+
assert_eq!(f32::can_decode(val.into_iter()), false);
97+
}
98+
99+
#[test]
100+
fn try_decode_returns_correct_value() {
101+
let val = vec![0x72, 0x41, 0x70,0x00, 0x10];
102+
assert_eq!(f32::try_decode(val.into_iter()).unwrap(), 15.000015) ;
103+
}
104+
105+
#[test]
106+
fn try_decode_returns_error_when_value_bytes_are_invalid() {
107+
let val = vec![0x66, 0x44];
108+
assert!(f32::try_decode(val.into_iter()).is_err());
109+
}
110+
111+
#[test]
112+
fn try_decode_returns_error_when_bytes_are_missing() {
113+
let val = vec![0x72, 0x00, 0x01];
114+
assert!(f32::try_decode(val.into_iter()).is_err());
115+
}
116+
117+
118+
}

amqp-type/src/fixed_width/long.rs

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
use crate::serde::encode::{Encode, Encoded};
2+
use crate::serde::decode::Decode;
3+
use crate::verify::verify_bytes_read_eq;
4+
use crate::error::AppError;
5+
6+
7+
const DEFAULT_CONSTR: u8 = 0x81;
8+
const SMALL_LONG_CONSTR: u8 = 0x55;
9+
210

311
impl Encode for i64 {
412
fn encode(&self) -> Encoded {
@@ -9,6 +17,52 @@ impl Encode for i64 {
917
}
1018
}
1119

20+
21+
impl Decode for i64 {
22+
23+
fn can_decode(iter: impl Iterator<Item = u8>) -> bool {
24+
match iter.peekable().peek() {
25+
Some(&DEFAULT_CONSTR) => true,
26+
Some(&SMALL_LONG_CONSTR) => true,
27+
_ => false
28+
}
29+
}
30+
31+
fn try_decode(mut iter: impl Iterator<Item = u8>) -> Result<Self, crate::error::AppError>
32+
where
33+
Self: Sized {
34+
match iter.next() {
35+
Some(DEFAULT_CONSTR) => Ok(parse_i64(iter)?),
36+
Some(SMALL_LONG_CONSTR) => Ok(parse_small_i64(iter)?),
37+
Some(c) => Err(AppError::DeserializationIllegalConstructorError(c)),
38+
None => Err(AppError::IteratorEmptyOrTooShortError),
39+
}
40+
}
41+
}
42+
43+
fn parse_i64(iter: impl Iterator<Item = u8>) -> Result<i64, AppError> {
44+
let mut byte_vals = [0; 8];
45+
let mut index = 0;
46+
for b in iter.take(8) {
47+
byte_vals[index] = b;
48+
index += 1;
49+
}
50+
verify_bytes_read_eq(index, 8)?;
51+
Ok(i64::from_be_bytes(byte_vals))
52+
}
53+
54+
fn parse_small_i64(mut iter: impl Iterator<Item = u8>) -> Result<i64, AppError> {
55+
if let Some(val) = iter.next() {
56+
Ok(val as i64)
57+
} else {
58+
Err(AppError::IteratorEmptyOrTooShortError)
59+
}
60+
}
61+
62+
63+
64+
65+
1266
#[cfg(test)]
1367
mod test {
1468

@@ -27,4 +81,48 @@ mod test {
2781
assert_eq!(lower.encode().constructor(), 0x55);
2882
assert_eq!(higher.encode().constructor(), 0x55);
2983
}
30-
}
84+
85+
#[test]
86+
fn can_deocde_returns_true_if_constructor_is_valid() {
87+
let val_norm = vec![0x81];
88+
let val_small = vec![0x55];
89+
assert_eq!(i64::can_decode(val_norm.into_iter()), true);
90+
assert_eq!(i64::can_decode(val_small.into_iter()), true);
91+
}
92+
93+
#[test]
94+
fn can_decode_return_false_if_constructor_is_invalid() {
95+
let val = vec![0x71];
96+
assert_eq!(i64::can_decode(val.into_iter()), false);
97+
}
98+
99+
#[test]
100+
fn try_decode_returns_correct_value() {
101+
let val = vec![0x81, 0x00, 0x00,0x00, 0x00, 0x00, 0x10, 0x00, 0x10];
102+
assert_eq!(i64::try_decode(val.into_iter()).unwrap(), 1048592) ;
103+
}
104+
105+
#[test]
106+
fn try_decode_returns_error_when_value_bytes_are_invalid() {
107+
let val = vec![0x66, 0x44];
108+
assert!(i64::try_decode(val.into_iter()).is_err());
109+
}
110+
111+
#[test]
112+
fn try_decode_returns_error_when_bytes_are_missing() {
113+
let val = vec![0x81, 0x00, 0x00, 0x01];
114+
assert!(i64::try_decode(val.into_iter()).is_err());
115+
}
116+
117+
#[test]
118+
fn try_decode_can_decode_smalli64_values() {
119+
let val = vec![0x55, 0xff];
120+
assert_eq!(i64::try_decode(val.into_iter()).unwrap(), 255);
121+
}
122+
123+
#[test]
124+
fn try_decode_returns_error_when_parsing_small_i64_and_bytes_are_missing() {
125+
let val = vec![0x55];
126+
assert!(i64::try_decode(val.into_iter()).is_err());
127+
}
128+
}

amqp-type/src/fixed_width/ulong.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ impl Decode for u64 {
4242
}
4343
}
4444

45-
fn parse_ulong(mut iter: impl Iterator<Item = u8>) -> Result<u64, AppError> {
45+
fn parse_ulong(iter: impl Iterator<Item = u8>) -> Result<u64, AppError> {
4646
let mut byte_vals = [0; 8];
4747
let mut index = 0;
4848
for b in iter.take(8) {

0 commit comments

Comments
 (0)