Initial commit

This commit is contained in:
Xiphoseer
2022-07-21 00:36:50 +02:00
commit 3d00236f6f
7 changed files with 781 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
/target
/Cargo.lock
*.bin
*.json
*.txt

12
Cargo.toml Normal file
View File

@@ -0,0 +1,12 @@
[package]
name = "serde-amf3"
version = "0.1.0"
edition = "2021"
[dependencies]
serde = { version = "1.0.140" }
[dev-dependencies]
serde_json = "1.0.82"
serde = { version = "1.0.140", features = ["derive"] }
clap = { version = "3.2.13", features = ["derive"] }

22
examples/amf3-pp.rs Normal file
View File

@@ -0,0 +1,22 @@
use std::path::PathBuf;
use clap::Parser;
use serde::Serialize;
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct Args {
/// Name of the file to pretty-print
#[clap(value_parser)]
path: PathBuf,
}
fn main() {
let args = Args::parse();
let bytes = std::fs::read(&args.path).unwrap();
let value = serde_amf3::deserialize::<serde_json::Value>(&bytes[..]).unwrap();
let mut serializer = serde_json::Serializer::pretty(std::io::stdout().lock());
value.serialize(&mut serializer).unwrap();
println!();
}

85
examples/bbb-msg.rs Normal file
View File

@@ -0,0 +1,85 @@
use std::path::PathBuf;
use clap::Parser;
use serde::{Deserialize, Serialize};
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct Args {
/// Name of the file to pretty-print
#[clap(value_parser)]
path: PathBuf,
}
#[derive(Debug, Deserialize, Serialize)]
struct ExecutionStateStrip {
#[serde(rename = "actionIndex")]
action_index: u32,
id: u32,
}
#[derive(Debug, Deserialize, Serialize)]
struct ExecutionState {
#[serde(rename = "stateID")]
state_id: u32,
strips: Vec<ExecutionStateStrip>,
}
#[derive(Debug, Deserialize, Serialize)]
#[serde(tag = "Type")]
enum Action {
OnInteract {
#[serde(rename = "__callbackID__")]
callback_id: String,
},
FlyUp {
#[serde(rename = "Distance")]
distance: f64,
#[serde(rename = "__callbackID__")]
callback_id: String,
},
FlyDown {
#[serde(rename = "Distance")]
distance: f64,
#[serde(rename = "__callbackID__")]
callback_id: String,
},
}
#[derive(Debug, Deserialize, Serialize)]
struct Pos2 {
x: u32,
y: u32,
}
#[derive(Debug, Deserialize, Serialize)]
struct Strip {
id: u32,
actions: Vec<Action>,
ui: Pos2,
}
#[derive(Debug, Deserialize, Serialize)]
struct State {
id: u32,
strips: Vec<Strip>,
}
#[derive(Debug, Deserialize, Serialize)]
struct Root {
#[serde(rename = "BehaviorID")]
behavior_id: String,
#[serde(rename = "executionState")]
execution_state: ExecutionState,
#[serde(rename = "objectID")]
object_id: String,
states: Vec<State>,
}
fn main() {
let args = Args::parse();
let bytes = std::fs::read(&args.path).unwrap();
let value = serde_amf3::deserialize::<Root>(&bytes[..]).unwrap();
println!("{:#?}", value);
}

173
src/format.rs Normal file
View File

