1use crate::element::builders::{SequenceBuilder, StructBuilder};
16use crate::element::reader::ElementReader;
17use crate::ion_data::{IonEq, IonOrd};
18use crate::text::text_formatter::IonValueFormatter;
19use crate::{
20 ion_data, BinaryWriterBuilder, Decimal, Int, IonResult, IonType, IonWriter, ReaderBuilder, Str,
21 Symbol, TextWriterBuilder, Timestamp,
22};
23use num_bigint::BigInt;
24use std::cmp::Ordering;
25use std::fmt::{Display, Formatter};
26use std::io;
27
28mod annotations;
29pub mod builders;
30pub mod element_stream_reader;
31pub mod element_stream_writer;
32pub(crate) mod iterators;
33pub mod reader;
34pub mod writer;
35
36use crate::element::writer::{ElementWriter, Format, TextKind};
38pub use crate::types::{Blob, Bytes, Clob};
39pub use annotations::{Annotations, IntoAnnotations};
40
41pub use crate::types::{List, SExp, Sequence, Struct};
42
43impl IonEq for Value {
44 fn ion_eq(&self, other: &Self) -> bool {
45 use Value::*;
46 match (self, other) {
47 (Null(this), Null(that)) => this == that,
48 (Bool(this), Bool(that)) => ion_data::ion_eq_bool(this, that),
49 (Int(this), Int(that)) => this.ion_eq(that),
50 (Float(this), Float(that)) => ion_data::ion_eq_f64(this, that),
51 (Decimal(this), Decimal(that)) => this.ion_eq(that),
52 (Timestamp(this), Timestamp(that)) => this.ion_eq(that),
53 (Symbol(this), Symbol(that)) => this.ion_eq(that),
54 (String(this), String(that)) => this.ion_eq(that),
55 (Clob(this), Clob(that)) => this.ion_eq(that),
56 (Blob(this), Blob(that)) => this.ion_eq(that),
57 (List(this), List(that)) => this.ion_eq(that),
58 (SExp(this), SExp(that)) => this.ion_eq(that),
59 (Struct(this), Struct(that)) => this.ion_eq(that),
60 _ => false,
61 }
62 }
63}
64
65impl IonOrd for Value {
66 fn ion_cmp(&self, other: &Self) -> Ordering {
67 use Value::*;
68
69 let ord = self.ion_type().ion_cmp(&other.ion_type());
71 if !ord.is_eq() {
72 return ord;
73 }
74
75 macro_rules! compare {
76 ($p:pat => $e:expr) => {
77 match other {
78 $p => $e,
79 Null(_) => Ordering::Greater,
80 _ => unreachable!("We already checked the Ion Type!"),
81 }
82 };
83 }
84
85 match self {
86 Null(_) => {
87 if let Null(_) = other {
88 Ordering::Equal
89 } else {
90 Ordering::Less
91 }
92 }
93 Bool(this) => compare!(Bool(that) => ion_data::ion_cmp_bool(this, that)),
94 Int(this) => compare!(Int(that) => this.ion_cmp(that)),
95 Float(this) => compare!(Float(that) => ion_data::ion_cmp_f64(this, that)),
96 Decimal(this) => compare!(Decimal(that) => this.ion_cmp(that)),
97 Timestamp(this) => compare!(Timestamp(that) => this.ion_cmp(that)),
98 Symbol(this) => compare!(Symbol(that) => this.ion_cmp(that)),
99 String(this) => compare!(String(that) => this.ion_cmp(that)),
100 Clob(this) => compare!(Clob(that) => this.ion_cmp(that)),
101 Blob(this) => compare!(Blob(that) => this.ion_cmp(that)),
102 List(this) => compare!(List(that) => this.ion_cmp(that)),
103 SExp(this) => compare!(SExp(that) => this.ion_cmp(that)),
104 Struct(this) => compare!(Struct(that) => this.ion_cmp(that)),
105 }
106 }
107}
108
109#[derive(Debug, Clone, PartialEq)]
111pub enum Value {
112 Null(IonType),
113 Bool(bool),
114 Int(Int),
115 Float(f64),
116 Decimal(Decimal),
117 Timestamp(Timestamp),
118 Symbol(Symbol),
119 String(Str),
120 Clob(Bytes),
121 Blob(Bytes),
122 List(Sequence),
123 SExp(Sequence),
124 Struct(Struct),
125}
126
127impl Value {
128 pub fn ion_type(&self) -> IonType {
129 use Value::*;
130
131 match self {
132 Null(t) => *t,
133 Bool(_) => IonType::Bool,
134 Int(_) => IonType::Int,
135 Float(_) => IonType::Float,
136 Decimal(_) => IonType::Decimal,
137 Timestamp(_) => IonType::Timestamp,
138 Symbol(_) => IonType::Symbol,
139 String(_) => IonType::String,
140 Clob(_) => IonType::Clob,
141 Blob(_) => IonType::Blob,
142 List(_) => IonType::List,
143 SExp(_) => IonType::SExp,
144 Struct(_) => IonType::Struct,
145 }
146 }
147}
148
149impl Display for Value {
150 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
151 let mut ivf = IonValueFormatter { output: f };
152 match &self {
153 Value::Null(ion_type) => ivf.format_null(*ion_type),
154 Value::Bool(bool) => ivf.format_bool(*bool),
155 Value::Int(integer) => ivf.format_integer(integer),
156 Value::Float(float) => ivf.format_float(*float),
157 Value::Decimal(decimal) => ivf.format_decimal(decimal),
158 Value::Timestamp(timestamp) => ivf.format_timestamp(timestamp),
159 Value::Symbol(symbol) => ivf.format_symbol(symbol),
160 Value::String(string) => ivf.format_string(string),
161 Value::Clob(clob) => ivf.format_clob(clob),
162 Value::Blob(blob) => ivf.format_blob(blob),
163 Value::List(sequence) => ivf.format_list(sequence),
164 Value::SExp(sequence) => ivf.format_sexp(sequence),
165 Value::Struct(struct_) => ivf.format_struct(struct_),
166 }
167 .map_err(|_| std::fmt::Error)?;
168
169 Ok(())
170 }
171}
172
173impl From<IonType> for Value {
174 fn from(ion_type: IonType) -> Self {
175 Value::Null(ion_type)
176 }
177}
178
179impl From<i64> for Value {
180 fn from(i64_val: i64) -> Self {
181 Value::Int(Int::I64(i64_val))
182 }
183}
184
185impl From<BigInt> for Value {
186 fn from(big_int_val: BigInt) -> Self {
187 Value::Int(Int::BigInt(big_int_val))
188 }
189}
190
191impl From<Int> for Value {
192 fn from(integer_val: Int) -> Self {
193 Value::Int(integer_val)
194 }
195}
196
197impl From<f64> for Value {
198 fn from(f64_val: f64) -> Self {
199 Value::Float(f64_val)
200 }
201}
202
203impl From<Decimal> for Value {
204 fn from(decimal_val: Decimal) -> Self {
205 Value::Decimal(decimal_val)
206 }
207}
208
209impl From<Timestamp> for Value {
210 fn from(timestamp_val: Timestamp) -> Self {
211 Value::Timestamp(timestamp_val)
212 }
213}
214
215impl From<bool> for Value {
216 fn from(bool_val: bool) -> Self {
217 Value::Bool(bool_val)
218 }
219}
220
221impl From<&str> for Value {
222 fn from(string_val: &str) -> Self {
223 Value::String(string_val.into())
224 }
225}
226
227impl From<String> for Value {
228 fn from(value: String) -> Self {
229 let s: Str = value.into();
230 Value::String(s)
231 }
232}
233
234impl From<Str> for Value {
235 fn from(string_val: Str) -> Self {
236 Value::String(string_val)
237 }
238}
239
240impl From<Symbol> for Value {
241 fn from(sym_val: Symbol) -> Self {
242 Value::Symbol(sym_val)
243 }
244}
245
246impl From<&[u8]> for Value {
247 fn from(value: &[u8]) -> Self {
248 Value::Blob(value.into())
249 }
250}
251
252impl From<Vec<u8>> for Value {
253 fn from(value: Vec<u8>) -> Self {
254 Value::Blob(value.into())
255 }
256}
257
258impl From<Blob> for Value {
259 fn from(blob: Blob) -> Self {
260 let bytes: Bytes = blob.into();
261 Value::Blob(bytes)
262 }
263}
264
265impl From<Clob> for Value {
266 fn from(clob: Clob) -> Self {
267 let bytes: Bytes = clob.into();
268 Value::Clob(bytes)
269 }
270}
271
272impl From<List> for Value {
273 fn from(list: List) -> Self {
274 Value::List(list.into())
275 }
276}
277
278impl From<SExp> for Value {
279 fn from(s_expr: SExp) -> Self {
280 Value::SExp(s_expr.into())
281 }
282}
283
284impl From<Struct> for Value {
285 fn from(struct_val: Struct) -> Self {
286 Value::Struct(struct_val)
287 }
288}
289
290#[cfg(feature = "experimental-streaming")]
291impl From<crate::tokens::ScalarValue> for Value {
292 fn from(value: crate::tokens::ScalarValue) -> Self {
293 use crate::tokens::ScalarValue;
294 match value {
295 ScalarValue::Bool(bool) => Value::Bool(bool),
296 ScalarValue::Int(int) => Value::Int(int),
297 ScalarValue::Float(float) => Value::Float(float),
298 ScalarValue::Decimal(decimal) => Value::Decimal(decimal),
299 ScalarValue::Timestamp(timestamp) => Value::Timestamp(timestamp),
300 ScalarValue::String(text) => Value::String(text),
301 ScalarValue::Symbol(symbol) => Value::Symbol(symbol),
302 ScalarValue::Blob(bytes) => Value::Blob(bytes),
303 ScalarValue::Clob(bytes) => Value::Clob(bytes),
304 }
305 }
306}
307
308pub trait IntoAnnotatedElement: Into<Value> {
326 fn with_annotations<I: IntoAnnotations>(self, annotations: I) -> Element {
328 Element::new(annotations.into_annotations(), self.into())
329 }
330}
331
332impl<V> IntoAnnotatedElement for V where V: Into<Value> {}
333
334impl IonEq for Element {
335 fn ion_eq(&self, other: &Self) -> bool {
336 self.annotations == other.annotations && self.value.ion_eq(&other.value)
337 }
338}
339
340impl IonOrd for Element {
345 fn ion_cmp(&self, other: &Self) -> Ordering {
346 let ord = self.ion_type().ion_cmp(&other.ion_type());
347 if !ord.is_eq() {
348 return ord;
349 }
350
351 let a1 = self.annotations();
352 let a2 = other.annotations();
353
354 let ord = a1.ion_cmp(a2);
355 if !ord.is_eq() {
356 return ord;
357 }
358
359 let v1 = self.value();
360 let v2 = other.value();
361 v1.ion_cmp(v2)
362 }
363}
364
365#[derive(Debug, Clone)]
367pub struct Element {
368 annotations: Annotations,
369 value: Value,
370}
371
372impl Element {
373 pub(crate) fn new(annotations: Annotations, value: impl Into<Value>) -> Self {
374 Self {
375 annotations,
376 value: value.into(),
377 }
378 }
379
380 pub fn value(&self) -> &Value {
392 &self.value
393 }
394
395 pub fn null(null_type: IonType) -> Element {
396 null_type.into()
397 }
398
399 pub fn boolean(value: bool) -> Element {
400 value.into()
401 }
402
403 pub fn string<I: Into<Str>>(str: I) -> Element {
404 let text: Str = str.into();
405 text.into()
406 }
407
408 pub fn symbol<I: Into<Symbol>>(symbol: I) -> Element {
409 let symbol: Symbol = symbol.into();
410 symbol.into()
411 }
412
413 pub fn integer<I: Into<Int>>(integer: I) -> Element {
414 let integer: Int = integer.into();
415 integer.into()
416 }
417
418 pub fn decimal(decimal: Decimal) -> Element {
419 decimal.into()
420 }
421
422 pub fn timestamp(timestamp: Timestamp) -> Element {
423 timestamp.into()
424 }
425
426 pub fn float(float: f64) -> Element {
427 float.into()
428 }
429
430 pub fn clob<A: AsRef<[u8]>>(bytes: A) -> Element {
431 let bytes: &[u8] = bytes.as_ref();
432 Value::Clob(bytes.into()).into()
433 }
434
435 pub fn blob<A: AsRef<[u8]>>(bytes: A) -> Element {
436 let bytes: &[u8] = bytes.as_ref();
437 Value::Blob(bytes.into()).into()
438 }
439
440 pub fn sequence_builder() -> SequenceBuilder {
441 Sequence::builder()
442 }
443
444 pub fn struct_builder() -> StructBuilder {
445 Struct::builder()
446 }
447
448 pub fn ion_type(&self) -> IonType {
449 self.value.ion_type()
450 }
451
452 pub fn annotations(&self) -> &Annotations {
453 &self.annotations
454 }
455
456 pub fn with_annotations<I: IntoAnnotations>(self, annotations: I) -> Self {
457 Element::new(annotations.into_annotations(), self.value)
458 }
459
460 pub fn is_null(&self) -> bool {
461 matches!(&self.value, Value::Null(_))
462 }
463
464 pub fn as_int(&self) -> Option<&Int> {
465 match &self.value {
466 Value::Int(i) => Some(i),
467 _ => None,
468 }
469 }
470
471 pub fn as_float(&self) -> Option<f64> {
472 match &self.value {
473 Value::Float(f) => Some(*f),
474 _ => None,
475 }
476 }
477
478 pub fn as_decimal(&self) -> Option<&Decimal> {
479 match &self.value {
480 Value::Decimal(d) => Some(d),
481 _ => None,
482 }
483 }
484
485 pub fn as_timestamp(&self) -> Option<&Timestamp> {
486 match &self.value {
487 Value::Timestamp(t) => Some(t),
488 _ => None,
489 }
490 }
491
492 pub fn as_text(&self) -> Option<&str> {
493 match &self.value {
494 Value::String(text) => Some(text.as_ref()),
495 Value::Symbol(sym) => sym.text(),
496 _ => None,
497 }
498 }
499
500 pub fn as_string(&self) -> Option<&str> {
501 match &self.value {
502 Value::String(text) => Some(text.as_ref()),
503 _ => None,
504 }
505 }
506
507 pub fn as_symbol(&self) -> Option<&Symbol> {
508 match &self.value {
509 Value::Symbol(sym) => Some(sym),
510 _ => None,
511 }
512 }
513
514 pub fn as_bool(&self) -> Option<bool> {
515 match &self.value {
516 Value::Bool(b) => Some(*b),
517 _ => None,
518 }
519 }
520
521 pub fn as_lob(&self) -> Option<&[u8]> {
522 match &self.value {
523 Value::Blob(bytes) | Value::Clob(bytes) => Some(bytes.as_ref()),
524 _ => None,
525 }
526 }
527
528 pub fn as_blob(&self) -> Option<&[u8]> {
529 match &self.value {
530 Value::Blob(bytes) => Some(bytes.as_ref()),
531 _ => None,
532 }
533 }
534
535 pub fn as_clob(&self) -> Option<&[u8]> {
536 match &self.value {
537 Value::Clob(bytes) => Some(bytes.as_ref()),
538 _ => None,
539 }
540 }
541
542 pub fn as_sequence(&self) -> Option<&Sequence> {
543 match &self.value {
544 Value::SExp(s) | Value::List(s) => Some(s),
545 _ => None,
546 }
547 }
548
549 pub fn as_struct(&self) -> Option<&Struct> {
550 match &self.value {
551 Value::Struct(structure) => Some(structure),
552 _ => None,
553 }
554 }
555
556 pub fn read_first<A: AsRef<[u8]>>(data: A) -> IonResult<Option<Element>> {
562 let bytes: &[u8] = data.as_ref();
563 let mut reader = ReaderBuilder::default().build(bytes)?;
565 reader.read_next_element()
566 }
567
568 pub fn read_one<A: AsRef<[u8]>>(data: A) -> IonResult<Element> {
571 let bytes: &[u8] = data.as_ref();
572 let mut reader = ReaderBuilder::default().build(bytes)?;
574 reader.read_one_element()
575 }
576
577 pub fn read_all<A: AsRef<[u8]>>(data: A) -> IonResult<Vec<Element>> {
582 let bytes: &[u8] = data.as_ref();
583 ReaderBuilder::default().build(bytes)?.elements().collect()
584 }
585
586 pub fn write_to<W: ElementWriter>(&self, writer: &mut W) -> IonResult<()> {
611 writer.write_element(self)?;
612 Ok(())
613 }
614
615 pub fn write_as<W: io::Write>(&self, format: Format, output: W) -> IonResult<()> {
646 match format {
647 Format::Text(text_kind) => {
648 let mut text_writer = TextWriterBuilder::new(text_kind).build(output)?;
649 self.write_to(&mut text_writer)?;
650 text_writer.flush()
651 }
652 Format::Binary => {
653 let mut binary_writer = BinaryWriterBuilder::default().build(output)?;
654 self.write_to(&mut binary_writer)?;
655 binary_writer.flush()
656 }
657 }
658 }
659
660 pub fn to_binary(&self) -> IonResult<Vec<u8>> {
689 let mut buffer = Vec::new();
690 self.write_as(Format::Binary, &mut buffer)?;
691 Ok(buffer)
692 }
693
694 pub fn to_text(&self, text_kind: TextKind) -> IonResult<String> {
722 let mut buffer = Vec::new();
723 self.write_as(Format::Text(text_kind), &mut buffer)?;
724 Ok(std::str::from_utf8(&buffer)
725 .expect("writer produced invalid utf-8")
726 .to_string())
727 }
728}
729
730impl Display for Element {
731 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
732 let mut ivf = IonValueFormatter { output: f };
733
734 ivf.format_annotations(&self.annotations)
736 .map_err(|_| std::fmt::Error)?;
737
738 self.value.fmt(f)
739 }
740}
741
742impl PartialEq for Element {
743 fn eq(&self, other: &Self) -> bool {
744 self.value == other.value && self.annotations == other.annotations
745 }
746}
747
748impl Eq for Element {}
749
750impl<'a> From<&'a Element> for Element {
753 fn from(element: &'a Element) -> Self {
754 element.clone()
755 }
756}
757
758impl<T> From<T> for Element
761where
762 T: Into<Value>,
763{
764 fn from(value: T) -> Self {
765 Element::new(Annotations::empty(), value.into())
766 }
767}
768
769#[cfg(test)]
770mod tests {
771 use crate::element::annotations::IntoAnnotations;
772 use crate::types::Timestamp;
773 use crate::{ion_list, ion_sexp, ion_struct, Decimal, Int, IonType, Symbol};
774 use chrono::*;
775 use rstest::*;
776 use std::iter::{once, Once};
777
778 fn make_timestamp<T: AsRef<str>>(text: T) -> Timestamp {
780 DateTime::parse_from_rfc3339(text.as_ref()).unwrap().into()
781 }
782
783 struct CaseAnnotations {
784 elem: Element,
785 annotations: Annotations,
786 }
787
788 fn annotations_text_case() -> CaseAnnotations {
789 CaseAnnotations {
790 elem: 10i64.with_annotations(["foo", "bar", "baz"]),
791 annotations: ["foo", "bar", "baz"].into_annotations(),
792 }
793 }
794
795 fn no_annotations_case() -> CaseAnnotations {
796 CaseAnnotations {
797 elem: 10i64.into(),
798 annotations: Annotations::empty(),
799 }
800 }
801
802 #[rstest]
803 #[case::annotations_text(annotations_text_case())]
804 #[case::no_annotations(no_annotations_case())]
805 fn annotations_with_element(#[case] input: CaseAnnotations) {
806 let actual: &Annotations = input.elem.annotations();
807 let expected: &Annotations = &input.annotations;
808 assert_eq!(actual, expected);
809 }
810
811 struct CaseSym {
812 eq_annotations: Vec<Symbol>,
813 ne_annotations: Vec<Symbol>,
814 }
815
816 fn sym_text_case() -> CaseSym {
817 CaseSym {
819 eq_annotations: vec![Symbol::owned("foo"), Symbol::owned("foo")],
820 ne_annotations: vec![Symbol::owned("bar"), Symbol::owned("baz")],
822 }
823 }
824
825 #[rstest]
828 #[case::owned_sym_text(sym_text_case())]
829 fn symbol_token_eq(#[case] input: CaseSym) {
830 for eq_this_token in &input.eq_annotations {
832 for eq_other_token in &input.eq_annotations {
833 assert_eq!(eq_this_token, eq_other_token);
834 }
835 }
836
837 for eq_token in &input.eq_annotations {
840 for non_eq_token in &input.ne_annotations {
841 assert_ne!(eq_token, non_eq_token);
842 }
843 }
844 }
845
846 struct CaseStruct {
848 eq_elements: Vec<Element>,
850 ne_elements: Vec<Element>,
852 }
853
854 fn ion_vec<E: Into<Element>, I: IntoIterator<Item = E>>(values: I) -> Vec<Element> {
857 values.into_iter().map(|v| v.into()).collect()
858 }
859
860 fn struct_with_multiple_fields_case() -> CaseStruct {
861 CaseStruct {
862 eq_elements: ion_vec([
863 ion_struct! {
865 "greetings": "hello",
866 "name": "Ion"
867 },
868 ion_struct! {
869 "name": "Ion",
870 "greetings": "hello"
871 },
872 ]),
873 ne_elements: ion_vec([
874 ion_struct! {
876 "greetings": "hello",
877 "name": "Ion",
878 "greetings": "hello"
879 },
880 ion_struct! {
882 "greetings": "hello",
883 "name": "Ion",
884 "greetings": "bye"
885 },
886 ion_struct! {
888 "greetings": "hello",
889 "name": "Ion",
890 "message": "bye"
891 },
892 ]),
893 }
894 }
895
896 fn struct_with_duplicates_in_multiple_fields_case() -> CaseStruct {
897 CaseStruct {
898 eq_elements: ion_vec([
900 ion_struct! {
901 "a" : 2i64,
902 "a" : 2i64,
903 "a" : 1i64
904 },
905 ion_struct! {
906 "a" : 2i64,
907 "a" : 1i64,
908 "a" : 2i64
909 },
910 ion_struct! {
911 "a" : 1i64,
912 "a" : 2i64,
913 "a" : 2i64
914 },
915 ]),
916 ne_elements: ion_vec([
917 ion_struct! {
919 "a" : 1i64,
920 "a" : 2i64
921 },
922 ion_struct! {
924 "a" : 2i64,
925 "a" : 1i64.with_annotations(["a"]),
926 "a" : 2i64
927 },
928 ion_struct! {
930 "a" : 2i64,
931 "a" : 3i64,
932 "a" : 2i64
933 },
934 ]),
935 }
936 }
937
938 fn struct_with_duplicate_fieldnames_case() -> CaseStruct {
939 CaseStruct {
940 eq_elements: ion_vec([
941 ion_struct! {
943 "greetings" : "world",
944 "greetings" : "hello"
945 },
946 ion_struct! {
947 "greetings" : "world",
948 "greetings" : "hello"
949 },
950 ]),
951 ne_elements: ion_vec([
952 ion_struct! {
954 "greetings" : "world",
955 "greetings" : "hello",
956 "greetings" : "hey"
957 },
958 ion_struct! {
960 "greetings" : "world",
961 "greetings" : "hello".with_annotations(["foo"])
962 },
963 ion_struct! {
965 "greetings" : "world",
966 "greetings" : "hello",
967 "name" : "hello"
968 },
969 ]),
970 }
971 }
972
973 #[rstest]
974 #[case::owned_struct_with_multiple_fields(struct_with_multiple_fields_case())]
975 #[case::owned_struct_with_duplicates_in_multiple_fields(
976 struct_with_duplicates_in_multiple_fields_case()
977 )]
978 #[case::owned_struct_with_duplicate_fieldnames(struct_with_duplicate_fieldnames_case())]
979 fn struct_accessors(#[case] input: CaseStruct) {
980 for eq_this_struct in &input.eq_elements {
982 for eq_other_struct in &input.eq_elements {
983 assert_eq!(eq_this_struct, eq_other_struct);
984 }
985 }
986
987 for eq_struct in &input.eq_elements {
990 for non_eq_struct in &input.ne_elements {
991 assert_ne!(eq_struct, non_eq_struct);
992 }
993 }
994 }
995
996 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
998 enum ElemOp {
999 IsNull,
1000 AsBool,
1001 AsAnyInt,
1002 AsF64,
1003 AsDecimal,
1004 AsTimestamp,
1005 AsStr,
1006 AsSym,
1007 AsBytes,
1008 AsSequence,
1009 AsStruct,
1010 }
1011
1012 impl IntoIterator for ElemOp {
1013 type Item = ElemOp;
1014 type IntoIter = <Once<ElemOp> as IntoIterator>::IntoIter;
1015
1016 fn into_iter(self) -> Self::IntoIter {
1017 once(self)
1018 }
1019 }
1020
1021 use crate::element::{Annotations, Element, IntoAnnotatedElement, Struct};
1022 use crate::types::IntAccess;
1023 use num_bigint::BigInt;
1024 use std::collections::HashSet;
1025 use std::str::FromStr;
1026 use ElemOp::*;
1027
1028 type ElemAssertFn = Box<dyn FnOnce(&Element)>;
1029
1030 struct Case {
1031 elem: Element,
1032 ion_type: IonType,
1033 ops: Vec<ElemOp>,
1034 op_assert: ElemAssertFn,
1035 }
1036
1037 fn null_case() -> Case {
1038 Case {
1039 elem: Element::from(IonType::Null), ion_type: IonType::Null,
1041 ops: vec![IsNull],
1042 op_assert: Box::new(|e: &Element| assert!(e.is_null())),
1043 }
1044 }
1045
1046 fn bool_case() -> Case {
1047 Case {
1048 elem: true.into(),
1049 ion_type: IonType::Bool,
1050 ops: vec![AsBool],
1051 op_assert: Box::new(|e: &Element| {
1052 let expected = Element::from(true);
1053 assert_eq!(Some(true), e.as_bool());
1054 assert_eq!(&expected, e);
1055 }),
1056 }
1057 }
1058
1059 fn i64_case() -> Case {
1060 Case {
1061 elem: 100.into(),
1062 ion_type: IonType::Int,
1063 ops: vec![AsAnyInt],
1064 op_assert: Box::new(|e: &Element| {
1065 let expected: Element = 100i64.into();
1066 assert_eq!(Some(&Int::I64(100)), e.as_int());
1067 assert_eq!(Some(100), e.as_i64());
1068 assert_eq!(None, e.as_big_int());
1069 assert_eq!(&expected, e);
1070 }),
1071 }
1072 }
1073
1074 fn big_int_case() -> Case {
1075 Case {
1076 elem: BigInt::from(100).into(),
1077 ion_type: IonType::Int,
1078 ops: vec![AsAnyInt],
1079 op_assert: Box::new(|e: &Element| {
1080 let expected: Element = BigInt::from(100).into();
1081 assert_eq!(Some(&Int::BigInt(BigInt::from(100))), e.as_int());
1082 assert_eq!(BigInt::from_str("100").unwrap(), *e.as_big_int().unwrap());
1083 assert_eq!(&expected, e);
1084 }),
1085 }
1086 }
1087
1088 fn f64_case() -> Case {
1089 Case {
1090 elem: 16.0.into(),
1091 ion_type: IonType::Float,
1092 ops: vec![AsF64],
1093 op_assert: Box::new(|e: &Element| {
1094 let expected = Element::from(16.0f64);
1095 assert_eq!(Some(16.0), e.as_float());
1096 assert_eq!(&expected, e);
1097 }),
1098 }
1099 }
1100
1101 fn timestamp_case() -> Case {
1102 Case {
1103 elem: make_timestamp("2014-10-16T12:01:00-00:00").into(),
1104 ion_type: IonType::Timestamp,
1105 ops: vec![AsTimestamp],
1106 op_assert: Box::new(|e: &Element| {
1107 let expected: Element = make_timestamp("2014-10-16T12:01:00+00:00").into();
1108 assert_eq!(
1109 Some(&make_timestamp("2014-10-16T12:01:00+00:00")),
1110 e.as_timestamp()
1111 );
1112 assert_eq!(&expected, e);
1113 }),
1114 }
1115 }
1116
1117 fn decimal_case() -> Case {
1118 Case {
1119 elem: Decimal::new(8, 3).into(),
1120 ion_type: IonType::Decimal,
1121 ops: vec![AsDecimal],
1122 op_assert: Box::new(|e: &Element| {
1123 let expected: Element = Decimal::new(8, 3).into();
1124 assert_eq!(Some(&Decimal::new(80, 2)), e.as_decimal());
1125 assert_eq!(&expected, e);
1126 }),
1127 }
1128 }
1129
1130 fn string_case() -> Case {
1131 Case {
1132 elem: "hello".into(),
1133 ion_type: IonType::String,
1134 ops: vec![AsStr],
1135 op_assert: Box::new(|e: &Element| assert_eq!(Some("hello"), e.as_text())),
1136 }
1137 }
1138
1139 fn symbol_case() -> Case {
1140 Case {
1141 elem: Symbol::owned("foo").into(),
1142 ion_type: IonType::Symbol,
1143 ops: vec![AsSym, AsStr],
1144 op_assert: Box::new(|e: &Element| {
1145 assert_eq!(Some("foo"), e.as_symbol().unwrap().text());
1146 assert_eq!(Some("foo"), e.as_text());
1147 }),
1148 }
1149 }
1150
1151 fn blob_case() -> Case {
1152 Case {
1153 elem: Element::blob(b"hello"),
1154 ion_type: IonType::Blob,
1155 ops: vec![AsBytes],
1156 op_assert: Box::new(|e: &Element| assert_eq!(Some("hello".as_bytes()), e.as_lob())),
1157 }
1158 }
1159
1160 fn clob_case() -> Case {
1161 Case {
1162 elem: Element::clob(b"goodbye"),
1163 ion_type: IonType::Clob,
1164 ops: vec![AsBytes],
1165 op_assert: Box::new(|e: &Element| assert_eq!(Some("goodbye".as_bytes()), e.as_lob())),
1166 }
1167 }
1168
1169 fn list_case() -> Case {
1170 Case {
1171 elem: ion_list![true, false].into(),
1172 ion_type: IonType::List,
1173 ops: vec![AsSequence],
1174 op_assert: Box::new(|e: &Element| {
1175 let actual = e.as_sequence().unwrap();
1176 let expected: Vec<Element> = ion_vec([true, false]);
1177 assert_eq!(2, actual.len());
1179 for (i, actual_item) in actual.elements().enumerate() {
1180 assert_eq!(&expected[i], actual_item);
1182 }
1183 assert!(!actual.is_empty());
1184 }),
1185 }
1186 }
1187
1188 fn sexp_case() -> Case {
1189 Case {
1190 elem: ion_sexp!(true false).into(),
1191 ion_type: IonType::SExp,
1192 ops: vec![AsSequence],
1193 op_assert: Box::new(|e: &Element| {
1194 let actual = e.as_sequence().unwrap();
1195 let expected: Vec<Element> = ion_vec([true, false]);
1196 assert_eq!(2, actual.len());
1198 for (i, actual_item) in actual.elements().enumerate() {
1199 assert_eq!(&expected[i], actual_item);
1201 }
1202 }),
1203 }
1204 }
1205
1206 fn struct_case() -> Case {
1207 Case {
1208 elem: ion_struct! {"greetings": "hello", "name": "ion"}.into(),
1209 ion_type: IonType::Struct,
1210 ops: vec![AsStruct],
1211 op_assert: Box::new(|e: &Element| {
1212 let actual: &Struct = e.as_struct().unwrap();
1213
1214 assert_eq!(
1216 actual.iter().next(),
1217 Some((&"greetings".into(), &"hello".into()))
1218 );
1219
1220 assert_eq!(actual.get("greetings"), Some(&"hello".into()));
1221 }),
1222 }
1223 }
1224 #[rstest]
1227 #[case::owned_null(null_case())]
1228 #[case::owned_bool(bool_case())]
1229 #[case::owned_i64(i64_case())]
1230 #[case::owned_big_int(big_int_case())]
1231 #[case::owned_f64(f64_case())]
1232 #[case::owned_decimal(decimal_case())]
1233 #[case::owned_timestamp(timestamp_case())]
1234 #[case::owned_string(string_case())]
1235 #[case::owned_blob(blob_case())]
1236 #[case::owned_clob(clob_case())]
1237 #[case::owned_list(list_case())]
1238 #[case::owned_sexp(sexp_case())]
1239 #[case::owned_struct(struct_case())]
1240 #[case::owned_symbol(symbol_case())]
1241 fn element_accessors(#[case] input_case: Case) {
1242 let neg_table: Vec<(ElemOp, ElemAssertFn)> = vec![
1244 (IsNull, Box::new(|e| assert!(!e.is_null()))),
1245 (AsBool, Box::new(|e| assert_eq!(None, e.as_bool()))),
1246 (
1247 AsAnyInt,
1248 Box::new(|e| {
1249 assert_eq!(None, e.as_int());
1250 assert_eq!(None, e.as_i64());
1251 assert_eq!(None, e.as_big_int());
1252 }),
1253 ),
1254 (AsF64, Box::new(|e| assert_eq!(None, e.as_float()))),
1255 (AsDecimal, Box::new(|e| assert_eq!(None, e.as_decimal()))),
1256 (
1257 AsTimestamp,
1258 Box::new(|e| assert_eq!(None, e.as_timestamp())),
1259 ),
1260 (AsStr, Box::new(|e| assert_eq!(None, e.as_text()))),
1261 (AsSym, Box::new(|e| assert_eq!(None, e.as_symbol()))),
1262 (AsBytes, Box::new(|e| assert_eq!(None, e.as_lob()))),
1263 (AsSequence, Box::new(|e| assert!(e.as_sequence().is_none()))),
1264 (AsStruct, Box::new(|e| assert_eq!(None, e.as_struct()))),
1265 ];
1266
1267 let valid_ops: HashSet<ElemOp> = input_case.ops.into_iter().collect();
1270 let op_assertions: Vec<ElemAssertFn> = neg_table
1271 .into_iter()
1272 .filter(|(op, _)| !valid_ops.contains(op))
1273 .map(|(_, neg_assert)| neg_assert)
1274 .chain(once(input_case.op_assert))
1275 .collect();
1276
1277 assert_eq!(input_case.ion_type, input_case.elem.ion_type());
1279
1280 for assert in op_assertions {
1281 assert(&input_case.elem);
1282 }
1283
1284 let itself = &input_case.elem;
1287 assert_eq!(&input_case.elem, itself);
1288 }
1289}
1290
1291#[cfg(test)]
1292mod value_tests {
1293 use crate::element::*;
1294 use crate::ion_data::IonEq;
1295 use crate::{ion_list, ion_sexp, ion_struct, IonType};
1296 use rstest::*;
1297
1298 #[test]
1299 fn demonstrate_element_implements_send() {
1300 use std::thread;
1301 let list: Element = ion_list![1, 2, 3].into();
1307 thread::scope(|_| {
1308 let elements = vec![list];
1310 assert_eq!(elements.len(), 1);
1312 });
1313 }
1314
1315 #[rstest]
1316 #[case::strings(
1317 Element::from("hello"), "hello" )]
1320 #[case::symbols(
1321 Element::from(Symbol::owned("hello")), Symbol::owned("hello") )]
1324 #[case::struct_(
1325 ion_struct!{"greetings": "hello"},
1326 Element::read_one(r#"{greetings: "hello"}"#).unwrap()
1327 )]
1328 #[case::strings(
1329 Element::from("hello"), "hello" )]
1332 #[case::symbols(
1333 Element::from(Symbol::owned("hello")), Symbol::owned("hello") )]
1336 #[case::struct_(
1337 ion_struct!{"greetings": "hello"},
1338 Element::read_one(r#"{greetings: "hello"}"#).unwrap()
1339 )]
1340 fn owned_element_accessors<E1, E2>(#[case] e1: E1, #[case] e2: E2)
1341 where
1342 E1: Into<Element>,
1343 E2: Into<Element>,
1344 {
1345 assert_eq!(e1.into(), e2.into());
1347 }
1348
1349 #[rstest]
1350 #[case::struct_(ion_struct!{"greetings": "hello", "name": "Ion"}, 2)]
1351 #[case::list(ion_list!["greetings", 5, true], 3)]
1352 #[case::sexp(ion_sexp!(5 true), 2)]
1353 fn owned_container_len_test<I: Into<Element>>(#[case] container: I, #[case] length: usize) {
1354 let container = container.into();
1355 match container.ion_type() {
1356 IonType::List | IonType::SExp => {
1357 assert_eq!(container.as_sequence().unwrap().len(), length);
1359 }
1360 IonType::Struct => {
1361 assert_eq!(container.as_struct().unwrap().len(), length);
1363 }
1364 _ => {
1365 unreachable!("This test is only for container type elements")
1366 }
1367 }
1368 }
1369
1370 #[rstest]
1371 #[case::struct_(ion_struct!{"greetings": "hello", "name": "Ion"}, false)]
1372 #[case::list(ion_list!["greetings", 5, true], false)]
1373 #[case::list_empty(ion_list![], true)]
1374 #[case::sexp(ion_sexp!(5 true), false)]
1375 #[case::sexp_empty(ion_sexp!(), true)]
1376 fn owned_container_is_empty_test<I: Into<Element>>(
1377 #[case] container: I,
1378 #[case] is_empty: bool,
1379 ) {
1380 let container = container.into();
1381 match container.ion_type() {
1382 IonType::List | IonType::SExp => {
1383 assert_eq!(container.as_sequence().unwrap().is_empty(), is_empty);
1385 }
1386 IonType::Struct => {
1387 assert_eq!(container.as_struct().unwrap().is_empty(), is_empty);
1389 }
1390 _ => {
1391 unreachable!("This test is only for container type elements")
1392 }
1393 }
1394 }
1395
1396 #[test]
1397 fn list_display_roundtrip() {
1398 let list = ion_list![1, 2, 3, true, false];
1399
1400 let text_list = format!("{list}");
1402 let expected_element: Element = list.into();
1404 let actual_element = Element::read_one(text_list).unwrap();
1405 assert!(expected_element.ion_eq(&actual_element));
1406 }
1407
1408 #[test]
1409 fn sexp_display_roundtrip() {
1410 let sexp = ion_sexp! (1 2 3 true false);
1411
1412 let text_sexp = format!("{sexp}");
1414 let expected_element: Element = sexp.into();
1416 let actual_element = Element::read_one(text_sexp).unwrap();
1417 assert!(expected_element.ion_eq(&actual_element));
1418 }
1419
1420 #[test]
1421 fn struct_display_roundtrip() {
1422 let struct_ = ion_struct! {"foo": 1, "bar": 2, "baz": ion_list! [true, false]};
1423
1424 let text_struct = format!("{struct_}");
1426 let expected_element: Element = struct_.into();
1428 let actual_element = Element::read_one(text_struct).unwrap();
1429 assert!(expected_element.ion_eq(&actual_element));
1430 }
1431}