use crate::element::builders::SequenceBuilder;
use crate::element::iterators::SequenceIterator;
use crate::element::Element;
use crate::ion_data::{IonDataHash, IonDataOrd, IonEq};
use crate::lazy::encoding::Encoding;
use crate::write_config::WriteConfig;
use crate::IonResult;
use std::cmp::Ordering;
use std::collections::VecDeque;
use std::fmt::{Debug, Formatter};
use std::hash::Hasher;
use std::io;
#[derive(Clone, PartialEq)]
pub struct Sequence {
elements: Vec<Element>,
}
impl Debug for Sequence {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "Sequence<")?;
let mut is_first = true;
for element in self {
if is_first {
write!(f, "{element}")?;
is_first = false;
} else {
write!(f, ", {element}")?;
}
}
write!(f, ">")
}
}
impl Sequence {
pub fn new<E: Into<Element>, I: IntoIterator<Item = E>>(elements: I) -> Sequence {
let elements = elements.into_iter().map(|e| e.into()).collect();
Sequence { elements }
}
pub fn builder() -> SequenceBuilder {
SequenceBuilder::new()
}
pub fn clone_builder(&self) -> SequenceBuilder {
SequenceBuilder::with_initial_elements(&self.elements)
}
pub fn elements(&self) -> SequenceIterator<'_> {
SequenceIterator::new(&self.elements)
}
pub fn get(&self, index: usize) -> Option<&Element> {
self.elements.get(index)
}
pub fn len(&self) -> usize {
self.elements.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn iter(&self) -> SequenceIterator<'_> {
self.elements()
}
pub fn encode_as<E: Encoding, C: Into<WriteConfig<E>>>(
&self,
config: C,
) -> IonResult<E::Output> {
config.into().encode_all(self.elements())
}
pub fn encode_to<E: Encoding, C: Into<WriteConfig<E>>, W: io::Write>(
&self,
output: W,
config: C,
) -> IonResult<W> {
config.into().encode_all_to(output, self.elements())
}
}
impl AsRef<Sequence> for Sequence {
fn as_ref(&self) -> &Sequence {
self
}
}
impl AsRef<[Element]> for Sequence {
fn as_ref(&self) -> &[Element] {
self.elements.as_slice()
}
}
impl From<Sequence> for Vec<Element> {
fn from(value: Sequence) -> Self {
value.elements
}
}
impl From<Vec<Element>> for Sequence {
fn from(elements: Vec<Element>) -> Self {
Sequence { elements }
}
}
impl<'a> IntoIterator for &'a Sequence {
type Item = &'a Element;
type IntoIter = SequenceIterator<'a>;
fn into_iter(self) -> Self::IntoIter {
self.elements()
}
}
impl IntoIterator for Sequence {
type Item = Element;
type IntoIter = OwnedSequenceIterator;
fn into_iter(self) -> Self::IntoIter {
OwnedSequenceIterator {
elements: VecDeque::from(self.elements),
}
}
}
impl FromIterator<Element> for Sequence {
fn from_iter<T: IntoIterator<Item = Element>>(iter: T) -> Self {
Vec::from_iter(iter).into()
}
}
impl IonEq for Sequence {
fn ion_eq(&self, other: &Self) -> bool {
self.elements.ion_eq(&other.elements)
}
}
impl IonDataOrd for Sequence {
fn ion_cmp(&self, other: &Self) -> Ordering {
self.elements.ion_cmp(&other.elements)
}
}
impl IonDataHash for Sequence {
fn ion_data_hash<H: Hasher>(&self, state: &mut H) {
self.elements.ion_data_hash(state)
}
}
#[derive(Clone)]
pub struct OwnedSequenceIterator {
elements: VecDeque<Element>,
}
impl Iterator for OwnedSequenceIterator {
type Item = Element;
fn next(&mut self) -> Option<Self::Item> {
self.elements.pop_front()
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.elements.len();
(len, Some(len))
}
}
impl DoubleEndedIterator for OwnedSequenceIterator {
fn next_back(&mut self) -> Option<Self::Item> {
self.elements.pop_back()
}
}
impl Debug for OwnedSequenceIterator {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("OwnedSequenceIterator")
.field(&self.elements)
.finish()
}
}
#[cfg(test)]
mod tests {
use crate::{ion_list, Element};
#[test]
fn owned_sequence() {
let list: Element = ion_list![true, false, "hello"].into();
let seq = list.try_into_sequence().unwrap();
let mut it = seq.into_iter();
assert_eq!(
format!("{it:?}"),
"OwnedSequenceIterator([true, false, \"hello\"])"
);
assert_eq!(it.size_hint(), (3, Some(3)));
assert_eq!(it.next(), Some(true.into()));
assert_eq!(it.size_hint(), (2, Some(2)));
assert_eq!(it.next(), Some(false.into()));
assert_eq!(it.size_hint(), (1, Some(1)));
assert_eq!(it.next(), Some("hello".into()));
assert_eq!(it.size_hint(), (0, Some(0)));
assert_eq!(it.next(), None);
}
}