use crate::Checksum;
use uniffi_pipeline::{MapNode, Node};
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Checksum, Ord, PartialOrd, Node, MapNode)]
pub enum ObjectImpl {
Struct,
Trait(TraitKind),
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Checksum, Ord, PartialOrd, Node, MapNode)]
pub enum TraitKind {
RustOnly,
Both,
ForeignOnly,
}
impl ObjectImpl {
pub fn rust_name_for(&self, name: &str) -> String {
if self.is_trait_interface() {
format!("dyn r#{name}")
} else {
format!("r#{name}")
}
}
pub fn is_trait_interface(&self) -> bool {
matches!(self, Self::Trait(_))
}
pub fn has_callback_interface(&self) -> bool {
matches!(self, Self::Trait(TraitKind::Both | TraitKind::ForeignOnly))
}
pub fn has_struct(&self) -> bool {
matches!(self, Self::Struct)
}
}
impl TraitKind {
pub fn has_foreign(&self) -> bool {
matches!(self, Self::Both | Self::ForeignOnly)
}
pub fn has_rust(&self) -> bool {
matches!(self, Self::RustOnly | Self::Both)
}
}
#[derive(Debug, Clone, Eq, PartialEq, Checksum, Ord, PartialOrd)]
pub enum Type {
UInt8,
Int8,
UInt16,
Int16,
UInt32,
Int32,
UInt64,
Int64,
Float32,
Float64,
Boolean,
String,
Bytes,
Timestamp,
Duration,
Object {
module_path: String,
name: String,
imp: ObjectImpl,
},
Record {
module_path: String,
name: String,
},
Enum {
module_path: String,
name: String,
},
CallbackInterface {
module_path: String,
name: String,
},
Box {
inner_type: Box<Type>,
},
Optional {
inner_type: Box<Type>,
},
Sequence {
inner_type: Box<Type>,
},
Map {
key_type: Box<Type>,
value_type: Box<Type>,
},
Set {
inner_type: Box<Type>,
},
Custom {
module_path: String,
name: String,
builtin: Box<Type>,
},
}
impl Type {
pub fn iter_types(&self) -> TypeIterator<'_> {
Box::new(std::iter::once(self).chain(self.iter_nested_types()))
}
pub fn iter_nested_types(&self) -> TypeIterator<'_> {
match self {
Type::Optional { inner_type }
| Type::Sequence { inner_type }
| Type::Set { inner_type } => inner_type.iter_types(),
Type::Map {
key_type,
value_type,
} => Box::new(key_type.iter_types().chain(value_type.iter_types())),
Type::Custom { builtin, .. } => builtin.iter_types(),
_ => Box::new(std::iter::empty()),
}
}
pub fn name(&self) -> Option<&str> {
match self {
Type::Object { name, .. } => Some(name),
Type::Record { name, .. } => Some(name),
Type::Enum { name, .. } => Some(name),
Type::Custom { name, .. } => Some(name),
Type::CallbackInterface { name, .. } => Some(name),
_ => None,
}
}
pub fn module_path(&self) -> Option<&str> {
match self {
Type::Object { module_path, .. } => Some(module_path),
Type::Record { module_path, .. } => Some(module_path),
Type::Enum { module_path, .. } => Some(module_path),
Type::Custom { module_path, .. } => Some(module_path),
Type::CallbackInterface { module_path, .. } => Some(module_path),
_ => None,
}
}
pub fn crate_name(&self) -> Option<&str> {
self.module_path()
.map(|module_path| module_path.split("::").next().unwrap())
}
fn rename(&mut self, new_name: String) {
match self {
Type::Object { name, .. } => *name = new_name,
Type::Record { name, .. } => *name = new_name,
Type::Enum { name, .. } => *name = new_name,
Type::Custom { name, .. } => *name = new_name,
Type::CallbackInterface { name, .. } => *name = new_name,
_ => {}
}
}
pub fn rename_recursive(&mut self, name_transformer: &impl Fn(&str) -> String) {
if let Some(name) = self.name() {
self.rename(name_transformer(name));
}
match self {
Type::Optional { inner_type }
| Type::Sequence { inner_type }
| Type::Set { inner_type } => {
inner_type.rename_recursive(name_transformer);
}
Type::Map {
key_type,
value_type,
..
} => {
key_type.rename_recursive(name_transformer);
value_type.rename_recursive(name_transformer);
}
Type::Custom { builtin, .. } => {
builtin.rename_recursive(name_transformer);
}
_ => {}
}
}
}
pub trait AsType: ::core::fmt::Debug {
fn as_type(&self) -> Type;
}
impl AsType for Type {
fn as_type(&self) -> Type {
self.clone()
}
}
impl<T, C> AsType for T
where
T: std::ops::Deref<Target = C> + std::fmt::Debug,
C: AsType,
{
fn as_type(&self) -> Type {
self.deref().as_type()
}
}
pub type TypeIterator<'a> = Box<dyn Iterator<Item = &'a Type> + 'a>;