Skip to main content

ion_rs/types/
sexp.rs

1use crate::element::builders::SequenceBuilder;
2use crate::element::iterators::SequenceIterator;
3use crate::ion_data::{IonDataHash, IonEq};
4use crate::text::text_formatter::FmtValueFormatter;
5use crate::{Element, Sequence};
6use delegate::delegate;
7use std::fmt::{Display, Formatter};
8use std::hash::Hasher;
9
10/// An in-memory representation of an Ion s-expression
11/// ```
12/// use ion_rs::{Element, ion_sexp};
13/// # use ion_rs::IonResult;
14/// # fn main() -> IonResult<()> {
15/// let sexp = ion_sexp!(1 2 3);
16/// assert_eq!(sexp.len(), 3);
17/// assert_eq!(sexp.get(1), Some(&Element::int(2)));
18/// # Ok(())
19/// # }
20/// ```
21/// To build a `SExp` incrementally, see [SequenceBuilder].
22///
23/// The inner [`Sequence`] is public to match `Value::SExp(Sequence)`, allowing
24/// direct construction and destructuring.
25#[derive(Debug, Clone, PartialEq)]
26pub struct SExp(pub Sequence);
27
28impl SExp {
29    pub fn new(elements: impl Into<Sequence>) -> Self {
30        SExp(elements.into())
31    }
32}
33
34impl SExp {
35    delegate! {
36        to self.0 {
37            pub fn clone_builder(&self) -> SequenceBuilder;
38            pub fn elements(&self) -> SequenceIterator<'_>;
39            pub fn get(&self, index: usize) -> Option<&Element>;
40            pub fn len(&self) -> usize;
41            pub fn is_empty(&self) -> bool;
42        }
43    }
44}
45
46impl IonEq for SExp {
47    fn ion_eq(&self, other: &Self) -> bool {
48        // The inner `Sequence` of both Lists are IonEq
49        self.0.ion_eq(&other.0)
50    }
51}
52
53impl IonDataHash for SExp {
54    fn ion_data_hash<H: Hasher>(&self, state: &mut H) {
55        self.0.ion_data_hash(state)
56    }
57}
58
59impl AsRef<Sequence> for SExp {
60    fn as_ref(&self) -> &Sequence {
61        &self.0
62    }
63}
64
65impl AsRef<[Element]> for SExp {
66    fn as_ref(&self) -> &[Element] {
67        self.0.as_ref()
68    }
69}
70
71// Allows `for element in &sexp {...}` syntax
72impl<'a> IntoIterator for &'a SExp {
73    type Item = &'a Element;
74    type IntoIter = SequenceIterator<'a>;
75
76    fn into_iter(self) -> Self::IntoIter {
77        self.elements()
78    }
79}
80
81impl Display for SExp {
82    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
83        let mut ivf = FmtValueFormatter { output: f };
84        ivf.format_sexp(self).map_err(|_| std::fmt::Error)?;
85        Ok(())
86    }
87}
88
89impl From<Sequence> for SExp {
90    fn from(sequence: Sequence) -> Self {
91        SExp(sequence)
92    }
93}
94
95impl From<Vec<Element>> for SExp {
96    fn from(elements: Vec<Element>) -> Self {
97        Self(elements.into())
98    }
99}
100
101impl FromIterator<Element> for SExp {
102    fn from_iter<T: IntoIterator<Item = Element>>(iter: T) -> Self {
103        Vec::from_iter(iter).into()
104    }
105}
106
107impl From<SExp> for Sequence {
108    fn from(value: SExp) -> Self {
109        value.0
110    }
111}
112
113#[cfg(test)]
114mod tests {
115    use crate::{ion_sexp, Element, IonResult, SExp};
116
117    #[test]
118    fn for_element_in_sexp() -> IonResult<()> {
119        // Simple example to exercise SExp's implementation of IntoIterator
120        let sexp = ion_sexp!(1 2 3);
121        let mut sum = 0;
122        for element in &sexp {
123            sum += element.expect_int()?.expect_i64()?;
124        }
125        assert_eq!(sum, 6i64);
126        Ok(())
127    }
128
129    #[test]
130    fn sexp_from_vec() -> IonResult<()> {
131        let elements = vec![Element::int(1), Element::int(2), Element::int(3)];
132        let actual: SExp = elements.into();
133        let expected = ion_sexp!(1 2 3);
134        assert_eq!(actual, expected);
135        Ok(())
136    }
137
138    #[test]
139    fn sexp_from_iter() -> IonResult<()> {
140        let elements = vec![Element::int(1), Element::int(2), Element::int(3)];
141        let actual: SExp = elements.into_iter().collect();
142        let expected = ion_sexp!(1 2 3);
143        assert_eq!(actual, expected);
144        Ok(())
145    }
146}