Skip to main content

ion_rs/element/
mod.rs

1// Copyright Amazon.com, Inc. or its affiliates.
2
3// Disabled for this file because `Element`'s `try_into_<x>` methods return
4// `ConversionOperationError<Element, <X>>` which embeds an `Element`. `Element` itself is 128 bytes.
5// This trips `clippy::result_large_err`. However, most usages of this type are expected to be
6// converted or destructured immediately.
7//
8// Cf. https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err
9#![allow(clippy::result_large_err)]
10
11//! Provides a dynamically typed, materialized representation of an Ion value.
12//!
13//! An [Element] represents an `(annotations, value)` pair, where a `value` is
14//! an Ion `integer`, `float`, `list`, `struct`, etc.
15//!
16//! For reference here are a couple other _value_ style APIs for JSON:
17//! * [`simd_json`'s `Value` API][simd-json-value]
18//! * [`serde_json`'s `Value` API][serde-json-value]
19//!
20//! [simd-json-value]: https://docs.rs/simd-json/latest/simd_json/value/index.html
21//! [serde-json-value]: https://docs.serde.rs/serde_json/value/enum.Value.html
22
23pub use annotations::{Annotations, IntoAnnotations};
24pub use sequence::Sequence;
25use std::cmp::Ordering;
26use std::fmt::{Display, Formatter};
27use std::hash::Hasher;
28use std::io;
29
30use crate::{ion_data, Decimal, Int, IonResult, IonType, Str, Symbol, SymbolRef, Timestamp};
31use crate::{Blob, Bytes, Clob, List, SExp, Struct};
32// Re-export the Value variant types and traits so they can be accessed directly from this module.
33use crate::element::builders::{SequenceBuilder, StructBuilder};
34use crate::element::reader::ElementReader;
35use crate::ion_data::{IonDataHash, IonDataOrd, IonEq};
36use crate::lazy::any_encoding::AnyEncoding;
37use crate::lazy::encoding::Encoding;
38use crate::lazy::reader::Reader;
39use crate::lazy::streaming_raw_reader::{IonInput, IonSlice};
40use crate::location::SourceLocation;
41use crate::result::{
42    ConversionOperationError, ConversionOperationResult, IonTypeExpectation, TypeExpectation,
43};
44use crate::text::text_formatter::FmtValueFormatter;
45use crate::types::symbol::SymbolText;
46use crate::write_config::WriteConfig;
47
48mod annotations;
49pub(crate) mod iterators;
50
51pub mod builders;
52pub mod element_writer;
53pub mod reader;
54mod sequence;
55
56impl IonEq for Value {
57    fn ion_eq(&self, other: &Self) -> bool {
58        use Value::*;
59        match (self, other) {
60            (Null(this), Null(that)) => this == that,
61            (Bool(this), Bool(that)) => ion_data::ion_eq_bool(this, that),
62            (Int(this), Int(that)) => this.ion_eq(that),
63            (Float(this), Float(that)) => ion_data::ion_eq_f64(this, that),
64            (Decimal(this), Decimal(that)) => this.ion_eq(that),
65            (Timestamp(this), Timestamp(that)) => this.ion_eq(that),
66            (Symbol(this), Symbol(that)) => this.ion_eq(that),
67            (String(this), String(that)) => this.ion_eq(that),
68            (Clob(this), Clob(that)) => this.ion_eq(that),
69            (Blob(this), Blob(that)) => this.ion_eq(that),
70            (List(this), List(that)) => this.ion_eq(that),
71            (SExp(this), SExp(that)) => this.ion_eq(that),
72            (Struct(this), Struct(that)) => this.ion_eq(that),
73            _ => false,
74        }
75    }
76}
77
78impl IonDataOrd for Value {
79    fn ion_cmp(&self, other: &Self) -> Ordering {
80        use Value::*;
81
82        // First compare Ion types
83        let ord = self.ion_type().ion_cmp(&other.ion_type());
84        if !ord.is_eq() {
85            return ord;
86        }
87
88        macro_rules! compare {
89            ($p:pat => $e:expr) => {
90                match other {
91                    $p => $e,
92                    Null(_) => Ordering::Greater,
93                    _ => unreachable!("We already checked the Ion Type!"),
94                }
95            };
96        }
97
98        match self {
99            Null(_) => {
100                if let Null(_) = other {
101                    Ordering::Equal
102                } else {
103                    Ordering::Less
104                }
105            }
106            Bool(this) => compare!(Bool(that) => ion_data::ion_cmp_bool(this, that)),
107            Int(this) => compare!(Int(that) => this.ion_cmp(that)),
108            Float(this) => compare!(Float(that) => ion_data::ion_cmp_f64(this, that)),
109            Decimal(this) => compare!(Decimal(that) => this.ion_cmp(that)),
110            Timestamp(this) => compare!(Timestamp(that) => this.ion_cmp(that)),
111            Symbol(this) => compare!(Symbol(that) => this.ion_cmp(that)),
112            String(this) => compare!(String(that) => this.ion_cmp(that)),
113            Clob(this) => compare!(Clob(that) => this.ion_cmp(that)),
114            Blob(this) => compare!(Blob(that) => this.ion_cmp(that)),
115            List(this) => compare!(List(that) => this.ion_cmp(that)),
116            SExp(this) => compare!(SExp(that) => this.ion_cmp(that)),
117            Struct(this) => compare!(Struct(that) => this.ion_cmp(that)),
118        }
119    }
120}
121
122impl IonDataHash for Value {
123    fn ion_data_hash<H: Hasher>(&self, state: &mut H) {
124        use Value::*;
125        self.ion_type().ion_data_hash(state);
126        match self {
127            Null(_) => state.write_u8(0),
128            Bool(this) => ion_data::ion_data_hash_bool(*this, state),
129            Int(this) => this.ion_data_hash(state),
130            Float(this) => ion_data::ion_data_hash_f64(*this, state),
131            Decimal(this) => this.ion_data_hash(state),
132            Timestamp(this) => this.ion_data_hash(state),
133            Symbol(this) => this.ion_data_hash(state),
134            String(this) => this.ion_data_hash(state),
135            Clob(this) => this.ion_data_hash(state),
136            Blob(this) => this.ion_data_hash(state),
137            List(this) => this.ion_data_hash(state),
138            SExp(this) => this.ion_data_hash(state),
139            Struct(this) => this.ion_data_hash(state),
140        }
141    }
142}
143
144/// Variants for all _values_ within an [`Element`].
145#[derive(Debug, Clone, PartialEq)]
146pub enum Value {
147    Null(IonType),
148    Bool(bool),
149    Int(Int),
150    Float(f64),
151    Decimal(Decimal),
152    Timestamp(Timestamp),
153    Symbol(Symbol),
154    String(Str),
155    Clob(Bytes),
156    Blob(Bytes),
157    List(Sequence),
158    SExp(Sequence),
159    Struct(Struct),
160}
161
162impl Value {
163    pub fn ion_type(&self) -> IonType {
164        use Value::*;
165
166        match self {
167            Null(t) => *t,
168            Bool(_) => IonType::Bool,
169            Int(_) => IonType::Int,
170            Float(_) => IonType::Float,
171            Decimal(_) => IonType::Decimal,
172            Timestamp(_) => IonType::Timestamp,
173            Symbol(_) => IonType::Symbol,
174            String(_) => IonType::String,
175            Clob(_) => IonType::Clob,
176            Blob(_) => IonType::Blob,
177            List(_) => IonType::List,
178            SExp(_) => IonType::SExp,
179            Struct(_) => IonType::Struct,
180        }
181    }
182}
183
184impl IonTypeExpectation for Value {
185    fn ion_type(&self) -> IonType {
186        self.ion_type()
187    }
188}
189
190impl Display for Value {
191    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
192        let mut ivf = FmtValueFormatter { output: f };
193        match &self {
194            Value::Null(ion_type) => ivf.format_null(*ion_type),
195            Value::Bool(bool) => ivf.format_bool(*bool),
196            Value::Int(integer) => ivf.format_integer(integer),
197            Value::Float(float) => ivf.format_float(*float),
198            Value::Decimal(decimal) => ivf.format_decimal(decimal),
199            Value::Timestamp(timestamp) => ivf.format_timestamp(timestamp),
200            Value::Symbol(symbol) => ivf.format_symbol(symbol),
201            Value::String(string) => ivf.format_string(string),
202            Value::Clob(clob) => ivf.format_clob(clob),
203            Value::Blob(blob) => ivf.format_blob(blob),
204            Value::List(sequence) => ivf.format_list(sequence),
205            Value::SExp(sequence) => ivf.format_sexp(sequence),
206            Value::Struct(struct_) => ivf.format_struct(struct_),
207        }
208        .map_err(|_| std::fmt::Error)?;
209
210        Ok(())
211    }
212}
213
214impl From<IonType> for Value {
215    fn from(ion_type: IonType) -> Self {
216        Value::Null(ion_type)
217    }
218}
219
220// Provides Into<Value> for all int types, both signed and unsigned.
221// Those types can also use the blanket Into<Element> impl that exists for T: Into<Value>.
222impl<I: Into<Int>> From<I> for Value {
223    fn from(value: I) -> Self {
224        let int: Int = value.into();
225        Value::Int(int)
226    }
227}
228
229impl From<f64> for Value {
230    fn from(f64_val: f64) -> Self {
231        Value::Float(f64_val)
232    }
233}
234
235impl From<Decimal> for Value {
236    fn from(decimal_val: Decimal) -> Self {
237        Value::Decimal(decimal_val)
238    }
239}
240
241impl From<Timestamp> for Value {
242    fn from(timestamp_val: Timestamp) -> Self {
243        Value::Timestamp(timestamp_val)
244    }
245}
246
247impl From<bool> for Value {
248    fn from(bool_val: bool) -> Self {
249        Value::Bool(bool_val)
250    }
251}
252
253impl From<&str> for Value {
254    fn from(string_val: &str) -> Self {
255        Value::String(string_val.into())
256    }
257}
258
259impl From<String> for Value {
260    fn from(value: String) -> Self {
261        let s: Str = value.into();
262        Value::String(s)
263    }
264}
265
266impl From<Str> for Value {
267    fn from(string_val: Str) -> Self {
268        Value::String(string_val)
269    }
270}
271
272impl From<Symbol> for Value {
273    fn from(sym_val: Symbol) -> Self {
274        Value::Symbol(sym_val)
275    }
276}
277
278impl From<SymbolRef<'_>> for Value {
279    fn from(sym_val: SymbolRef<'_>) -> Self {
280        Value::Symbol(sym_val.to_owned())
281    }
282}
283
284impl From<&[u8]> for Value {
285    fn from(value: &[u8]) -> Self {
286        Value::Blob(value.into())
287    }
288}
289
290impl From<Vec<u8>> for Value {
291    fn from(value: Vec<u8>) -> Self {
292        Value::Blob(value.into())
293    }
294}
295
296impl From<Blob> for Value {
297    fn from(blob: Blob) -> Self {
298        let bytes: Bytes = blob.into();
299        Value::Blob(bytes)
300    }
301}
302
303impl From<Clob> for Value {
304    fn from(clob: Clob) -> Self {
305        let bytes: Bytes = clob.into();
306        Value::Clob(bytes)
307    }
308}
309
310impl From<List> for Value {
311    fn from(list: List) -> Self {
312        Value::List(list.into())
313    }
314}
315
316impl From<SExp> for Value {
317    fn from(s_expr: SExp) -> Self {
318        Value::SExp(s_expr.into())
319    }
320}
321
322impl From<Struct> for Value {
323    fn from(struct_val: Struct) -> Self {
324        Value::Struct(struct_val)
325    }
326}
327
328/// Allows types that can be converted into an Ion [Value] to also specify annotations, producing
329/// an [Element].
330///
331/// ```
332/// use ion_rs::{Element, IntoAnnotatedElement, Value};
333///
334/// // Explicit ConversionResult of a Rust bool (`true`) into a `Value`...
335/// let boolean_value: Value = true.into();
336/// // and then into an `Element`...
337/// let mut boolean_element: Element = boolean_value.into();
338/// // and then adding annotations to the `Element`.
339/// let boolean_element = boolean_element.with_annotations(["foo", "bar"]);
340///
341/// // Much more concise equivalent leveraging the `IntoAnnotatedElement` trait.
342/// let boolean_element = true.with_annotations(["foo", "bar"]);
343/// ```
344pub trait IntoAnnotatedElement: Into<Value> {
345    /// Converts the value into an [Element] with the specified annotations.
346    fn with_annotations<I: IntoAnnotations>(self, annotations: I) -> Element {
347        Element::new(annotations.into_annotations(), self.into())
348    }
349}
350
351impl<V> IntoAnnotatedElement for V where V: Into<Value> {}
352
353impl IonEq for Element {
354    fn ion_eq(&self, other: &Self) -> bool {
355        self.annotations == other.annotations && self.value.ion_eq(&other.value)
356    }
357}
358
359// Ordering is done as follows:
360// 1. Ion type -- It is a logical way to group Ion values, and it is the cheapest comparison
361// 2. Annotations -- the vast majority of Ion values have few annotations, so this should usually be cheap
362// 3. Value -- compared using IonOrd
363impl IonDataOrd for Element {
364    fn ion_cmp(&self, other: &Self) -> Ordering {
365        let ord = self.ion_type().ion_cmp(&other.ion_type());
366        if !ord.is_eq() {
367            return ord;
368        }
369
370        let a1 = self.annotations();
371        let a2 = other.annotations();
372
373        let ord = a1.ion_cmp(a2);
374        if !ord.is_eq() {
375            return ord;
376        }
377
378        let v1 = self.value();
379        let v2 = other.value();
380        v1.ion_cmp(v2)
381    }
382}
383
384impl IonDataHash for Element {
385    fn ion_data_hash<H: Hasher>(&self, state: &mut H) {
386        self.annotations.ion_data_hash(state);
387        self.value.ion_data_hash(state);
388    }
389}
390
391/// An `(annotations, value)` pair representing an Ion value.
392#[derive(Clone)]
393pub struct Element {
394    annotations: Annotations,
395    value: Value,
396    // Represents the source location metadata (row, column).
397    location: SourceLocation,
398}
399
400impl std::fmt::Debug for Element {
401    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
402        <Element as Display>::fmt(self, f)
403    }
404}
405
406macro_rules! impl_try_from_element {
407    ($to_type:ident, $to_fn:ident) => {
408        impl TryFrom<Element> for $to_type {
409            type Error = ConversionOperationError<Element, $to_type>;
410
411            fn try_from(element: Element) -> ConversionOperationResult<Element, $to_type> {
412                element.$to_fn().into()
413            }
414        }
415    };
416}
417
418impl_try_from_element!(f64, try_into_float);
419impl_try_from_element!(Decimal, try_into_decimal);
420impl_try_from_element!(Timestamp, try_into_timestamp);
421impl_try_from_element!(String, try_into_text);
422impl_try_from_element!(Str, try_into_string);
423impl_try_from_element!(Symbol, try_into_symbol);
424impl_try_from_element!(bool, try_into_bool);
425impl_try_from_element!(Bytes, try_into_lob);
426impl_try_from_element!(Sequence, try_into_sequence);
427impl_try_from_element!(Struct, try_into_struct);
428
429impl Element {
430    pub(crate) fn new(annotations: Annotations, value: impl Into<Value>) -> Self {
431        Self {
432            annotations,
433            value: value.into(),
434            location: SourceLocation::empty(),
435        }
436    }
437
438    pub(crate) fn with_location(self, location: SourceLocation) -> Self {
439        Self {
440            annotations: self.annotations,
441            value: self.value,
442            location,
443        }
444    }
445
446    fn expected<ToType>(&self, maybe: Option<ToType>) -> IonResult<ToType>
447    where
448        ToType: TypeExpectation,
449    {
450        Ok(maybe.ok_or_else(|| ConversionOperationError::<&Element, ToType>::new(self))?)
451    }
452
453    /// Returns a reference to this [Element]'s [Value].
454    ///
455    /// ```
456    /// use ion_rs::{Element, Value};
457    /// let element: Element = true.into();
458    /// if let Value::Bool(b) = element.value() {
459    ///     println!("It was a boolean: {b}");
460    /// } else {
461    ///     println!("It was something else.");
462    /// }
463    /// ```
464    pub fn value(&self) -> &Value {
465        &self.value
466    }
467
468    /// Returns the source location (row, column) of this element in the original Ion text.
469    ///
470    /// The location metadata is primarily intended for error reporting and debugging purposes,
471    /// helping applications provide meaningful feedback to users about the source of issues.
472    ///
473    /// # Returns
474    /// * `Some((row, column))` - Position where this element was found in the source text
475    /// * `None` - Location information is not available
476    ///
477    /// # Important
478    /// Location information is best-effort and may not be available in all cases:
479    /// * Elements created programmatically won't have locations
480    /// * Some parsing scenarios might not preserve location data
481    /// * Binary Ion data does not contain location information
482    ///
483    /// Do not rely on this metadata for programmatic manipulation of Ion data.
484    pub fn location(&self) -> &SourceLocation {
485        &self.location
486    }
487
488    /// Consumes self and returns this [Element]'s [Value].
489    pub fn into_value(self) -> Value {
490        self.value
491    }
492
493    /// Consumes self and returns this [Element]'s [Annotations].
494    pub fn into_annotations(self) -> Annotations {
495        self.annotations
496    }
497
498    /// Consumes self and returns this [Element]'s [Annotations] and [Value].
499    pub fn into_parts(self) -> (Annotations, Value) {
500        (self.annotations, self.value)
501    }
502
503    pub fn null(null_type: IonType) -> Element {
504        null_type.into()
505    }
506
507    pub fn boolean(value: bool) -> Element {
508        value.into()
509    }
510
511    pub fn string<I: Into<Str>>(str: I) -> Element {
512        let text: Str = str.into();
513        text.into()
514    }
515
516    pub fn symbol<I: Into<Symbol>>(symbol: I) -> Element {
517        let symbol: Symbol = symbol.into();
518        symbol.into()
519    }
520
521    pub fn int<I: Into<Int>>(integer: I) -> Element {
522        let integer: Int = integer.into();
523        integer.into()
524    }
525
526    pub fn decimal(decimal: Decimal) -> Element {
527        decimal.into()
528    }
529
530    pub fn timestamp(timestamp: Timestamp) -> Element {
531        timestamp.into()
532    }
533
534    pub fn float(float: f64) -> Element {
535        float.into()
536    }
537
538    pub fn clob<A: AsRef<[u8]>>(bytes: A) -> Element {
539        let bytes: &[u8] = bytes.as_ref();
540        Value::Clob(bytes.into()).into()
541    }
542
543    pub fn blob<A: AsRef<[u8]>>(bytes: A) -> Element {
544        let bytes: &[u8] = bytes.as_ref();
545        Value::Blob(bytes.into()).into()
546    }
547
548    pub fn sequence_builder() -> SequenceBuilder {
549        Sequence::builder()
550    }
551
552    pub fn struct_builder() -> StructBuilder {
553        Struct::builder()
554    }
555
556    pub fn ion_type(&self) -> IonType {
557        self.value.ion_type()
558    }
559
560    pub fn annotations(&self) -> &Annotations {
561        &self.annotations
562    }
563
564    pub fn with_annotations<I: IntoAnnotations>(self, annotations: I) -> Self {
565        Element::new(annotations.into_annotations(), self.value)
566    }
567
568    pub fn is_null(&self) -> bool {
569        matches!(&self.value, Value::Null(_))
570    }
571
572    pub fn as_int(&self) -> Option<&Int> {
573        match &self.value {
574            Value::Int(i) => Some(i),
575            _ => None,
576        }
577    }
578
579    pub fn expect_int(&self) -> IonResult<&Int> {
580        self.expected(self.as_int())
581    }
582
583    pub fn try_into_int(self) -> ConversionOperationResult<Element, Int> {
584        match self.value {
585            Value::Int(i) => Ok(i),
586            _ => Err(self.into()),
587        }
588    }
589
590    pub fn as_i64(&self) -> Option<i64> {
591        match &self.value {
592            Value::Int(i) => i.as_i64(),
593            _ => None,
594        }
595    }
596
597    pub fn expect_i64(&self) -> IonResult<i64> {
598        self.expected(self.as_i64())
599    }
600
601    pub fn try_into_i64(self) -> ConversionOperationResult<Element, i64> {
602        match self.value {
603            Value::Int(i) if i.as_i64().is_some() => Ok(i.as_i64().unwrap()),
604            _ => Err(self.into()),
605        }
606    }
607
608    pub fn as_usize(&self) -> Option<usize> {
609        match &self.value {
610            Value::Int(i) => i.as_usize(),
611            _ => None,
612        }
613    }
614
615    pub fn expect_usize(&self) -> IonResult<usize> {
616        self.expected(self.as_usize())
617    }
618
619    pub fn try_into_usize(self) -> ConversionOperationResult<Element, usize> {
620        self.as_usize().ok_or_else(|| self.into())
621    }
622
623    pub fn as_float(&self) -> Option<f64> {
624        match &self.value {
625            Value::Float(f) => Some(*f),
626            _ => None,
627        }
628    }
629
630    pub fn expect_float(&self) -> IonResult<f64> {
631        self.expected(self.as_float())
632    }
633
634    pub fn try_into_float(self) -> ConversionOperationResult<Element, f64> {
635        match self.value {
636            Value::Float(f) => Ok(f),
637            _ => Err(self.into()),
638        }
639    }
640
641    pub fn as_decimal(&self) -> Option<Decimal> {
642        match &self.value {
643            Value::Decimal(d) => Some(d.clone()),
644            _ => None,
645        }
646    }
647
648    pub fn expect_decimal(&self) -> IonResult<Decimal> {
649        self.expected(self.as_decimal())
650    }
651
652    pub fn try_into_decimal(self) -> ConversionOperationResult<Element, Decimal> {
653        match self.value {
654            Value::Decimal(d) => Ok(d),
655            _ => Err(self.into()),
656        }
657    }
658
659    pub fn as_timestamp(&self) -> Option<Timestamp> {
660        match &self.value {
661            Value::Timestamp(t) => Some(t.clone()),
662            _ => None,
663        }
664    }
665
666    pub fn expect_timestamp(&self) -> IonResult<Timestamp> {
667        self.expected(self.as_timestamp())
668    }
669
670    pub fn try_into_timestamp(self) -> ConversionOperationResult<Element, Timestamp> {
671        match self.value {
672            Value::Timestamp(t) => Ok(t),
673            _ => Err(self.into()),
674        }
675    }
676
677    pub fn as_text(&self) -> Option<&str> {
678        match &self.value {
679            Value::String(text) => Some(text.as_ref()),
680            Value::Symbol(sym) => sym.text(),
681            _ => None,
682        }
683    }
684
685    pub fn expect_text(&self) -> IonResult<&str> {
686        self.expected(self.as_text())
687    }
688
689    pub fn try_into_text(self) -> ConversionOperationResult<Element, String> {
690        let Self {
691            value,
692            annotations,
693            location,
694        } = self;
695        match value {
696            Value::String(text) => Ok(text.to_string()),
697            Value::Symbol(sym) => match sym.text {
698                SymbolText::Shared(shared) => Ok((*shared).to_string()),
699                SymbolText::Owned(owned) => Ok(owned),
700                SymbolText::Unknown => {
701                    let sym = Self {
702                        value: Value::Symbol(Symbol::unknown_text()),
703                        annotations,
704                        location,
705                    };
706                    Err(ConversionOperationError::new(sym))
707                }
708                SymbolText::Static(static_str) => Ok((*static_str).to_string()),
709            },
710            _ => {
711                let sym = Self {
712                    value,
713                    annotations,
714                    location,
715                };
716                Err(ConversionOperationError::new(sym))
717            }
718        }
719    }
720
721    pub fn as_string(&self) -> Option<&str> {
722        match &self.value {
723            Value::String(text) => Some(text.as_ref()),
724            _ => None,
725        }
726    }
727
728    pub fn expect_string(&self) -> IonResult<&str> {
729        self.expected(self.as_string())
730    }
731
732    pub fn try_into_string(self) -> ConversionOperationResult<Element, Str> {
733        match self.value {
734            Value::String(text) => Ok(text),
735            _ => Err(self.into()),
736        }
737    }
738
739    pub fn as_symbol(&self) -> Option<&Symbol> {
740        match &self.value {
741            Value::Symbol(sym) => Some(sym),
742            _ => None,
743        }
744    }
745
746    pub fn expect_symbol(&self) -> IonResult<&Symbol> {
747        self.expected(self.as_symbol())
748    }
749
750    pub fn try_into_symbol(self) -> ConversionOperationResult<Element, Symbol> {
751        match self.value {
752            Value::Symbol(sym) => Ok(sym),
753            _ => Err(self.into()),
754        }
755    }
756
757    pub fn as_bool(&self) -> Option<bool> {
758        match &self.value {
759            Value::Bool(b) => Some(*b),
760            _ => None,
761        }
762    }
763
764    pub fn expect_bool(&self) -> IonResult<bool> {
765        self.expected(self.as_bool())
766    }
767
768    pub fn try_into_bool(self) -> ConversionOperationResult<Element, bool> {
769        match self.value {
770            Value::Bool(b) => Ok(b),
771            _ => Err(self.into()),
772        }
773    }
774
775    pub fn as_lob(&self) -> Option<&[u8]> {
776        match &self.value {
777            Value::Blob(bytes) | Value::Clob(bytes) => Some(bytes.as_ref()),
778            _ => None,
779        }
780    }
781
782    pub fn expect_lob(&self) -> IonResult<&[u8]> {
783        self.expected(self.as_lob())
784    }
785
786    pub fn try_into_lob(self) -> ConversionOperationResult<Element, Bytes> {
787        match self.value {
788            Value::Blob(bytes) | Value::Clob(bytes) => Ok(bytes),
789            _ => Err(self.into()),
790        }
791    }
792
793    pub fn as_blob(&self) -> Option<&[u8]> {
794        match &self.value {
795            Value::Blob(bytes) => Some(bytes.as_ref()),
796            _ => None,
797        }
798    }
799
800    pub fn expect_blob(&self) -> IonResult<&[u8]> {
801        self.expected(self.as_blob())
802    }
803
804    pub fn try_into_blob(self) -> ConversionOperationResult<Element, Bytes> {
805        match self.value {
806            Value::Blob(bytes) => Ok(bytes),
807            _ => Err(self.into()),
808        }
809    }
810
811    pub fn as_clob(&self) -> Option<&[u8]> {
812        match &self.value {
813            Value::Clob(bytes) => Some(bytes.as_ref()),
814            _ => None,
815        }
816    }
817
818    pub fn expect_clob(&self) -> IonResult<&[u8]> {
819        self.expected(self.as_clob())
820    }
821
822    pub fn try_into_clob(self) -> ConversionOperationResult<Element, Bytes> {
823        match self.value {
824            Value::Clob(bytes) => Ok(bytes),
825            _ => Err(self.into()),
826        }
827    }
828
829    pub fn as_sequence(&self) -> Option<&Sequence> {
830        match &self.value {
831            Value::SExp(s) | Value::List(s) => Some(s),
832            _ => None,
833        }
834    }
835
836    pub fn expect_sequence(&self) -> IonResult<&Sequence> {
837        self.expected(self.as_sequence())
838    }
839
840    pub fn try_into_sequence(self) -> ConversionOperationResult<Element, Sequence> {
841        match self.value {
842            Value::SExp(s) | Value::List(s) => Ok(s),
843            _ => Err(self.into()),
844        }
845    }
846
847    pub fn as_list(&self) -> Option<&Sequence> {
848        match &self.value {
849            Value::List(s) => Some(s),
850            _ => None,
851        }
852    }
853
854    pub fn expect_list(&self) -> IonResult<&Sequence> {
855        self.expected(self.as_list())
856    }
857
858    pub fn try_into_list(self) -> ConversionOperationResult<Element, Sequence> {
859        match self.value {
860            Value::List(s) => Ok(s),
861            _ => Err(self.into()),
862        }
863    }
864
865    pub fn as_sexp(&self) -> Option<&Sequence> {
866        match &self.value {
867            Value::SExp(s) => Some(s),
868            _ => None,
869        }
870    }
871
872    pub fn expect_sexp(&self) -> IonResult<&Sequence> {
873        self.expected(self.as_sexp())
874    }
875
876    pub fn try_into_sexp(self) -> ConversionOperationResult<Element, Sequence> {
877        match self.value {
878            Value::SExp(s) => Ok(s),
879            _ => Err(self.into()),
880        }
881    }
882
883    pub fn as_struct(&self) -> Option<&Struct> {
884        match &self.value {
885            Value::Struct(structure) => Some(structure),
886            _ => None,
887        }
888    }
889
890    pub fn expect_struct(&self) -> IonResult<&Struct> {
891        self.expected(self.as_struct())
892    }
893
894    pub fn try_into_struct(self) -> ConversionOperationResult<Element, Struct> {
895        match self.value {
896            Value::Struct(structure) => Ok(structure),
897            _ => Err(self.into()),
898        }
899    }
900
901    /// Reads a single Ion [`Element`] from the provided data source.
902    ///
903    /// If the data source is empty, returns `Ok(None)`.
904    /// If the data source has at least one value, returns `Ok(Some(Element))`.
905    /// If the data source has invalid data, returns `Err`.
906    pub fn read_first<A: AsRef<[u8]>>(data: A) -> IonResult<Option<Element>> {
907        let mut reader = Reader::new(AnyEncoding, IonSlice::new(data))?;
908        reader.read_next_element()
909    }
910
911    /// Reads a single Ion [`Element`] from the provided data source. If the input has invalid
912    /// data or does not contain at exactly one Ion value, returns `Err(IonError)`.
913    pub fn read_one<A: AsRef<[u8]>>(data: A) -> IonResult<Element> {
914        let mut reader = Reader::new(AnyEncoding, IonSlice::new(data))?;
915        reader.read_one_element()
916    }
917
918    /// Reads all available [`Element`]s from the provided data source.
919    ///
920    /// If the input has valid data, returns `Ok(Sequence)`.
921    /// If the input has invalid data, returns `Err(IonError)`.
922    pub fn read_all<A: AsRef<[u8]>>(data: A) -> IonResult<Sequence> {
923        Ok(Reader::new(AnyEncoding, IonSlice::new(data))?
924            .into_elements()
925            .collect::<IonResult<Vec<_>>>()?
926            .into())
927    }
928
929    /// Returns an iterator over the Elements in the provided Ion data source.
930    /// If the data source cannot be read or contains invalid Ion data, this method
931    /// will return an `Err`.
932    pub fn iter<'a, I: IonInput + 'a>(
933        source: I,
934    ) -> IonResult<impl Iterator<Item = IonResult<Element>> + 'a> {
935        Ok(Reader::new(AnyEncoding, source)?.into_elements())
936    }
937
938    /// Encodes this element as an Ion stream with itself as the only top-level value.
939    /// If the stream's encoding is binary Ion, returns a `Vec<u8>` containing the encoded bytes.
940    /// If the stream's encoding is text Ion, returns a `String` containing the UTF-8 encoded text.
941    ///
942    /// ```
943    ///# use ion_rs::IonResult;
944    ///# fn main() -> IonResult<()> {
945    /// use ion_rs::Element;
946    /// use ion_rs::v1_0::Binary;
947    ///
948    /// let ion_data = r#"{foo: "hello", bar: quux::5, baz: null, bar: false}"#;
949    /// let element_before = Element::read_one(ion_data)?;
950    ///
951    /// // Encode the element as a binary Ion stream
952    /// let ion_bytes: Vec<u8> = element_before.encode_as(Binary)?;
953    /// // Read the element back from the binary stream
954    /// let element_after = Element::read_one(ion_bytes)?;
955    ///
956    /// // Confirm that the value we read back is identical to the one we serialized
957    /// assert_eq!(element_before, element_after);
958    ///
959    ///# Ok(())
960    ///# }
961    /// ```
962    pub fn encode_as<E: Encoding, C: Into<WriteConfig<E>>>(
963        &self,
964        config: C,
965    ) -> IonResult<E::Output> {
966        config.into().encode(self)
967    }
968
969    /// Encodes this element as an Ion stream with itself as the only top-level value.
970    /// The encoded bytes are written to the provided [`io::Write`] implementation.
971    ///
972    /// ```
973    ///# use ion_rs::IonResult;
974    ///# fn main() -> IonResult<()> {
975    /// use ion_rs::Element;
976    /// use ion_rs::v1_0::Binary;
977    ///
978    /// let ion_data = r#"{foo: "hello", bar: quux::5, baz: null, bar: false}"#;
979    /// let element_before = Element::read_one(ion_data)?;
980    ///
981    /// // Encode the element as a binary Ion stream. The bytes will be written to the provided
982    /// //  Vec<u8>, and the Vec<u8> will be returned when encoding is complete.
983    /// let ion_bytes: Vec<u8> = element_before.encode_to(Vec::new(), Binary)?;
984    /// // Read the element back from the binary stream
985    /// let element_after = Element::read_one(ion_bytes)?;
986    ///
987    /// // Confirm that the value we read back is identical to the one we serialized
988    /// assert_eq!(element_before, element_after);
989    ///
990    ///# Ok(())
991    ///# }
992    /// ```
993    pub fn encode_to<E: Encoding, C: Into<WriteConfig<E>>, W: io::Write>(
994        &self,
995        output: W,
996        config: C,
997    ) -> IonResult<W> {
998        config.into().encode_to(self, output)
999    }
1000}
1001
1002impl IonTypeExpectation for Element {
1003    fn ion_type(&self) -> IonType {
1004        Element::ion_type(self)
1005    }
1006}
1007
1008impl IonTypeExpectation for &Element {
1009    fn ion_type(&self) -> IonType {
1010        Element::ion_type(self)
1011    }
1012}
1013
1014impl Display for Element {
1015    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
1016        let mut ivf = FmtValueFormatter { output: f };
1017
1018        // display for annotations of this element
1019        ivf.format_annotations(&self.annotations)
1020            .map_err(|_| std::fmt::Error)?;
1021
1022        self.value.fmt(f)
1023    }
1024}
1025
1026impl PartialEq for Element {
1027    fn eq(&self, other: &Self) -> bool {
1028        self.value == other.value && self.annotations == other.annotations
1029    }
1030}
1031
1032// This implementation allows APIs that require an Into<Element> to accept references to an existing
1033// Element.
1034impl<'a> From<&'a Element> for Element {
1035    fn from(element: &'a Element) -> Self {
1036        element.clone()
1037    }
1038}
1039
1040// Anything that can be turned into a `Value` can then be turned into an `Element`
1041// by associating it with an empty annotations sequence.
1042impl<T> From<T> for Element
1043where
1044    T: Into<Value>,
1045{
1046    fn from(value: T) -> Self {
1047        Element::new(Annotations::empty(), value.into())
1048    }
1049}
1050
1051impl AsRef<Element> for Element {
1052    fn as_ref(&self) -> &Element {
1053        self
1054    }
1055}
1056
1057#[cfg(test)]
1058mod tests {
1059    use chrono::*;
1060    use rstest::*;
1061    use std::collections::HashSet;
1062    use std::iter::{once, Once};
1063
1064    use ElemOp::*;
1065
1066    use crate::element::annotations::IntoAnnotations;
1067    use crate::{ion_list, ion_sexp, ion_struct, Decimal, Int, IonType, Symbol, Timestamp, Value};
1068    use crate::{Annotations, Element, IntoAnnotatedElement, Struct};
1069
1070    /// Makes a timestamp from an RFC-3339 string and panics if it can't
1071    fn make_timestamp<T: AsRef<str>>(text: T) -> Timestamp {
1072        let dt = DateTime::parse_from_rfc3339(text.as_ref()).unwrap();
1073        Timestamp::from_fixed_offset_datetime(dt)
1074    }
1075
1076    struct CaseAnnotations {
1077        elem: Element,
1078        annotations: Annotations,
1079    }
1080
1081    fn annotations_text_case() -> CaseAnnotations {
1082        CaseAnnotations {
1083            elem: 10i64.with_annotations(["foo", "bar", "baz"]),
1084            annotations: ["foo", "bar", "baz"].into_annotations(),
1085        }
1086    }
1087
1088    fn no_annotations_case() -> CaseAnnotations {
1089        CaseAnnotations {
1090            elem: 10i64.into(),
1091            annotations: Annotations::empty(),
1092        }
1093    }
1094
1095    #[rstest]
1096    #[case::annotations_text(annotations_text_case())]
1097    #[case::no_annotations(no_annotations_case())]
1098    fn annotations_with_element(#[case] input: CaseAnnotations) {
1099        let actual: &Annotations = input.elem.annotations();
1100        let expected: &Annotations = &input.annotations;
1101        assert_eq!(actual, expected);
1102    }
1103
1104    struct CaseSym {
1105        eq_annotations: Vec<Symbol>,
1106        ne_annotations: Vec<Symbol>,
1107    }
1108
1109    fn sym_text_case() -> CaseSym {
1110        // SymbolTokens with same text are equivalent
1111        CaseSym {
1112            eq_annotations: vec![Symbol::owned("foo"), Symbol::owned("foo")],
1113            // These are not equal to any of the ones in `eq_annotations` above
1114            ne_annotations: vec![Symbol::owned("bar"), Symbol::owned("baz")],
1115        }
1116    }
1117
1118    /// Each case is a set of tokens that are the same, and a set of tokens that are not ever equal to the first.
1119    /// This should test symmetry/transitivity/commutativity
1120    #[rstest]
1121    #[case::owned_sym_text(sym_text_case())]
1122    fn symbol_token_eq(#[case] input: CaseSym) {
1123        // check if equivalent vector contains set of tokens that are all equal
1124        for eq_this_token in &input.eq_annotations {
1125            for eq_other_token in &input.eq_annotations {
1126                assert_eq!(eq_this_token, eq_other_token);
1127            }
1128        }
1129
1130        // check if non_equivalent vector contains a set of tokens that are not ever equal
1131        // to the equivalent set tokens.
1132        for eq_token in &input.eq_annotations {
1133            for non_eq_token in &input.ne_annotations {
1134                assert_ne!(eq_token, non_eq_token);
1135            }
1136        }
1137    }
1138
1139    /// A struct that defines input case for `struct_accessors` method
1140    struct CaseStruct {
1141        /// set of struct elements that are the same
1142        eq_elements: Vec<Element>,
1143        /// set of struct elements that are never equal to `eq_annotations`
1144        ne_elements: Vec<Element>,
1145    }
1146
1147    /// A convenience method for constructing a Vec<Element> from a collection of
1148    /// homogeneously typed values that implement Into<Element>.
1149    fn ion_vec<E: Into<Element>, I: IntoIterator<Item = E>>(values: I) -> Vec<Element> {
1150        values.into_iter().map(|v| v.into()).collect()
1151    }
1152
1153    fn struct_with_multiple_fields_case() -> CaseStruct {
1154        CaseStruct {
1155            eq_elements: ion_vec([
1156                // structs with different order of fields
1157                ion_struct! {
1158                    "greetings": "hello",
1159                    "name": "Ion"
1160                },
1161                ion_struct! {
1162                    "name": "Ion",
1163                    "greetings": "hello"
1164                },
1165            ]),
1166            ne_elements: ion_vec([
1167                // structs with different length and duplicates
1168                ion_struct! {
1169                    "greetings": "hello",
1170                    "name": "Ion",
1171                    "greetings": "hello"
1172                },
1173                // structs with different fields length and duplicates
1174                ion_struct! {
1175                    "greetings": "hello",
1176                    "name": "Ion",
1177                    "greetings": "bye"
1178                },
1179                // structs with different fields length
1180                ion_struct! {
1181                    "greetings": "hello",
1182                    "name": "Ion",
1183                    "message": "bye"
1184                },
1185            ]),
1186        }
1187    }
1188
1189    fn struct_with_duplicates_in_multiple_fields_case() -> CaseStruct {
1190        CaseStruct {
1191            // Structs are bags of (field, value) pairs, order is irrelevant
1192            eq_elements: ion_vec([
1193                ion_struct! {
1194                    "a" : 2i64,
1195                    "a" : 2i64,
1196                    "a" : 1i64
1197                },
1198                ion_struct! {
1199                    "a" : 2i64,
1200                    "a" : 1i64,
1201                    "a" : 2i64
1202                },
1203                ion_struct! {
1204                    "a" : 1i64,
1205                    "a" : 2i64,
1206                    "a" : 2i64
1207                },
1208            ]),
1209            ne_elements: ion_vec([
1210                // structs with different length
1211                ion_struct! {
1212                    "a" : 1i64,
1213                    "a" : 2i64
1214                },
1215                // structs with annotated values
1216                ion_struct! {
1217                    "a" : 2i64,
1218                    "a" : 1i64.with_annotations(["a"]),
1219                    "a" : 2i64
1220                },
1221                // structs with different value for duplicates
1222                ion_struct! {
1223                    "a" : 2i64,
1224                    "a" : 3i64,
1225                    "a" : 2i64
1226                },
1227            ]),
1228        }
1229    }
1230
1231    fn struct_with_duplicate_fieldnames_case() -> CaseStruct {
1232        CaseStruct {
1233            eq_elements: ion_vec([
1234                // structs with unordered fields
1235                ion_struct! {
1236                    "greetings" : "world",
1237                    "greetings" : "hello"
1238                },
1239                ion_struct! {
1240                    "greetings" : "world",
1241                    "greetings" : "hello"
1242                },
1243            ]),
1244            ne_elements: ion_vec([
1245                // structs with different length and duplicates
1246                ion_struct! {
1247                    "greetings" : "world",
1248                    "greetings" : "hello",
1249                    "greetings" : "hey"
1250                },
1251                // structs with annotated values
1252                ion_struct! {
1253                    "greetings" : "world",
1254                    "greetings" : "hello".with_annotations(["foo"])
1255                },
1256                // structs with different length
1257                ion_struct! {
1258                    "greetings" : "world",
1259                    "greetings" : "hello",
1260                    "name" : "hello"
1261                },
1262            ]),
1263        }
1264    }
1265
1266    #[rstest]
1267    #[case::owned_struct_with_multiple_fields(struct_with_multiple_fields_case())]
1268    #[case::owned_struct_with_duplicates_in_multiple_fields(
1269        struct_with_duplicates_in_multiple_fields_case()
1270    )]
1271    #[case::owned_struct_with_duplicate_fieldnames(struct_with_duplicate_fieldnames_case())]
1272    fn struct_accessors(#[case] input: CaseStruct) {
1273        // check if equivalent vector contains set of structs that are all equal
1274        for eq_this_struct in &input.eq_elements {
1275            for eq_other_struct in &input.eq_elements {
1276                assert_eq!(eq_this_struct, eq_other_struct);
1277            }
1278        }
1279
1280        // check if non_equivalent vector contains a set of structs that are not ever equal
1281        // to the equivalent set structs.
1282        for eq_struct in &input.eq_elements {
1283            for non_eq_struct in &input.ne_elements {
1284                assert_ne!(eq_struct, non_eq_struct);
1285            }
1286        }
1287    }
1288
1289    /// Models the operations on `Element` that we want to test.
1290    #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
1291    enum ElemOp {
1292        IsNull,
1293        AsBool,
1294        AsAnyInt,
1295        AsF64,
1296        AsDecimal,
1297        AsTimestamp,
1298        AsStr,
1299        AsSym,
1300        AsBytes,
1301        AsSequence,
1302        AsStruct,
1303        TryIntoInt,
1304        TryIntoI64,
1305        TryIntoF64,
1306        TryIntoDecimal,
1307        TryIntoTimestamp,
1308        TryIntoText,
1309        TryIntoString,
1310        TryIntoSymbol,
1311        TryIntoBool,
1312        TryIntoLob,
1313        TryIntoBlob,
1314        TryIntoClob,
1315        TryIntoSequence,
1316        TryIntoList,
1317        TryIntoSexp,
1318        TryIntoStruct,
1319    }
1320
1321    impl IntoIterator for ElemOp {
1322        type Item = ElemOp;
1323        type IntoIter = <Once<ElemOp> as IntoIterator>::IntoIter;
1324
1325        fn into_iter(self) -> Self::IntoIter {
1326            once(self)
1327        }
1328    }
1329
1330    type ElemAssertFn = Box<dyn FnOnce(&Element)>;
1331    type OwnedElemAssertFn = Box<dyn FnOnce(Element)>;
1332
1333    macro_rules! assert_pass_try_into {
1334        ($f:ident) => {
1335            Box::new(|e: Element| assert!(e.$f().is_ok()))
1336        };
1337    }
1338
1339    macro_rules! assert_fail_try_into {
1340        ($f:ident) => {
1341            Box::new(|e: Element| assert!(e.$f().is_err()))
1342        };
1343    }
1344
1345    struct Case {
1346        elem: Element,
1347        ion_type: IonType,
1348        ops: Vec<ElemOp>,
1349        op_assert: ElemAssertFn,
1350        owned_asserts: Vec<OwnedElemAssertFn>,
1351    }
1352
1353    fn null_case() -> Case {
1354        Case {
1355            elem: Element::from(IonType::Null), // null.null
1356            ion_type: IonType::Null,
1357            ops: vec![IsNull],
1358            op_assert: Box::new(|e: &Element| assert!(e.is_null())),
1359            owned_asserts: vec![],
1360        }
1361    }
1362
1363    fn bool_case() -> Case {
1364        Case {
1365            elem: true.into(),
1366            ion_type: IonType::Bool,
1367            ops: vec![AsBool, TryIntoBool],
1368            op_assert: Box::new(|e: &Element| {
1369                let _ = e.expect_bool().expect("expected bool");
1370                let expected = Element::from(true);
1371                assert_eq!(Some(true), e.as_bool());
1372                assert_eq!(&expected, e);
1373            }),
1374            owned_asserts: vec![Box::new(|e: Element| assert!(e.try_into_bool().is_ok()))],
1375        }
1376    }
1377
1378    fn i64_case() -> Case {
1379        Case {
1380            elem: 100.into(),
1381            ion_type: IonType::Int,
1382            ops: vec![AsAnyInt, TryIntoInt, TryIntoI64],
1383            op_assert: Box::new(|e: &Element| {
1384                let _ = e.expect_i64().expect("expected i64");
1385                let _ = e.expect_int().expect("expected int");
1386                let expected: Element = 100i64.into();
1387                assert_eq!(Some(&Int::from(100i64)), e.as_int());
1388                assert_eq!(Some(100), e.as_i64());
1389                assert_eq!(&expected, e);
1390            }),
1391            owned_asserts: vec![
1392                assert_pass_try_into!(try_into_i64),
1393                assert_pass_try_into!(try_into_int),
1394            ],
1395        }
1396    }
1397
1398    fn big_int_case() -> Case {
1399        Case {
1400            elem: ((i64::MAX as i128) + 1).into(),
1401            ion_type: IonType::Int,
1402            ops: vec![AsAnyInt, TryIntoInt],
1403            op_assert: Box::new(|e: &Element| {
1404                let _ = e.expect_int().expect("expected int");
1405                let expected: Element = 9223372036854775808i128.into();
1406                assert_eq!(Some(&Int::from(9223372036854775808i128)), e.as_int());
1407                assert_eq!(&expected, e);
1408            }),
1409            owned_asserts: vec![assert_pass_try_into!(try_into_int)],
1410        }
1411    }
1412
1413    fn f64_case() -> Case {
1414        Case {
1415            elem: 16.0.into(),
1416            ion_type: IonType::Float,
1417            ops: vec![AsF64, TryIntoF64],
1418            op_assert: Box::new(|e: &Element| {
1419                let _ = e.expect_float().expect("expected float");
1420                let expected = Element::from(16.0f64);
1421                assert_eq!(Some(16.0), e.as_float());
1422                assert_eq!(&expected, e);
1423            }),
1424            owned_asserts: vec![assert_pass_try_into!(try_into_float)],
1425        }
1426    }
1427
1428    fn timestamp_case() -> Case {
1429        Case {
1430            elem: make_timestamp("2014-10-16T12:01:00-00:00").into(),
1431            ion_type: IonType::Timestamp,
1432            ops: vec![AsTimestamp, TryIntoTimestamp],
1433            op_assert: Box::new(|e: &Element| {
1434                let _ = e.expect_timestamp().expect("expected timestamp");
1435                let expected: Element = make_timestamp("2014-10-16T12:01:00+00:00").into();
1436                assert_eq!(
1437                    Some(make_timestamp("2014-10-16T12:01:00+00:00")),
1438                    e.as_timestamp()
1439                );
1440                assert_eq!(&expected, e);
1441            }),
1442            owned_asserts: vec![assert_pass_try_into!(try_into_timestamp)],
1443        }
1444    }
1445
1446    fn decimal_case() -> Case {
1447        Case {
1448            elem: Decimal::new(8, 3).into(),
1449            ion_type: IonType::Decimal,
1450            ops: vec![AsDecimal, TryIntoDecimal],
1451            op_assert: Box::new(|e: &Element| {
1452                let _ = e.expect_decimal().expect("expected decimal");
1453                let expected: Element = Decimal::new(8, 3).into();
1454                assert_eq!(Some(Decimal::new(80, 2)), e.as_decimal());
1455                assert_eq!(&expected, e);
1456            }),
1457            owned_asserts: vec![assert_pass_try_into!(try_into_decimal)],
1458        }
1459    }
1460
1461    fn string_case() -> Case {
1462        Case {
1463            elem: "hello".into(),
1464            ion_type: IonType::String,
1465            ops: vec![AsStr, TryIntoText, TryIntoString],
1466            op_assert: Box::new(|e: &Element| {
1467                let _ = e.expect_text().expect("expected text");
1468                let _ = e.expect_string().expect("expected string");
1469                assert_eq!(Some("hello"), e.as_text())
1470            }),
1471            owned_asserts: vec![
1472                assert_pass_try_into!(try_into_text),
1473                assert_pass_try_into!(try_into_string),
1474            ],
1475        }
1476    }
1477
1478    fn symbol_case() -> Case {
1479        Case {
1480            elem: Symbol::owned("foo").into(),
1481            ion_type: IonType::Symbol,
1482            ops: vec![AsSym, AsStr, TryIntoText, TryIntoSymbol],
1483            op_assert: Box::new(|e: &Element| {
1484                let _ = e.expect_text().expect("expected text");
1485                let _ = e.expect_symbol().expect("expected symbol");
1486                assert_eq!(Some("foo"), e.as_symbol().unwrap().text());
1487                assert_eq!(Some("foo"), e.as_text());
1488            }),
1489            owned_asserts: vec![assert_pass_try_into!(try_into_symbol)],
1490        }
1491    }
1492
1493    fn blob_case() -> Case {
1494        Case {
1495            elem: Element::blob(b"hello"),
1496            ion_type: IonType::Blob,
1497            ops: vec![AsBytes, TryIntoLob, TryIntoBlob],
1498            op_assert: Box::new(|e: &Element| {
1499                let _ = e.expect_lob().expect("expected lob");
1500                let _ = e.expect_blob().expect("expected blob");
1501                assert_eq!(Some("hello".as_bytes()), e.as_lob())
1502            }),
1503            owned_asserts: vec![
1504                assert_pass_try_into!(try_into_lob),
1505                assert_pass_try_into!(try_into_blob),
1506                Box::new(|e: Element| {
1507                    if let Value::Blob(bytes) = e.into_value() {
1508                        let data: Vec<_> = bytes.into();
1509                        assert_eq!(b"hello", data.as_slice());
1510                    } else {
1511                        panic!("expected blob");
1512                    }
1513                }),
1514            ],
1515        }
1516    }
1517
1518    fn clob_case() -> Case {
1519        Case {
1520            elem: Element::clob(b"goodbye"),
1521            ion_type: IonType::Clob,
1522            ops: vec![AsBytes, TryIntoLob, TryIntoClob],
1523            op_assert: Box::new(|e: &Element| {
1524                let _ = e.expect_lob().expect("expected lob");
1525                let _ = e.expect_clob().expect("expected clob");
1526                assert_eq!(Some("goodbye".as_bytes()), e.as_lob())
1527            }),
1528            owned_asserts: vec![
1529                assert_pass_try_into!(try_into_lob),
1530                assert_pass_try_into!(try_into_clob),
1531                Box::new(|e: Element| {
1532                    if let Value::Clob(bytes) = e.into_value() {
1533                        let data: Vec<_> = bytes.into();
1534                        assert_eq!(b"goodbye", data.as_slice());
1535                    } else {
1536                        panic!("expected clob");
1537                    }
1538                }),
1539            ],
1540        }
1541    }
1542
1543    fn list_case() -> Case {
1544        Case {
1545            elem: ion_list![true, false].into(),
1546            ion_type: IonType::List,
1547            ops: vec![AsSequence, TryIntoList, TryIntoSequence],
1548            op_assert: Box::new(|e: &Element| {
1549                let _ = e.expect_list().expect("expected list");
1550                let _ = e.expect_sequence().expect("expected sequence");
1551                let actual = e.as_sequence().unwrap();
1552                let expected: Vec<Element> = ion_vec([true, false]);
1553                // assert the length of list
1554                assert_eq!(2, actual.len());
1555                for (i, actual_item) in actual.elements().enumerate() {
1556                    // assert the list elements one-by-one
1557                    assert_eq!(&expected[i], actual_item);
1558                }
1559                assert!(!actual.is_empty());
1560            }),
1561            owned_asserts: vec![
1562                assert_pass_try_into!(try_into_list),
1563                assert_pass_try_into!(try_into_sequence),
1564            ],
1565        }
1566    }
1567
1568    fn sexp_case() -> Case {
1569        Case {
1570            elem: ion_sexp!(true false).into(),
1571            ion_type: IonType::SExp,
1572            ops: vec![AsSequence, TryIntoSexp, TryIntoSequence],
1573            op_assert: Box::new(|e: &Element| {
1574                let _ = e.expect_sexp().expect("expected sexp");
1575                let _ = e.expect_sequence().expect("expected sequence");
1576                let actual = e.as_sequence().unwrap();
1577                let expected: Vec<Element> = ion_vec([true, false]);
1578                // assert the length of s-expression
1579                assert_eq!(2, actual.len());
1580                for (i, actual_item) in actual.elements().enumerate() {
1581                    // assert the s-expression elements one-by-one
1582                    assert_eq!(&expected[i], actual_item);
1583                }
1584            }),
1585            owned_asserts: vec![
1586                assert_pass_try_into!(try_into_sexp),
1587                assert_pass_try_into!(try_into_sequence),
1588            ],
1589        }
1590    }
1591
1592    fn struct_case() -> Case {
1593        Case {
1594            elem: ion_struct! {"greetings": "hello", "name": "ion"}.into(),
1595            ion_type: IonType::Struct,
1596            ops: vec![AsStruct, TryIntoStruct],
1597            op_assert: Box::new(|e: &Element| {
1598                let _ = e.expect_struct().expect("expected struct");
1599                let actual: &Struct = e.as_struct().unwrap();
1600
1601                // verify that the field order is maintained when creating Struct
1602                assert_eq!(
1603                    actual.iter().next(),
1604                    Some((&"greetings".into(), &"hello".into()))
1605                );
1606
1607                assert_eq!(actual.get("greetings"), Some(&"hello".into()));
1608            }),
1609            owned_asserts: vec![assert_pass_try_into!(try_into_struct)],
1610        }
1611    }
1612    // TODO add more tests to remove the separate Owned/Borrowed tests and only keep generic tests
1613
1614    #[rstest]
1615    #[case::owned_null(null_case())]
1616    #[case::owned_bool(bool_case())]
1617    #[case::owned_i64(i64_case())]
1618    #[case::owned_big_int(big_int_case())]
1619    #[case::owned_f64(f64_case())]
1620    #[case::owned_decimal(decimal_case())]
1621    #[case::owned_timestamp(timestamp_case())]
1622    #[case::owned_string(string_case())]
1623    #[case::owned_blob(blob_case())]
1624    #[case::owned_clob(clob_case())]
1625    #[case::owned_list(list_case())]
1626    #[case::owned_sexp(sexp_case())]
1627    #[case::owned_struct(struct_case())]
1628    #[case::owned_symbol(symbol_case())]
1629    fn element_accessors(#[case] input_case: Case) {
1630        // table of negative assertions for each operation
1631        let neg_table: Vec<(ElemOp, ElemAssertFn)> = vec![
1632            (IsNull, Box::new(|e| assert!(!e.is_null()))),
1633            (AsBool, Box::new(|e| assert_eq!(None, e.as_bool()))),
1634            (
1635                AsAnyInt,
1636                Box::new(|e| {
1637                    assert_eq!(None, e.as_int());
1638                    assert_eq!(None, e.as_i64());
1639                }),
1640            ),
1641            (AsF64, Box::new(|e| assert_eq!(None, e.as_float()))),
1642            (AsDecimal, Box::new(|e| assert_eq!(None, e.as_decimal()))),
1643            (
1644                AsTimestamp,
1645                Box::new(|e| assert_eq!(None, e.as_timestamp())),
1646            ),
1647            (AsStr, Box::new(|e| assert_eq!(None, e.as_text()))),
1648            (AsSym, Box::new(|e| assert_eq!(None, e.as_symbol()))),
1649            (AsBytes, Box::new(|e| assert_eq!(None, e.as_lob()))),
1650            (AsSequence, Box::new(|e| assert!(e.as_sequence().is_none()))),
1651            (AsStruct, Box::new(|e| assert_eq!(None, e.as_struct()))),
1652        ];
1653
1654        let owned_neg_table: Vec<(ElemOp, OwnedElemAssertFn)> = vec![
1655            (TryIntoInt, assert_fail_try_into!(try_into_int)),
1656            (TryIntoI64, assert_fail_try_into!(try_into_i64)),
1657            (TryIntoF64, assert_fail_try_into!(try_into_float)),
1658            (TryIntoDecimal, assert_fail_try_into!(try_into_decimal)),
1659            (TryIntoTimestamp, assert_fail_try_into!(try_into_timestamp)),
1660            (TryIntoText, assert_fail_try_into!(try_into_text)),
1661            (TryIntoString, assert_fail_try_into!(try_into_string)),
1662            (TryIntoSymbol, assert_fail_try_into!(try_into_symbol)),
1663            (TryIntoBool, assert_fail_try_into!(try_into_bool)),
1664            (TryIntoLob, assert_fail_try_into!(try_into_lob)),
1665            (TryIntoBlob, assert_fail_try_into!(try_into_blob)),
1666            (TryIntoClob, assert_fail_try_into!(try_into_clob)),
1667            (TryIntoSequence, assert_fail_try_into!(try_into_sequence)),
1668            (TryIntoList, assert_fail_try_into!(try_into_list)),
1669            (TryIntoSexp, assert_fail_try_into!(try_into_sexp)),
1670            (TryIntoStruct, assert_fail_try_into!(try_into_struct)),
1671        ];
1672
1673        // produce the table of assertions to operate on, replacing the one specified by
1674        // the test case
1675        let valid_ops: HashSet<ElemOp> = input_case.ops.into_iter().collect();
1676        let borrowed_pos = once(input_case.op_assert);
1677        let owned_pos = input_case.owned_asserts.into_iter();
1678        let borrowed_neg = neg_table
1679            .into_iter()
1680            .filter_map(|(op, f)| (!valid_ops.contains(&op)).then_some(f));
1681        let owned_neg = owned_neg_table
1682            .into_iter()
1683            .filter_map(|(op, f)| (!valid_ops.contains(&op)).then_some(f));
1684        let borrowed = borrowed_pos.chain(borrowed_neg);
1685        let owned = owned_pos
1686            .chain(owned_neg)
1687            .map(|owned_fn| Box::new(|e: &Element| owned_fn(e.clone())) as ElemAssertFn);
1688        let op_assertions: Vec<ElemAssertFn> = borrowed.chain(owned).collect();
1689
1690        // construct an element to test
1691        assert_eq!(input_case.ion_type, input_case.elem.ion_type());
1692
1693        // assert value & annotation accessors
1694        let val_ref = input_case.elem.value();
1695        let ann_ref = input_case.elem.annotations();
1696        let val_owned = input_case.elem.clone().into_value();
1697        let ann_owned = input_case.elem.clone().into_annotations();
1698        let (ann_owned2, val_owned2) = input_case.elem.clone().into_parts();
1699        assert_eq!(val_ref, &val_owned);
1700        assert_eq!(val_owned, val_owned2);
1701        assert_eq!(ann_ref, &ann_owned);
1702        assert_eq!(ann_owned, ann_owned2);
1703
1704        // assert element operations
1705        for assert in op_assertions {
1706            assert(&input_case.elem);
1707        }
1708
1709        // assert that an element as-is is equal to itself
1710        // Creating an alias here bypasses clippy's objection to comparing any literal to itself.
1711        let itself = &input_case.elem;
1712        assert_eq!(&input_case.elem, itself);
1713    }
1714}
1715
1716#[cfg(test)]
1717mod value_tests {
1718    use std::fmt::Debug;
1719
1720    use rstest::*;
1721
1722    use crate::element::*;
1723    use crate::ion_data::IonEq;
1724    use crate::types::UInt;
1725    use crate::{ion_list, ion_sexp, ion_struct, IonType};
1726
1727    #[test]
1728    fn demonstrate_element_implements_send() {
1729        use std::thread;
1730        // The Element type must implement `Send` in order for values to be
1731        // moved between threads. If changes are made to the `Element` type
1732        // or its nested field types (like the `Value` enum and its variants)
1733        // which accidentally cause it not to implement `Send`, then this test
1734        // will fail to compile.
1735        let list: Element = ion_list![1, 2, 3].into();
1736        thread::scope(|_| {
1737            // Move `list` into this scope, demonstrating `Send`
1738            let elements = [list];
1739            // Trivial assertion to use `elements`
1740            assert_eq!(elements.len(), 1);
1741        });
1742    }
1743
1744    #[rstest]
1745    #[case::strings(
1746        Element::from("hello"), // An explicitly constructed String Element
1747        "hello"                 // A Rust &str, which implements Into<Element>
1748    )]
1749    #[case::symbols(
1750        Element::from(Symbol::owned("hello")), // An explicitly constructed Symbol Element
1751        Symbol::owned("hello")                 // A Symbol, which implements Into<Element>
1752    )]
1753    #[case::struct_(
1754        ion_struct!{"greetings": "hello"},
1755        Element::read_one(r#"{greetings: "hello"}"#).unwrap()
1756    )]
1757    #[case::strings(
1758        Element::from("hello"), // An explicitly constructed String Element
1759        "hello"                 // A Rust &str, which implements Into<Element>
1760    )]
1761    #[case::symbols(
1762        Element::from(Symbol::owned("hello")), // An explicitly constructed Symbol Element
1763        Symbol::owned("hello")                 // A Symbol, which implements Into<Element>
1764    )]
1765    #[case::struct_(
1766        ion_struct!{"greetings": "hello"},
1767        Element::read_one(r#"{greetings: "hello"}"#).unwrap()
1768    )]
1769    fn owned_element_accessors<E1, E2>(#[case] e1: E1, #[case] e2: E2)
1770    where
1771        E1: Into<Element>,
1772        E2: Into<Element>,
1773    {
1774        // assert that both element construction methods create the same element
1775        assert_eq!(e1.into(), e2.into());
1776    }
1777
1778    #[rstest]
1779    #[case::struct_(ion_struct!{"greetings": "hello", "name": "Ion"}, 2)]
1780    #[case::list(ion_list!["greetings", 5, true], 3)]
1781    #[case::sexp(ion_sexp!(5 true), 2)]
1782    fn owned_container_len_test<I: Into<Element>>(#[case] container: I, #[case] length: usize) {
1783        let container = container.into();
1784        match container.ion_type() {
1785            IonType::List | IonType::SExp => {
1786                // check length for given sequence value
1787                assert_eq!(container.as_sequence().unwrap().len(), length);
1788            }
1789            IonType::Struct => {
1790                // check length for given struct value
1791                assert_eq!(container.as_struct().unwrap().len(), length);
1792            }
1793            _ => {
1794                unreachable!("This test is only for container type elements")
1795            }
1796        }
1797    }
1798
1799    #[rstest]
1800    #[case::struct_(ion_struct!{"greetings": "hello", "name": "Ion"}, false)]
1801    #[case::list(ion_list!["greetings", 5, true], false)]
1802    #[case::list_empty(ion_list![], true)]
1803    #[case::sexp(ion_sexp!(5 true), false)]
1804    #[case::sexp_empty(ion_sexp!(), true)]
1805    fn owned_container_is_empty_test<I: Into<Element>>(
1806        #[case] container: I,
1807        #[case] is_empty: bool,
1808    ) {
1809        let container = container.into();
1810        match container.ion_type() {
1811            IonType::List | IonType::SExp => {
1812                // check length for given sequence value
1813                assert_eq!(container.as_sequence().unwrap().is_empty(), is_empty);
1814            }
1815            IonType::Struct => {
1816                // check length for given struct value
1817                assert_eq!(container.as_struct().unwrap().is_empty(), is_empty);
1818            }
1819            _ => {
1820                unreachable!("This test is only for container type elements")
1821            }
1822        }
1823    }
1824
1825    #[test]
1826    fn list_display_roundtrip() {
1827        let list = ion_list![1, 2, 3, true, false];
1828
1829        // Use the Display impl to serialize the list to text
1830        let text_list = format!("{list}");
1831        // Parse the result and make sure it represents the same data
1832        let expected_element: Element = list.into();
1833        let actual_element = Element::read_one(text_list).unwrap();
1834        assert!(expected_element.ion_eq(&actual_element));
1835    }
1836
1837    #[test]
1838    fn sexp_display_roundtrip() {
1839        let sexp = ion_sexp! (1 2 3 true false);
1840
1841        // Use the Display impl to serialize the sexp to text
1842        let text_sexp = format!("{sexp}");
1843        // Parse the result and make sure it represents the same data
1844        let expected_element: Element = sexp.into();
1845        let actual_element = Element::read_one(text_sexp).unwrap();
1846        assert!(expected_element.ion_eq(&actual_element));
1847    }
1848
1849    #[test]
1850    fn struct_display_roundtrip() {
1851        let struct_ = ion_struct! {"foo": 1, "bar": 2, "baz": ion_list! [true, false]};
1852
1853        // Use the Display impl to serialize the struct to text
1854        let text_struct = format!("{struct_}");
1855        // Parse the result and make sure it represents the same data
1856        let expected_element: Element = struct_.into();
1857        let actual_element = Element::read_one(text_struct).unwrap();
1858        assert!(expected_element.ion_eq(&actual_element));
1859    }
1860
1861    #[rstest]
1862    #[case::i8(42i8)]
1863    #[case::i8_neg(-42i8)]
1864    #[case::i16(42i16)]
1865    #[case::i16_neg(-42i16)]
1866    #[case::i32(42i32)]
1867    #[case::i32_neg(-42i32)]
1868    #[case::i64(42i64)]
1869    #[case::i64_neg(-42i64)]
1870    #[case::i128(42i128)]
1871    #[case::i128_neg(-42i128)]
1872    #[case::isize(42isize)]
1873    #[case::isize_neg(-42isize)]
1874    #[case::int(Int::from(42i64))]
1875    #[case::int_neg(Int::from(-42i64))]
1876    #[case::u8(42u8)]
1877    #[case::u16(42u16)]
1878    #[case::u32(42u32)]
1879    #[case::u64(42u64)]
1880    #[case::u128(42u128)]
1881    #[case::usize(42usize)]
1882    #[case::uint(UInt::from(42u64))]
1883    fn element_from_int<I, E>(#[case] source_int: I)
1884    where
1885        E: Debug,
1886        I: TryInto<Int, Error = E>,
1887    {
1888        let int: Int = source_int.try_into().unwrap();
1889        let element: Element = int.clone().into();
1890        assert_eq!(element.expect_i64(), int.expect_i64())
1891    }
1892
1893    #[rstest]
1894    fn read_a_symbol_terminated_by_end_of_input(
1895        #[values(
1896        "a","b","c","d","e","f","g","h","i","j",
1897        "k","l","m","n","o","p","q","r","s","t",
1898        // These are all things that look like they _could_
1899        // be an incomplete value (or IVM).
1900        "fa", "fal", "fals",
1901        "na", "nu", "nul",
1902        "tr", "tru",
1903        "$ion_",
1904        "$ion_1",
1905        "$ion_1_",
1906        )]
1907        input: &str,
1908    ) -> IonResult<()> {
1909        let value = Element::read_one(input)?;
1910        let actual_text = value.as_symbol().unwrap().text().unwrap();
1911        assert_eq!(actual_text, input);
1912        Ok(())
1913    }
1914}