#[derive(hard_xml::XmlWrite, hard_xml::XmlRead, Default, PartialEq, Clone, Debug)]
#[xml(tag = "Creatives")]
pub struct Creatives<'a> {
#[xml(child = "Creative")]
pub creatives: Vec<Creative<'a>>,
}
#[derive(hard_xml::XmlWrite, hard_xml::XmlRead, Default, PartialEq, Clone, Debug)]
#[xml(tag = "Creative")]
pub struct Creative<'a> {
#[xml(attr = "sequence", default)]
pub sequence: Option<i32>,
#[xml(attr = "apiFramework", default)]
pub api_framework: Option<std::borrow::Cow<'a, str>>,
#[xml(attr = "id", default)]
pub id: Option<std::borrow::Cow<'a, str>>,
#[xml(attr = "adId", default)]
pub ad_id: Option<std::borrow::Cow<'a, str>>,
#[xml(child = "CompanionAds", default)]
pub companion_ads: Option<crate::CompanionAds<'a>>,
#[xml(child = "CreativeExtensions", default)]
pub creative_extensions: Option<CreativeExtensions>,
#[xml(child = "Linear", default)]
pub linear: Option<crate::Linear<'a>>,
#[xml(child = "NonLinearAds", default)]
pub non_linear_ads: Option<crate::NonLinearAds<'a>>,
#[xml(child = "UniversalAdId", default)]
pub universal_ad_id: Vec<UniversalAdId<'a>>,
}
#[derive(hard_xml::XmlWrite, hard_xml::XmlRead, Default, PartialEq, Clone, Debug)]
#[xml(tag = "UniversalAdId")]
pub struct UniversalAdId<'a> {
#[xml(attr = "idRegistry", default = "unknown")]
pub id_registry: std::borrow::Cow<'a, str>,
#[xml(text, default = "unknown")]
pub id: std::borrow::Cow<'a, str>,
}
#[derive(hard_xml::XmlWrite, hard_xml::XmlRead, Default, PartialEq, Clone, Debug)]
#[xml(tag = "CreativeExtensions")]
pub struct CreativeExtensions {
#[xml(child = "CreativeExtension", default)]
pub creative_extensions: Vec<CreativeExtension>,
}
#[derive(Default, PartialEq, Clone, Debug)]
pub struct CreativeExtension {
pub mime_type: Option<String>,
pub xml: String,
}
impl CreativeExtension {
pub fn from_struct<T: hard_xml::XmlWrite>(
mime_type: &str,
value: &T,
) -> hard_xml::XmlResult<Self> {
Ok(Self {
mime_type: Some(mime_type.to_owned()),
xml: hard_xml::XmlWrite::to_string(value)?,
})
}
pub fn as_struct<'a, 'b, T>(&'a self) -> hard_xml::XmlResult<T>
where
T: hard_xml::XmlRead<'b>,
'a: 'b,
{
<T as hard_xml::XmlRead<'b>>::from_str(&self.xml)
}
}
impl hard_xml::XmlWrite for CreativeExtension {
fn to_writer<W: std::io::Write>(
&self,
writer: &mut hard_xml::XmlWriter<W>,
) -> hard_xml::XmlResult<()> {
writer.write_element_start("CreativeExtension")?;
if let Some(ref attr) = self.mime_type {
writer.write_attribute("type", attr)?;
}
writer.write_element_end_open()?;
write!(writer.inner, "{}", self.xml)?;
writer.write_element_end_close("CreativeExtension")?;
Ok(())
}
}
impl<'a> hard_xml::XmlRead<'a> for CreativeExtension {
fn from_reader(reader: &mut hard_xml::XmlReader<'a>) -> hard_xml::XmlResult<Self> {
use hard_xml::xmlparser::{ElementEnd, Token};
reader.read_till_element_start("CreativeExtension")?;
let mut mime_type = None;
while let Some(("type", value)) = reader.find_attribute()? {
mime_type = Some(match value {
std::borrow::Cow::Borrowed(s) => s.to_owned(),
std::borrow::Cow::Owned(s) => s,
});
}
if let Some(t) = reader.next() {
let t = t?;
if !matches!(
t,
Token::ElementEnd {
end: ElementEnd::Open,
..
}
) {
return Err(hard_xml::XmlError::UnexpectedToken {
token: format!("{t:?}"),
});
}
}
let mut depth = 0;
let mut xml = String::new();
while let Some(t) = reader.next() {
match t? {
Token::Declaration { span, .. }
| Token::ProcessingInstruction { span, .. }
| Token::Comment { span, .. }
| Token::DtdStart { span, .. }
| Token::EmptyDtd { span, .. }
| Token::EntityDeclaration { span, .. }
| Token::DtdEnd { span }
| Token::ElementStart { span, .. }
| Token::Cdata { span, .. } => xml.push_str(span.as_str()),
Token::Attribute { span, .. } => {
xml.push(' ');
xml.push_str(span.as_str())
}
Token::Text { text } => xml.push_str(text.as_str()),
Token::ElementEnd { end, span } => {
match end {
ElementEnd::Open => {
depth += 1;
}
ElementEnd::Close(_, name) => {
if depth == 0 && name.as_str() == "CreativeExtension" {
break;
} else {
depth -= 1;
}
}
ElementEnd::Empty => {}
};
xml.push_str(span.as_str())
}
}
}
Ok(Self { mime_type, xml })
}
}
crate::declare_test!(
test_creative_extension,
CreativeExtension,
r#"<CreativeExtension type="text/javascript">
<Ext>
<Some id="hoge">fuga</Some>
<Text><![CDATA[some cdata text]]></Text>
</Ext>
</CreativeExtension>"#,
CreativeExtension {
mime_type: Some("text/javascript".to_owned()),
xml: r#"
<Ext>
<Some id="hoge">fuga</Some>
<Text><![CDATA[some cdata text]]></Text>
</Ext>
"#
.into()
}
);
#[cfg(test)]
#[test]
fn test_creative_extension_attribute() {
let xml = r#"<CreativeExtension type="text/javascript" attr="value1">
<Ext>
<Some id="hoge">fuga</Some>
<Text><![CDATA[some cdata text]]></Text>
</Ext>
</CreativeExtension>"#;
let ext = crate::from_str::<CreativeExtension>(xml).unwrap();
assert_eq!(
ext,
CreativeExtension {
mime_type: Some("text/javascript".to_owned()),
xml: r#"
<Ext>
<Some id="hoge">fuga</Some>
<Text><![CDATA[some cdata text]]></Text>
</Ext>
"#
.into()
}
);
assert_eq!(
crate::to_string(&ext).unwrap(),
r#"<CreativeExtension type="text/javascript">
<Ext>
<Some id="hoge">fuga</Some>
<Text><![CDATA[some cdata text]]></Text>
</Ext>
</CreativeExtension>"#
);
}