#[cfg(any(feature = "write", feature = "memory-optimized-read"))]
use instant_xml::Error;
#[cfg(feature = "write")]
use instant_xml::ToXml;
#[cfg(feature = "memory-optimized-read")]
use instant_xml::{FromXml, Kind};
#[cfg(feature = "speed-optimized-read")]
use serde::Deserialize;
const RELATIONSHIP_NS: &str = "http://schemas.openxmlformats.org/package/2006/relationships";
#[cfg_attr(feature = "speed-optimized-read", derive(Deserialize))]
#[cfg_attr(feature = "memory-optimized-read", derive(FromXml))]
#[cfg_attr(feature = "write", derive(ToXml))]
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(
any(feature = "write", feature = "memory-optimized-read"),
xml(ns(RELATIONSHIP_NS))
)]
pub struct Relationship {
#[cfg_attr(
any(feature = "write", feature = "memory-optimized-read"),
xml(attribute, rename = "Id")
)]
#[cfg_attr(feature = "speed-optimized-read", serde(rename = "Id"))]
pub id: String,
#[cfg_attr(
any(feature = "write", feature = "memory-optimized-read"),
xml(attribute, rename = "Target")
)]
#[cfg_attr(feature = "speed-optimized-read", serde(rename = "Target"))]
pub target: String,
#[cfg_attr(
any(feature = "write", feature = "memory-optimized-read"),
xml(attribute, rename = "Type")
)]
#[cfg_attr(feature = "speed-optimized-read", serde(rename = "Type"))]
pub relationship_type: RelationshipType,
}
#[cfg_attr(feature = "speed-optimized-read", derive(Deserialize))]
#[cfg_attr(feature = "memory-optimized-read", derive(FromXml))]
#[cfg_attr(feature = "write", derive(ToXml))]
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(
any(feature = "write", feature = "memory-optimized-read"),
xml(ns(RELATIONSHIP_NS))
)]
pub struct Relationships {
#[cfg_attr(feature = "speed-optimized-read", serde(rename = "Relationship"))]
pub relationships: Vec<Relationship>,
}
#[cfg_attr(feature = "speed-optimized-read", derive(Deserialize))]
#[cfg_attr(feature = "speed-optimized-read", serde(from = "String"))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RelationshipType {
Thumbnail,
Model,
Unknown(String),
}
const THUMBNAIL_TYPE_NS: &str =
"http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
const MODEL_TYPE_NS: &str = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel";
#[cfg(feature = "write")]
impl ToXml for RelationshipType {
fn serialize<W: std::fmt::Write + ?Sized>(
&self,
_: Option<instant_xml::Id<'_>>,
serializer: &mut instant_xml::Serializer<W>,
) -> Result<(), Error> {
let ns_str = match self {
Self::Thumbnail => THUMBNAIL_TYPE_NS,
Self::Model => MODEL_TYPE_NS,
Self::Unknown(value) => value,
};
serializer.write_str(ns_str)?;
Ok(())
}
}
#[cfg(feature = "memory-optimized-read")]
impl<'xml> FromXml<'xml> for RelationshipType {
fn matches(id: instant_xml::Id<'_>, field: Option<instant_xml::Id<'_>>) -> bool {
match field {
Some(field) => id == field,
None => false,
}
}
fn deserialize<'cx>(
into: &mut Self::Accumulator,
field: &'static str,
deserializer: &mut instant_xml::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 RelationshipType string found")),
};
match value.into_owned().as_ref() {
THUMBNAIL_TYPE_NS => *into = Some(Self::Thumbnail),
MODEL_TYPE_NS => *into = Some(Self::Model),
value => *into = Some(Self::Unknown(value.to_owned())),
}
Ok(())
}
type Accumulator = Option<Self>;
const KIND: Kind = Kind::Scalar;
}
impl From<String> for RelationshipType {
fn from(value: String) -> Self {
match value.as_ref() {
THUMBNAIL_TYPE_NS => Self::Thumbnail,
MODEL_TYPE_NS => Self::Model,
value => Self::Unknown(value.to_owned()),
}
}
}
#[cfg(feature = "write")]
#[cfg(test)]
mod write_tests {
use instant_xml::to_string;
use pretty_assertions::assert_eq;
use super::{
MODEL_TYPE_NS, RELATIONSHIP_NS, Relationship, RelationshipType, Relationships,
THUMBNAIL_TYPE_NS,
};
#[test]
pub fn toxml_relationships_test() {
let xml_string = format!(
r#"<Relationships xmlns="{}"><Relationship Id="someId" Target="//somePath//Of//Resources" Type="{}" /><Relationship Id="someId1" Target="//somePath//Of//Resources" Type="{}" /><Relationship Id="someId2" Target="//somePath//Of//Unknown" Type="unknown" /></Relationships>"#,
RELATIONSHIP_NS, MODEL_TYPE_NS, THUMBNAIL_TYPE_NS
);
let relationships = Relationships {
relationships: vec![
Relationship {
id: "someId".to_owned(),
target: "//somePath//Of//Resources".to_owned(),
relationship_type: RelationshipType::Model,
},
Relationship {
id: "someId1".to_owned(),
target: "//somePath//Of//Resources".to_owned(),
relationship_type: RelationshipType::Thumbnail,
},
Relationship {
id: "someId2".to_owned(),
target: "//somePath//Of//Unknown".to_owned(),
relationship_type: RelationshipType::Unknown("unknown".to_owned()),
},
],
};
let relationships_string = to_string(&relationships).unwrap();
assert_eq!(relationships_string, xml_string);
}
}
#[cfg(feature = "memory-optimized-read")]
#[cfg(test)]
mod memory_optimized_read_tests {
use instant_xml::from_str;
use pretty_assertions::assert_eq;
use super::{
MODEL_TYPE_NS, RELATIONSHIP_NS, Relationship, RelationshipType, Relationships,
THUMBNAIL_TYPE_NS,
};
#[test]
pub fn fromxml_relationships_test() {
let xml_string = format!(
r#"<Relationships xmlns="{}"><Relationship Id="someId" Target="//somePath//Of//Resources" Type="{}" /><Relationship Id="someId1" Target="//somePath//Of//Resources" Type="{}" /><Relationship Id="someId2" Target="//somePath//Of//Unknown" Type="unknown" /></Relationships>"#,
RELATIONSHIP_NS, MODEL_TYPE_NS, THUMBNAIL_TYPE_NS
);
let relationships = from_str::<Relationships>(&xml_string).unwrap();
assert_eq!(
relationships,
Relationships {
relationships: vec![
Relationship {
id: "someId".to_owned(),
target: "//somePath//Of//Resources".to_owned(),
relationship_type: RelationshipType::Model,
},
Relationship {
id: "someId1".to_owned(),
target: "//somePath//Of//Resources".to_owned(),
relationship_type: RelationshipType::Thumbnail,
},
Relationship {
id: "someId2".to_owned(),
target: "//somePath//Of//Unknown".to_owned(),
relationship_type: RelationshipType::Unknown("unknown".to_owned()),
},
],
}
);
}
}
#[cfg(feature = "speed-optimized-read")]
#[cfg(test)]
mod speed_optimized_read_tests {
use pretty_assertions::assert_eq;
use serde_roxmltree::from_str;
use super::{
MODEL_TYPE_NS, RELATIONSHIP_NS, Relationship, RelationshipType, Relationships,
THUMBNAIL_TYPE_NS,
};
#[test]
pub fn fromxml_relationships_test() {
let xml_string = format!(
r#"<Relationships xmlns="{}"><Relationship Id="someId" Target="//somePath//Of//Resources" Type="{}" /><Relationship Id="someId1" Target="//somePath//Of//Resources" Type="{}" /><Relationship Id="someId2" Target="//somePath//Of//Unknown" Type="unknown" /></Relationships>"#,
RELATIONSHIP_NS, MODEL_TYPE_NS, THUMBNAIL_TYPE_NS
);
let relationships = from_str::<Relationships>(&xml_string).unwrap();
assert_eq!(
relationships,
Relationships {
relationships: vec![
Relationship {
id: "someId".to_owned(),
target: "//somePath//Of//Resources".to_owned(),
relationship_type: RelationshipType::Model,
},
Relationship {
id: "someId1".to_owned(),
target: "//somePath//Of//Resources".to_owned(),
relationship_type: RelationshipType::Thumbnail,
},
Relationship {
id: "someId2".to_owned(),
target: "//somePath//Of//Unknown".to_owned(),
relationship_type: RelationshipType::Unknown("unknown".to_owned()),
},
],
}
);
}
}