Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,33 @@ impl SerdeXml {
self.from_reader(s.as_bytes())
}

/// Same as [`crate::from_str_with`], but uses the config `self`.
pub fn from_str_with<T>(self, s: &str, deserialize: impl FnOnce(&mut Deserializer<&[u8]>) -> Result<T>) -> Result<T> {
self.from_reader_with(s.as_bytes(), deserialize)
}

pub fn from_reader<'de, T: Deserialize<'de>, R: Read>(self, reader: R) -> Result<T> {
T::deserialize(&mut Deserializer::from_config(self, reader))
}

/// Same as [`crate::from_reader_with`], but uses the config `self`.
pub fn from_reader_with<R: Read, T>(self, reader: R, deserialize: impl FnOnce(&mut Deserializer<R>) -> Result<T>) -> Result<T> {
deserialize(&mut Deserializer::from_config(self, reader))
}

pub fn to_string<S: Serialize>(self, value: &S) -> Result<String> {
let mut buffer = Vec::new();
self.to_writer(&mut buffer, value)?;
Ok(String::from_utf8(buffer)?)
}

/// Same as [`crate::to_string_with`], but uses the config `self`.
pub fn to_string_with(self, serialize: impl FnOnce(&mut Serializer<&mut Vec<u8>>) -> Result<()>) -> Result<String> {
let mut buffer = Vec::new();
self.to_writer_with(&mut buffer, serialize)?;
Ok(String::from_utf8(buffer)?)
}

pub fn to_writer<W, S>(self, writer: W, value: &S) -> Result<()>
where
W: Write,
Expand All @@ -113,6 +130,11 @@ impl SerdeXml {
let mut s = Serializer::from_config(self, writer);
value.serialize(&mut s)
}

/// Same as [`crate::to_writer_with`], but uses the config `self`.
pub fn to_writer_with<W: Write>(self, writer: W, serialize: impl FnOnce(&mut Serializer<W>) -> Result<()>) -> Result<()> {
serialize(&mut Serializer::new_from_writer(writer))
}
}

#[derive(Clone, Debug, Default)]
Expand Down
73 changes: 73 additions & 0 deletions src/de/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,42 @@ pub fn from_str<'de, T: Deserialize<'de>>(s: &str) -> Result<T> {
from_reader(s.as_bytes())
}

/// A convenience method for deserializing from a [string][str] with a custom [`Deserialize`] function.
///
/// See how to [manually implement `Deserialize`](https://serde.rs/impl-deserialize.html).
///
/// # Example
///
/// ```no_run
/// # use serde::{Deserialize, de::{Deserializer, Visitor}};
/// # use serde_xml_rs::from_str_with;
/// let s = r##"<item><name>hello</name><source>world.rs</source></item>"##;
/// let item: (String, String) = from_str_with(s, |deserializer| {
/// #[derive(Deserialize)]
/// #[serde(field_identifier, rename_all = "lowercase")]
/// enum Field { Name, Source }
///
/// struct ItemVisitor;
/// impl<'de> Visitor<'de> for ItemVisitor {
/// type Value = (String, String);
///
/// fn expecting(&self, _: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
/// // ...
/// # Ok(())
/// }
/// // ...
/// }
///
/// deserializer.deserialize_struct("item", &["name", "source"], ItemVisitor)
/// }).unwrap();
///
/// assert_eq!(item.0, "hello");
/// assert_eq!(item.1, "world.rs");
/// ```
pub fn from_str_with<T>(s: &str, deserialize: impl FnOnce(&mut Deserializer<&[u8]>) -> Result<T>) -> Result<T> {
from_reader_with(s.as_bytes(), deserialize)
}

/// A convenience method for deserialize some object from a reader.
///
/// ```rust
Expand All @@ -62,6 +98,43 @@ pub fn from_reader<'de, T: Deserialize<'de>, R: Read>(reader: R) -> Result<T> {
T::deserialize(&mut Deserializer::from_config(SerdeXml::default(), reader))
}

