use super::*;
#[derive(Debug, PartialEq, Clone)]
pub struct List {
pub(crate) robj: Robj,
}
impl Default for List {
fn default() -> Self {
List::new()
}
}
impl List {
pub fn new() -> List {
let values: &[Robj] = &[];
List::from_values(values)
}
pub fn from_values<V>(values: V) -> Self
where
V: IntoIterator,
V::IntoIter: ExactSizeIterator,
V::Item: Into<Robj>,
{
Self {
robj: make_vector(VECSXP, values),
}
}
pub fn from_pairs<V>(pairs: V) -> Self
where
V: IntoIterator,
V::IntoIter: ExactSizeIterator + Clone,
V::Item: Into<(&'static str, Robj)>,
{
let iter = pairs.into_iter();
let res = List::from_values(iter.clone().map(|kv| {
let (_, v) = kv.into();
v
}));
res.set_names(iter.map(|kv| {
let (k, _) = kv.into();
k
}))
.unwrap()
.as_list()
.unwrap()
}
pub fn values(&self) -> ListIter {
ListIter::from_parts(self.robj.clone(), 0, self.robj.len())
}
pub fn iter(&self) -> NamedListIter {
self.names()
.map(|n| n.zip(self.values()))
.unwrap_or_else(|| StrIter::new().zip(ListIter::new()))
}
}
impl IntoIterator for List {
type IntoIter = NamedListIter;
type Item = (&'static str, Robj);
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[derive(Clone)]
pub struct ListIter {
robj: Robj,
i: usize,
len: usize,
}
impl Default for ListIter {
fn default() -> Self {
ListIter::new()
}
}
impl ListIter {
pub fn new() -> Self {
ListIter::from_parts(().into(), 0, 0)
}
pub(crate) fn from_parts(robj: Robj, i: usize, len: usize) -> Self {
Self { robj, i, len }
}
}
impl Iterator for ListIter {
type Item = Robj;
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
fn next(&mut self) -> Option<Self::Item> {
let i = self.i;
self.i += 1;
if i >= self.len {
None
} else {
Some(unsafe { new_owned(VECTOR_ELT(self.robj.get(), i as isize)) })
}
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.i += n;
self.next()
}
}
impl ExactSizeIterator for ListIter {
fn len(&self) -> usize {
self.len - self.i
}
}
pub struct FromList<T>(pub T);
impl<T> TryFrom<Robj> for FromList<Vec<T>>
where
T: TryFrom<Robj>,
<T as TryFrom<Robj>>::Error: Into<Error>,
{
type Error = Error;
fn try_from(robj: Robj) -> Result<Self> {
let listiter: ListIter = robj.try_into()?;
let res: Result<Vec<_>> = listiter
.map(|robj| T::try_from(robj).map_err(|e| e.into()))
.collect();
res.map(FromList)
}
}
impl TryFrom<Robj> for ListIter {
type Error = Error;
fn try_from(robj: Robj) -> Result<Self> {
let list: List = robj.try_into()?;
Ok(list.values())
}
}
impl From<ListIter> for Robj {
fn from(iter: ListIter) -> Self {
iter.robj
}
}
impl<'a> FromRobj<'a> for ListIter {
fn from_robj(robj: &'a Robj) -> std::result::Result<Self, &'static str> {
robj.as_list().map(|l| l.values()).ok_or("Not a list.")
}
}