#[cfg_attr(docsrs, doc(cfg(feature = "writer")))]
#[macro_export]
macro_rules! write_v7400_binary {
(
writer=$writer:expr,
tree={$($tree:tt)*},
) => {{
let mut f = || -> $crate::writer::v7400::binary::Result<()> {
let _writer = &mut $writer;
write_v7400_binary! { @__node, _writer, $($tree)* };
Ok(())
};
f()
}};
(@__node, $writer:ident,) => {};
(@__node, $writer:ident, , $($tree:tt)*) => {
write_v7400_binary! { @__node, $writer, $($tree)* }
};
(@__node, $writer:ident,
$name:ident: {
$($subtree:tt)*
}
$($rest:tt)*
) => {{
$writer.new_node(stringify!($name))?;
write_v7400_binary! { @__node, $writer, $($subtree)* }
$writer.close_node()?;
write_v7400_binary! { @__node, $writer, $($rest)* }
}};
(@__node, $writer:ident,
$name:ident: [$($attr:expr),* $(,)?] {
$($subtree:tt)*
}
$($rest:tt)*
) => {{
let mut _attrs = $writer.new_node(stringify!($name))?;
$({
let attr = $attr;
write_v7400_binary!(@__attr, _attrs, attr.into())?;
})*
write_v7400_binary! { @__node, $writer, $($subtree)* }
$writer.close_node()?;
write_v7400_binary! { @__node, $writer, $($rest)* }
}};
(@__node, $writer:ident,
$name:ident: ($attrs:expr) {
$($subtree:tt)*
}
$($rest:tt)*
) => {{
let mut _attrs = $writer.new_node(stringify!($name))?;
$attrs.into_iter().try_for_each(|attr: $crate::low::v7400::AttributeValue| {
write_v7400_binary!(@__attr, _attrs, attr.into())
})?;
write_v7400_binary! { @__node, $writer, $($subtree)* }
$writer.close_node()?;
write_v7400_binary! { @__node, $writer, $($rest)* }
}};
(@__attr, $attrs:ident, $attr:expr) => {{
use $crate::low::v7400::AttributeValue::*;
match $attr {
Bool(v) => $attrs.append_bool(v),
I16(v) => $attrs.append_i16(v),
I32(v) => $attrs.append_i32(v),
I64(v) => $attrs.append_i64(v),
F32(v) => $attrs.append_f32(v),
F64(v) => $attrs.append_f64(v),
ArrBool(v) => $attrs.append_arr_bool_from_iter(None, v),
ArrI32(v) => $attrs.append_arr_i32_from_iter(None, v),
ArrI64(v) => $attrs.append_arr_i64_from_iter(None, v),
ArrF32(v) => $attrs.append_arr_f32_from_iter(None, v),
ArrF64(v) => $attrs.append_arr_f64_from_iter(None, v),
Binary(v) => $attrs.append_binary_direct(&v),
String(v) => $attrs.append_string_direct(&v),
}
}};
}
#[cfg(test)]
mod tests {
use std::io::Cursor;
use crate::{
low::FbxVersion,
writer::v7400::binary::{Result, Writer},
};
#[test]
fn empty_writer() -> Result<()> {
let mut writer = Writer::new(Cursor::new(Vec::new()), FbxVersion::V7_4)?;
write_v7400_binary!(writer = writer, tree = {},)?;
let _buf = writer.finalize_and_flush(&Default::default())?;
Ok(())
}
#[test]
fn empty_node() -> Result<()> {
let mut writer = Writer::new(Cursor::new(Vec::new()), FbxVersion::V7_4)?;
write_v7400_binary!(
writer=writer,
tree={
Hello: {}
World: {},
},
)?;
let _buf = writer.finalize_and_flush(&Default::default())?;
Ok(())
}
#[test]
fn nested_node() -> Result<()> {
let mut writer = Writer::new(Cursor::new(Vec::new()), FbxVersion::V7_4)?;
write_v7400_binary!(
writer=writer,
tree={
Hello: {
Hello1: {},
Hello2: {}
}
World: {
World1: {
World1_1: {}
World1_2: {}
}
World2: {},
},
},
)?;
let _buf = writer.finalize_and_flush(&Default::default())?;
Ok(())
}
#[test]
fn nested_node_with_attrs() -> Result<()> {
let mut writer = Writer::new(Cursor::new(Vec::new()), FbxVersion::V7_4)?;
write_v7400_binary!(
writer=writer,
tree={
Hello: {
Hello1: (vec!["string".into()]) {},
Hello2: [1.234f32, 42i64] {}
}
World: {
World1: {
World1_1: (vec!["Hello".into(), 42i32.into()]) {}
World1_2: [] {}
}
World2: {},
},
},
)?;
let _buf = writer.finalize_and_flush(&Default::default())?;
Ok(())
}
}