use crate::amf0::writer::strict_array_writer::StrictArrayWriter;
use crate::types::{AMFVersion, Element, Lso, Reference, Value};
use std::collections::BTreeMap;
use super::{ArrayWriter, CacheKey, ObjWriter, ObjectWriter, TypedObjectWriter};
#[derive(Default)]
pub struct Amf0Writer {
pub(crate) elements: Vec<Element>,
pub(crate) ref_num: u16,
pub(crate) cache: BTreeMap<CacheKey, Reference>,
}
impl<'a> ObjWriter<'a> for Amf0Writer {
fn add_element(&mut self, name: &str, s: Value, inc_ref: bool) {
if inc_ref {
self.ref_num += 1;
}
self.elements.push(Element::new(name, s))
}
fn object<'c: 'a, 'd>(
&'d mut self,
cache_key: CacheKey,
) -> (Option<ObjectWriter<'d, 'c>>, Reference)
where
'a: 'c,
'a: 'd,
{
if let Some(existing_ref) = self.cache.get(&cache_key) {
(None, *existing_ref)
} else {
let r = Reference(self.ref_num);
self.ref_num += 1;
self.cache.insert(cache_key, r);
(
Some(ObjectWriter {
elements: Vec::new(),
parent: self,
}),
r,
)
}
}
fn array<'c: 'a, 'd>(
&'d mut self,
cache_key: CacheKey,
) -> (Option<ArrayWriter<'d, 'c>>, Reference)
where
'a: 'c,
'a: 'd,
{
if let Some(existing_ref) = self.cache.get(&cache_key) {
(None, *existing_ref)
} else {
let r = Reference(self.ref_num);
self.ref_num += 1;
self.cache.insert(cache_key, r);
(
Some(ArrayWriter {
elements: Vec::new(),
parent: self,
}),
r,
)
}
}
fn strict_array<'c: 'a, 'd>(
&'d mut self,
cache_key: CacheKey,
) -> (Option<StrictArrayWriter<'d, 'c>>, Reference)
where
'a: 'c,
'a: 'd,
{
if let Some(existing_ref) = self.cache_get(&cache_key) {
(None, existing_ref)
} else {
let r = self.make_reference();
self.cache_add(cache_key, r);
(
Some(StrictArrayWriter {
values: Vec::new(),
parent: self,
}),
r,
)
}
}
fn typed_object<'c: 'a, 'd>(
&'d mut self,
class_name: &str,
cache_key: CacheKey,
) -> (Option<TypedObjectWriter<'d, 'c>>, Reference)
where
'a: 'c,
'a: 'd,
{
if let Some(existing_ref) = self.cache.get(&cache_key) {
(None, *existing_ref)
} else {
let r = Reference(self.ref_num);
self.ref_num += 1;
self.cache.insert(cache_key, r);
(
Some(TypedObjectWriter {
class_name: class_name.to_string(),
elements: Vec::new(),
parent: self,
}),
r,
)
}
}
fn make_reference(&mut self) -> Reference {
let ref_num = Reference(self.ref_num);
self.ref_num += 1;
ref_num
}
fn cache_get(&mut self, cache_key: &CacheKey) -> Option<Reference> {
self.cache.get(cache_key).copied()
}
fn cache_add(&mut self, cache_key: CacheKey, reference: Reference) {
self.cache.insert(cache_key, reference);
}
}
impl Amf0Writer {
pub fn commit_lso(self, name: &str) -> Lso {
Lso::new(self.elements, name, AMFVersion::AMF0)
}
}