sheave_core/messages/amf/v0/
string.rs

1use std::{
2    borrow::Cow,
3    error::Error,
4    ffi::OsString,
5    fmt::{
6        Display,
7        Formatter,
8        Result as FormatResult
9    },
10    io::Result as IOResult,
11    ops::{
12        Deref,
13        DerefMut
14    },
15    path::{
16        Path,
17        PathBuf
18    },
19    rc::Rc,
20    string::String as StdString,
21    sync::Arc,
22};
23use crate::{
24    Decoder,
25    Encoder,
26    ByteBuffer
27};
28use super::{
29    Marker,
30    super::{
31        ensure_marker,
32        invalid_string
33    }
34};
35
36/// The UTF-8 string of AMF data types.
37#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
38pub struct AmfString(StdString);
39
40impl AmfString {
41    /// Constructs an AMF's String.
42    pub fn new(string: StdString) -> Self {
43        Self(string)
44    }
45}
46
47impl Deref for AmfString {
48    type Target = StdString;
49
50    fn deref(&self) -> &Self::Target {
51        &self.0
52    }
53}
54
55impl DerefMut for AmfString {
56    fn deref_mut(&mut self) -> &mut Self::Target {
57        &mut self.0
58    }
59}
60
61impl PartialEq<str> for AmfString {
62    fn eq(&self, other: &str) -> bool {
63        self.0.eq(other)
64    }
65}
66
67impl PartialEq<AmfString> for str {
68    fn eq(&self, other: &AmfString) -> bool {
69        self.eq(&other.0)
70    }
71}
72
73impl<'a> PartialEq<&'a str> for AmfString {
74    fn eq(&self, other: &&'a str) -> bool {
75        self.0.eq(other)
76    }
77}
78
79impl<'a> PartialEq<AmfString> for &'a str {
80    fn eq(&self, other: &AmfString) -> bool {
81        self.eq(&other.0)
82    }
83}
84
85impl<'a> PartialEq<Cow<'a, str>> for AmfString {
86    fn eq(&self, other: &Cow<'a, str>) -> bool {
87        self.0.eq(other)
88    }
89}
90
91impl<'a> PartialEq<AmfString> for Cow<'a, str> {
92    fn eq(&self, other: &AmfString) -> bool {
93        self.eq(&other.0)
94    }
95}
96
97impl PartialEq<Path> for AmfString {
98    fn eq(&self, other: &Path) -> bool {
99        self.0.eq(other)
100    }
101}
102
103impl PartialEq<AmfString> for Path {
104    fn eq(&self, other: &AmfString) -> bool {
105        self.eq(&other.0)
106    }
107}
108
109impl PartialEq<PathBuf> for AmfString {
110    fn eq(&self, other: &PathBuf) -> bool {
111        self.0.eq(other)
112    }
113}
114
115impl PartialEq<AmfString> for PathBuf {
116    fn eq(&self, other: &AmfString) -> bool {
117        self.eq(&other.0)
118    }
119}
120
121impl PartialEq<StdString> for AmfString {
122    fn eq(&self, other: &StdString) -> bool {
123        self.0.eq(other)
124    }
125}
126
127impl PartialEq<AmfString> for StdString {
128    fn eq(&self, other: &AmfString) -> bool {
129        self.eq(&other.0)
130    }
131}
132
133impl From<&AmfString> for AmfString {
134    fn from(s: &AmfString) -> Self {
135        s.clone()
136    }
137}
138
139impl From<char> for AmfString {
140    fn from(c: char) -> Self {
141        Self(String::from(c))
142    }
143}
144
145impl From<&str> for AmfString {
146    fn from(s: &str) -> Self {
147        Self(String::from(s))
148    }
149}
150
151impl From<&mut str> for AmfString {
152    fn from(s: &mut str) -> Self {
153        Self(String::from(s))
154    }
155}
156
157impl From<AmfString> for OsString {
158    fn from(s: AmfString) -> Self {
159        Self::from(s.0)
160    }
161}
162
163impl From<AmfString> for PathBuf {
164    fn from(s: AmfString) -> Self {
165        Self::from(s.0)
166    }
167}
168
169impl From<AmfString> for Rc<str> {
170    fn from(v: AmfString) -> Self {
171        Self::from(v.0)
172    }
173}
174
175impl From<AmfString> for Arc<str> {
176    fn from(v: AmfString) -> Self {
177        Self::from(v.0)
178    }
179}
180
181impl From<AmfString> for Vec<u8> {
182    fn from(s: AmfString) -> Self {
183        Self::from(s.0)
184    }
185}
186
187impl<'a> From<AmfString> for Box<dyn Error + 'a> {
188    fn from(str_err: AmfString) -> Self {
189        Self::from(str_err.0)
190    }
191}
192
193impl<'a> From<AmfString> for Box<dyn Error + Send + Sync + 'a> {
194    fn from(str_err: AmfString) -> Self {
195        Self::from(str_err.0)
196    }
197}
198
199impl<'a> From<Cow<'a, str>> for AmfString {
200    fn from(s: Cow<'a, str>) -> Self {
201        Self(String::from(s))
202    }
203}
204
205impl<'a> From<AmfString> for Cow<'a, str> {
206    fn from(s: AmfString) -> Self {
207        Self::from(s.0)
208    }
209}
210
211impl<'a> From<&'a AmfString> for Cow<'a, str> {
212    fn from(s: &'a AmfString) -> Self {
213        Self::from(&s.0)
214    }
215}
216
217impl From<Box<str>> for AmfString {
218    fn from(s: Box<str>) -> Self {
219        Self(String::from(s))
220    }
221}
222
223impl From<AmfString> for Box<str> {
224    fn from(s: AmfString) -> Self {
225        Self::from(s.0)
226    }
227}
228
229impl Display for AmfString {
230    fn fmt(&self, f: &mut Formatter<'_>) -> FormatResult {
231        Display::fmt(&self.0, f)
232    }
233}
234
235impl Decoder<AmfString> for ByteBuffer {
236    /// Decodes bytes into an AMF's String.
237    ///
238    /// # Errors
239    ///
240    /// * [`InsufficientBufferLength`]
241    ///
242    /// When buffer isn't remained at least 3 bytes.
243    ///
244    /// * [`InconsistentMarker`]
245    ///
246    /// When a marker byte doesn't indicate the AMF String.
247    ///
248    /// * [`InvalidString`]
249    ///
250    /// When bytes are invalid for a UTF-8 string.
251    ///
252    /// # Examples
253    ///
254    /// ```rust
255    /// use sheave_core::{
256    ///     ByteBuffer,
257    ///     Decoder,
258    ///     messages::amf::v0::{
259    ///         Marker,
260    ///         AmfString
261    ///     }
262    /// };
263    ///
264    /// let s = "hello world!".as_bytes();
265    /// let mut buffer = ByteBuffer::default();
266    /// buffer.put_u8(Marker::AmfString as u8);
267    /// buffer.put_u16_be(s.len() as u16);
268    /// buffer.put_bytes(s);
269    /// assert!(Decoder::<AmfString>::decode(&mut buffer).is_ok());
270    ///
271    /// let mut buffer = ByteBuffer::default();
272    /// buffer.put_u8(Marker::Number as u8);
273    /// buffer.put_u16_be(s.len() as u16);
274    /// buffer.put_bytes(s);
275    /// assert!(Decoder::<AmfString>::decode(&mut buffer).is_err());
276    ///
277    /// // This is a missing sequence of the "sparkle heart(💖)".
278    /// let bytes = vec![0, 159, 146, 150];
279    /// let mut buffer = ByteBuffer::default();
280    /// buffer.put_u8(Marker::AmfString as u8);
281    /// buffer.put_u16_be(bytes.len() as u16);
282    /// buffer.put_bytes(&bytes);
283    /// assert!(Decoder::<AmfString>::decode(&mut buffer).is_err());
284    ///
285    /// let mut buffer = ByteBuffer::default();
286    /// assert!(Decoder::<AmfString>::decode(&mut buffer).is_err())
287    /// ```
288    ///
289    /// [`InsufficientBufferLength`]: crate::byte_buffer::InsufficientBufferLength
290    /// [`InconsistentMarker`]: crate::messages::amf::InconsistentMarker
291    /// [`InvalidString`]: crate::messages::amf::InvalidString
292    fn decode(&mut self) -> IOResult<AmfString> {
293        self.get_u8().and_then(
294            |marker| ensure_marker(Marker::AmfString as u8, marker)
295        )?;
296
297        let len = self.get_u16_be()? as usize;
298        if len == 0 {
299            return Ok("".into())
300        }
301        let bytes = self.get_bytes(len)?;
302        StdString::from_utf8(bytes.to_vec()).map(AmfString::new).map_err(invalid_string)
303    }
304}
305
306impl Encoder<AmfString> for ByteBuffer {
307    /// Encodes an AMF String into bytes.
308    ///
309    /// # Panics
310    ///
311    /// Its length must be the range of 16 bits.
312    /// If it exceeds, a panic is occured.
313    ///
314    /// # Examples
315    ///
316    /// ```rust
317    /// use std::panic::catch_unwind;
318    /// use sheave_core::{
319    ///     ByteBuffer,
320    ///     Encoder,
321    ///     messages::amf::v0::{
322    ///         Marker,
323    ///         AmfString
324    ///     }
325    /// };
326    ///
327    /// let s = "hello world!";
328    /// let mut buffer = ByteBuffer::default();
329    /// buffer.encode(&AmfString::from(s));
330    /// let bytes: Vec<u8> = buffer.into();
331    /// assert_eq!(Marker::AmfString as u8, bytes[0]);
332    /// assert_eq!((s.len() as u16).to_be_bytes().as_slice(), &bytes[1..3]);
333    /// assert_eq!(s.as_bytes(), &bytes[3..]);
334    ///
335    /// let result = catch_unwind(
336    ///     || {
337    ///         let mut buffer = ByteBuffer::default();
338    ///         buffer.encode(&AmfString::new("a".repeat(1 + u16::MAX as usize)))
339    ///     }
340    /// );
341    /// assert!(result.is_err())
342    /// ```
343    fn encode(&mut self, string: &AmfString) {
344        assert!(string.len() <= u16::MAX as usize);
345        self.put_u8(Marker::AmfString as u8);
346        self.put_u16_be(string.len() as u16);
347        self.put_bytes(string.as_bytes());
348    }
349}
350
351#[cfg(test)]
352mod tests {
353    use super::*;
354
355    #[test]
356    fn decode_string() {
357        let string = "connect".as_bytes();
358        let mut buffer = ByteBuffer::default();
359        buffer.put_u8(Marker::AmfString as u8);
360        buffer.put_u16_be(string.len() as u16);
361        buffer.put_bytes(string);
362        let result: IOResult<AmfString> = buffer.decode();
363        assert!(result.is_ok());
364        let string = result.unwrap();
365        assert_eq!("connect", string)
366    }
367
368    #[test]
369    fn encode_string() {
370        let string = AmfString::from("connect");
371        let mut buffer = ByteBuffer::default();
372        buffer.encode(&string);
373        let result: Vec<u8> = buffer.into();
374        assert_eq!(Marker::AmfString as u8, result[0]);
375        assert_eq!(&(string.len() as u16).to_be_bytes(), &result[1..3]);
376        assert_eq!("connect".as_bytes(), &result[3..])
377    }
378
379    #[test]
380    #[should_panic]
381    fn panic_when_length_exceeded() {
382        let mut buffer = ByteBuffer::default();
383        buffer.encode(&AmfString::new("a".repeat(1 + u16::MAX as usize)));
384    }
385}