use std::marker::PhantomData;
use crate::objc::{ObjcRuntime, class::ClassIter, protocol::ProtocolNameIter};
#[derive(Debug, Clone, Copy)]
pub struct ConformanceEdge<'a> {
pub class_address: u64,
pub class_name: Option<&'a str>,
pub protocol_name: &'a str,
pub is_meta: bool,
}
pub struct ConformanceIter<'a, 'p> {
classes: ClassIter<'a, 'p>,
current: Option<ConformanceEdgeCursor<'a, 'p>>,
_phantom: PhantomData<&'a ()>,
}
struct ConformanceEdgeCursor<'a, 'p> {
class_address: u64,
class_name: Option<&'a str>,
is_meta: bool,
protocols: ProtocolNameIter<'a, 'p>,
}
impl<'a, 'p> ConformanceIter<'a, 'p> {
pub(crate) fn new(rt: &'p ObjcRuntime<'a>) -> Self {
Self {
classes: ClassIter::new(rt),
current: None,
_phantom: PhantomData,
}
}
}
impl<'a, 'p> Iterator for ConformanceIter<'a, 'p> {
type Item = ConformanceEdge<'a>;
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(cur) = self.current.as_mut() {
if let Some(name) = cur.protocols.next() {
return Some(ConformanceEdge {
class_address: cur.class_address,
class_name: cur.class_name,
protocol_name: name,
is_meta: cur.is_meta,
});
}
self.current = None;
}
let cls = self.classes.next()?;
let class_address = cls.address();
let is_meta = cls.is_meta();
let (class_name, protocols) = match cls.ro() {
Some(ro) => (Some(ro.name()), ro.protocols()),
None => continue,
};
self.current = Some(ConformanceEdgeCursor {
class_address,
class_name,
is_meta,
protocols,
});
}
}
}