sheave_core/messages/amf/
v0.rs

1//! # The AMF Data Types (version 0).
2//!
3//! These are data types which are defined in the Action Message Format version 0 specification.
4//! Currently the RTMP uses following types:
5//!
6//! |Marker|AMF Data Type|Description|
7//! | -: | :- | :- |
8//! |`0`|[`Number`]|The IEEE 754 double precision floating point number.|
9//! |`1`|`Boolean`|The boolean that is represented as a 1 byte data. (C-like)|
10//! |`2`|[`AmfString`]|The string that is limited its length the range of 2 bytes.|
11//! |`3`|[`Object`]|The key/value-paired object that its value type is flexible.|
12//! |`5`|[`Null`]|Only the marker. Any value doesn't contain.|
13//! |`8`|[`EcmaArray`]|Same as the [`Object`] except this has its length.|
14//! |`9`|Object End|Indicates a stream of object terminaites there.|
15//!
16//! These are checked whether matched its marker with an actual data, by the receiver-side.
17//! Therefore any stream which contains any unmatched marker will be considered it's invalid.
18//! Note that a marker of the Object End must appear only in AMF's Object.
19//! Following descriptions are the actual formats of AMF.
20//!
21//! ## [`Number`]
22//!
23//! 1. [`Marker`] (1 byte)
24//! 2. An IEEE 754 double precision value (8 bytes)
25//!
26//! ## [`Boolean`]
27//!
28//! 1. [`Marker`] (1 byte)
29//! 2. A boolean value (1 byte)
30//!
31//! ## [`String`]
32//!
33//! 1. [`Marker`] (1 byte)
34//! 2. Length (2 bytes)
35//! 3. UTF-8 characters (variable)
36//!
37//! ## [`Object`]
38//!
39//! 1. [`Marker`] (1 byte)
40//! 2. Arbitrary number key-value pairs (variable)
41//! 3. The Object End marker that is associated with an empty string.
42//!
43//! Note keys are without markers of the AMF String.
44//! To be exact, these aren't defined as the AMF String in the specification, that is, these are just strings with lengths (within 2 bytes) at the beginning.
45//!
46//! Next, values are limited just in the AMF data types.
47//! Currently, following AMF data types to be used in the RTMP are allowed to insert into the AMF Object type:
48//!
49//! * [`Number`]
50//! * [`Boolean`]
51//! * [`AmfString`]
52//! * [`Object`]
53//! * [`Null`]
54//! * [`EcmaArray`]
55//!
56//! ## [`Null`]
57//!
58//! 1. [`Marker`] (1 byte)
59//!
60//! ## [`EcmaArray`]
61//!
62//! 1. [`Marker`] (1 byte)
63//! 2. Length (4 bytes)
64//! 3. Arbitrary number key-value pairs (variable)
65//! 4. The Object End marker that is associated with an empty string.
66//!
67//! [`Marker`]: Marker
68//! [`Number`]: Number
69//! [`Boolean`]: Boolean
70//! [`AmfString`]: AmfString
71//! [`Object`]: Object
72//! [`Null`]: Null
73//! [`EcmaArray`]: EcmaArray
74
75mod number;
76mod boolean;
77mod string;
78mod object;
79mod null;
80mod ecma_array;
81
82use std::{
83    alloc::{
84        GlobalAlloc,
85        Layout,
86        System
87    },
88    borrow::Cow,
89    collections::HashMap,
90    fmt::{
91        Debug,
92        Formatter,
93        Result as FormatResult
94    },
95    io::Result as IOResult,
96    ops::{
97        Deref,
98        DerefMut,
99        Index
100    },
101    sync::Arc
102};
103use crate::{
104    Decoder,
105    Encoder,
106    ByteBuffer,
107    messages::amf::{
108        ensure_marker,
109        invalid_string
110    }
111};
112pub use self::{
113    number::Number,
114    boolean::Boolean,
115    string::AmfString,
116    object::Object,
117    null::Null,
118    ecma_array::EcmaArray
119};
120
121/// Representation of markers of the AMF data types.
122///
123/// Variants correspond to respectively following numbers:
124///
125/// |Pattern|Number|
126/// | :- | :- |
127/// |`Number`|`0`|
128/// |`Boolean`|`1`|
129/// |`AmfString`|`2`|
130/// |`Object`|`3`|
131/// |`Null`|`5`|
132/// |`EcmaArray`|`8`|
133/// |`ObjectEnd`|`9`|
134/// |`Other`|other numbers|
135///
136#[repr(u8)]
137#[derive(Debug, Clone, Copy, PartialEq, Eq)]
138pub enum Marker {
139    Number,
140    Boolean,
141    AmfString,
142    Object,
143    Null = 0x05,
144    EcmaArray = 0x08,
145    ObjectEnd = 0x09,
146    Other = 0xff
147}
148
149impl From<u8> for Marker {
150    fn from(marker: u8) -> Self {
151        use Marker::*;
152
153        match marker {
154            0 => Number,
155            1 => Boolean,
156            2 => AmfString,
157            3 => Object,
158            5 => Null,
159            8 => EcmaArray,
160            9 => ObjectEnd,
161            _ => Other
162        }
163    }
164}
165
166impl From<Marker> for u8 {
167    fn from(marker: Marker) -> Self {
168        marker as u8
169    }
170}
171
172#[doc(hidden)]
173#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
174pub struct UnmarkedString(String);
175
176#[doc(hidden)]
177impl UnmarkedString {
178    pub(self) fn new(key: String) -> Self {
179        Self(key)
180    }
181}
182
183#[doc(hidden)]
184impl Deref for UnmarkedString {
185    type Target = String;
186
187    fn deref(&self) -> &Self::Target {
188        &self.0
189    }
190}
191
192#[doc(hidden)]
193impl DerefMut for UnmarkedString {
194    fn deref_mut(&mut self) -> &mut Self::Target {
195        &mut self.0
196    }
197}
198
199#[doc(hidden)]
200impl<'a> PartialEq<&'a str> for UnmarkedString {
201    fn eq(&self, other: &&'a str) -> bool {
202        self.0.eq(other)
203    }
204}
205
206#[doc(hidden)]
207impl<'a> PartialEq<Cow<'a, str>> for UnmarkedString {
208    fn eq(&self, other: &Cow<'a, str>) -> bool {
209        self.0.eq(other)
210    }
211}
212
213#[doc(hidden)]
214impl<'a> PartialEq<UnmarkedString> for &'a str {
215    fn eq(&self, other: &UnmarkedString) -> bool {
216        self.eq(&other.0)
217    }
218}
219
220#[doc(hidden)]
221impl<'a> PartialEq<UnmarkedString> for Cow<'a, str> {
222    fn eq(&self, other: &UnmarkedString) -> bool {
223        self.eq(&other.0)
224    }
225}
226
227#[doc(hidden)]
228impl PartialEq<UnmarkedString> for str {
229    fn eq(&self, other: &UnmarkedString) -> bool {
230        self.eq(&other.0)
231    }
232}
233
234#[doc(hidden)]
235impl PartialEq<String> for UnmarkedString {
236    fn eq(&self, other: &String) -> bool {
237        self.0.eq(other)
238    }
239}
240
241#[doc(hidden)]
242impl PartialEq<UnmarkedString> for String {
243    fn eq(&self, other: &UnmarkedString) -> bool {
244        self.eq(&other.0)
245    }
246}
247
248#[doc(hidden)]
249impl From<&str> for UnmarkedString {
250    fn from(s: &str) -> Self {
251        Self(s.into())
252    }
253}
254
255#[doc(hidden)]
256impl Decoder<UnmarkedString> for ByteBuffer {
257    fn decode(&mut self) -> IOResult<UnmarkedString> {
258        let len = self.get_u16_be()? as usize;
259        if len == 0 {
260            return Ok("".into())
261        }
262        let bytes = self.get_bytes(len)?;
263        String::from_utf8(bytes.to_vec()).map(UnmarkedString::new).map_err(invalid_string)
264    }
265}
266
267#[doc(hidden)]
268impl Encoder<UnmarkedString> for ByteBuffer {
269    fn encode(&mut self, string: &UnmarkedString) {
270        assert!(string.len() <= u16::MAX as usize);
271        self.put_u16_be(string.len() as u16);
272        self.put_bytes(string.as_bytes());
273    }
274}
275
276#[doc(hidden)]
277pub struct Value {
278    layout: Layout,
279    ptr: *mut u8,
280    marker: Marker
281}
282
283#[doc(hidden)]
284impl Value {
285    fn as_number(&self) -> &Number {
286        unsafe {
287            assert_eq!(Marker::Number, self.marker);
288            &*self.ptr.cast::<Number>()
289        }
290    }
291
292    fn as_boolean(&self) -> &Boolean {
293        unsafe {
294            assert_eq!(Marker::Boolean, self.marker);
295            &*self.ptr.cast::<Boolean>()
296        }
297    }
298
299    fn as_string(&self) -> &AmfString {
300        unsafe {
301            assert_eq!(Marker::AmfString, self.marker);
302            &*self.ptr.cast::<AmfString>()
303        }
304    }
305
306    fn as_null(&self) -> &Null {
307        unsafe {
308            assert_eq!(Marker::Null, self.marker);
309            &*self.ptr.cast::<Null>()
310        }
311    }
312
313    fn as_object(&self) -> &Object {
314        unsafe {
315            assert_eq!(Marker::Object, self.marker);
316            &*self.ptr.cast::<Object>()
317        }
318    }
319
320    fn as_ecma_array(&self) -> &EcmaArray {
321        unsafe {
322            assert_eq!(Marker::EcmaArray, self.marker);
323            &*self.ptr.cast::<EcmaArray>()
324        }
325    }
326}
327
328#[doc(hidden)]
329impl From<Number> for Value {
330    fn from(value: Number) -> Self {
331        unsafe {
332            let layout = Layout::new::<Number>();
333            let ptr = System.alloc(layout);
334            ptr.cast::<Number>().write(value);
335            Self {
336                layout,
337                ptr,
338                marker: Marker::Number
339            }
340        }
341    }
342}
343
344#[doc(hidden)]
345impl<'a> From<&'a Value> for &'a Number {
346    fn from(value: &'a Value) -> Self {
347        value.as_number()
348    }
349}
350
351#[doc(hidden)]
352impl From<Boolean> for Value {
353    fn from(value: Boolean) -> Self {
354        unsafe {
355            let layout = Layout::new::<Boolean>();
356            let ptr = System.alloc(layout);
357            ptr.cast::<Boolean>().write(value);
358            Self {
359                layout,
360                ptr,
361                marker: Marker::Boolean
362            }
363        }
364    }
365}
366
367#[doc(hidden)]
368impl From<AmfString> for Value {
369    fn from(value: AmfString) -> Self {
370        unsafe {
371            let layout = Layout::new::<AmfString>();
372            let ptr = System.alloc(layout);
373            ptr.cast::<AmfString>().write(value);
374            Self {
375                layout,
376                ptr,
377                marker: Marker::AmfString
378            }
379        }
380    }
381}
382
383#[doc(hidden)]
384impl<'a> From<&'a Value> for &'a AmfString {
385    fn from(value: &'a Value) -> Self {
386        value.as_string()
387    }
388}
389
390#[doc(hidden)]
391impl From<Null> for Value {
392    fn from(value: Null) -> Self {
393        unsafe {
394            let layout = Layout::new::<Null>();
395            let ptr = System.alloc(layout);
396            ptr.cast::<Null>().write(value);
397            Self {
398                layout,
399                ptr,
400                marker: Marker::Null
401            }
402        }
403    }
404}
405
406#[doc(hidden)]
407impl From<Object> for Value {
408    fn from(value: Object) -> Self {
409        unsafe {
410            let layout = Layout::new::<Object>();
411            let ptr = System.alloc(layout);
412            ptr.cast::<Object>().write(value);
413            Self {
414                layout,
415                ptr,
416                marker: Marker::Object
417            }
418        }
419    }
420}
421
422#[doc(hidden)]
423impl From<EcmaArray> for Value {
424    fn from(value: EcmaArray) -> Self {
425        unsafe {
426            let layout = Layout::new::<EcmaArray>();
427            let ptr = System.alloc(layout);
428            ptr.cast::<EcmaArray>().write(value);
429            Self {
430                layout,
431                ptr,
432                marker: Marker::EcmaArray
433            }
434        }
435    }
436}
437
438#[doc(hidden)]
439impl Drop for Value {
440    fn drop(&mut self) {
441        unsafe {
442            System.dealloc(self.ptr, self.layout);
443        }
444    }
445}
446
447#[doc(hidden)]
448impl Debug for Value {
449    fn fmt(&self, f: &mut Formatter<'_>) -> FormatResult {
450        match self.marker {
451            Marker::Number => Debug::fmt(self.as_number(), f),
452            Marker::Boolean => Debug::fmt(self.as_boolean(), f),
453            Marker::AmfString => Debug::fmt(self.as_string(), f),
454            Marker::Null => Debug::fmt(self.as_null(), f),
455            Marker::Object => Debug::fmt(self.as_object(), f),
456            Marker::EcmaArray => Debug::fmt(self.as_ecma_array(), f),
457            _ => unimplemented!("Debugging other types.")
458        }
459    }
460}
461
462#[doc(hidden)]
463impl PartialEq<Self> for Value {
464    fn eq(&self, other: &Self) -> bool {
465        if self.marker != other.marker {
466            false
467        } else {
468            match self.marker {
469                Marker::Number => PartialEq::eq(self.as_number(), other.as_number()),
470                Marker::Boolean => PartialEq::eq(self.as_boolean(), other.as_boolean()),
471                Marker::AmfString => PartialEq::eq(self.as_string(), other.as_string()),
472                Marker::Null => PartialEq::eq(self.as_null(), other.as_null()),
473                Marker::Object => PartialEq::eq(self.as_object(), other.as_object()),
474                Marker::EcmaArray => PartialEq::eq(self.as_ecma_array(), other.as_ecma_array()),
475                _ => unimplemented!("Comparing other types.")
476            }
477        }
478    }
479}
480
481#[doc(hidden)]
482impl<T: Into<Value> + Clone> PartialEq<T> for Value {
483    fn eq(&self, other: &T) -> bool {
484        let value: Self = other.clone().into();
485        self.eq(&value)
486    }
487}
488
489#[doc(hidden)]
490impl Eq for Value {}
491#[doc(hidden)]
492unsafe impl Send for Value {}
493#[doc(hidden)]
494unsafe impl Sync for Value {}
495
496#[doc(hidden)]
497impl Decoder<Value> for ByteBuffer {
498    fn decode(&mut self) -> IOResult<Value> {
499        let marker: Marker = self.peek_u8()?.into();
500
501        match marker {
502            Marker::Number => Decoder::<Number>::decode(self).map(Value::from),
503            Marker::Boolean => Decoder::<Boolean>::decode(self).map(Value::from),
504            Marker::AmfString => Decoder::<AmfString>::decode(self).map(Value::from),
505            Marker::Null => Decoder::<Null>::decode(self).map(Value::from),
506            Marker::Object => Decoder::<Object>::decode(self).map(Value::from),
507            Marker::EcmaArray => Decoder::<EcmaArray>::decode(self).map(Value::from),
508            _ => unimplemented!("Decoding other types.")
509        }
510    }
511}
512
513#[doc(hidden)]
514impl Encoder<Value> for ByteBuffer {
515    fn encode(&mut self, value: &Value) {
516        match value.marker {
517            Marker::Number => self.encode(value.as_number()),
518            Marker::Boolean => self.encode(value.as_boolean()),
519            Marker::AmfString => self.encode(value.as_string()),
520            Marker::Null => self.encode(value.as_null()),
521            Marker::Object => self.encode(value.as_object()),
522            Marker::EcmaArray => self.encode(value.as_ecma_array()),
523            _ => unimplemented!("Encoding other types.")
524        }
525    }
526}
527
528#[doc(hidden)]
529#[derive(Debug, Clone, Default, PartialEq, Eq)]
530pub struct Properties(HashMap<UnmarkedString, Arc<Value>>);
531
532#[doc(hidden)]
533impl Properties {
534    pub fn insert<V: Into<Value>>(&mut self, key: &str, value: V) {
535        self.0.insert(key.into(), Arc::new(value.into()));
536    }
537
538    pub fn get(&self, key: &str) -> Option<&Value> {
539        self.0.get(&key.into()).map(|value| &**value)
540    }
541
542    pub fn len(&self) -> usize {
543        self.0.len()
544    }
545}
546
547#[doc(hidden)]
548impl Index<&str> for Properties {
549    type Output = Value;
550
551    fn index(&self, key: &str) -> &Self::Output {
552        &**self.0.index(&key.into())
553    }
554}
555
556#[doc(hidden)]
557impl Decoder<Properties> for ByteBuffer {
558    fn decode(&mut self) -> IOResult<Properties> {
559        let mut m: HashMap<UnmarkedString, Arc<Value>> = HashMap::new();
560        loop {
561            let key: UnmarkedString = self.decode()?;
562
563            if key == "" {
564                self.get_u8().and_then(
565                    |marker| ensure_marker(Marker::ObjectEnd as u8, marker)
566                )?;
567
568                return Ok(Properties(m))
569            } else {
570                let value: Value = self.decode()?;
571                m.insert(key, Arc::new(value));
572            }
573        }
574    }
575}
576
577#[doc(hidden)]
578impl Encoder<Properties> for ByteBuffer {
579    fn encode(&mut self, properties: &Properties) {
580        for (k, v) in &properties.0 {
581            self.encode(k);
582            self.encode(&**v);
583        }
584        self.encode(&UnmarkedString::from(""));
585        self.put_u8(Marker::ObjectEnd as u8);
586    }
587}
588
589#[cfg(test)]
590mod tests {
591    use super::*;
592
593    #[test]
594    fn number_value() {
595        let number = Number::new(0f64);
596        let allocated = Value::from(number);
597        assert_eq!(number, *allocated.as_number())
598    }
599
600    #[test]
601    fn boolean_value() {
602        let boolean = Boolean::new(0u8);
603        let allocated = Value::from(boolean);
604        assert_eq!(boolean, *allocated.as_boolean())
605    }
606
607    #[test]
608    fn string_value() {
609        let string = AmfString::new("".into());
610        let allocated = Value::from(string.clone());
611        assert_eq!(string, *allocated.as_string())
612    }
613
614    #[test]
615    fn null_value() {
616        let null = Null;
617        let allocated = Value::from(null);
618        assert_eq!(null, *allocated.as_null())
619    }
620
621    #[test]
622    fn object_value() {
623        let object = Object::default();
624        let allocated = Value::from(object.clone());
625        assert_eq!(object, *allocated.as_object())
626    }
627
628    #[test]
629    fn ecma_array_value() {
630        let ecma_array = EcmaArray::default();
631        let allocated = Value::from(ecma_array.clone());
632        assert_eq!(ecma_array, *allocated.as_ecma_array());
633    }
634
635    #[test]
636    fn decode_unmarked_string() {
637        let mut buffer = ByteBuffer::default();
638        let app_key = "app";
639        buffer.put_u16_be(app_key.len() as u16);
640        buffer.put_bytes(app_key.as_bytes());
641        let result: IOResult<UnmarkedString> = buffer.decode();
642        assert!(result.is_ok());
643        let actual = result.unwrap();
644        assert_eq!(app_key, actual)
645    }
646
647    #[test]
648    fn encode_unmarked_string() {
649        let mut buffer = ByteBuffer::default();
650        let app_key = "app";
651        buffer.encode(&UnmarkedString::from(app_key));
652        let result: Vec<u8> = buffer.into();
653        assert_eq!(&(app_key.len() as u16).to_be_bytes(), &result[..2]);
654        assert_eq!(app_key.as_bytes(), &result[2..])
655    }
656
657    #[test]
658    #[should_panic]
659    fn panic_when_length_exceeded() {
660        let mut buffer = ByteBuffer::default();
661        buffer.encode(&UnmarkedString::new("a".repeat(1 + u16::MAX as usize)));
662    }
663
664    #[test]
665    fn decode_value() {
666        let mut buffer = ByteBuffer::default();
667        let ondemand = "ondemand";
668        buffer.put_u8(Marker::AmfString as u8);
669        buffer.put_u16_be(ondemand.len() as u16);
670        buffer.put_bytes(ondemand.as_bytes());
671        let result: IOResult<Value> = buffer.decode();
672        assert!(result.is_ok());
673        let actual = result.unwrap();
674        assert_eq!(Value::from(AmfString::from(ondemand)), actual)
675    }
676
677    #[test]
678    fn encode_value() {
679        let mut buffer = ByteBuffer::default();
680        let ondemand = "ondemand";
681        buffer.encode(&Value::from(AmfString::from(ondemand)));
682        let result: Vec<u8> = buffer.into();
683        assert_eq!(Marker::AmfString as u8, result[0]);
684        assert_eq!(&(ondemand.len() as u16).to_be_bytes(), &result[1..3]);
685        assert_eq!(ondemand.as_bytes(), &result[3..])
686    }
687}