ion_rs/stream_reader.rs
1use crate::element::{Blob, Clob};
2use crate::result::IonResult;
3use crate::types::{Decimal, Int, IonType, Str, Timestamp};
4
5/**
6 * This trait captures the format-agnostic parser functionality needed to navigate within an Ion
7 * stream and read the values encountered into native Rust data types.
8 *
9 * Once a value has successfully been read from the stream using one of the read_* functions,
10 * calling that function again may return an Err. This is left to the discretion of the implementor.
11 */
12pub trait IonReader {
13 /// The type returned by calls to [Self::next], indicating the next entity in the stream.
14 /// Reader implementations representing different levels of abstraction will surface
15 /// different sets of encoding artifacts. While an application-level Reader would only surface
16 /// Ion values, a lower level Reader might surface symbol tables, Ion version markers, etc.
17 type Item;
18
19 /// The types used to represent field names, annotations, and symbol values at this Reader's
20 /// level of abstraction.
21 type Symbol;
22
23 /// Returns the (major, minor) version of the Ion stream being read. If ion_version is called
24 /// before an Ion Version Marker has been read, the version (1, 0) will be returned.
25 fn ion_version(&self) -> (u8, u8);
26
27 /// Attempts to advance the cursor to the next value in the stream at the current depth.
28 /// If no value is encountered, returns None; otherwise, returns the Ion type of the next value.
29 fn next(&mut self) -> IonResult<Self::Item>;
30
31 /// Returns a value describing the stream entity over which the Reader is currently positioned.
32 /// Depending on the Reader's level of abstraction, that entity may or may not be an Ion value.
33 fn current(&self) -> Self::Item;
34
35 /// If the current item is a value, returns that value's Ion type. Otherwise, returns None.
36 fn ion_type(&self) -> Option<IonType>;
37
38 /// Returns an iterator that will yield each of the annotations for the current value in order.
39 /// If there is no current value, returns an empty iterator.
40 // TODO: When GATs are stabilized, we can change this to a known associated type that's generic
41 // over the lifetime of &self.
42 fn annotations<'a>(&'a self) -> Box<dyn Iterator<Item = IonResult<Self::Symbol>> + 'a>;
43
44 /// If the reader is positioned over a value with one or more annotations, returns `true`.
45 /// Otherwise, returns `false`.
46 fn has_annotations(&self) -> bool {
47 // Implementations are encouraged to override this when there's a cheaper way of
48 // determining whether the current value has annotations.
49 self.annotations().next().is_some()
50 }
51
52 /// Returns the number of annotations on the current value. If there is no current value,
53 /// returns zero.
54 fn number_of_annotations(&self) -> usize {
55 // Implementations are encouraged to override this when there's a cheaper way of
56 // calculating the number of annotations.
57 self.annotations().count()
58 }
59
60 /// If the current item is a field within a struct, returns `Ok(_)` with a [Self::Symbol]
61 /// representing the field's name; otherwise, returns an [crate::IonError::IllegalOperation].
62 ///
63 /// Implementations may also return an error for other reasons; for example, if [Self::Symbol]
64 /// is a text data type but the field name is an undefined symbol ID, the reader may return
65 /// a decoding error.
66 fn field_name(&self) -> IonResult<Self::Symbol>;
67
68 /// Returns `true` if the reader is currently positioned over an Ion null of any type.
69 fn is_null(&self) -> bool;
70
71 /// Attempts to read the current item as an Ion null and return its Ion type. If the current
72 /// item is not a null or an IO error is encountered while reading, returns [crate::IonError].
73 fn read_null(&mut self) -> IonResult<IonType>;
74
75 /// Attempts to read the current item as an Ion boolean and return it as a bool. If the current
76 /// item is not a boolean or an IO error is encountered while reading, returns [crate::IonError].
77 fn read_bool(&mut self) -> IonResult<bool>;
78
79 /// Attempts to read the current item as an Ion integer and return it as an i64. If the current
80 /// item is not an integer, the integer is too large to be represented as an `i64`, or an IO
81 /// error is encountered while reading, returns [crate::IonError].
82 fn read_i64(&mut self) -> IonResult<i64>;
83
84 /// Attempts to read the current item as an Ion integer and return it as an [`Int`](crate::types::Int). If the
85 /// current item is not an integer or an IO error is encountered while reading, returns
86 /// [crate::IonError].
87 fn read_int(&mut self) -> IonResult<Int>;
88
89 /// Attempts to read the current item as an Ion float and return it as an f32. If the current
90 /// item is not a float or an IO error is encountered while reading, returns [crate::IonError].
91 fn read_f32(&mut self) -> IonResult<f32>;
92
93 /// Attempts to read the current item as an Ion float and return it as an f64. If the current
94 /// item is not a float or an IO error is encountered while reading, returns [crate::IonError].
95 fn read_f64(&mut self) -> IonResult<f64>;
96
97 /// Attempts to read the current item as an Ion decimal and return it as a [crate::Decimal]. If the current
98 /// item is not a decimal or an IO error is encountered while reading, returns [crate::IonError].
99 fn read_decimal(&mut self) -> IonResult<Decimal>;
100
101 /// Attempts to read the current item as an Ion string and return it as a [String]. If the current
102 /// item is not a string or an IO error is encountered while reading, returns [crate::IonError].
103 fn read_string(&mut self) -> IonResult<Str>;
104
105 /// Attempts to read the current item as an Ion string and return it as a [&str]. If the
106 /// current item is not a string or an IO error is encountered while reading, returns
107 /// [crate::IonError].
108 fn read_str(&mut self) -> IonResult<&str>;
109
110 /// Attempts to read the current item as an Ion symbol and return it as a [Self::Symbol]. If the
111 /// current item is not a symbol or an IO error is encountered while reading, returns [crate::IonError].
112 fn read_symbol(&mut self) -> IonResult<Self::Symbol>;
113
114 /// Attempts to read the current item as an Ion blob and return it as a `Vec<u8>`. If the
115 /// current item is not a blob or an IO error is encountered while reading, returns [crate::IonError].
116 fn read_blob(&mut self) -> IonResult<Blob>;
117
118 /// Attempts to read the current item as an Ion clob and return it as a `Vec<u8>`. If the
119 /// current item is not a clob or an IO error is encountered while reading, returns [crate::IonError].
120 fn read_clob(&mut self) -> IonResult<Clob>;
121
122 /// Attempts to read the current item as an Ion timestamp and return [crate::Timestamp]. If the current
123 /// item is not a timestamp or an IO error is encountered while reading, returns [crate::IonError].
124 fn read_timestamp(&mut self) -> IonResult<Timestamp>;
125
126 /// If the current value is a container (i.e. a struct, list, or s-expression), positions the
127 /// cursor at the beginning of that container's sequence of child values. The application must
128 /// call [Self::next()] to advance to the first child value. If the current value is not a container,
129 /// returns [crate::IonError].
130 fn step_in(&mut self) -> IonResult<()>;
131
132 /// Positions the cursor at the end of the container currently being traversed. Calling [Self::next()]
133 /// will position the cursor over the item that follows the container. If the cursor is not in
134 /// a container (i.e. it is already at the top level), returns [crate::IonError].
135 fn step_out(&mut self) -> IonResult<()>;
136
137 /// If the reader is positioned at the top level, returns `None`. Otherwise, returns
138 /// `Some(_)` with the parent container's [crate::IonType].
139 fn parent_type(&self) -> Option<IonType>;
140
141 /// Returns a [usize] indicating the Reader's current level of nesting. That is: the number of
142 /// times the Reader has stepped into a container without later stepping out. At the top level,
143 /// this method returns `0`.
144 fn depth(&self) -> usize;
145}