Skip to main content

android_abx/decode/
stream.rs

1//! [`AbxStreamParser`] — pull parser over any `Read` source.
2//!
3//! Unlike [`crate::AbxParser`] which requires the whole document in memory,
4//! `AbxStreamParser` reads from any `std::io::Read` implementor (files, TCP
5//! sockets, `stdin`, in-memory `Cursor<Vec<u8>>`, …) using a small internal
6//! ring buffer.
7//!
8//! The public surface is intentionally identical to `AbxParser` so the two
9//! types are interchangeable; just swap the constructor.
10//!
11//! # Internal design
12//!
13//! We keep a `Vec<u8>` ring buffer (`buf`) and a `pos` cursor.  When a nom
14//! parser reports `Incomplete` we refill from the reader, slide unconsumed
15//! bytes to the front, and retry.  This gives us:
16//!
17//! - **bounded memory** — the buffer only grows when a single atom (e.g. a
18//!   very long string) exceeds the current capacity.
19//! - **zero extra copies** — nom operates directly on `&buf[pos..]`.
20//! - **identical event types** — `Event`, `Attribute`, `AttributeValue` are
21//!   all shared with the slice parser.
22
23use std::io::Read;
24
25use nom::{
26    Needed,
27    number::streaming::{be_f32, be_f64, be_i32, be_i64, be_u8, be_u16},
28};
29
30use crate::{
31    AbxError, Attribute, AttributeValue, CMD_ATTRIBUTE, CMD_CDSECT, CMD_COMMENT, CMD_DOCDECL,
32    CMD_END_DOCUMENT, CMD_END_TAG, CMD_ENTITY_REF, CMD_IGNORABLE_WHITESPACE,
33    CMD_PROCESSING_INSTRUCTION, CMD_START_DOCUMENT, CMD_START_TAG, CMD_TEXT, Event, MAGIC, Result,
34    TYPE_BOOLEAN_FALSE, TYPE_BOOLEAN_TRUE, TYPE_BYTES_BASE64, TYPE_BYTES_HEX, TYPE_DOUBLE,
35    TYPE_FLOAT, TYPE_INT, TYPE_INT_HEX, TYPE_LONG, TYPE_LONG_HEX, TYPE_NULL, TYPE_STRING,
36    TYPE_STRING_INTERNED, render_event,
37};
38
39use crate::INTERNED_NEW;
40use std::collections::HashMap;
41
42/// Initial ring-buffer capacity (4 KiB).
43const INITIAL_BUF: usize = 4096;
44/// How many bytes to try to read per refill.
45const READ_CHUNK: usize = 4096;
46
47/// Pull parser that reads from any `R: Read` source.
48///
49/// # Example
50/// ```rust,ignore
51/// use android_abx::AbxStreamParser;
52/// use std::io::BufReader;
53///
54/// let file = std::fs::File::open("backup.abx")?;
55/// let mut p = AbxStreamParser::new(BufReader::new(file))?;
56///
57/// while let Some(ev) = p.next_event()? {
58///     match ev {
59///         android_abx::Event::StartTag { name, attributes } => {
60///             println!("<{name}>");
61///             for a in &attributes {
62///                 println!("  {}={}", a.name, a.as_str());
63///             }
64///         }
65///         android_abx::Event::EndTag { name } => println!("</{name}>"),
66///         _ => {}
67///     }
68/// }
69/// ```
70#[derive(Debug)]
71pub struct AbxStreamParser<R: Read> {
72    reader: R,
73    /// Internal ring buffer.
74    buf: Vec<u8>,
75    /// Read cursor inside `buf`.
76    pos: usize,
77    /// Total valid bytes in `buf` (always >= pos).
78    len: usize,
79    /// `true` once the underlying reader returned 0 bytes.
80    eof: bool,
81    /// Interned string pool.
82    pool: Vec<crate::InternedStr>,
83}
84
85impl<R: Read> AbxStreamParser<R> {
86    /// Create a new parser from any reader.
87    ///
88    /// Reads and validates the 4-byte magic header immediately.  Returns an
89    /// error if the reader is too short or the header does not match.
90    pub fn new(reader: R) -> Result<Self> {
91        let mut p = AbxStreamParser {
92            reader,
93            buf: vec![0u8; INITIAL_BUF],
94            pos: 0,
95            len: 0,
96            eof: false,
97            pool: Vec::with_capacity(32),
98        };
99
100        // Read at least 4 bytes for the magic header.
101        p.ensure(4)?;
102
103        let magic: [u8; 4] = p.buf[p.pos..p.pos + 4].try_into().unwrap();
104        if magic != MAGIC {
105            return Err(AbxError::InvalidMagic {
106                expected: MAGIC,
107                actual: magic,
108            });
109        }
110        p.pos += 4;
111        Ok(p)
112    }
113
114    /// Number of unconsumed bytes currently in the buffer.
115    #[inline]
116    fn available(&self) -> usize {
117        self.len - self.pos
118    }
119
120    /// Compact the buffer (slide unconsumed bytes to front) then read from the
121    /// underlying reader until we have at least `needed` bytes available, or
122    /// until EOF.
123    fn ensure(&mut self, needed: usize) -> Result<()> {
124        // Bail out before touching the buffer at all when nothing needs to
125        // be read: this is called on every event (and every string/blob
126        // read), so compacting unconditionally here turned every one of
127        // those calls into an O(available()) memmove even when no refill
128        // was going to happen.
129        if self.available() >= needed || self.eof {
130            return Ok(());
131        }
132
133        // Compact first so we always have room at the back.
134        if self.pos > 0 {
135            self.buf.copy_within(self.pos..self.len, 0);
136            self.len -= self.pos;
137            self.pos = 0;
138        }
139
140        while self.available() < needed && !self.eof {
141            // Grow if necessary.
142            let spare = self.buf.len() - self.len;
143            if spare < READ_CHUNK {
144                self.buf
145                    .resize(self.len + READ_CHUNK.max(needed - self.available()), 0);
146            }
147
148            let n = self.reader.read(&mut self.buf[self.len..])?;
149            if n == 0 {
150                self.eof = true;
151            } else {
152                self.len += n;
153            }
154        }
155
156        Ok(())
157    }
158
159    /// Run a nom parser against the unconsumed tail of the buffer, refilling
160    /// if necessary.  Returns the parsed value and advances `pos`.
161    fn parse<F, T>(&mut self, mut f: F) -> Result<T>
162    where
163        F: FnMut(&[u8]) -> nom::IResult<&[u8], T>,
164    {
165        loop {
166            match f(&self.buf[self.pos..self.len]) {
167                Ok((rest, val)) => {
168                    self.pos = self.len - rest.len();
169                    return Ok(val);
170                }
171                Err(nom::Err::Incomplete(Needed::Size(n))) => {
172                    let need = self.available() + n.get();
173                    self.ensure(need)?;
174                    if self.eof && self.available() < n.get() {
175                        return Err(AbxError::UnexpectedEof("primitive"));
176                    }
177                }
178                Err(nom::Err::Incomplete(Needed::Unknown)) => {
179                    // Should not happen with our complete:: parsers, but handle gracefully.
180                    self.ensure(self.available() + 1)?;
181                    if self.eof {
182                        return Err(AbxError::UnexpectedEof("primitive"));
183                    }
184                }
185                Err(e) => return Err(AbxError::Nom(format!("{e:?}"))),
186            }
187        }
188    }
189
190    fn read_u8(&mut self) -> Result<u8> {
191        self.parse(|i| be_u8(i))
192    }
193    fn read_u16(&mut self) -> Result<u16> {
194        self.parse(|i| be_u16(i))
195    }
196    fn read_i32(&mut self) -> Result<i32> {
197        self.parse(|i| be_i32(i))
198    }
199    fn read_i64(&mut self) -> Result<i64> {
200        self.parse(|i| be_i64(i))
201    }
202    fn read_f32(&mut self) -> Result<f32> {
203        self.parse(|i| be_f32(i))
204    }
205    fn read_f64(&mut self) -> Result<f64> {
206        self.parse(|i| be_f64(i))
207    }
208
209    /// Read a `u16`-length-prefixed UTF-8 blob.
210    fn read_utf(&mut self) -> Result<String> {
211        let len = self.read_u16()? as usize;
212        // Make sure the whole string payload is buffered.
213        self.ensure(len)?;
214        if self.available() < len {
215            return Err(AbxError::UnexpectedEof("UTF string payload"));
216        }
217        let s = std::str::from_utf8(&self.buf[self.pos..self.pos + len])
218            .map_err(|_| AbxError::InvalidUtf8)?
219            .to_owned();
220        self.pos += len;
221        Ok(s)
222    }
223
224    /// Read a `u16`-length-prefixed raw byte blob.
225    fn read_bytes_blob(&mut self) -> Result<Vec<u8>> {
226        let len = self.read_u16()? as usize;
227        self.ensure(len)?;
228        if self.available() < len {
229            return Err(AbxError::UnexpectedEof("bytes payload"));
230        }
231        let v = self.buf[self.pos..self.pos + len].to_vec();
232        self.pos += len;
233        Ok(v)
234    }
235
236    /// Read an interned string. Every occurrence after the first is a
237    /// back-reference into `pool`, resolved with `InternedStr::clone` (a
238    /// refcount bump) rather than a fresh allocation and copy.
239    fn read_interned(&mut self) -> Result<crate::InternedStr> {
240        let idx = self.read_u16()?;
241        if idx == INTERNED_NEW {
242            let s: crate::InternedStr = self.read_utf()?.into();
243            self.pool.push(s.clone());
244            Ok(s)
245        } else {
246            self.pool
247                .get(idx as usize)
248                .cloned()
249                .ok_or(AbxError::BadInternedIndex(idx))
250        }
251    }
252
253    fn read_attr_value(&mut self, type_nibble: u8) -> Result<AttributeValue> {
254        match type_nibble {
255            TYPE_NULL => Ok(AttributeValue::Null),
256            TYPE_STRING => Ok(AttributeValue::String(self.read_utf()?)),
257            TYPE_STRING_INTERNED => Ok(AttributeValue::String(String::from(self.read_interned()?))),
258            TYPE_BYTES_HEX => Ok(AttributeValue::BytesHex(self.read_bytes_blob()?)),
259            TYPE_BYTES_BASE64 => Ok(AttributeValue::BytesBase64(self.read_bytes_blob()?)),
260            TYPE_INT => Ok(AttributeValue::Int(self.read_i32()?)),
261            TYPE_INT_HEX => Ok(AttributeValue::IntHex(self.read_i32()? as u32)),
262            TYPE_LONG => Ok(AttributeValue::Long(self.read_i64()?)),
263            TYPE_LONG_HEX => Ok(AttributeValue::LongHex(self.read_i64()? as u64)),
264            TYPE_FLOAT => Ok(AttributeValue::Float(self.read_f32()?)),
265            TYPE_DOUBLE => Ok(AttributeValue::Double(self.read_f64()?)),
266            TYPE_BOOLEAN_TRUE => Ok(AttributeValue::Boolean(true)),
267            TYPE_BOOLEAN_FALSE => Ok(AttributeValue::Boolean(false)),
268            other => Err(AbxError::UnknownAttributeType(other)),
269        }
270    }
271
272    /// Peek at the next byte without consuming it. Returns `None` on EOF.
273    fn peek_u8(&mut self) -> Result<Option<u8>> {
274        self.ensure(1)?;
275        Ok(self.buf.get(self.pos).copied())
276    }
277
278    /// Pull the next [`Event`]. Returns `None` at end of input.
279    pub fn next_event(&mut self) -> Result<Option<Event>> {
280        // Refill at least 1 byte.
281        self.ensure(1)?;
282        if self.available() == 0 {
283            return Ok(None);
284        }
285
286        let token = self.read_u8()?;
287        let cmd = token & 0x0F;
288        let type_nibble = token & 0xF0;
289
290        let event = match cmd {
291            CMD_START_DOCUMENT => Event::StartDocument,
292            CMD_END_DOCUMENT => return Ok(Some(Event::EndDocument)),
293
294            CMD_START_TAG => {
295                let name = self.read_interned()?;
296                let mut attributes = Vec::with_capacity(4);
297
298                // Eagerly consume following ATTRIBUTE tokens without peeking
299                // across I/O boundaries more than necessary.
300                loop {
301                    match self.peek_u8()? {
302                        Some(next) if (next & 0x0F) == CMD_ATTRIBUTE => {
303                            self.pos += 1; // consume peeked byte
304                            let attr_type = next & 0xF0;
305                            let attr_name = self.read_interned()?;
306                            let attr_value = self.read_attr_value(attr_type)?;
307                            attributes.push(Attribute {
308                                name: attr_name,
309                                value: attr_value,
310                            });
311                        }
312                        _ => break,
313                    }
314                }
315
316                Event::StartTag { name, attributes }
317            }
318
319            CMD_END_TAG => Event::EndTag {
320                name: self.read_interned()?,
321            },
322
323            CMD_TEXT => Event::Text(if type_nibble == TYPE_STRING {
324                self.read_utf()?
325            } else {
326                String::new()
327            }),
328            CMD_CDSECT => Event::CdataSection(if type_nibble == TYPE_STRING {
329                self.read_utf()?
330            } else {
331                String::new()
332            }),
333            CMD_ENTITY_REF => Event::EntityReference(if type_nibble == TYPE_STRING {
334                self.read_utf()?
335            } else {
336                String::new()
337            }),
338            CMD_IGNORABLE_WHITESPACE => Event::IgnorableWhitespace(if type_nibble == TYPE_STRING {
339                self.read_utf()?
340            } else {
341                String::new()
342            }),
343            CMD_PROCESSING_INSTRUCTION => {
344                Event::ProcessingInstruction(if type_nibble == TYPE_STRING {
345                    self.read_utf()?
346                } else {
347                    String::new()
348                })
349            }
350            CMD_COMMENT => Event::Comment(if type_nibble == TYPE_STRING {
351                self.read_utf()?
352            } else {
353                String::new()
354            }),
355            CMD_DOCDECL => Event::DocDecl(if type_nibble == TYPE_STRING {
356                self.read_utf()?
357            } else {
358                String::new()
359            }),
360
361            other => return Err(AbxError::UnknownCommand(other)),
362        };
363
364        Ok(Some(event))
365    }
366
367    /// Drain all remaining events into a `Vec`.
368    pub fn collect_events(&mut self) -> Result<Vec<Event>> {
369        let mut out = Vec::new();
370        while let Some(ev) = self.next_event()? {
371            out.push(ev);
372        }
373        Ok(out)
374    }
375
376    /// Return the value of the first matching `attr` inside any `<element>`
377    /// tag. `Ok(None)` means the element/attribute wasn't found before the
378    /// document ended; `Err` means a parse failure interrupted the search.
379    /// Callers that don't care about that distinction can collapse both
380    /// into `None` with `.ok().flatten()`.
381    pub fn find_attribute(&mut self, element: &str, attr: &str) -> Result<Option<AttributeValue>> {
382        loop {
383            match self.next_event()? {
384                Some(Event::StartTag { name, attributes }) if name == element => {
385                    if let Some(a) = attributes.into_iter().find(|a| a.name == attr) {
386                        return Ok(Some(a.value));
387                    }
388                }
389                Some(Event::EndDocument) | None => return Ok(None),
390                _ => {}
391            }
392        }
393    }
394
395    /// All values of `attr` found in `<element>` tags.
396    pub fn find_all_attributes(
397        &mut self,
398        element: &str,
399        attr: &str,
400    ) -> Result<Vec<AttributeValue>> {
401        let mut out = Vec::new();
402        while let Some(ev) = self.next_event()? {
403            if let Event::StartTag { name, attributes } = ev
404                && name == element
405            {
406                out.extend(
407                    attributes
408                        .into_iter()
409                        .filter(|a| a.name == attr)
410                        .map(|a| a.value),
411                );
412            }
413        }
414        Ok(out)
415    }
416
417    /// Attributes of the first `<element>` tag. `Ok(None)` means no
418    /// matching tag was found before the document ended; `Err` means a
419    /// parse failure interrupted the search — see
420    /// [`find_attribute`](Self::find_attribute) for how to collapse both
421    /// into a plain `None`.
422    pub fn attributes_of(&mut self, element: &str) -> Result<Option<Vec<Attribute>>> {
423        loop {
424            match self.next_event()? {
425                Some(Event::StartTag { name, attributes }) if name == element => {
426                    return Ok(Some(attributes));
427                }
428                Some(Event::EndDocument) | None => return Ok(None),
429                _ => {}
430            }
431        }
432    }
433
434    /// Attributes of every `<element>` tag.
435    pub fn all_attributes_of(&mut self, element: &str) -> Result<Vec<Vec<Attribute>>> {
436        let mut out = Vec::new();
437        while let Some(ev) = self.next_event()? {
438            if let Event::StartTag { name, attributes } = ev
439                && name == element
440            {
441                out.push(attributes);
442            }
443        }
444        Ok(out)
445    }
446
447    /// Find the next `<element>`, deserialize its attributes (and direct
448    /// text content, via a `#[serde(rename = "$text")]` field) into `T`,
449    /// then skip past its matching end tag. `Ok(None)` at end of document.
450    #[cfg(feature = "serialize")]
451    pub fn deserialize_next<T: serde::de::DeserializeOwned>(
452        &mut self,
453        element: &str,
454    ) -> Result<Option<T>> {
455        crate::de::find_and_consume_element(self, element)
456    }
457
458    /// Deserialize every remaining `<element>` into a `Vec<T>`.
459    #[cfg(feature = "serialize")]
460    pub fn deserialize_all<T: serde::de::DeserializeOwned>(
461        &mut self,
462        element: &str,
463    ) -> Result<Vec<T>> {
464        let mut out = Vec::new();
465        while let Some(item) = self.deserialize_next(element)? {
466            out.push(item);
467        }
468        Ok(out)
469    }
470
471    /// Lazily deserialize every remaining `<element>` as a `T`, one at a
472    /// time, without buffering the whole document or the whole result set —
473    /// the streaming counterpart to [`deserialize_all`](Self::deserialize_all).
474    #[cfg(feature = "serialize")]
475    pub fn deserialize_iter<'p, T: serde::de::DeserializeOwned>(
476        &'p mut self,
477        element: &'p str,
478    ) -> DeserializeIter<'p, R, T> {
479        DeserializeIter {
480            parser: self,
481            element,
482            _marker: std::marker::PhantomData,
483        }
484    }
485
486    /// Render the rest of the document as an XML string.
487    pub fn to_xml(&mut self) -> Result<String> {
488        let mut buf = String::from(r#"<?xml version="1.0" encoding="UTF-8"?>"#);
489        while let Some(ev) = self.next_event()? {
490            if matches!(ev, Event::EndDocument) {
491                break;
492            }
493            render_event(&ev, &mut buf);
494        }
495        Ok(buf)
496    }
497
498    /// Write the rest of the document as XML into any `std::io::Write` sink.
499    ///
500    /// More memory-efficient than [`to_xml`](AbxStreamParser::to_xml) for very
501    /// large files because it does not accumulate the whole result in a `String`.
502    pub fn write_xml(&mut self, writer: &mut impl std::io::Write) -> Result<()> {
503        writer.write_all(b"<?xml version=\"1.0\" encoding=\"UTF-8\"?>")?;
504        // One scratch buffer reused (cleared, not reallocated) across every
505        // event, instead of a fresh allocation per event.
506        let mut tmp = String::new();
507        while let Some(ev) = self.next_event()? {
508            if matches!(ev, Event::EndDocument) {
509                break;
510            }
511            tmp.clear();
512            render_event(&ev, &mut tmp);
513            writer.write_all(tmp.as_bytes())?;
514        }
515        Ok(())
516    }
517
518    /// Collect the whole document into a `HashMap<element → Vec<HashMap<attr → value_str>>>`.
519    pub fn into_map(mut self) -> Result<HashMap<String, Vec<HashMap<String, String>>>> {
520        let mut map: HashMap<String, Vec<HashMap<String, String>>> = HashMap::new();
521        while let Some(ev) = self.next_event()? {
522            if let Event::StartTag { name, attributes } = ev {
523                let entry = map.entry(name.into()).or_default();
524                let mut attrs = HashMap::new();
525                for attr in attributes {
526                    attrs.insert(attr.name.into(), attr.value.as_str().into_owned());
527                }
528                entry.push(attrs);
529            }
530        }
531        Ok(map)
532    }
533
534    /// Unwrap the underlying reader, discarding any buffered data.
535    pub fn into_inner(self) -> R {
536        self.reader
537    }
538}
539
540impl<R: Read> Iterator for AbxStreamParser<R> {
541    type Item = Result<Event>;
542
543    fn next(&mut self) -> Option<Self::Item> {
544        match self.next_event() {
545            Ok(Some(ev)) => Some(Ok(ev)),
546            Ok(None) => None,
547            Err(e) => Some(Err(e)),
548        }
549    }
550}
551
552/// Lazily yields each remaining `<element>`, deserialized into `T`. See
553/// [`AbxStreamParser::deserialize_iter`].
554#[cfg(feature = "serialize")]
555pub struct DeserializeIter<'p, R: Read, T> {
556    parser: &'p mut AbxStreamParser<R>,
557    element: &'p str,
558    _marker: std::marker::PhantomData<T>,
559}
560
561#[cfg(feature = "serialize")]
562impl<'p, R: Read, T: serde::de::DeserializeOwned> Iterator for DeserializeIter<'p, R, T> {
563    type Item = Result<T>;
564
565    fn next(&mut self) -> Option<Self::Item> {
566        self.parser.deserialize_next(self.element).transpose()
567    }
568}