mica 0.7.1

A simple, user-friendly, embeddable scripting language
Documentation
use crate::{
    builtin_traits::iterator, ll::value::RawValue, Engine, Error, Gc, TypeBuilder, UserData,
};

pub(crate) struct StringRSplit {
    string: RawValue,
    separator: Gc<String>,
    index: usize,
}

impl StringRSplit {
    pub unsafe fn new(s: RawValue, separator: Gc<String>) -> Self {
        Self { string: s, separator, index: unsafe { s.get_raw_string_unchecked().get().len() } }
    }

    fn has_next(&self) -> bool {
        self.index != 0
    }

    fn next(&mut self) -> Option<String> {
        unsafe {
            let s = self.string.get_raw_string_unchecked().get();
            let fragment = s[0..self.index].rsplit(&**self.separator).next();
            if let Some(fragment) = fragment {
                self.index -= fragment.len();
                self.index = self.index.saturating_sub(self.separator.len());
            }
            fragment.map(String::from)
        }
    }
}

impl UserData for StringRSplit {}

pub(crate) fn load_string_rsplit_iter(engine: &mut Engine) -> Result<(), Error> {
    engine.add_type(
        TypeBuilder::<StringRSplit>::new("StringRSplit")
            .add_builtin_trait_function(iterator::HasNext, StringRSplit::has_next)
            .add_builtin_trait_function(iterator::Next, StringRSplit::next),
    )?;

    Ok(())
}