@@ -0,0 +1,173 @@
use std::str::Utf8Error;
#[repr(u8)]
#[derive(Copy, Clone, PartialEq, Eq)]
#[allow(dead_code)]
pub enum Marker {
Undefined = 0x00,
Null = 0x01,
False = 0x02,
True = 0x03,
Integer = 0x04,
Double = 0x05,
String = 0x06,
XmlDoc = 0x07,
Date = 0x08,
Array = 0x09,
Object = 0x0A,
Xml = 0x0B,
ByteArray = 0x0C,
VectorInt = 0x0D,
VectorUInt = 0x0E,
VectorDouble = 0x0F,
VectorObject = 0x10,
Dictionary = 0x11,
}
impl Marker {
fn new(value: u8) -> Result<Self, Error> {
if value < 0x12 {
Ok(unsafe { std::mem::transmute(value) })
} else {
Err(Error::InvalidMarker(value))
}
}
}
#[derive(Debug, PartialEq)]
pub(super) enum Error {
InvalidMarker(u8),
StringDecode(Utf8Error),
EndOfStream,
MissingStringReference,
}
impl From<Utf8Error> for Error {
fn from(e: Utf8Error) -> Self {
Self::StringDecode(e)
}
}
pub struct Deserializer<'de> {
input: std::slice::Iter<'de, u8>,
string_reference_table: Vec<&'de str>,
}
fn try_split_array_ref<const N: usize>(slice: &[u8]) -> Result<(&[u8; N], &[u8]), Error> {
if slice.len() < N {
Err(Error::EndOfStream)
} else {
let rest = unsafe { slice.get_unchecked(N..) };
// SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at)
Ok((unsafe { &*(slice.as_ptr() as *const [u8; N]) }, rest))
}
}
impl<'de> Deserializer<'de> {
pub(super) fn read_byte(&mut self) -> Result<u8, Error> {
self.input.next().copied().ok_or(Error::EndOfStream)
}
pub(super) fn read_marker(&mut self) -> Result<Marker, Error> {
let byte = self.read_byte()?;
Marker::new(byte)
}
/// 0x00000000 - 0x0000007F : 0xxxxxxx
/// 0x00000080 - 0x00003FFF : 1xxxxxxx 0xxxxxxx
/// 0x00004000 - 0x001FFFFF : 1xxxxxxx 1xxxxxxx 0xxxxxxx
/// 0x00200000 - 0x3FFFFFFF : 1xxxxxxx 1xxxxxxx 1xxxxxxx xxxxxxxx
/// 0x40000000 - 0xFFFFFFFF : throw range exception
pub(super) fn read_u29(&mut self) -> Result<u32, Error> {
let first = self.read_byte()?;
let mut value = u32::from(first & 0x7F);
if first >= 0x80 {
let second = self.read_byte()?;
value <<= 7;
value |= u32::from(second & 0x7F);
if second >= 0x80 {
let third = self.read_byte()?;
value <<= 7;
value |= u32::from(third & 0x7F);
if third >= 0x80 {
let fourth = self.read_byte()?;
value <<= 8;
value |= u32::from(fourth);
}
}
}
Ok(value)
}
pub(super) fn read_double(&mut self) -> Result<f64, Error> {
let slice = self.input.as_slice();
let (double_bytes, rest) = try_split_array_ref(slice)?;
self.input = rest.iter();
Ok(f64::from_le_bytes(*double_bytes))
}
pub(super) fn read_string(&mut self) -> Result<&'de str, Error> {
let header = self.read_u29()?;
let value = (header >> 1) as usize;
if header & 1 == 0 {
// by reference
let string = *(self
.string_reference_table
.get(value)
.ok_or(Error::MissingStringReference)?);
Ok(string)
} else if self.input.len() >= value {
// by value
let slice = self.input.as_slice();
let string_bytes = unsafe { slice.get_unchecked(..value) };
let rest = unsafe { slice.get_unchecked(value..) };
self.input = rest.iter();
let string = std::str::from_utf8(string_bytes)?;
if !string.is_empty() {
self.string_reference_table.push(string);
}
Ok(string)
} else {
Err(Error::EndOfStream)
}
}
pub(crate) fn new(input: &'de [u8]) -> Self {
Self {
input: input.iter(),
string_reference_table: Vec::new(),
}
}
pub(crate) fn skip(&mut self) -> Result<(), Error> {
let marker = self.read_marker()?;
match marker {
Marker::Integer => {
self.read_u29()?;
}
Marker::Double => {
self.input = self
.input
.as_slice()
.get(8..)
.ok_or(Error::EndOfStream)?
.iter();
}
Marker::String => todo!(),
Marker::XmlDoc => todo!(),
Marker::Date => todo!(),
Marker::Array => todo!(),
Marker::Object => todo!(),
Marker::Xml => todo!(),
Marker::ByteArray => todo!(),
Marker::VectorInt => todo!(),
Marker::VectorUInt => todo!(),
Marker::VectorDouble => todo!(),
Marker::VectorObject => todo!(),
Marker::Dictionary => todo!(),
_ => {}
}
Ok(())
}
}

