use std::io::Write;
use quick_xml::events::{BytesDecl, BytesEnd, BytesStart, BytesText, Event};
use quick_xml::Writer;
use super::error::Result;
use super::define::package::*;
use super::define::model::*;
impl Model {
pub fn write<W: Write>(self: &Self, writer: W) -> Result<()> {
let mut xml_writer = Writer::new_with_indent(writer, b' ', 2);
xml_writer.write_event(Event::Decl(BytesDecl::new("1.0", Some("UTF-8"), None)))?;
let mut model_elem = BytesStart::new("model");
model_elem.push_attribute(("xmlns", Namespace::CORE_NS));
model_elem.push_attribute(("unit", self.unit.to_string().as_str()));
if let Some(ref lang) = self.language {
model_elem.push_attribute(("xml:lang", lang.as_str()));
}
let mut required_extensions = self.required_extensions.clone();
if self.resources.slices.is_some() {
model_elem.push_attribute(("xmlns:s", Namespace::SLICE_NS));
required_extensions.push("s".to_string());
}
if !required_extensions.is_empty() {
model_elem.push_attribute(("requiredextensions", self.required_extensions.join(" ").as_str()));
}
if !self.recommended_extensions.is_empty() {
model_elem.push_attribute(("recommendedextensions", self.recommended_extensions.join(" ").as_str()));
}
xml_writer.write_event(Event::Start(model_elem))?;
for meta in &self.metadatas {
meta.write(&mut xml_writer)?;
}
self.resources.write(&mut xml_writer)?;
self.build.write(&mut xml_writer)?;
xml_writer.write_event(Event::End(BytesEnd::new("model")))?;
Ok(())
}
}
impl Metadata {
fn write<W: Write>(self: &Self, writer: &mut Writer<W>) -> Result<()> {
let mut elem = BytesStart::new("metadata");
elem.push_attribute(("name", self.name.as_str()));
if self.preserve {
elem.push_attribute(("preserve", "1"));
}
if let Some(ref dtype) = self.r#type {
elem.push_attribute(("type", dtype.as_str()));
}
writer.write_event(Event::Start(elem))?;
writer.write_event(Event::Text(BytesText::new(&self.value)))?;
writer.write_event(Event::End(BytesEnd::new("metadata")))?;
Ok(())
}
}
impl Resources {
fn write<W: Write>(self: &Self, writer: &mut Writer<W>) -> Result<()> {
writer.write_event(Event::Start(BytesStart::new("resources")))?;
for materials in &self.base_materials {
materials.write(writer)?;
}
for object in &self.objects {
object.write(writer)?;
}
if let Some(ref displacements) = self.displacements {
displacements.write(writer)?;
}
if let Some(ref materials) = self.materials {
materials.write(writer)?;
}
if let Some(ref slices) = self.slices {
slices.write(writer)?;
}
if let Some(ref volumetric) = self.volumetric {
volumetric.write(writer)?;
}
if let Some(ref implicit) = self.implicit {
implicit.write(writer)?;
}
writer.write_event(Event::End(BytesEnd::new("resources")))?;
Ok(())
}
}
impl BaseMaterials {
fn write<W: Write>(self: &Self, writer: &mut Writer<W>) -> Result<()> {
let mut elem = BytesStart::new("basematerials");
elem.push_attribute(("id", self.id.to_string().as_str()));
if let Some(props_id) = self.display_properties_id {
elem.push_attribute(("displaypropertiesid", props_id.to_string().as_str()));
}
writer.write_event(Event::Start(elem))?;
for material in &self.materials {
let mut base_elem = BytesStart::new("base");
base_elem.push_attribute(("name", material.name.as_str()));
base_elem.push_attribute(("displaycolor", material.display_color.to_string().as_str()));
writer.write_event(Event::Empty(base_elem))?;
}
writer.write_event(Event::End(BytesEnd::new("basematerials")))?;
Ok(())
}
}
impl Object {
fn write<W: Write>(self: &Self, writer: &mut Writer<W>) -> Result<()> {
let mut elem = BytesStart::new("object");
elem.push_attribute(("id", self.id.to_string().as_str()));
if self.r#type != ObjectType::Model {
elem.push_attribute(("type", self.r#type.to_string().as_str()));
}
if let Some(ref name) = self.name {
elem.push_attribute(("name", name.as_str()));
}
if let Some(ref partnumber) = self.part_number {
elem.push_attribute(("partnumber", partnumber.as_str()));
}
if let Some(ref thumbnail) = self.thumbnail {
elem.push_attribute(("thumbnail", thumbnail.as_str()));
}
if let Some(pid) = self.pid {
elem.push_attribute(("pid", pid.to_string().as_str()));
}
if let Some(pindex) = self.pindex {
elem.push_attribute(("pindex", pindex.to_string().as_str()));
}
if let Some(ref production) = self.production {
production.write(&mut elem)?;
}
if let Some(ref slice) = self.slice {
slice.write(&mut elem)?;
}
writer.write_event(Event::Start(elem))?;
if !self.metadata_group.metadatas.is_empty() {
writer.write_event(Event::Start(BytesStart::new("metadatagroup")))?;
for meta in &self.metadata_group.metadatas {
meta.write(writer)?;
}
writer.write_event(Event::End(BytesEnd::new("metadatagroup")))?;
}
match &self.content {
ObjectContent::Mesh(mesh) => mesh.write(writer)?,
ObjectContent::Components(components) => components.write(writer)?,
ObjectContent::BooleanShape(boolean_shape) => boolean_shape.write(writer)?,
ObjectContent::DisplacementMesh(displacement_mesh) => displacement_mesh.write(writer)?,
ObjectContent::Alternatives(alternatives) => alternatives.write(writer)?,
ObjectContent::LevelSet(levelset) => levelset.write(writer)?,
}
writer.write_event(Event::End(BytesEnd::new("object")))?;
Ok(())
}
}
impl Components {
fn write<W: Write>(self: &Self, writer: &mut Writer<W>) -> Result<()> {
writer.write_event(Event::Start(BytesStart::new("components")))?;
for component in &self.components {
let mut elem = BytesStart::new("component");
elem.push_attribute(("objectid", component.object_id.to_string().as_str()));
if let Some(ref transform) = component.transform {
elem.push_attribute(("transform", transform.to_string().as_str()));
}
if let Some(ref production) = component.production {
production.write(&mut elem)?;
}
writer.write_event(Event::Empty(elem))?;
}
writer.write_event(Event::End(BytesEnd::new("components")))?;
Ok(())
}
}
impl Build {
fn write<W: Write>(self: &Self, writer: &mut Writer<W>) -> Result<()> {
let mut build = BytesStart::new("build");
if let Some(ref production) = self.production {
production.write(&mut build)?;
}
writer.write_event(Event::Start(build))?;
for item in &self.items {
let mut elem = BytesStart::new("item");
elem.push_attribute(("objectid", item.object_id.to_string().as_str()));
if let Some(ref transform) = item.transform {
elem.push_attribute(("transform", transform.to_string().as_str()));
}
if let Some(ref partnumber) = item.part_number {
elem.push_attribute(("partnumber", partnumber.as_str()));
}
if let Some(ref production) = item.production {
production.write(&mut elem)?;
}
if item.metadata_group.metadatas.is_empty() {
writer.write_event(Event::Empty(elem))?;
} else {
writer.write_event(Event::Start(elem))?;
writer.write_event(Event::Start(BytesStart::new("metadatagroup")))?;
for meta in &item.metadata_group.metadatas {
meta.write(writer)?;
}
writer.write_event(Event::End(BytesEnd::new("metadatagroup")))?;
writer.write_event(Event::End(BytesEnd::new("item")))?;
}
}
writer.write_event(Event::End(BytesEnd::new("build")))?;
Ok(())
}
}