/// A convenience method for deserializing from some [reader][Read] with a custom [`Deserialize`] function.
///
/// See how to [manually implement `Deserialize`](https://serde.rs/impl-deserialize.html).
///
/// # Example
///
/// ```no_run
/// # use serde::{Deserialize, de::{Deserializer, Visitor}};
/// # use serde_xml_rs::from_reader_with;
/// let file = std::fs::File::open("file.xml").unwrap(); // <item><name>hello</name><source>world.rs</source></item>
/// let item: (String, String) = from_reader_with(&file, |deserializer| {
/// #[derive(Deserialize)]
/// #[serde(field_identifier, rename_all = "lowercase")]
/// enum Field { Name, Source }
///
/// struct ItemVisitor;
/// impl<'de> Visitor<'de> for ItemVisitor {
/// type Value = (String, String);
///
/// fn expecting(&self, _: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
/// // ...
/// # Ok(())
/// }
///
/// // ...
/// }
///
/// deserializer.deserialize_struct("item", &["name", "source"], ItemVisitor)
/// }).unwrap();
///
/// assert_eq!(item.0, "hello");
/// assert_eq!(item.1, "world.rs");
/// ```
pub fn from_reader_with<R: Read, T>(reader: R, deserialize: impl FnOnce(&mut Deserializer<R>) -> Result<T>) -> Result<T> {
SerdeXml::default().from_reader_with(reader, deserialize)
}

pub struct Deserializer<R: Read> {
reader: RootReader<R>,
}
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ pub mod ser;
mod test;

pub use crate::config::SerdeXml;
pub use crate::de::{from_reader, from_str, Deserializer};
pub use crate::de::{from_reader, from_reader_with, from_str, from_str_with, Deserializer};
pub use crate::error::Error;
pub use crate::ser::{to_string, to_writer, Serializer};
pub use crate::ser::{to_string, to_string_with, to_writer, to_writer_with, Serializer};

#[doc = include_str!("../README.md")]
#[cfg(doctest)]
Expand Down
39 changes: 39 additions & 0 deletions src/ser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,26 @@ pub fn to_string<S: Serialize>(value: &S) -> Result<String> {
Ok(String::from_utf8(buffer)?)
}

/// A convenience method for serializing to a [String] with a custom [`Serialize`] function.
///
/// # Example
///
/// ```
/// # use serde::ser::{Serialize, Serializer, SerializeStructVariant as _};
/// # use serde_xml_rs::to_string_with;
/// let serialized = to_string_with(|serializer| {
/// let mut s = serializer.serialize_struct("person", 2)?;
/// s.serialize_field("name", "joe")?;
/// s.serialize_field("age", &42)?;
/// s.end()
/// }).unwrap();
///
/// assert_eq!(serialized, r#"<?xml version="1.0" encoding="UTF-8"?><person><name>joe</name><age>42</age></person>"#);
/// ```
pub fn to_string_with(serialize: impl FnOnce(&mut Serializer<&mut Vec<u8>>) -> Result<()>) -> Result<String> {
SerdeXml::default().to_string_with(serialize)
}

/// A convenience method for serializing some object to a buffer.
///
/// # Examples
Expand Down Expand Up @@ -70,6 +90,25 @@ pub fn to_writer<W: Write, S: Serialize>(writer: W, value: &S) -> Result<()> {
value.serialize(&mut serializer)
}

/// A convenience method for serializing to a [writer][Write] with a custom [`Serialize`] function.
///
/// # Example
///
/// ```no_run
/// # use serde::ser::{Serialize, Serializer, SerializeStructVariant as _};
/// # use serde_xml_rs::to_writer_with;
/// let mut file = std::fs::File::options().write(true).open("file.xml").unwrap();
/// let serialized = to_writer_with(&mut file, |serializer| {
/// let mut s = serializer.serialize_struct("person", 2)?;
/// s.serialize_field("name", "joe")?;
/// s.serialize_field("age", &42)?;
/// s.end()
/// }).unwrap(); // <?xml version="1.0" encoding="UTF-8"?><person><name>joe</name><age>42</age></person>"
/// ```
pub fn to_writer_with<W: Write>(writer: W, serialize: impl FnOnce(&mut Serializer<W>) -> Result<()>) -> Result<()> {
SerdeXml::default().to_writer_with(writer, serialize)
}

/// An XML `Serializer`.
pub struct Serializer<W> {
writer: Writer<W>,
Expand Down
Loading