426
src/lib.rs Normal file
View File

@@ -0,0 +1,426 @@
use std::fmt;
use format::Marker;
use serde::{de::value::BorrowedStrDeserializer, forward_to_deserialize_any, Deserialize};
use traits::{VisitDouble, VisitInt};
mod format;
mod traits;
#[derive(Debug, PartialEq)]
enum ErrorKind {
#[allow(dead_code)]
Unimplemented,
Custom(String),
Format(format::Error),
}
#[derive(Debug, PartialEq)]
pub struct Error {
kind: ErrorKind,
}
impl std::error::Error for Error {}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.kind {
ErrorKind::Unimplemented => write!(f, "Unimplemented"),
ErrorKind::Custom(msg) => write!(f, "Custom: {}", msg),
ErrorKind::Format(fmt) => write!(f, "Format error: {:?}", fmt),
}
}
}
impl serde::de::Error for Error {
fn custom<T>(msg: T) -> Self
where
T: fmt::Display,
{
Self {
kind: ErrorKind::Custom(msg.to_string()),
}
}
}
struct ByteDeserializerSeq<'a, 'de> {
len: usize,
inner: &'a mut ByteDeserializer<'de>,
}
impl<'a, 'de> serde::de::SeqAccess<'de> for ByteDeserializerSeq<'a, 'de> {
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: serde::de::DeserializeSeed<'de>,
{
if self.len > 0 {
self.len -= 1;
seed.deserialize(&mut *self.inner).map(Some)
} else {
Ok(None)
}
}
}
struct ByteDeserializerMap<'a, 'de> {
len: usize,
next_key: &'de str,
inner: &'a mut ByteDeserializer<'de>,
}
impl<'a, 'de> serde::de::MapAccess<'de> for ByteDeserializerMap<'a, 'de> {
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
where
K: serde::de::DeserializeSeed<'de>,
{
if self.next_key.is_empty() {
if self.len > 0 {
self.len -= 1;
let deserializer = serde::de::value::UsizeDeserializer::new(self.len);
seed.deserialize(deserializer).map(Some)
} else {
Ok(None)
}
} else {
let deserializer = BorrowedStrDeserializer::new(self.next_key);
seed.deserialize(deserializer).map(Some)
}
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
where
V: serde::de::DeserializeSeed<'de>,
{
let value = seed.deserialize(&mut *self.inner)?;
if !self.next_key.is_empty() {
self.next_key = self.inner.inner.read_string()?;
}
Ok(value)
}
}
pub struct ByteDeserializer<'de> {
inner: format::Deserializer<'de>,
}
impl<'de> ByteDeserializer<'de> {
pub fn from_bytes(input: &'de [u8]) -> Self {
Self {
inner: format::Deserializer::new(input),
}
}
fn deserialize_array<V: serde::de::Visitor<'de>>(
&mut self,
visitor: V,
) -> Result<V::Value, Error> {
let header = self.inner.read_u29()?;
let value = (header >> 1) as usize;
if header & 1 == 0 {
// array by reference
unimplemented!()
} else {
// dense count
let first_key = self.inner.read_string()?;
if first_key.is_empty() {
// only dense keys => array
visitor.visit_seq(ByteDeserializerSeq {
inner: self,
len: value,
})
} else {
visitor.visit_map(ByteDeserializerMap {
inner: self,
len: value,
next_key: first_key,
})
}
}
}
fn deserialize_into<V, N: VisitInt, F: VisitDouble>(
&mut self,
visitor: V,
) -> Result<V::Value, Error>
where
V: serde::de::Visitor<'de>,
{
let marker = self.inner.read_marker()?;
match marker {
Marker::Undefined => visitor.visit_none(),
Marker::Null => visitor.visit_none(),
Marker::False => visitor.visit_bool(false),
Marker::True => visitor.visit_bool(true),
Marker::Integer => N::visit_int(visitor, self.inner.read_u29()?),
Marker::Double => F::visit_double(visitor, self.inner.read_double()?),
Marker::String => visitor.visit_borrowed_str(self.inner.read_string()?),
Marker::XmlDoc => todo!(),
Marker::Date => todo!(),
Marker::Array => self.deserialize_array(visitor),
Marker::Object => todo!(),
Marker::Xml => todo!(),
Marker::ByteArray => todo!(),
Marker::VectorInt => todo!(),
Marker::VectorUInt => todo!(),
Marker::VectorDouble => todo!(),
Marker::VectorObject => todo!(),
Marker::Dictionary => todo!(),
}
}
}
impl From<format::Error> for Error {
fn from(e: format::Error) -> Self {
Self {
kind: ErrorKind::Format(e),
}
}
}
pub fn deserialize<'de, T: Deserialize<'de>>(input: &'de [u8]) -> Result<T, Error> {
let mut deserializer = ByteDeserializer::from_bytes(input);
T::deserialize(&mut deserializer)
}
impl<'de> serde::Deserializer<'de> for &mut ByteDeserializer<'de> {
type Error = Error;
forward_to_deserialize_any! { bool str string option unit seq tuple map struct identifier }
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.deserialize_into::<V, u32, f64>(visitor)
}
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.deserialize_into::<V, i8, i8>(visitor)
}
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.deserialize_into::<V, i16, i16>(visitor)
}
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.deserialize_into::<V, i32, i32>(visitor)
}
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.deserialize_into::<V, i64, i64>(visitor)
}
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.deserialize_into::<V, u8, u8>(visitor)
}
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.deserialize_into::<V, u16, u16>(visitor)
}
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.deserialize_into::<V, u32, u32>(visitor)
}
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.deserialize_into::<V, u64, u64>(visitor)
}
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.deserialize_into::<V, f32, f32>(visitor)
}
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.deserialize_into::<V, f64, f64>(visitor)
}
fn deserialize_char<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
todo!()
}
fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
todo!()
}
fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
todo!()
}
fn deserialize_unit_struct<V>(
self,
_name: &'static str,
_visitor: V,
) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
todo!()
}
fn deserialize_newtype_struct<V>(
self,
_name: &'static str,
_visitor: V,
) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
todo!()
}
fn deserialize_tuple_struct<V>(
self,
_name: &'static str,
_len: usize,
_visitor: V,
) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
todo!()
}
fn deserialize_enum<V>(
self,
_name: &'static str,
_variants: &'static [&'static str],
_visitor: V,
) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
todo!()
}
/*fn deserialize_identifier<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
todo!()
}*/
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.inner.skip()?;
visitor.visit_none()
}
}
#[cfg(test)]
mod tests {
use serde::Deserialize;
use super::{format, Error, ErrorKind};
const EOS_ERROR: Error = Error {
kind: ErrorKind::Format(format::Error::EndOfStream),
};
#[test]
fn test_bool() {
assert_eq!(super::deserialize::<bool>(&[]), Err(EOS_ERROR));
assert_eq!(super::deserialize::<bool>(&[0x02]), Ok(false));
assert_eq!(super::deserialize::<bool>(&[0x03]), Ok(true));
}
#[test]
fn test_integer() {
assert_eq!(super::deserialize(&[0x04, 0x05]), Ok(5u8));
assert_eq!(super::deserialize(&[0x04, 0x05]), Ok(5u16));
assert_eq!(super::deserialize(&[0x04, 0x05]), Ok(5u32));
assert_eq!(super::deserialize(&[0x04, 0x05]), Ok(5u64));
}
#[test]
fn test_double() {
assert_eq!(super::deserialize(&[0x05, 0, 0, 0, 0, 0, 0, 0, 0]), Ok(0.0));
assert_eq!(
super::deserialize(&[0x05, 0, 0, 0, 0, 0, 0, 0, 0]),
Ok(0.0f32)
);
assert_eq!(
super::deserialize(&[0x05, 0, 0, 0, 0, 0, 0, 0xD0, 0x3F]),
Ok(0.25)
);
assert_eq!(
super::deserialize(&[0x05, 0, 0, 0, 0, 0, 0, 0xD0, 0x3F]),
Ok(0.25f32)
);
assert_eq!(
super::deserialize(&[0x05, 0x9A, 0x99, 0x99, 0x99, 0x99, 0x99, 0xB9, 0x3F]),
Ok(0.1)
);
}
#[test]
fn test_string() {
assert_eq!(super::deserialize(b"\x06\x0BHello"), Ok("Hello"));
}
#[test]
fn test_option() {
assert_eq!(super::deserialize::<Option<u32>>(b"\x00"), Ok(None));
}
#[derive(Deserialize, Debug, PartialEq)]
struct Test {
a: u32,
b: u32,
}
#[test]
fn test_array() {
assert_eq!(
super::deserialize::<Vec<u32>>(&[0x09, 0x7, 0x01, 0x04, 1, 0x04, 2, 0x04, 3]),
Ok(vec![1, 2, 3])
);
assert_eq!(
super::deserialize(&[0x09, 0x1, 0x03, b'a', 0x04, 5, 0x03, b'b', 0x04, 7, 0x01]),
Ok(Test { a: 5, b: 7 })
);
}
}

