sheave_core/messages/amf/v0/
string.rs1use 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#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
38pub struct AmfString(StdString);
39
40impl AmfString {
41 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 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 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}