use std::{collections::BTreeMap, hash::Hasher};
pub use uniffi_checksum_derive::Checksum;
mod ffi_names;
pub use ffi_names::*;
mod group;
pub use group::{create_metadata_groups, fixup_external_type, group_metadata, MetadataGroup};
mod reader;
pub use reader::{read_metadata, read_metadata_type};
mod types;
pub use types::{AsType, ExternalKind, ObjectImpl, Type, TypeIterator};
mod metadata;
pub const UNIFFI_CONTRACT_VERSION: u32 = 24;
pub trait Checksum {
fn checksum<H: Hasher>(&self, state: &mut H);
}
impl Checksum for bool {
fn checksum<H: Hasher>(&self, state: &mut H) {
state.write_u8(*self as u8);
}
}
impl Checksum for u64 {
fn checksum<H: Hasher>(&self, state: &mut H) {
state.write(&self.to_le_bytes());
}
}
impl Checksum for i64 {
fn checksum<H: Hasher>(&self, state: &mut H) {
state.write(&self.to_le_bytes());
}
}
impl<T: Checksum> Checksum for Box<T> {
fn checksum<H: Hasher>(&self, state: &mut H) {
(**self).checksum(state)
}
}
impl<T: Checksum> Checksum for [T] {
fn checksum<H: Hasher>(&self, state: &mut H) {
state.write(&(self.len() as u64).to_le_bytes());
for item in self {
Checksum::checksum(item, state);
}
}
}
impl<T: Checksum> Checksum for Vec<T> {
fn checksum<H: Hasher>(&self, state: &mut H) {
Checksum::checksum(&**self, state);
}
}
impl<K: Checksum, V: Checksum> Checksum for BTreeMap<K, V> {
fn checksum<H: Hasher>(&self, state: &mut H) {
state.write(&(self.len() as u64).to_le_bytes());
for (key, value) in self {
Checksum::checksum(key, state);
Checksum::checksum(value, state);
}
}
}
impl<T: Checksum> Checksum for Option<T> {
fn checksum<H: Hasher>(&self, state: &mut H) {
match self {
None => state.write(&0u64.to_le_bytes()),
Some(value) => {
state.write(&1u64.to_le_bytes());
Checksum::checksum(value, state)
}
}
}
}
impl Checksum for str {
fn checksum<H: Hasher>(&self, state: &mut H) {
state.write(self.as_bytes());
state.write_u8(0xff);
}
}
impl Checksum for String {
fn checksum<H: Hasher>(&self, state: &mut H) {
(**self).checksum(state)
}
}
impl Checksum for &str {
fn checksum<H: Hasher>(&self, state: &mut H) {
(**self).checksum(state)
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct NamespaceMetadata {
pub crate_name: String,
pub name: String,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct UdlFile {
pub module_path: String,
pub namespace: String,
pub file_stub: String,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct FnMetadata {
pub module_path: String,
pub name: String,
pub is_async: bool,
pub inputs: Vec<FnParamMetadata>,
pub return_type: Option<Type>,
pub throws: Option<Type>,
pub checksum: Option<u16>,
}
impl FnMetadata {
pub fn ffi_symbol_name(&self) -> String {
fn_symbol_name(&self.module_path, &self.name)
}
pub fn checksum_symbol_name(&self) -> String {
fn_checksum_symbol_name(&self.module_path, &self.name)
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct ConstructorMetadata {
pub module_path: String,
pub self_name: String,
pub name: String,
pub inputs: Vec<FnParamMetadata>,
pub throws: Option<Type>,
pub checksum: Option<u16>,
}
impl ConstructorMetadata {
pub fn ffi_symbol_name(&self) -> String {
constructor_symbol_name(&self.module_path, &self.self_name, &self.name)
}
pub fn checksum_symbol_name(&self) -> String {
constructor_checksum_symbol_name(&self.module_path, &self.self_name, &self.name)
}
pub fn is_primary(&self) -> bool {
self.name == "new"
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct MethodMetadata {
pub module_path: String,
pub self_name: String,
pub name: String,
pub is_async: bool,
pub inputs: Vec<FnParamMetadata>,
pub return_type: Option<Type>,
pub throws: Option<Type>,
pub takes_self_by_arc: bool, pub checksum: Option<u16>,
}
impl MethodMetadata {
pub fn ffi_symbol_name(&self) -> String {
method_symbol_name(&self.module_path, &self.self_name, &self.name)
}
pub fn checksum_symbol_name(&self) -> String {
method_checksum_symbol_name(&self.module_path, &self.self_name, &self.name)
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct TraitMethodMetadata {
pub module_path: String,
pub trait_name: String,
pub index: u32,
pub name: String,
pub is_async: bool,
pub inputs: Vec<FnParamMetadata>,
pub return_type: Option<Type>,
pub throws: Option<Type>,
pub takes_self_by_arc: bool, pub checksum: Option<u16>,
}
impl TraitMethodMetadata {
pub fn ffi_symbol_name(&self) -> String {
method_symbol_name(&self.module_path, &self.trait_name, &self.name)
}
pub fn checksum_symbol_name(&self) -> String {
method_checksum_symbol_name(&self.module_path, &self.trait_name, &self.name)
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct FnParamMetadata {
pub name: String,
pub ty: Type,
pub by_ref: bool,
pub optional: bool,
pub default: Option<LiteralMetadata>,
}
impl FnParamMetadata {
pub fn simple(name: &str, ty: Type) -> Self {
Self {
name: name.to_string(),
ty,
by_ref: false,
optional: false,
default: None,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Checksum)]
pub enum LiteralMetadata {
Boolean(bool),
String(String),
UInt(u64, Radix, Type),
Int(i64, Radix, Type),
Float(String, Type),
Enum(String, Type),
EmptySequence,
EmptyMap,
Null,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Checksum)]
pub enum Radix {
Decimal = 10,
Octal = 8,
Hexadecimal = 16,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct RecordMetadata {
pub module_path: String,
pub name: String,
pub fields: Vec<FieldMetadata>,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct FieldMetadata {
pub name: String,
pub ty: Type,
pub default: Option<LiteralMetadata>,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct EnumMetadata {
pub module_path: String,
pub name: String,
pub variants: Vec<VariantMetadata>,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct VariantMetadata {
pub name: String,
pub fields: Vec<FieldMetadata>,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct ObjectMetadata {
pub module_path: String,
pub name: String,
pub imp: types::ObjectImpl,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct CallbackInterfaceMetadata {
pub module_path: String,
pub name: String,
}
impl ObjectMetadata {
pub fn free_ffi_symbol_name(&self) -> String {
free_fn_symbol_name(&self.module_path, &self.name)
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum UniffiTraitMetadata {
Debug {
fmt: MethodMetadata,
},
Display {
fmt: MethodMetadata,
},
Eq {
eq: MethodMetadata,
ne: MethodMetadata,
},
Hash {
hash: MethodMetadata,
},
}
impl UniffiTraitMetadata {
fn module_path(&self) -> &String {
&match self {
UniffiTraitMetadata::Debug { fmt } => fmt,
UniffiTraitMetadata::Display { fmt } => fmt,
UniffiTraitMetadata::Eq { eq, .. } => eq,
UniffiTraitMetadata::Hash { hash } => hash,
}
.module_path
}
pub fn self_name(&self) -> &String {
&match self {
UniffiTraitMetadata::Debug { fmt } => fmt,
UniffiTraitMetadata::Display { fmt } => fmt,
UniffiTraitMetadata::Eq { eq, .. } => eq,
UniffiTraitMetadata::Hash { hash } => hash,
}
.self_name
}
}
#[repr(u8)]
pub enum UniffiTraitDiscriminants {
Debug,
Display,
Eq,
Hash,
}
impl UniffiTraitDiscriminants {
pub fn from(v: u8) -> anyhow::Result<Self> {
Ok(match v {
0 => UniffiTraitDiscriminants::Debug,
1 => UniffiTraitDiscriminants::Display,
2 => UniffiTraitDiscriminants::Eq,
3 => UniffiTraitDiscriminants::Hash,
_ => anyhow::bail!("invalid trait discriminant {v}"),
})
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum ErrorMetadata {
Enum { enum_: EnumMetadata, is_flat: bool },
}
impl ErrorMetadata {
pub fn name(&self) -> &String {
match self {
Self::Enum { enum_, .. } => &enum_.name,
}
}
pub fn module_path(&self) -> &String {
match self {
Self::Enum { enum_, .. } => &enum_.module_path,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct CustomTypeMetadata {
pub module_path: String,
pub name: String,
pub builtin: Type,
}
pub fn checksum<T: Checksum>(val: &T) -> u16 {
let mut hasher = siphasher::sip::SipHasher13::new();
val.checksum(&mut hasher);
(hasher.finish() & 0x000000000000FFFF) as u16
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum Metadata {
Namespace(NamespaceMetadata),
UdlFile(UdlFile),
Func(FnMetadata),
Object(ObjectMetadata),
CallbackInterface(CallbackInterfaceMetadata),
Record(RecordMetadata),
Enum(EnumMetadata),
Error(ErrorMetadata),
Constructor(ConstructorMetadata),
Method(MethodMetadata),
TraitMethod(TraitMethodMetadata),
CustomType(CustomTypeMetadata),
UniffiTrait(UniffiTraitMetadata),
}
impl Metadata {
pub fn read(data: &[u8]) -> anyhow::Result<Self> {
read_metadata(data)
}
pub(crate) fn module_path(&self) -> &String {
match self {
Metadata::Namespace(meta) => &meta.crate_name,
Metadata::UdlFile(meta) => &meta.module_path,
Metadata::Func(meta) => &meta.module_path,
Metadata::Constructor(meta) => &meta.module_path,
Metadata::Method(meta) => &meta.module_path,
Metadata::Record(meta) => &meta.module_path,
Metadata::Enum(meta) => &meta.module_path,
Metadata::Object(meta) => &meta.module_path,
Metadata::CallbackInterface(meta) => &meta.module_path,
Metadata::TraitMethod(meta) => &meta.module_path,
Metadata::Error(meta) => meta.module_path(),
Metadata::CustomType(meta) => &meta.module_path,
Metadata::UniffiTrait(meta) => meta.module_path(),
}
}
}
impl From<NamespaceMetadata> for Metadata {
fn from(value: NamespaceMetadata) -> Metadata {
Self::Namespace(value)
}
}
impl From<UdlFile> for Metadata {
fn from(value: UdlFile) -> Metadata {
Self::UdlFile(value)
}
}
impl From<FnMetadata> for Metadata {
fn from(value: FnMetadata) -> Metadata {
Self::Func(value)
}
}
impl From<ConstructorMetadata> for Metadata {
fn from(c: ConstructorMetadata) -> Self {
Self::Constructor(c)
}
}
impl From<MethodMetadata> for Metadata {
fn from(m: MethodMetadata) -> Self {
Self::Method(m)
}
}
impl From<RecordMetadata> for Metadata {
fn from(r: RecordMetadata) -> Self {
Self::Record(r)
}
}
impl From<EnumMetadata> for Metadata {
fn from(e: EnumMetadata) -> Self {
Self::Enum(e)
}
}
impl From<ErrorMetadata> for Metadata {
fn from(e: ErrorMetadata) -> Self {
Self::Error(e)
}
}
impl From<ObjectMetadata> for Metadata {
fn from(v: ObjectMetadata) -> Self {
Self::Object(v)
}
}
impl From<CallbackInterfaceMetadata> for Metadata {
fn from(v: CallbackInterfaceMetadata) -> Self {
Self::CallbackInterface(v)
}
}
impl From<TraitMethodMetadata> for Metadata {
fn from(v: TraitMethodMetadata) -> Self {
Self::TraitMethod(v)
}
}
impl From<CustomTypeMetadata> for Metadata {
fn from(v: CustomTypeMetadata) -> Self {
Self::CustomType(v)
}
}
impl From<UniffiTraitMetadata> for Metadata {
fn from(v: UniffiTraitMetadata) -> Self {
Self::UniffiTrait(v)
}
}