use idakit_sys as sys;
use super::diff::{CanonicalOptions, CanonicalType};
use super::{Type, walk_type};
use crate::Database;
use crate::error::{Error, Result};
use crate::ffi::read_string;
impl Database {
#[inline]
#[must_use]
#[doc(alias("get_ordinal_limit"))]
pub fn named_types(&self) -> NamedTypes<'_> {
NamedTypes::new(self)
}
}
#[derive(Clone, Copy)]
#[doc(alias("get_numbered_type"))]
pub struct NamedType<'db> {
db: &'db Database,
ordinal: u32,
}
impl<'db> NamedType<'db> {
#[inline]
fn new(db: &'db Database, ordinal: u32) -> Self {
Self { db, ordinal }
}
#[inline]
#[must_use]
pub const fn ordinal(&self) -> u32 {
self.ordinal
}
#[must_use]
#[doc(alias("get_numbered_type_name"))]
pub fn name(&self) -> String {
read_string(|buf, cap| self.db.type_name_at(self.ordinal, buf, cap)).unwrap_or_default()
}
#[doc(alias("get_numbered_type"))]
pub fn resolve(&self) -> Result<Type> {
match walk_type(|sink| sys::walk_type_ordinal(self.ordinal, sink)) {
Ok(Some(ty)) => Ok(ty),
Ok(None) => Err(Error::TypeNotFound { name: self.name() }),
Err(source) => Err(Error::Extract { address: 0, source }),
}
}
pub fn canonical(&self) -> Result<CanonicalType> {
Ok(self.resolve()?.canonical())
}
pub fn canonical_with(&self, opts: CanonicalOptions) -> Result<CanonicalType> {
Ok(self.resolve()?.canonical_with(opts))
}
}
#[doc(alias("get_ordinal_limit"))]
pub struct NamedTypes<'db> {
db: &'db Database,
next: u32,
limit: u32,
}
impl<'db> NamedTypes<'db> {
fn new(db: &'db Database) -> Self {
let limit = match db.type_ordinal_limit() {
u32::MAX => 0,
n => n,
};
Self { db, next: 1, limit }
}
}
impl<'db> Iterator for NamedTypes<'db> {
type Item = NamedType<'db>;
fn next(&mut self) -> Option<Self::Item> {
while self.next < self.limit {
let candidate = NamedType::new(self.db, self.next);
self.next += 1;
if !candidate.name().is_empty() {
return Some(candidate);
}
}
None
}
}