ion_rs/types/
mod.rs

1//! This module provides an implementation of the data types described by the
2//! [Ion Data Model](https://amazon-ion.github.io/ion-docs/docs/spec.html#the-ion-data-model)
3//! section of the Ion 1.0 spec.
4
5pub type SymbolId = usize;
6
7mod bytes;
8mod coefficient;
9mod decimal;
10mod integer;
11mod list;
12mod lob;
13mod sequence;
14mod sexp;
15mod string;
16mod r#struct;
17mod symbol;
18mod timestamp;
19
20pub use crate::types::bytes::Bytes;
21pub use coefficient::{Coefficient, Sign};
22pub use decimal::Decimal;
23pub use integer::{Int, IntAccess, UInt};
24pub use list::List;
25pub use lob::{Blob, Clob};
26pub use r#struct::Struct;
27pub use sequence::Sequence;
28pub use sexp::SExp;
29pub use string::Str;
30pub use symbol::Symbol;
31pub use timestamp::{
32    DaySetter, FractionalSecondSetter, HourAndMinuteSetter, Mantissa, MonthSetter, Precision,
33    SecondSetter, Timestamp,
34};
35
36use crate::ion_data::IonOrd;
37use std::cmp::Ordering;
38use std::fmt;
39
40/// Represents the Ion data type of a given value. To learn more about each data type,
41/// read [the Ion Data Model](https://amazon-ion.github.io/ion-docs/docs/spec.html#the-ion-data-model)
42/// section of the spec.
43#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
44pub enum IonType {
45    Null,
46    Bool,
47    Int,
48    Float,
49    Decimal,
50    Timestamp,
51    Symbol,
52    String,
53    Clob,
54    Blob,
55    List,
56    SExp,
57    Struct,
58}
59
60impl fmt::Display for IonType {
61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62        write!(
63            f,
64            "{}",
65            match self {
66                IonType::Null => "null",
67                IonType::Bool => "bool",
68                IonType::Int => "int",
69                IonType::Float => "float",
70                IonType::Decimal => "decimal",
71                IonType::Timestamp => "timestamp",
72                IonType::Symbol => "symbol",
73                IonType::String => "string",
74                IonType::Clob => "clob",
75                IonType::Blob => "blob",
76                IonType::List => "list",
77                IonType::SExp => "sexp",
78                IonType::Struct => "struct",
79            }
80        )
81    }
82}
83
84impl IonType {
85    pub fn is_container(&self) -> bool {
86        use IonType::*;
87        matches!(self, List | SExp | Struct)
88    }
89}
90
91impl IonOrd for IonType {
92    fn ion_cmp(&self, other: &Self) -> Ordering {
93        self.cmp(other)
94    }
95}
96
97#[cfg(feature = "experimental-streaming")]
98impl From<crate::tokens::ScalarType> for IonType {
99    fn from(value: crate::tokens::ScalarType) -> Self {
100        use crate::tokens::ScalarType::*;
101        match value {
102            Bool => IonType::Bool,
103            Int => IonType::Int,
104            Float => IonType::Float,
105            Decimal => IonType::Decimal,
106            Timestamp => IonType::Timestamp,
107            String => IonType::String,
108            Symbol => IonType::Symbol,
109            Blob => IonType::Blob,
110            Clob => IonType::Clob,
111        }
112    }
113}
114
115#[cfg(feature = "experimental-streaming")]
116impl From<crate::tokens::ContainerType> for IonType {
117    fn from(value: crate::tokens::ContainerType) -> Self {
118        use crate::tokens::ContainerType::*;
119        match value {
120            SExp => IonType::SExp,
121            List => IonType::List,
122            Struct => IonType::Struct,
123        }
124    }
125}
126
127// Represents a level into which the writer has stepped.
128// A writer that has not yet called step_in() is at the top level.
129#[derive(Debug, PartialEq, Default)]
130pub(crate) enum ContainerType {
131    #[default]
132    TopLevel,
133    SExpression,
134    List,
135    Struct,
136}
137
138/// Returns the number of base-10 digits needed to represent `value`.
139fn num_decimal_digits_in_u64(value: u64) -> u64 {
140    if value == 0 {
141        return 1;
142    }
143    let log_base_ten = (value as f64).log10();
144    let count = log_base_ten.ceil();
145    if log_base_ten == count {
146        // If ceil() didn't change the count, then `value` is an exact power of ten.
147        // We need to add one to get the correct count.
148        // Examples:
149        //    (1).log10() ==   (1).log10().ceil() == 0
150        //   (10).log10() ==  (10).log10().ceil() == 1
151        //  (100).log10() == (100).log10().ceil() == 2
152        count as u64 + 1
153    } else {
154        count as u64
155    }
156}