use crate::class::Class;
use crate::object::Object;
use jni::errors::Result;
use jni::sys::_jobject;
use jni::JNIEnv;
pub struct Iterator<'a> {
pub inner: Object<'a>,
pub class: Class<'a>,
env: &'a JNIEnv<'a>,
}
#[allow(clippy::from_over_into)]
impl<'a> Into<*mut _jobject> for Iterator<'a> {
fn into(self) -> *mut _jobject {
self.inner.inner.into_inner()
}
}
impl<'a> Drop for Iterator<'a> {
fn drop(&mut self) {
let _ = self.env.delete_local_ref(self.inner.inner);
}
}
impl<'a> std::iter::Iterator for Iterator<'a> {
type Item = Result<Object<'a>>;
fn next(&mut self) -> Option<Self::Item> {
Iterator::next(self).transpose()
}
}
impl<'a> Iterator<'a> {
pub fn new(env: &'a JNIEnv<'a>, object: Object<'a>, class: Class<'a>) -> Self {
Self {
inner: object,
class,
env,
}
}
pub fn has_next(&self) -> Result<bool> {
let has_next = self
.env
.call_method(self.inner.inner, "hasNext", "()Z", &[])?;
has_next.z()
}
pub fn next(&self) -> Result<Option<Object<'a>>> {
if !self.has_next()? {
return Ok(None);
}
let next = self
.env
.call_method(self.inner.inner, "next", "()Ljava/lang/Object;", &[])?;
let object = Object::new(self.env, next.l()?, self.class.clone());
match object.inner.is_null() {
true => Ok(None),
false => Ok(Some(object)),
}
}
pub fn to_vec(&self) -> Result<Vec<Object>> {
let mut objects = Vec::new();
while let Some(i) = self.next()? {
objects.push(i);
}
Ok(objects)
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::test::JVM;
use crate::List;
#[test]
fn has_next() {
let jvm = JVM.lock().unwrap();
let env = jvm.attach_current_thread().unwrap();
let int_class = Class::Integer(&env).unwrap();
let list = List::arraylist(&env, int_class).unwrap();
let iterator = list.iterator().unwrap();
let has_next = iterator.has_next();
assert!(has_next.is_ok());
assert!(!has_next.unwrap());
list.add(&Object::new_integer_object(&env, 10).unwrap())
.unwrap();
let iterator = list.iterator().unwrap();
let has_next = iterator.has_next();
assert!(has_next.is_ok());
assert!(has_next.unwrap());
}
#[test]
fn next() {
let jvm = JVM.lock().unwrap();
let env = jvm.attach_current_thread().unwrap();
let list = List::arraylist(&env, Class::Integer(&env).unwrap()).unwrap();
let iterator = list.iterator().unwrap();
let next = iterator.next();
assert!(next.is_ok());
assert!(next.unwrap().is_none());
let value = Object::new_integer_object(&env, 10).unwrap();
list.add(&value).unwrap();
let iterator = list.iterator().unwrap();
let next = iterator.next();
assert!(next.is_ok());
let next = next.unwrap();
assert!(next.is_some());
let next = next.unwrap();
assert_eq!(value.get_integer().unwrap(), next.get_integer().unwrap());
}
#[test]
fn to_vec() {
let jvm = JVM.lock().unwrap();
let env = jvm.attach_current_thread().unwrap();
let list = List::arraylist(&env, Class::Integer(&env).unwrap()).unwrap();
let iterator = list.iterator().unwrap();
let vec = iterator.to_vec();
assert!(vec.is_ok());
let vec = vec.unwrap();
assert!(vec.is_empty());
let value = Object::new_integer_object(&env, 10).unwrap();
list.add(&value).unwrap();
let iterator = list.iterator().unwrap();
let vec = iterator.to_vec();
assert!(vec.is_ok());
let vec = vec.unwrap();
assert!(!vec.is_empty());
let front = vec.first();
assert!(front.is_some());
let front = front.unwrap();
assert_eq!(value.get_integer().unwrap(), front.get_integer().unwrap());
}
}