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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
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()
}
}
|