sheave_core/messages/amf/v0/
number.rs

1use std::{
2    cmp::Ordering,
3    fmt::{
4        Display,
5        Formatter,
6        Result as FormatResult
7    },
8    io::Result as IOResult,
9    ops::{
10        Add,
11        AddAssign,
12        Div
13    }
14};
15use super::{
16    Marker,
17    super::ensure_marker
18};
19use crate::{
20    Decoder,
21    Encoder,
22    ByteBuffer
23};
24
25/// The IEEE 754 double precision floating point number of AMF data types.
26#[derive(Debug, Clone, Copy, Default, PartialEq, PartialOrd)]
27pub struct Number(f64);
28
29impl Number {
30    /// Constructs an AMF's Number.
31    pub fn new(number: f64) -> Self {
32        Self(number)
33    }
34
35    /// Gets an inner value as an integer.
36    /// This is prepared for converting any message ID to an integer from an AMF's number.
37    pub fn as_integer(&self) -> u64 {
38        self.0 as u64
39    }
40
41    pub fn as_signed_integer(&self) -> i64 {
42        self.0 as i64
43    }
44}
45
46impl From<bool> for Number {
47    fn from(number: bool) -> Self {
48        Self(number.into())
49    }
50}
51
52impl From<f32> for Number {
53    fn from(number: f32) -> Self {
54        Self(number.into())
55    }
56}
57
58impl From<i8> for Number {
59    fn from(number: i8) -> Self {
60        Self(number.into())
61    }
62}
63
64impl From<i16> for Number {
65    fn from(number: i16) -> Self {
66        Self(number.into())
67    }
68}
69
70impl From<i32> for Number {
71    fn from(number: i32) -> Self {
72        Self(number.into())
73    }
74}
75
76impl From<u8> for Number {
77    fn from(number: u8) -> Self {
78        Self(number.into())
79    }
80}
81
82impl From<u16> for Number {
83    fn from(number: u16) -> Self {
84        Self(number.into())
85    }
86}
87
88impl From<u32> for Number {
89    fn from(number: u32) -> Self {
90        Self(number.into())
91    }
92}
93
94impl Display for Number {
95    fn fmt(&self, f: &mut Formatter<'_>) -> FormatResult {
96        writeln!(f, "{}", self.0)
97    }
98}
99
100impl PartialEq<f64> for Number {
101    fn eq(&self, other: &f64) -> bool {
102        self.0.eq(other)
103    }
104}
105
106impl PartialOrd<f64> for Number {
107    fn partial_cmp(&self, other: &f64) -> Option<Ordering> {
108        self.0.partial_cmp(other)
109    }
110}
111
112impl PartialEq<Number> for f64 {
113    fn eq(&self, other: &Number) -> bool {
114        self.eq(&other.0)
115    }
116}
117
118impl PartialOrd<Number> for f64 {
119    fn partial_cmp(&self, other: &Number) -> Option<Ordering> {
120        self.partial_cmp(&other.0)
121    }
122}
123
124impl Add for Number {
125    type Output = Number;
126
127    fn add(self, rhs: Self) -> Self::Output {
128        Number(self.0 + rhs.0)
129    }
130}
131
132impl Add<f64> for Number {
133    type Output = Number;
134
135    fn add(self, rhs: f64) -> Self::Output {
136        Number(self.0 + rhs)
137    }
138}
139
140impl AddAssign for Number {
141    fn add_assign(&mut self, rhs: Self) {
142        self.0 += rhs.0;
143    }
144}
145
146impl AddAssign<f64> for Number {
147    fn add_assign(&mut self, rhs: f64) {
148        self.0 += rhs;
149    }
150}
151
152impl Div for Number {
153    type Output = Self;
154
155    fn div(self, rhs: Self) -> Self::Output {
156        Self(self.0 / rhs.0)
157    }
158}
159
160impl Div<f64> for Number {
161    type Output = Self;
162
163    fn div(self, rhs: f64) -> Self::Output {
164        Self(self.0 / rhs)
165    }
166}
167
168impl Decoder<Number> for ByteBuffer {
169    /// Decodes bytes into an AMF's Number.
170    ///
171    /// # Errors
172    ///
173    /// * [`InsufficientBufferLength`]
174    ///
175    /// When buffer isn't remained at least 9 bytes.
176    ///
177    /// * [`InconsistentMarker`]
178    ///
179    /// When a marker byte doesn't indicate the AMF Number.
180    ///
181    /// # Examples
182    ///
183    /// ```rust
184    /// use rand::random;
185    /// use sheave_core::{
186    ///     ByteBuffer,
187    ///     Decoder,
188    ///     messages::amf::v0::{
189    ///         Marker,
190    ///         Number
191    ///     }
192    /// };
193    ///
194    /// let mut buffer = ByteBuffer::default();
195    /// buffer.put_u8(Marker::Number as u8);
196    /// buffer.put_f64(f64::from_bits(random::<u64>()));
197    /// assert!(Decoder::<Number>::decode(&mut buffer).is_ok());
198    ///
199    /// let mut buffer = ByteBuffer::default();
200    /// buffer.put_u8(Marker::Boolean as u8);
201    /// buffer.put_f64(f64::from_bits(random::<u64>()));
202    /// assert!(Decoder::<Number>::decode(&mut buffer).is_err());
203    ///
204    /// let mut buffer = ByteBuffer::default();
205    /// assert!(Decoder::<Number>::decode(&mut buffer).is_err())
206    /// ```
207    ///
208    /// [`InsufficientBufferLength`]: crate::byte_buffer::InsufficientBufferLength
209    /// [`InconsistentMarker`]: crate::messages::amf::InconsistentMarker
210    fn decode(&mut self) -> IOResult<Number> {
211        self.get_u8().and_then(
212            |marker| ensure_marker(Marker::Number as u8, marker)
213        )?;
214
215        self.get_f64().map(Number::new)
216    }
217}
218
219impl Encoder<Number> for ByteBuffer {
220    /// Encodes an AMF's Number into bytes.
221    fn encode(&mut self, n: &Number) {
222        self.put_u8(Marker::Number as u8);
223        self.put_f64(n.0);
224    }
225}
226
227#[cfg(test)]
228mod tests {
229    use super::*;
230
231    #[test]
232    fn decode_number() {
233        let mut buffer = ByteBuffer::default();
234        buffer.put_u8(Marker::Number as u8);
235        buffer.put_f64(1f64);
236        let result: IOResult<Number> = buffer.decode();
237        assert!(result.is_ok());
238        let number = result.unwrap();
239        assert_eq!(1f64, number)
240    }
241
242    #[test]
243    fn encode_number() {
244        let mut buffer = ByteBuffer::default();
245        buffer.encode(&Number::new(1f64));
246        let result: Vec<u8> = buffer.into();
247        assert_eq!(Marker::Number as u8, result[0]);
248        assert_eq!(&1f64.to_be_bytes(), &result[1..])
249    }
250}