58
src/traits.rs Normal file
View File

@@ -0,0 +1,58 @@
use super::Error;
pub(super) trait VisitInt {
fn visit_int<'de, V: serde::de::Visitor<'de>>(visitor: V, v: u32) -> Result<V::Value, Error>;
}
macro_rules! impl_visit_int {
($f:ident $t:ty) => {
impl VisitInt for $t {
fn visit_int<'de, V: serde::de::Visitor<'de>>(
visitor: V,
v: u32,
) -> Result<V::Value, Error> {
visitor.$f(v as $t)
}
}
};
}
impl_visit_int!(visit_u8 u8);
impl_visit_int!(visit_u16 u16);
impl_visit_int!(visit_u32 u32);
impl_visit_int!(visit_u64 u64);
impl_visit_int!(visit_i8 i8);
impl_visit_int!(visit_i16 i16);
impl_visit_int!(visit_i32 i32);
impl_visit_int!(visit_i64 i64);
impl_visit_int!(visit_f32 f32);
impl_visit_int!(visit_f64 f64);
pub(super) trait VisitDouble {
fn visit_double<'de, V: serde::de::Visitor<'de>>(visitor: V, v: f64)
-> Result<V::Value, Error>;
}
macro_rules! impl_visit_double {
($f:ident $t:ty) => {
impl VisitDouble for $t {
fn visit_double<'de, V: serde::de::Visitor<'de>>(
visitor: V,
v: f64,
) -> Result<V::Value, Error> {
visitor.$f(v as $t)
}
}
};
}
impl_visit_double!(visit_f32 f32);
impl_visit_double!(visit_f64 f64);
impl_visit_double!(visit_i8 i8);
impl_visit_double!(visit_u8 u8);
impl_visit_double!(visit_i16 i16);
impl_visit_double!(visit_u16 u16);
impl_visit_double!(visit_i32 i32);
impl_visit_double!(visit_u32 u32);
impl_visit_double!(visit_i64 i64);
impl_visit_double!(visit_u64 u64);