amf_rs/amf0/
marker.rs

1use crate::amf0::type_marker::TypeMarker;
2use crate::errors::AmfError;
3use crate::traits::{Marshall, MarshallLength, Unmarshall};
4use std::fmt::Display;
5use std::hash::{Hash, Hasher};
6
7pub trait MarkerType: Sized {
8    const TM: TypeMarker;
9}
10
11impl<M: MarkerType> Marshall for M {
12    fn marshall(&self) -> Result<Vec<u8>, AmfError> {
13        let mut buf = [0u8; 1];
14        buf[0] = M::TM as u8; // 单字节情况下,不需考虑字节序问题
15        Ok(buf.to_vec())
16    }
17}
18
19impl<M: MarkerType> MarshallLength for M {
20    fn marshall_length(&self) -> usize {
21        1
22    }
23}
24
25impl<M: MarkerType + Default> Unmarshall for M {
26    fn unmarshall(buf: &[u8]) -> Result<(Self, usize), AmfError> {
27        if buf.len() < 1 {
28            return Err(AmfError::BufferTooSmall {
29                want: 1,
30                got: buf.len(),
31            });
32        }
33        let type_marker = TypeMarker::try_from(buf[0])?;
34        if type_marker != M::TM {
35            return Err(AmfError::TypeMarkerValueMismatch {
36                want: M::TM as u8,
37                got: buf[0],
38            });
39        }
40        Ok((M::default(), 1))
41    }
42}
43
44//	The null type is represented by the null type marker. No further information is encoded
45//	for this value.
46#[derive(Debug, Clone, PartialEq, Eq, Default)]
47pub struct NullType;
48
49impl MarkerType for NullType {
50    const TM: TypeMarker = TypeMarker::Null;
51}
52
53// 实现 rust 惯用语("idiom") 方便用户使用
54
55impl TryFrom<&[u8]> for NullType {
56    type Error = AmfError;
57
58    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
59        Self::unmarshall(value).map(|(o, _)| o)
60    }
61}
62
63impl TryFrom<Vec<u8>> for NullType {
64    type Error = AmfError;
65
66    fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
67        Self::try_from(value.as_slice())
68    }
69}
70
71impl TryFrom<NullType> for Vec<u8> {
72    type Error = AmfError;
73
74    fn try_from(value: NullType) -> Result<Self, Self::Error> {
75        value.marshall()
76    }
77}
78
79impl Display for NullType {
80    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81        write!(f, "null")
82    }
83}
84
85impl Hash for NullType {
86    fn hash<H: Hasher>(&self, state: &mut H) {
87        TypeMarker::Null.hash(state);
88    }
89}
90
91//    The undefined type is represented by the undefined type marker. No further information is encoded
92//    for this value.
93#[derive(Debug, Clone, PartialEq, Eq, Default)]
94pub struct UndefinedType;
95
96impl MarkerType for UndefinedType {
97    const TM: TypeMarker = TypeMarker::Undefined;
98}
99
100// 实现 rust 惯用语("idiom") 方便用户使用
101
102impl TryFrom<&[u8]> for UndefinedType {
103    type Error = AmfError;
104
105    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
106        Self::unmarshall(value).map(|(o, _)| o)
107    }
108}
109
110impl TryFrom<Vec<u8>> for UndefinedType {
111    type Error = AmfError;
112
113    fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
114        Self::try_from(value.as_slice())
115    }
116}
117
118impl TryFrom<UndefinedType> for Vec<u8> {
119    type Error = AmfError;
120
121    fn try_from(value: UndefinedType) -> Result<Self, Self::Error> {
122        value.marshall()
123    }
124}
125
126impl Display for UndefinedType {
127    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128        write!(f, "undefined")
129    }
130}
131
132impl Hash for UndefinedType {
133    fn hash<H: Hasher>(&self, state: &mut H) {
134        TypeMarker::Undefined.hash(state);
135    }
136}
137
138#[cfg(test)]
139mod tests {
140    use super::*;
141    use crate::amf0::type_marker::TypeMarker;
142    use std::hash::{DefaultHasher, Hash, Hasher};
143
144    // NullType 测试
145    #[test]
146    fn test_null_marshall() {
147        let null = NullType;
148        let data = null.marshall().unwrap();
149        assert_eq!(data, vec![TypeMarker::Null as u8]);
150    }
151
152    #[test]
153    fn test_null_marshall_length() {
154        let null = NullType;
155        assert_eq!(null.marshall_length(), 1);
156    }
157
158    #[test]
159    fn test_null_unmarshall_valid() {
160        let data = [TypeMarker::Null as u8];
161        let (null, bytes_read) = NullType::unmarshall(&data).unwrap();
162        assert_eq!(bytes_read, 1);
163        assert_eq!(null, NullType);
164    }
165
166    #[test]
167    fn test_null_unmarshall_buffer_too_small() {
168        let data = [];
169        let result = NullType::unmarshall(&data);
170        assert!(matches!(
171            result,
172            Err(AmfError::BufferTooSmall { want: 1, got: 0 })
173        ));
174    }
175
176    #[test]
177    fn test_null_try_from() {
178        let data = [TypeMarker::Null as u8];
179        let null = NullType::try_from(&data[..]).unwrap();
180        assert_eq!(null, NullType);
181    }
182
183    #[test]
184    fn test_null_display() {
185        assert_eq!(format!("{}", NullType), "null");
186    }
187
188    // UndefinedType 测试
189    #[test]
190    fn test_undefined_marshall() {
191        let undefined = UndefinedType;
192        let data = undefined.marshall().unwrap();
193        assert_eq!(data, vec![TypeMarker::Undefined as u8]);
194    }
195
196    #[test]
197    fn test_undefined_marshall_length() {
198        let undefined = UndefinedType;
199        assert_eq!(undefined.marshall_length(), 1);
200    }
201
202    #[test]
203    fn test_undefined_unmarshall_valid() {
204        let data = [TypeMarker::Undefined as u8];
205        let (undefined, bytes_read) = UndefinedType::unmarshall(&data).unwrap();
206        assert_eq!(bytes_read, 1);
207        assert_eq!(undefined, UndefinedType);
208    }
209
210    #[test]
211    fn test_undefined_unmarshall_buffer_too_small() {
212        let data = [];
213        let result = UndefinedType::unmarshall(&data);
214        assert!(matches!(
215            result,
216            Err(AmfError::BufferTooSmall { want: 1, got: 0 })
217        ));
218    }
219
220    #[test]
221    fn test_undefined_try_from() {
222        let data = [TypeMarker::Undefined as u8];
223        let undefined = UndefinedType::try_from(&data[..]).unwrap();
224        assert_eq!(undefined, UndefinedType);
225    }
226
227    #[test]
228    fn test_undefined_display() {
229        assert_eq!(format!("{}", UndefinedType), "undefined");
230    }
231
232    // 泛型实现的额外测试
233    #[test]
234    fn test_generic_marker_type() {
235        // 验证 NullType 的标记
236        assert_eq!(NullType::TM, TypeMarker::Null);
237
238        // 验证 UndefinedType 的标记
239        assert_eq!(UndefinedType::TM, TypeMarker::Undefined);
240    }
241
242    /// Helper to compute the hash of a value
243    fn calculate_hash<T: Hash>(t: &T) -> u64 {
244        let mut hasher = DefaultHasher::new();
245        t.hash(&mut hasher);
246        hasher.finish()
247    }
248
249    #[test]
250    fn null_and_undefined_clone_eq_hash() {
251        // Clone and Eq
252        let n1 = NullType::default(); // via Default
253        let n2 = n1.clone();
254        assert_eq!(n1, n2);
255
256        let u1 = UndefinedType::default();
257        let u2 = u1.clone();
258        assert_eq!(u1, u2);
259
260        // Hash equality for equal values
261        assert_eq!(calculate_hash(&n1), calculate_hash(&n2));
262        assert_eq!(calculate_hash(&u1), calculate_hash(&u2));
263
264        // Different types should hash differently
265        assert_ne!(calculate_hash(&n1), calculate_hash(&u1));
266    }
267}