aboutsummaryrefslogtreecommitdiff
path: root/examples/simple.rs
blob: 563530c94a55f36eee53593ec794d51e3137907d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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::{impl_from_deserializer_error, 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_from_deserializer_error!(DataError);

#[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_from_deserializer_error!(FavoritesError);