#[cfg(any(feature = "write", feature = "memory-optimized-read"))]
use instant_xml::{Error, Id};
#[cfg(feature = "write")]
use instant_xml::{Serializer, ToXml};
#[cfg(feature = "memory-optimized-read")]
use instant_xml::{Deserializer, FromXml, Kind};
#[cfg(feature = "speed-optimized-read")]
use serde::Deserialize;
use std::ops::Index;
const MATRIX_SIZE: usize = 12;
#[cfg_attr(feature = "speed-optimized-read", derive(Deserialize))]
#[cfg_attr(feature = "speed-optimized-read", serde(from = "String"))]
#[derive(Debug, PartialEq, Clone)]
pub struct Transform(pub [f64; MATRIX_SIZE]);
#[cfg(feature = "write")]
impl ToXml for Transform {
fn serialize<W: std::fmt::Write + ?Sized>(
&self,
field: Option<Id<'_>>,
serializer: &mut Serializer<W>,
) -> Result<(), Error> {
let prefix = match field {
Some(id) => {
let prefix = serializer.write_start(id.name, id.ns)?;
serializer.end_start()?;
Some((prefix, id.name))
}
None => None,
};
let transform_str = self
.0
.iter()
.map(|&m| format!("{:.6}", m))
.collect::<Vec<String>>()
.join(" ");
serializer.write_str(&transform_str)?;
if let Some((prefix, name)) = prefix {
serializer.write_close(prefix, name)?;
}
Ok(())
}
}
#[cfg(feature = "memory-optimized-read")]
impl<'xml> FromXml<'xml> for Transform {
fn matches(id: Id<'_>, field: Option<Id<'_>>) -> bool {
match field {
Some(field) => id == field,
None => false,
}
}
fn deserialize<'cx>(
into: &mut Self::Accumulator,
field: &'static str,
deserializer: &mut Deserializer<'cx, 'xml>,
) -> Result<(), Error> {
if into.is_some() {
return Err(Error::DuplicateValue(field));
}
let value = match deserializer.take_str()? {
Some(value) => value,
None => return Err(Error::MissingValue("No transform string found")),
};
let result = Transform::from(value.into_owned());
*into = Some(result);
Ok(())
}
type Accumulator = Option<Self>;
const KIND: Kind = Kind::Scalar;
}
#[cfg(any(feature = "memory-optimized-read", feature = "speed-optimized-read"))]
impl From<String> for Transform {
fn from(value: String) -> Self {
let values = value
.split(" ")
.map(|v| lexical_core::parse(v.as_bytes()).unwrap_or_default())
.collect::<Vec<f64>>();
Self(values.try_into().unwrap())
}
}
impl Index<usize> for Transform {
type Output = f64;
fn index(&self, index: usize) -> &Self::Output {
if index < MATRIX_SIZE {
&self.0[index]
} else {
panic!("Unexpected index for Transform {:?}", index);
}
}
}
#[cfg(feature = "write")]
#[cfg(test)]
mod write_tests {
use instant_xml::{ToXml, to_string};
use pretty_assertions::assert_eq;
use super::Transform;
#[derive(ToXml, PartialEq, Debug)]
struct TestTransform {
transform: Transform,
}
#[test]
#[rustfmt::skip]
fn toxml_test_transform() {
let xml_string = "<TestTransform><transform>3.665893 -2718.281828 1618.033988 707.106781 -1414.213562 2236.067977 1442.249570 -866.025403 0.693556 1732.050807 -523.598775 577.215664</transform></TestTransform>";
let test_transform = TestTransform{ transform: Transform([
3.665893, -2718.281828, 1618.033988,
707.106781, -1414.213562, 2236.067977,
1442.249570, -866.025403, 0.693556,
1732.050807, -523.598775, 577.215664,
])};
let transform_string = to_string(&test_transform).unwrap();
assert_eq!(transform_string, xml_string);
}
#[derive(ToXml, PartialEq, Debug)]
#[xml(rename = "rename")]
struct TestTransformRename {
#[xml(rename = "transform-matrix")]
transform: Transform,
}
#[test]
#[rustfmt::skip]
fn toxml_test_transform_rename() {
let xml_string = "<rename><transform-matrix>4.141592 -2718.281828 1618.033988 707.106781 -1414.213562 2236.067977 1442.249570 -866.025403 0.793147 1732.050807 -523.598775 577.215664</transform-matrix></rename>";
let test_transform = TestTransformRename {
transform: Transform([
4.141592, -2718.281828, 1618.033988,
707.106781, -1414.213562, 2236.067977,
1442.249570, -866.025403, 0.793147,
1732.050807, -523.598775, 577.215664,
])
};
let transform_string = to_string(&test_transform).unwrap();
assert_eq!(transform_string, xml_string);
}
}
#[cfg(feature = "memory-optimized-read")]
#[cfg(test)]
mod memory_optimized_read_tests {
use instant_xml::{FromXml, from_str};
use pretty_assertions::assert_eq;
use super::Transform;
#[derive(FromXml, PartialEq, Debug)]
struct TestTransform {
transform: Transform,
}
#[test]
#[rustfmt::skip]
fn fromxml_test_transform() {
let xml_string = "<TestTransform><transform>3.665893 -2718.281828 1618.033988 707.106781 -1414.213562 2236.067977 1442.249570 -866.025403 0.693556 1732.050807 -523.598775 577.215664</transform></TestTransform>";
let test_transform = from_str::<TestTransform>(xml_string).unwrap();
assert_eq!(
test_transform.transform,
Transform([
3.665893, -2718.281828, 1618.033988,
707.106781, -1414.213562, 2236.067977,
1442.249570, -866.025403, 0.693556,
1732.050807, -523.598775, 577.215664,
]));
}
#[derive(FromXml, PartialEq, Debug)]
#[xml(rename = "rename")]
struct TestTransformRename {
#[xml(rename = "transform-matrix")]
transform: Transform,
}
#[test]
#[rustfmt::skip]
fn fromxml_test_transform_rename() {
let xml_string =
"<rename><transform-matrix>4.141592 -2718.281828 1618.033988 707.106781 -1414.213562 2236.067977 1442.249570 -866.025403 0.793147 1732.050807 -523.598775 577.215664</transform-matrix></rename>";
let test_transform = from_str::<TestTransformRename>(xml_string).unwrap();
assert_eq!(
test_transform.transform,
Transform([
4.141592, -2718.281828, 1618.033988,
707.106781, -1414.213562, 2236.067977,
1442.249570, -866.025403, 0.793147,
1732.050807, -523.598775, 577.215664,
])
);
}
}
#[cfg(feature = "speed-optimized-read")]
#[cfg(test)]
mod speed_optimized_read_tests {
use pretty_assertions::assert_eq;
use serde::Deserialize;
use serde_roxmltree::from_str;
use super::Transform;
#[derive(Deserialize, PartialEq, Debug)]
struct TestTransform {
transform: Transform,
}
#[test]
#[rustfmt::skip]
fn fromxml_test_transform() {
let xml_string = "<TestTransform><transform>3.665893 -2718.281828 1618.033988 707.106781 -1414.213562 2236.067977 1442.249570 -866.025403 0.693556 1732.050807 -523.598775 577.215664</transform></TestTransform>";
let test_transform = from_str::<TestTransform>(xml_string).unwrap();
assert_eq!(
test_transform.transform,
Transform([
3.665893, -2718.281828, 1618.033988,
707.106781, -1414.213562, 2236.067977,
1442.249570, -866.025403, 0.693556,
1732.050807, -523.598775, 577.215664,
]));
}
#[derive(Deserialize, PartialEq, Debug)]
#[serde(rename = "rename")]
struct TestTransformRename {
#[serde(rename = "transform-matrix")]
transform: Transform,
}
#[test]
#[rustfmt::skip]
fn fromxml_test_transform_rename() {
let xml_string =
"<rename><transform-matrix>4.141592 -2718.281828 1618.033988 707.106781 -1414.213562 2236.067977 1442.249570 -866.025403 0.793147 1732.050807 -523.598775 577.215664</transform-matrix></rename>";
let test_transform = from_str::<TestTransformRename>(xml_string).unwrap();
assert_eq!(
test_transform.transform,
Transform([
4.141592, -2718.281828, 1618.033988,
707.106781, -1414.213562, 2236.067977,
1442.249570, -866.025403, 0.793147,
1732.050807, -523.598775, 577.215664,
])
);
}
}