flash_lso/
types.rs

1use cookie_factory::lib::std::fmt::Formatter;
2use core::fmt;
3use derive_try_from_primitive::TryFromPrimitive;
4use enumset::EnumSet;
5use enumset::EnumSetType;
6use nom::lib::std::iter::FromIterator;
7use std::ops::Deref;
8use std::rc::Rc;
9
10/// A container for lso files
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12#[derive(Debug, PartialEq)]
13pub struct Lso {
14    /// The header of this lso
15    pub header: Header,
16    /// The elements at the root level of this lso
17    pub body: Vec<Element>,
18}
19
20impl Lso {
21    /// Create a new Lso with a header with the given name and version and an empty body
22    #[inline]
23    pub fn new_empty(name: impl Into<String>, version: AMFVersion) -> Self {
24        Self::new(Vec::new(), name, version)
25    }
26
27    /// Crate a new Lso with a header with the given name, version and body
28    #[inline]
29    pub fn new(body: Vec<Element>, name: impl Into<String>, version: AMFVersion) -> Self {
30        Self {
31            header: Header::new(name, version),
32            body,
33        }
34    }
35}
36
37impl IntoIterator for Lso {
38    type Item = Element;
39    type IntoIter = std::vec::IntoIter<Self::Item>;
40
41    fn into_iter(self) -> Self::IntoIter {
42        self.body.into_iter()
43    }
44}
45
46/// The version of AMF being used
47#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
48#[derive(TryFromPrimitive, Eq, PartialEq, Debug, Copy, Clone)]
49#[repr(u8)]
50pub enum AMFVersion {
51    /// AMF0
52    AMF0 = 0,
53    /// AMF3
54    AMF3 = 3,
55}
56
57impl fmt::Display for AMFVersion {
58    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
59        match self {
60            AMFVersion::AMF0 => f.write_str("AMF0"),
61            AMFVersion::AMF3 => f.write_str("AMF3"),
62        }
63    }
64}
65
66/// The header of a lso file
67#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
68#[derive(Debug, PartialEq)]
69pub struct Header {
70    /// The length of the lso in bytes
71    pub length: u32,
72    /// The name of the lso file
73    pub name: String,
74    /// The version of AMF used to encode the data
75    pub format_version: AMFVersion,
76}
77
78impl Header {
79    /// Create a new header with the given name and version, will have a size of 0 by default
80    #[inline]
81    pub fn new(name: impl Into<String>, version: AMFVersion) -> Self {
82        Self {
83            length: 0,
84            name: name.into(),
85            format_version: version,
86        }
87    }
88}
89
90/// Represent a named element
91#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
92#[derive(Clone, Debug, PartialEq)]
93pub struct Element {
94    /// The name of the element
95    pub name: String,
96    /// The value of the element
97    pub value: Rc<Value>,
98}
99
100impl Element {
101    /// Create a new Element
102    #[inline]
103    pub fn new(name: impl Into<String>, value: impl Into<Value>) -> Self {
104        Self {
105            name: name.into(),
106            value: Rc::new(value.into()),
107        }
108    }
109
110    /// Get the Value of this element
111    pub fn value(&self) -> &Value {
112        self.value.deref()
113    }
114
115    /// Get the name of this element
116    pub fn name(&self) -> &str {
117        self.name.as_str()
118    }
119}
120
121//TODO: should amf3 assoc arrays be their own type with a dense and assoc section
122/// A single or compound value
123#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
124#[derive(Debug, Clone, PartialEq)]
125pub enum Value {
126    /// Represent the type number (amf0) and double (amf3)
127    Number(f64),
128    /// Represents the type boolean (amf0) and both the true/false type (amf3)
129    Bool(bool),
130    /// Represent both the string (amf0/3) and long string type (amf0)
131    String(String),
132    /// Represents the object type in both amf0 and amf3, class definition are only available with amf3
133    Object(Vec<Element>, Option<ClassDefinition>),
134    /// Represent the null type
135    Null,
136    /// Represent the undefined type
137    Undefined,
138    /// Represent ECMA-Arrays (amf0) and associative arrays (amf3, even if they contain a dense part)
139    /// Final value represents the length of the array in amf0, this can differ from the actual number of elements
140    ECMAArray(Vec<Rc<Value>>, Vec<Element>, u32),
141    /// Represent a strict array (amf0) or a dense array (amf3)
142    StrictArray(Vec<Rc<Value>>),
143    /// Represent a timezone in the format (seconds since epoch, timezone or UTC if missing (amf3) )
144    Date(f64, Option<u16>),
145    /// Represent the unsupported type
146    Unsupported,
147    /// Represent the XML type, (value, is_string)
148    XML(String, bool),
149    /// Represent an amf3 element embedded in an AMF0 file
150    AMF3(Rc<Value>),
151    // AMF3
152    /// Represent the integer type (u29) (amf3)
153    Integer(i32),
154    /// Represent the bytearray type (amf3)
155    ByteArray(Vec<u8>),
156    /// Represent the int vector type (amf3)
157    /// Format is (values, is_fixed_length)
158    VectorInt(Vec<i32>, bool),
159    /// Represent the unsigned int vector type (amf3)
160    /// Format is (values, is_fixed_length)
161    VectorUInt(Vec<u32>, bool),
162    /// Represent the double vector type (amf3)
163    /// Format is (values, is_fixed_length)
164    VectorDouble(Vec<f64>, bool),
165    /// Represent the object vector type (amf3)
166    /// Format is (values, is_fixed_length)
167    VectorObject(Vec<Rc<Value>>, String, bool),
168    /// Represent the dictionary type (amf3)
169    /// Format is ((key, value), has_weak_keys)
170    Dictionary(Vec<(Rc<Value>, Rc<Value>)>, bool),
171    /// Represent a external object, such as from flex
172    /// (custom_elements, regular elements, class def)
173    Custom(Vec<Element>, Vec<Element>, Option<ClassDefinition>),
174}
175
176impl FromIterator<Value> for Vec<Rc<Value>> {
177    fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
178        iter.into_iter().map(Rc::new).collect()
179    }
180}
181
182/// A class definition (trait) used in AMF3
183#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
184#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
185pub struct ClassDefinition {
186    /// The name of the class definition
187    pub name: String,
188    /// The attributes on this trait
189    pub attributes: EnumSet<Attribute>,
190    /// The name of the static properties defined in this definition
191    pub static_properties: Vec<String>,
192}
193
194impl Default for ClassDefinition {
195    fn default() -> Self {
196        Self {
197            name: "Object".to_string(),
198            attributes: EnumSet::empty(),
199            static_properties: Vec::new(),
200        }
201    }
202}
203
204impl ClassDefinition {
205    /// Creates a new ClassDefinition with the given name, and no attributes or properties
206    pub fn default_with_name(name: String) -> Self {
207        Self {
208            name,
209            attributes: EnumSet::empty(),
210            static_properties: Vec::new(),
211        }
212    }
213}
214
215/// Encodes the possible attributes that can be given to a trait
216#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
217#[derive(EnumSetType, Debug)]
218pub enum Attribute {
219    /// If a trait is dynamic then the object it constructs may have additional properties other than the ones specified in the trait
220    Dynamic,
221    /// If a trait is external then it requires custom serialization and deserialization support
222    External,
223}