Skip to main content

android_abx/de/
mod.rs

1//! serde deserialization. Fields map to attributes, child elements
2//! (`Vec<T>` for repeats) or `$text`; an attribute wins over a same-named child.
3
4use std::io::Read;
5
6use serde::de::{self, DeserializeOwned};
7
8use crate::{AbxError, Attribute, Result};
9
10mod element;
11mod traversal;
12mod value;
13
14pub(crate) use traversal::{find_and_consume_element, find_and_consume_root_element};
15
16pub(crate) const TEXT_FIELD: &str = "$text";
17
18impl de::Error for AbxError {
19    fn custom<T: std::fmt::Display>(msg: T) -> Self {
20        AbxError::Deserialization(msg.to_string())
21    }
22}
23
24/// Deserializes `T` from an element's attributes and optional text.
25///
26/// Useful when an [`Event::StartTag`](crate::Event::StartTag) is already at
27/// hand. Child elements are not available here: use
28/// [`AbxParser::deserialize_next`](crate::AbxParser::deserialize_next) for types
29/// with child-element fields.
30///
31/// # Errors
32///
33/// Returns [`AbxError::Deserialization`] if the attributes do not match `T`.
34///
35/// # Examples
36///
37/// ```
38/// use android_abx::{Attribute, AttributeValue};
39/// use serde::Deserialize;
40///
41/// #[derive(Deserialize)]
42/// struct Pkg {
43///     name: String,
44///     version: Option<u32>,
45/// }
46///
47/// let attributes = [Attribute {
48///     name: "name".into(),
49///     value: AttributeValue::String("com.example".into()),
50/// }];
51/// let pkg: Pkg = android_abx::from_element(&attributes, None)?;
52/// assert_eq!(pkg.name, "com.example");
53/// assert_eq!(pkg.version, None);
54/// # Ok::<(), android_abx::AbxError>(())
55/// ```
56pub fn from_element<T: DeserializeOwned>(
57    attributes: &[Attribute],
58    text: Option<&str>,
59) -> Result<T> {
60    T::deserialize(element::ElementDeserializer {
61        attributes,
62        text,
63        children: &[],
64    })
65}
66
67/// Deserializes the root element of an ABX document into `T`.
68///
69/// The root's tag name is not checked. See
70/// [Deserializing with serde](crate#deserializing-with-serde) for how fields are
71/// matched.
72///
73/// # Errors
74///
75/// Returns a parse error if the input is malformed, or
76/// [`AbxError::Deserialization`] if the document has no root element or it does
77/// not match `T`.
78///
79/// # Examples
80///
81/// ```
82/// use serde::Deserialize;
83///
84/// #[derive(Deserialize)]
85/// struct Pkg {
86///     name: String,
87///     version: u32,
88/// }
89///
90/// # let data = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixtures/simple_pkg.abx"));
91/// let pkg: Pkg = android_abx::from_slice(data)?;
92/// assert_eq!(pkg.name, "com.example.chat");
93/// assert_eq!(pkg.version, 3);
94/// # Ok::<(), android_abx::AbxError>(())
95/// ```
96pub fn from_slice<T: DeserializeOwned>(data: &[u8]) -> Result<T> {
97    let mut parser = crate::AbxParser::new(data)?;
98    find_and_consume_root_element(&mut parser)
99}
100
101/// Deserializes the root element of an ABX document read from `reader` into `T`.
102///
103/// See [`from_slice`].
104///
105/// # Errors
106///
107/// Same as [`from_slice`], plus [`AbxError::Io`] if reading fails.
108pub fn from_reader<R: Read, T: DeserializeOwned>(reader: R) -> Result<T> {
109    let mut parser = crate::AbxStreamParser::new(reader)?;
110    find_and_consume_root_element(&mut parser)
111}
112
113/// Deserializes the root element of an ABX file into `T`.
114///
115/// See [`from_slice`].
116///
117/// # Errors
118///
119/// Same as [`from_slice`], plus [`AbxError::Io`] if the file cannot be opened or
120/// read.
121///
122/// # Examples
123///
124/// ```no_run
125/// use serde::Deserialize;
126///
127/// #[derive(Deserialize)]
128/// struct User {
129///     id: u32,
130///     name: String,
131/// }
132///
133/// let user: User = android_abx::from_file("/data/system/users/0.xml")?;
134/// # Ok::<(), android_abx::AbxError>(())
135/// ```
136pub fn from_file<T: DeserializeOwned>(path: impl AsRef<std::path::Path>) -> Result<T> {
137    let mut parser = crate::open_file(path)?;
138    find_and_consume_root_element(&mut parser)
139}