diff options
Diffstat (limited to 'examples/simple.rs')
-rw-r--r-- | examples/simple.rs | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/examples/simple.rs b/examples/simple.rs new file mode 100644 index 0000000..a4b76f2 --- /dev/null +++ b/examples/simple.rs @@ -0,0 +1,143 @@ +use std::convert::Infallible; +use std::error::Error; +use std::fmt::Debug; +use std::fs::File; +use std::io::BufReader; +use std::path::Path; + +use xml_stinks::deserializer::buffered::Buffered as BufferedDeserializer; +use xml_stinks::deserializer::{Deserializer, Error as DeserializerError, IgnoreEnd}; +use xml_stinks::tagged::TagStart; +use xml_stinks::DeserializeTagged; + +const MANIFEST_DIR: &str = std::env!("CARGO_MANIFEST_DIR"); + +fn main() -> Result<(), Box<dyn Error>> +{ + let data_file = Path::new(MANIFEST_DIR).join("examples/data.xml"); + + let reader = BufReader::new(File::open(data_file)?); + + let mut deserializer = BufferedDeserializer::new(reader); + + // Skip the <?xml version="1.0" encoding="UTF-8"?> + deserializer.skip_to_tag_start("data")?; + + let data = deserializer.de_tag::<Data>("data", IgnoreEnd::No)?; + + println!("The following data was deserialized:\n"); + + println!("Greeting: {}", data.greeting); + println!("Something: {}", data.something); + println!("Favorite food: {}", data.favorites.food); + println!("Favorite color: {}", data.favorites.color); + + Ok(()) +} + +#[derive(Debug)] +struct Data +{ + greeting: String, + something: String, + favorites: Favorites, +} + +impl DeserializeTagged for Data +{ + type Error = DataError; + + fn deserialize<TDeserializer: Deserializer>( + _start: &TagStart, + deserializer: &mut TDeserializer, + ) -> Result<Self, Self::Error> + { + let greeting_a = deserializer.de_text()?; + + let something = + deserializer.de_tag_with("something", IgnoreEnd::No, |_, deserializer| { + deserializer.de_text() + })?; + + let greeting_b = deserializer.de_text()?; + + let favorites = deserializer.de_tag::<Favorites>("favorites", IgnoreEnd::No)?; + + Ok(Self { + greeting: format!("{greeting_a} {greeting_b}"), + something, + favorites, + }) + } +} + +#[derive(Debug, thiserror::Error)] +enum DataError +{ + #[error("Invalid favorites")] + InvalidFavorites(#[from] FavoritesError), + + #[error(transparent)] + DeserializeFailed(#[from] DeserializerError<Infallible>), +} + +impl<DeError: Into<Self>> From<DeserializerError<DeError>> for DataError +{ + fn from(err: DeserializerError<DeError>) -> Self + { + if let DeserializerError::DeserializeFailed(de_err) = err { + return de_err.into(); + } + + err.into_never_de_err().into() + } +} + +#[derive(Debug)] +struct Favorites +{ + food: String, + color: String, +} + +impl DeserializeTagged for Favorites +{ + type Error = FavoritesError; + + fn deserialize<TDeserializer: Deserializer>( + _start: &TagStart, + deserializer: &mut TDeserializer, + ) -> Result<Self, Self::Error> + { + let food = + deserializer.de_tag_with("food", IgnoreEnd::No, |_, deserializer| { + deserializer.de_text() + })?; + + let color = + deserializer.de_tag_with("color", IgnoreEnd::No, |_, deserializer| { + deserializer.de_text() + })?; + + Ok(Self { food, color }) + } +} + +#[derive(Debug, thiserror::Error)] +enum FavoritesError +{ + #[error(transparent)] + DeserializeFailed(#[from] DeserializerError<Infallible>), +} + +impl<DeError: Into<Self>> From<DeserializerError<DeError>> for FavoritesError +{ + fn from(err: DeserializerError<DeError>) -> Self + { + if let DeserializerError::DeserializeFailed(de_err) = err { + return de_err.into(); + } + + err.into_never_de_err().into() + } +} |