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