use std::io::{BufRead, Write};
use quick_xml::events::attributes::Attributes;
use quick_xml::events::{BytesEnd, BytesStart, Event};
use quick_xml::Error as XmlError;
use quick_xml::Reader;
use quick_xml::Writer;
use crate::error::Error;
use crate::toxml::{ToXml, WriterExt};
use crate::util::{decode, element_text, skip};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "builders", derive(Builder))]
#[cfg_attr(
feature = "builders",
builder(
setter(into),
default,
build_fn(name = "build_impl", private, error = "never::Never")
)
)]
pub struct Image {
pub url: String,
pub title: String,
pub link: String,
pub width: Option<String>,
pub height: Option<String>,
pub description: Option<String>,
}
impl Image {
pub fn url(&self) -> &str {
self.url.as_str()
}
pub fn set_url<V>(&mut self, url: V)
where
V: Into<String>,
{
self.url = url.into();
}
pub fn title(&self) -> &str {
self.title.as_str()
}
pub fn set_title<V>(&mut self, title: V)
where
V: Into<String>,
{
self.title = title.into();
}
pub fn link(&self) -> &str {
self.link.as_str()
}
pub fn set_link<V>(&mut self, link: V)
where
V: Into<String>,
{
self.link = link.into();
}
pub fn width(&self) -> Option<&str> {
self.width.as_deref()
}
pub fn set_width<V>(&mut self, width: V)
where
V: Into<Option<String>>,
{
self.width = width.into();
}
pub fn height(&self) -> Option<&str> {
self.height.as_deref()
}
pub fn set_height<V>(&mut self, height: V)
where
V: Into<Option<String>>,
{
self.height = height.into();
}
pub fn description(&self) -> Option<&str> {
self.description.as_deref()
}
pub fn set_description<V>(&mut self, description: V)
where
V: Into<Option<String>>,
{
self.description = description.into();
}
}
impl Image {
pub fn from_xml<R: BufRead>(reader: &mut Reader<R>, _: Attributes) -> Result<Self, Error> {
let mut image = Image::default();
let mut buf = Vec::new();
loop {
match reader.read_event_into(&mut buf)? {
Event::Start(element) => match decode(element.name().as_ref(), reader)?.as_ref() {
"url" => image.url = element_text(reader)?.unwrap_or_default(),
"title" => image.title = element_text(reader)?.unwrap_or_default(),
"link" => image.link = element_text(reader)?.unwrap_or_default(),
"width" => image.width = element_text(reader)?,
"height" => image.height = element_text(reader)?,
"description" => image.description = element_text(reader)?,
_ => skip(element.name(), reader)?,
},
Event::End(_) => break,
Event::Eof => return Err(Error::Eof),
_ => {}
}
buf.clear();
}
Ok(image)
}
}
impl ToXml for Image {
fn to_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<(), XmlError> {
let name = "image";
writer.write_event(Event::Start(BytesStart::new(name)))?;
writer.write_text_element("url", &self.url)?;
writer.write_text_element("title", &self.title)?;
writer.write_text_element("link", &self.link)?;
if let Some(width) = self.width.as_ref() {
writer.write_text_element("width", width)?;
}
if let Some(height) = self.height.as_ref() {
writer.write_text_element("height", height)?;
}
if let Some(description) = self.description.as_ref() {
writer.write_text_element("description", description)?;
}
writer.write_event(Event::End(BytesEnd::new(name)))?;
Ok(())
}
}
#[cfg(feature = "builders")]
impl ImageBuilder {
pub fn build(&self) -> Image {
self.build_impl().unwrap()
}
}