From bdce3a36f72de6097fb78a917e29b7e093a6ef58 Mon Sep 17 00:00:00 2001 From: HampusM Date: Thu, 11 May 2023 21:27:36 +0200 Subject: docs: add examples --- examples/testing.rs | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 examples/testing.rs (limited to 'examples/testing.rs') diff --git a/examples/testing.rs b/examples/testing.rs new file mode 100644 index 0000000..3a9d912 --- /dev/null +++ b/examples/testing.rs @@ -0,0 +1,176 @@ +use std::convert::Infallible; +use std::error::Error; +use std::fmt::Debug; + +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; + +fn main() -> Result<(), Box> +{ + let mut deserializer = BufferedDeserializer::new( + concat!("BananaFruit",).as_bytes(), + ); + + let food = deserializer.de_tag::("food", IgnoreEnd::No)?; + + println!("Food {} with kind {:?}", food.name, food.kind); + + Ok(()) +} + +#[derive(Debug)] +struct Food +{ + name: String, + kind: FoodKind, +} + +impl DeserializeTagged for Food +{ + type Error = FoodError; + + fn deserialize( + _start: &TagStart, + deserializer: &mut TDeserializer, + ) -> Result + { + let name = + deserializer.de_tag_with("name", IgnoreEnd::No, |_, deserializer| { + deserializer.de_text() + })?; + + let kind = + deserializer.de_tag_with("kind", IgnoreEnd::No, |_, deserializer| { + match deserializer.de_text()?.as_str() { + "Fruit" => Ok(FoodKind::Fruit), + "Vegetable" => Ok(FoodKind::Vegetable), + unknown_kind => { + Err(FoodError::UnknownFoodKind(unknown_kind.to_string())) + } + } + })?; + + Ok(Self { name, kind }) + } +} + +#[derive(Debug)] +enum FoodKind +{ + Fruit, + Vegetable, +} + +#[derive(Debug, thiserror::Error)] +enum FoodError +{ + #[error("Unknown food kind '{0}'")] + UnknownFoodKind(String), + + #[error(transparent)] + DeserializeFailed(#[from] DeserializerError), +} + +impl> From> for FoodError +{ + fn from(err: DeserializerError) -> Self + { + if let DeserializerError::DeserializeFailed(de_err) = err { + return de_err.into(); + } + + err.into_never_de_err().into() + } +} + +#[cfg(test)] +mod tests +{ + use mockall::mock; + use mockall::predicate::{always, eq}; + use xml_stinks::deserializer::{Error, MaybeStatic}; + + use super::*; + + mock! { + pub Deserializer {} + + impl Deserializer for Deserializer + { + fn de_tag( + &mut self, + tag_name: &str, + ignore_end: IgnoreEnd, + ) -> Result>; + + fn de_tag_with( + &mut self, + tag_name: &str, + ignore_end: IgnoreEnd, + deserialize: Func, + ) -> Result> + where + TOutput: MaybeStatic, + Err: std::error::Error + Send + Sync + 'static, + Func: FnOnce(&TagStart, &mut MockDeserializer) -> Result + MaybeStatic; + + fn de_tag_list( + &mut self, + tag_name: Option + ) -> Result, Error> + where + De: DeserializeTagged, + TagName: AsRef + MaybeStatic; + + fn de_text(&mut self) -> Result>; + + fn skip_to_tag_start(&mut self, tag_name: &str) -> Result<(), Error>; + + fn skip_to_tag_end(&mut self, tag_name: &str) -> Result<(), Error>; + } + } + + #[test] + fn deserialize_food_works() + { + let mut mock_deserializer = MockDeserializer::new(); + + mock_deserializer + .expect_de_tag_with::>() + .with(eq("name"), eq(IgnoreEnd::No), always()) + .returning(|tag_name, _, func| { + let mut deserializer = MockDeserializer::new(); + + deserializer + .expect_de_text() + .returning(|| Ok("Carrot".to_string())) + .once(); + + Ok(func(&TagStart::new(tag_name), &mut deserializer)?) + }) + .once(); + + mock_deserializer + .expect_de_tag_with::() + .with(eq("kind"), eq(IgnoreEnd::No), always()) + .returning(|tag_name, _, func| { + let mut deserializer = MockDeserializer::new(); + + deserializer + .expect_de_text() + .returning(|| Ok("Vegetable".to_string())) + .once(); + + Ok(func(&TagStart::new(tag_name), &mut deserializer)?) + }) + .once(); + + let food = Food::deserialize(&TagStart::new("food"), &mut mock_deserializer) + .expect("Expected Ok"); + + assert_eq!(food.name, "Carrot"); + assert!(matches!(food.kind, FoodKind::Vegetable)); + } +} -- cgit v1.2.3-18-g5258