use derive_more::Display;
use gazebo::{any::AnyLifetime, coerce::Coerce};
use crate as starlark;
use crate::values::{Heap, StarlarkValue, Value, ValueLike};
#[derive(Debug, Trace, Coerce, Display, Freeze, NoSerialize, AnyLifetime)]
#[display(fmt = "iterator")]
#[repr(C)]
struct StringIteratorGen<V> {
string: V,
produce_char: bool, }
pub(crate) fn iterate_chars<'v>(string: Value<'v>, heap: &'v Heap) -> Value<'v> {
heap.alloc(StringIterator {
string,
produce_char: true,
})
}
pub(crate) fn iterate_codepoints<'v>(string: Value<'v>, heap: &'v Heap) -> Value<'v> {
heap.alloc(StringIterator {
string,
produce_char: false,
})
}
starlark_complex_value!(StringIterator);
impl<'v, T: ValueLike<'v>> StarlarkValue<'v> for StringIteratorGen<T>
where
Self: AnyLifetime<'v>,
{
starlark_type!("iterator");
fn iterate<'a>(
&'a self,
heap: &'v Heap,
) -> anyhow::Result<Box<dyn Iterator<Item = Value<'v>> + 'a>>
where
'v: 'a,
{
let s = self.string.to_value().unpack_str().unwrap().chars();
if self.produce_char {
Ok(box s.map(move |x| heap.alloc(x)))
} else {
Ok(box s.map(|x| Value::new_int(u32::from(x) as i32)))
}
}
fn with_iterator(
&self,
heap: &'v Heap,
f: &mut dyn FnMut(&mut dyn Iterator<Item = Value<'v>>) -> anyhow::Result<()>,
) -> anyhow::Result<()> {
let s = self.string.to_value().unpack_str().unwrap().chars();
if self.produce_char {
f(&mut s.map(|x| heap.alloc(x)))
} else {
f(&mut s.map(|x| Value::new_int(u32::from(x) as i32)))
}
}
}