sheave_core/messages/amf/
v0.rs1mod 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#[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}