xsd_parser/quick_xml/deserialize.rs
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 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
use std::fmt::Debug;
use std::marker::PhantomData;
use std::str::{from_utf8, FromStr};
use quick_xml::events::Event;
use super::{Error, ErrorKind, XmlReader, XmlReaderSync};
/// Trait that defines the [`Deserializer`] for a type.
pub trait WithDeserializer: Sized {
/// The deserializer to use for this type.
type Deserializer: for<'de> Deserializer<'de, Self>;
}
impl<X> WithDeserializer for X
where
X: DeserializeBytes + Debug,
{
type Deserializer = ContentDeserializer<X>;
}
/// Trait that defines a deserializer that can be used to construct a type from a
/// XML [`Event`]s.
pub trait Deserializer<'de, T>: Debug + Sized {
/// Initializes a new deserializer from the passed `reader` and the initial `event`.
///
/// # Errors
///
/// Returns an [`Error`] if the initialization of the deserializer failed.
fn init<R>(reader: &R, event: Event<'de>) -> DeserializerResult<'de, T, Self>
where
R: XmlReader;
/// Processes the next XML [`Event`].
///
/// # Errors
///
/// Returns an [`Error`] if processing the event failed.
fn next<R>(self, reader: &R, event: Event<'de>) -> DeserializerResult<'de, T, Self>
where
R: XmlReader;
/// Force the deserializer to finish.
///
/// # Errors
///
/// Returns an [`Error`] if the deserializer could not finish.
fn finish<R>(self, reader: &R) -> Result<T, Error>
where
R: XmlReader;
}
/// Result type returned by the [`Deserializer`] trait.
pub type DeserializerResult<'a, T, B> = Result<DeserializerOutput<'a, T, B>, Error>;
/// Type that is used to bundle the output of a [`Deserializer`] operation.
#[derive(Debug)]
pub struct DeserializerOutput<'a, T, B> {
/// Contains the actual type constructed by the deserializer, once the deserializer has
/// finished it's construction. If this is `None`, constructing the object has
/// not been finished yet.
pub data: Option<T>,
/// Contains the deserializer after an operation on the deserializer has been executed.
/// If this is `None` the deserializer is finished and can not be re-used.
pub deserializer: Option<B>,
/// Contains the processed event if it was not consumed by the deserializer.
pub event: Option<Event<'a>>,
/// Whether the deserializer allows other XML elements in the current state or not.
/// If this is set to `true` and the `event` is not consumed, the event should
/// be skipped. For [`Event::Start`] this would mean to skip the whole element
/// until the corresponding [`Event::End`] is received.
pub allow_any: bool,
}
/// Trait that could be implemented by types to support deserialization from XML
/// using the [`quick_xml`] crate.
pub trait DeserializeSync<'de, R>: Sized
where
R: XmlReaderSync<'de>,
{
/// Error that is returned by the `deserialize` method.
type Error;
/// Deserialize the type from the passed `reader`.
///
/// # Errors
///
/// Will return a suitable error if the operation failed.
fn deserialize(reader: &mut R) -> Result<Self, Self::Error>;
}
impl<'de, R, X> DeserializeSync<'de, R> for X
where
R: XmlReaderSync<'de>,
X: WithDeserializer,
{
type Error = Error;
fn deserialize(reader: &mut R) -> Result<Self, Self::Error> {
DeserializeHelper::new(reader).deserialize_sync()
}
}
/// Trait that could be implemented by types to support asynchronous
/// deserialization from XML using the [`quick_xml`] crate.
#[cfg(feature = "async")]
pub trait DeserializeAsync<'de, R>: Sized
where
R: super::XmlReaderAsync<'de>,
{
/// Future that is returned by the [`deserialize_async`] method.
type Future<'x>: std::future::Future<Output = Result<Self, Self::Error>>
where
R: 'x,
'de: 'x;
/// Error that is returned by the future generated by the [`deserialize_async`] method.
type Error;
/// Asynchronously deserializes the type from the passed `reader`.
fn deserialize_async<'x>(reader: &'x mut R) -> Self::Future<'x>
where
'de: 'x;
}
#[cfg(feature = "async")]
impl<'de, R, X> DeserializeAsync<'de, R> for X
where
R: super::XmlReaderAsync<'de>,
X: WithDeserializer,
{
type Future<'x>
= std::pin::Pin<Box<dyn std::future::Future<Output = Result<Self, Self::Error>> + 'x>>
where
R: 'x,
'de: 'x;
type Error = Error;
fn deserialize_async<'x>(reader: &'x mut R) -> Self::Future<'x>
where
'de: 'x,
{
Box::pin(async move { DeserializeHelper::new(reader).deserialize_async().await })
}
}
/// Trait that could be implemented by types to support deserialization from
/// XML byte streams using the [`quick_xml`] crate.
///
/// This is usually implemented for simple types like numbers, strings or enums.
pub trait DeserializeBytes: Sized {
/// Try to deserialize the type from bytes.
///
/// This is used to deserialize the type from attributes or raw element
/// content.
///
/// # Errors
///
/// Returns a suitable [`Error`] if the deserialization was not successful.
fn deserialize_bytes<R: XmlReader>(reader: &R, bytes: &[u8]) -> Result<Self, Error>;
}
impl<X> DeserializeBytes for X
where
X: FromStr,
X::Err: std::error::Error + Send + Sync + 'static,
{
fn deserialize_bytes<R: XmlReader>(reader: &R, bytes: &[u8]) -> Result<Self, Error> {
let _reader = reader;
let s = from_utf8(bytes).map_err(Error::from)?;
X::from_str(s).map_err(Error::custom)
}
}
/// Implements a [`Deserializer`] for any type that implements [`DeserializeBytes`].
#[derive(Debug)]
pub struct ContentDeserializer<T> {
data: Vec<u8>,
marker: PhantomData<T>,
}
impl<'de, T> Deserializer<'de, T> for ContentDeserializer<T>
where
T: DeserializeBytes + Debug,
{
fn init<R>(reader: &R, event: Event<'de>) -> DeserializerResult<'de, T, Self>
where
R: XmlReader,
{
match event {
Event::Start(_) => Ok(DeserializerOutput {
data: None,
deserializer: Some(Self {
data: Vec::new(),
marker: PhantomData,
}),
event: None,
allow_any: false,
}),
Event::Empty(_) => {
let data = T::deserialize_bytes(reader, &[])?;
Ok(DeserializerOutput {
data: Some(data),
deserializer: None,
event: None,
allow_any: false,
})
}
event => Ok(DeserializerOutput {
data: None,
deserializer: None,
event: Some(event),
allow_any: false,
}),
}
}
fn next<R>(mut self, reader: &R, event: Event<'de>) -> DeserializerResult<'de, T, Self>
where
R: XmlReader,
{
match event {
Event::Text(x) => {
self.data.extend_from_slice(&x.into_inner());
Ok(DeserializerOutput {
data: None,
deserializer: Some(self),
event: None,
allow_any: false,
})
}
Event::End(_) => {
let data = self.finish(reader)?;
Ok(DeserializerOutput {
data: Some(data),
deserializer: None,
event: None,
allow_any: false,
})
}
event => Ok(DeserializerOutput {
data: None,
deserializer: Some(self),
event: Some(event),
allow_any: false,
}),
}
}
fn finish<R>(self, reader: &R) -> Result<T, Error>
where
R: XmlReader,
{
T::deserialize_bytes(reader, &self.data)
}
}
/* DeserializeHelper */
struct DeserializeHelper<'a, 'de, T, R>
where
T: WithDeserializer,
{
reader: &'a mut R,
deserializer: Option<T::Deserializer>,
skip_depth: Option<usize>,
marker: PhantomData<&'de ()>,
}
impl<'a, 'de, T, R> DeserializeHelper<'a, 'de, T, R>
where
T: WithDeserializer,
R: XmlReader,
{
fn new(reader: &'a mut R) -> Self {
Self {
reader,
deserializer: None,
skip_depth: None,
marker: PhantomData,
}
}
fn handle_event(&mut self, event: Event<'_>) -> Result<Option<T>, Error> {
let ret = match self.deserializer.take() {
None => T::Deserializer::init(self.reader, event),
Some(b) => b.next(self.reader, event),
};
let DeserializerOutput {
data,
deserializer,
event,
allow_any,
} = ret?;
self.deserializer = deserializer;
match event {
None
| Some(
Event::Decl(_)
| Event::Text(_)
| Event::Comment(_)
| Event::DocType(_)
| Event::PI(_),
) => (),
Some(event) if allow_any => {
if matches!(event, Event::Start(_)) {
self.skip_depth = Some(1);
}
}
Some(event) => return Err(ErrorKind::UnexpectedEvent(event.into_owned()).into()),
}
Ok(data)
}
fn handle_skip(&mut self, event: Event<'de>) -> Option<Event<'de>> {
let Some(skip_depth) = self.skip_depth.as_mut() else {
return Some(event);
};
match event {
Event::Start(_) => *skip_depth += 1,
Event::End(_) if *skip_depth == 1 => {
self.skip_depth = None;
return None;
}
Event::End(_) => *skip_depth -= 1,
Event::Eof => return Some(Event::Eof),
_ => (),
}
None
}
}
impl<'de, T, R> DeserializeHelper<'_, 'de, T, R>
where
T: WithDeserializer,
R: XmlReaderSync<'de>,
{
fn deserialize_sync(&mut self) -> Result<T, Error> {
loop {
let event = self.reader.read_event()?;
if let Some(event) = self.handle_skip(event) {
if let Some(data) = self
.handle_event(event)
.map_err(|error| self.reader.extend_error(error))?
{
return Ok(data);
}
}
}
}
}
#[cfg(feature = "async")]
impl<'de, T, R> DeserializeHelper<'_, 'de, T, R>
where
T: WithDeserializer,
R: super::XmlReaderAsync<'de>,
{
async fn deserialize_async(&mut self) -> Result<T, Error> {
loop {
let event = self.reader.read_event_async().await?;
if let Some(event) = self.handle_skip(event) {
if let Some(data) = self.handle_event(event)? {
return Ok(data);
}
}
}
}
}