use crate::amf3;
use crate::{DecodeResult, Pair};
use std::io;
use std::time;
pub use self::decode::Decoder;
pub use self::encode::Encoder;
mod decode;
mod encode;
mod marker {
pub const NUMBER: u8 = 0x00;
pub const BOOLEAN: u8 = 0x01;
pub const STRING: u8 = 0x02;
pub const OBJECT: u8 = 0x03;
pub const MOVIECLIP: u8 = 0x04; pub const NULL: u8 = 0x05;
pub const UNDEFINED: u8 = 0x06;
pub const REFERENCE: u8 = 0x07;
pub const ECMA_ARRAY: u8 = 0x08;
pub const OBJECT_END_MARKER: u8 = 0x09;
pub const STRICT_ARRAY: u8 = 0x0A;
pub const DATE: u8 = 0x0B;
pub const LONG_STRING: u8 = 0x0C;
pub const UNSUPPORTED: u8 = 0x0D;
pub const RECORDSET: u8 = 0x0E; pub const XML_DOCUMENT: u8 = 0x0F;
pub const TYPED_OBJECT: u8 = 0x10;
pub const AVMPLUS_OBJECT: u8 = 0x11;
}
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum Value {
Number(f64),
Boolean(bool),
String(String),
Object {
class_name: Option<String>,
entries: Vec<Pair<String, Value>>,
},
Null,
Undefined,
EcmaArray {
entries: Vec<Pair<String, Value>>,
},
Array {
entries: Vec<Value>,
},
Date {
unix_time: time::Duration,
time_zone: i16,
},
XmlDocument(String),
AvmPlus(amf3::Value),
}
impl Value {
pub fn read_from<R>(reader: R) -> DecodeResult<Self>
where
R: io::Read,
{
Decoder::new(reader).decode()
}
pub fn write_to<W>(&self, writer: W) -> io::Result<()>
where
W: io::Write,
{
Encoder::new(writer).encode(self)
}
pub fn try_as_str(&self) -> Option<&str> {
match *self {
Value::String(ref x) => Some(x.as_ref()),
Value::XmlDocument(ref x) => Some(x.as_ref()),
Value::AvmPlus(ref x) => x.try_as_str(),
_ => None,
}
}
pub fn try_as_f64(&self) -> Option<f64> {
match *self {
Value::Number(x) => Some(x),
Value::AvmPlus(ref x) => x.try_as_f64(),
_ => None,
}
}
pub fn try_into_values(self) -> Result<Box<dyn Iterator<Item = super::Value>>, Self> {
match self {
Value::Array { entries } => Ok(Box::new(entries.into_iter().map(super::Value::Amf0))),
Value::AvmPlus(x) => x
.try_into_values()
.map(|iter| iter.map(super::Value::Amf3))
.map(super::iter_boxed)
.map_err(Value::AvmPlus),
_ => Err(self),
}
}
pub fn try_into_pairs(self) -> Result<Box<dyn Iterator<Item = (String, super::Value)>>, Self> {
match self {
Value::EcmaArray { entries } => Ok(Box::new(
entries
.into_iter()
.map(|p| (p.key, super::Value::Amf0(p.value))),
)),
Value::Object { entries, .. } => Ok(Box::new(
entries
.into_iter()
.map(|p| (p.key, super::Value::Amf0(p.value))),
)),
Value::AvmPlus(x) => x
.try_into_pairs()
.map(|ps| ps.map(|(k, v)| (k, super::Value::Amf3(v))))
.map(super::iter_boxed)
.map_err(Value::AvmPlus),
_ => Err(self),
}
}
}
pub fn string<T>(t: T) -> Value
where
String: From<T>,
{
Value::String(From::from(t))
}
pub fn number<T>(t: T) -> Value
where
f64: From<T>,
{
Value::Number(From::from(t))
}
pub fn object<I, K>(entries: I) -> Value
where
I: Iterator<Item = (K, Value)>,
String: From<K>,
{
Value::Object {
class_name: None,
entries: entries
.map(|(k, v)| Pair {
key: From::from(k),
value: v,
})
.collect(),
}
}
pub fn array(entries: Vec<Value>) -> Value {
Value::Array { entries }
}