Skip to main content

miniextendr_api/altrep_data/iter/
macros.rs

1//! Shared storage and constructors for the concrete iterator data adapters.
2
3macro_rules! define_iter_data {
4    ($(#[$meta:meta])* $name:ident, $item:ty) => {
5        $(#[$meta])*
6        #[derive(Clone)]
7        pub struct $name<I: Iterator<Item = $item>> {
8            state: super::IterState<I, $item>,
9        }
10
11        impl<I: Iterator<Item = $item>> $name<I> {
12            /// Create a lazy adapter for exactly the declared prefix.
13            ///
14            /// The iterator is not advanced during construction.
15            pub fn from_iter(iter: I, len: usize) -> Self {
16                Self {
17                    state: super::IterState::new(iter, len),
18                }
19            }
20        }
21
22        impl<I: Iterator<Item = $item>> crate::altrep_data::AltrepSerialize for $name<I> {
23            fn serialized_state(&self) -> crate::SEXP {
24                // A source shorter than the declared length leaves elements no
25                // saved state can restore. C NULL asks R to save the values the
26                // element reads give instead.
27                match self.state.try_materialize_all() {
28                    Ok(values) => crate::IntoR::into_sexp(values.to_vec()),
29                    Err(_) => crate::SEXP::null(),
30                }
31            }
32
33            fn unserialize(state: crate::SEXP) -> Option<Self> {
34                let values = <Vec<$item> as crate::TryFromSexp>::try_from_sexp(state).ok()?;
35                Some(Self { state: super::IterState::from_values(values) })
36            }
37        }
38
39        impl<I: ExactSizeIterator<Item = $item>> $name<I> {
40            /// Create a lazy adapter using the iterator's remaining length.
41            pub fn from_exact_iter(iter: I) -> Self {
42                let len = iter.len();
43                Self::from_iter(iter, len)
44            }
45        }
46
47        impl<I: Iterator<Item = $item>> crate::altrep_data::AltrepLen for $name<I> {
48            fn altrep_len(&self) -> usize {
49                self.state.len()
50            }
51        }
52    };
53}
54
55pub(super) use define_iter_data;