1use std::{collections::BTreeMap, hash::Hasher};
6pub use uniffi_internal_macros::{Checksum, Node};
7
8mod ffi_names;
9pub use ffi_names::*;
10
11mod group;
12pub use group::{create_metadata_groups, group_metadata, MetadataGroup, MetadataGroupMap};
13
14mod reader;
15pub use reader::{read_metadata, read_metadata_type};
16
17mod types;
18pub use types::{AsType, ObjectImpl, Type, TypeIterator};
19
20mod metadata;
21
22pub const UNIFFI_CONTRACT_VERSION: u32 = 30;
27
28pub trait Checksum {
33    fn checksum<H: Hasher>(&self, state: &mut H);
34}
35
36impl Checksum for bool {
37    fn checksum<H: Hasher>(&self, state: &mut H) {
38        state.write_u8(*self as u8);
39    }
40}
41
42impl Checksum for u64 {
43    fn checksum<H: Hasher>(&self, state: &mut H) {
44        state.write(&self.to_le_bytes());
45    }
46}
47
48impl Checksum for i64 {
49    fn checksum<H: Hasher>(&self, state: &mut H) {
50        state.write(&self.to_le_bytes());
51    }
52}
53
54impl<T: Checksum> Checksum for Box<T> {
55    fn checksum<H: Hasher>(&self, state: &mut H) {
56        (**self).checksum(state)
57    }
58}
59
60impl<T: Checksum> Checksum for [T] {
61    fn checksum<H: Hasher>(&self, state: &mut H) {
62        state.write(&(self.len() as u64).to_le_bytes());
63        for item in self {
64            Checksum::checksum(item, state);
65        }
66    }
67}
68
69impl<T: Checksum> Checksum for Vec<T> {
70    fn checksum<H: Hasher>(&self, state: &mut H) {
71        Checksum::checksum(&**self, state);
72    }
73}
74
75impl<K: Checksum, V: Checksum> Checksum for BTreeMap<K, V> {
76    fn checksum<H: Hasher>(&self, state: &mut H) {
77        state.write(&(self.len() as u64).to_le_bytes());
78        for (key, value) in self {
79            Checksum::checksum(key, state);
80            Checksum::checksum(value, state);
81        }
82    }
83}
84
85impl<T: Checksum> Checksum for Option<T> {
86    fn checksum<H: Hasher>(&self, state: &mut H) {
87        match self {
88            None => state.write(&0u64.to_le_bytes()),
89            Some(value) => {
90                state.write(&1u64.to_le_bytes());
91                Checksum::checksum(value, state)
92            }
93        }
94    }
95}
96
97impl Checksum for str {
98    fn checksum<H: Hasher>(&self, state: &mut H) {
99        state.write(self.as_bytes());
100        state.write_u8(0xff);
101    }
102}
103
104impl Checksum for String {
105    fn checksum<H: Hasher>(&self, state: &mut H) {
106        (**self).checksum(state)
107    }
108}
109
110impl Checksum for &str {
111    fn checksum<H: Hasher>(&self, state: &mut H) {
112        (**self).checksum(state)
113    }
114}
115
116#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Node)]
120pub struct NamespaceMetadata {
121    pub crate_name: String,
122    pub name: String,
123}
124
125#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Node)]
129pub struct UdlFile {
130    pub module_path: String,
132    pub namespace: String,
133    pub file_stub: String,
135}
136
137#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Node)]
138pub struct FnMetadata {
139    pub module_path: String,
140    pub name: String,
141    pub is_async: bool,
142    pub inputs: Vec<FnParamMetadata>,
143    pub return_type: Option<Type>,
144    pub throws: Option<Type>,
145    pub checksum: Option<u16>,
146    pub docstring: Option<String>,
147}
148
149impl FnMetadata {
150    pub fn ffi_symbol_name(&self) -> String {
151        fn_symbol_name(&self.module_path, &self.name)
152    }
153
154    pub fn checksum_symbol_name(&self) -> String {
155        fn_checksum_symbol_name(&self.module_path, &self.name)
156    }
157}
158
159#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Node)]
160pub struct ConstructorMetadata {
161    pub module_path: String,
162    pub self_name: String,
163    pub name: String,
164    pub is_async: bool,
165    pub inputs: Vec<FnParamMetadata>,
166    pub throws: Option<Type>,
167    pub checksum: Option<u16>,
168    pub docstring: Option<String>,
169}
170
171impl ConstructorMetadata {
172    pub fn ffi_symbol_name(&self) -> String {
173        constructor_symbol_name(&self.module_path, &self.self_name, &self.name)
174    }
175
176    pub fn checksum_symbol_name(&self) -> String {
177        constructor_checksum_symbol_name(&self.module_path, &self.self_name, &self.name)
178    }
179
180    pub fn is_primary(&self) -> bool {
181        self.name == "new"
182    }
183}
184
185#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Node)]
186pub struct MethodMetadata {
187    pub module_path: String,
188    pub self_name: String,
189    pub name: String,
190    pub is_async: bool,
191    pub inputs: Vec<FnParamMetadata>,
192    pub return_type: Option<Type>,
193    pub throws: Option<Type>,
194    pub takes_self_by_arc: bool, pub checksum: Option<u16>,
196    pub docstring: Option<String>,
197}
198
199impl MethodMetadata {
200    pub fn ffi_symbol_name(&self) -> String {
201        method_symbol_name(&self.module_path, &self.self_name, &self.name)
202    }
203
204    pub fn checksum_symbol_name(&self) -> String {
205        method_checksum_symbol_name(&self.module_path, &self.self_name, &self.name)
206    }
207}
208
209#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Node)]
210pub struct TraitMethodMetadata {
211    pub module_path: String,
212    pub trait_name: String,
213    pub index: u32,
216    pub name: String,
217    pub is_async: bool,
218    pub inputs: Vec<FnParamMetadata>,
219    pub return_type: Option<Type>,
220    pub throws: Option<Type>,
221    pub takes_self_by_arc: bool, pub checksum: Option<u16>,
223    pub docstring: Option<String>,
224}
225
226impl TraitMethodMetadata {
227    pub fn ffi_symbol_name(&self) -> String {
228        method_symbol_name(&self.module_path, &self.trait_name, &self.name)
229    }
230
231    pub fn checksum_symbol_name(&self) -> String {
232        method_checksum_symbol_name(&self.module_path, &self.trait_name, &self.name)
233    }
234}
235
236impl From<TraitMethodMetadata> for MethodMetadata {
237    fn from(meta: TraitMethodMetadata) -> Self {
238        MethodMetadata {
239            module_path: meta.module_path,
240            self_name: meta.trait_name,
241            name: meta.name,
242            is_async: meta.is_async,
243            inputs: meta.inputs,
244            return_type: meta.return_type,
245            throws: meta.throws,
246            takes_self_by_arc: meta.takes_self_by_arc,
247            checksum: meta.checksum,
248            docstring: meta.docstring,
249        }
250    }
251}
252
253#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Node)]
254pub struct FnParamMetadata {
255    pub name: String,
256    pub ty: Type,
257    pub by_ref: bool,
258    pub optional: bool,
259    pub default: Option<DefaultValueMetadata>,
260}
261
262impl FnParamMetadata {
263    pub fn simple(name: &str, ty: Type) -> Self {
264        Self {
265            name: name.to_string(),
266            ty,
267            by_ref: false,
268            optional: false,
269            default: None,
270        }
271    }
272}
273
274#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Checksum, Node)]
275pub enum LiteralMetadata {
276    Boolean(bool),
277    String(String),
278    UInt(u64, Radix, Type),
282    Int(i64, Radix, Type),
283    Float(String, Type),
288    Enum(String, Type),
289    EmptySequence,
290    EmptyMap,
291    None,
292    Some { inner: Box<DefaultValueMetadata> },
293}
294
295impl LiteralMetadata {
296    pub fn new_uint(v: u64) -> Self {
297        LiteralMetadata::UInt(v, Radix::Decimal, Type::UInt64)
298    }
299    pub fn new_int(v: i64) -> Self {
300        LiteralMetadata::Int(v, Radix::Decimal, Type::Int64)
301    }
302}
303
304#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Checksum, Node)]
307pub enum Radix {
308    Decimal = 10,
309    Octal = 8,
310    Hexadecimal = 16,
311}
312
313#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Checksum, Node)]
314pub enum DefaultValueMetadata {
315    Default,
317    Literal(LiteralMetadata),
319}
320
321#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Node)]
322pub struct RecordMetadata {
323    pub module_path: String,
324    pub name: String,
325    pub remote: bool, pub fields: Vec<FieldMetadata>,
327    pub docstring: Option<String>,
328}
329
330#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Node)]
331pub struct FieldMetadata {
332    pub name: String,
333    pub ty: Type,
334    pub default: Option<DefaultValueMetadata>,
335    pub docstring: Option<String>,
336}
337
338#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Checksum, Node)]
339pub enum EnumShape {
340    Enum,
341    Error { flat: bool },
342}
343
344impl EnumShape {
345    pub fn as_u8(&self) -> u8 {
346        match self {
347            EnumShape::Enum => 0,
348            EnumShape::Error { flat: false } => 1,
349            EnumShape::Error { flat: true } => 2,
350        }
351    }
352
353    pub fn from(v: u8) -> anyhow::Result<Self> {
354        Ok(match v {
355            0 => EnumShape::Enum,
356            1 => EnumShape::Error { flat: false },
357            2 => EnumShape::Error { flat: true },
358            _ => anyhow::bail!("invalid enum shape discriminant {v}"),
359        })
360    }
361}
362
363#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Node)]
364pub struct EnumMetadata {
365    pub module_path: String,
366    pub name: String,
367    pub shape: EnumShape,
368    pub remote: bool, pub variants: Vec<VariantMetadata>,
370    pub discr_type: Option<Type>,
371    pub non_exhaustive: bool,
372    pub docstring: Option<String>,
373}
374
375#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Node)]
376pub struct VariantMetadata {
377    pub name: String,
378    pub discr: Option<LiteralMetadata>,
379    pub fields: Vec<FieldMetadata>,
380    pub docstring: Option<String>,
381}
382
383#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Node)]
384pub struct ObjectMetadata {
385    pub module_path: String,
386    pub name: String,
387    pub remote: bool, pub imp: types::ObjectImpl,
389    pub docstring: Option<String>,
390}
391
392#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Node)]
393pub struct CallbackInterfaceMetadata {
394    pub module_path: String,
395    pub name: String,
396    pub docstring: Option<String>,
397}
398
399impl ObjectMetadata {
400    pub fn clone_ffi_symbol_name(&self) -> String {
405        clone_fn_symbol_name(&self.module_path, &self.name)
406    }
407
408    pub fn free_ffi_symbol_name(&self) -> String {
412        free_fn_symbol_name(&self.module_path, &self.name)
413    }
414}
415
416#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Node)]
420pub enum UniffiTraitMetadata {
421    Debug {
422        fmt: MethodMetadata,
423    },
424    Display {
425        fmt: MethodMetadata,
426    },
427    Eq {
428        eq: MethodMetadata,
429        ne: MethodMetadata,
430    },
431    Hash {
432        hash: MethodMetadata,
433    },
434    Ord {
435        cmp: MethodMetadata,
436    },
437}
438
439impl UniffiTraitMetadata {
440    fn module_path(&self) -> &str {
441        &match self {
442            UniffiTraitMetadata::Debug { fmt } => fmt,
443            UniffiTraitMetadata::Display { fmt } => fmt,
444            UniffiTraitMetadata::Eq { eq, .. } => eq,
445            UniffiTraitMetadata::Hash { hash } => hash,
446            UniffiTraitMetadata::Ord { cmp } => cmp,
447        }
448        .module_path
449    }
450
451    pub fn self_name(&self) -> &str {
452        &match self {
453            UniffiTraitMetadata::Debug { fmt } => fmt,
454            UniffiTraitMetadata::Display { fmt } => fmt,
455            UniffiTraitMetadata::Eq { eq, .. } => eq,
456            UniffiTraitMetadata::Hash { hash } => hash,
457            UniffiTraitMetadata::Ord { cmp } => cmp,
458        }
459        .self_name
460    }
461
462    pub fn name(&self) -> &str {
463        &match self {
464            UniffiTraitMetadata::Debug { fmt } => fmt,
465            UniffiTraitMetadata::Display { fmt } => fmt,
466            UniffiTraitMetadata::Eq { eq, .. } => eq,
467            UniffiTraitMetadata::Hash { hash } => hash,
468            UniffiTraitMetadata::Ord { cmp } => cmp,
469        }
470        .name
471    }
472}
473
474#[repr(u8)]
475#[derive(Debug, Eq, PartialEq, Hash, Node)]
476pub enum UniffiTraitDiscriminants {
477    Debug,
478    Display,
479    Eq,
480    Hash,
481    Ord,
482}
483
484impl UniffiTraitDiscriminants {
485    pub fn from(v: u8) -> anyhow::Result<Self> {
486        Ok(match v {
487            0 => UniffiTraitDiscriminants::Debug,
488            1 => UniffiTraitDiscriminants::Display,
489            2 => UniffiTraitDiscriminants::Eq,
490            3 => UniffiTraitDiscriminants::Hash,
491            4 => UniffiTraitDiscriminants::Ord,
492            _ => anyhow::bail!("invalid trait discriminant {v}"),
493        })
494    }
495}
496
497#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Node)]
500pub struct ObjectTraitImplMetadata {
501    pub ty: Type,
502    pub trait_ty: Type,
503}
504
505impl Checksum for ObjectTraitImplMetadata {
506    fn checksum<H: Hasher>(&self, state: &mut H) {
507        Checksum::checksum(&self.ty, state);
508        Checksum::checksum(&self.trait_ty, state);
509    }
510}
511
512#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Node)]
513pub struct CustomTypeMetadata {
514    pub module_path: String,
515    pub name: String,
516    pub builtin: Type,
517    pub docstring: Option<String>,
518}
519
520pub fn checksum<T: Checksum>(val: &T) -> u16 {
525    let mut hasher = siphasher::sip::SipHasher13::new();
526    val.checksum(&mut hasher);
527    (hasher.finish() & 0x000000000000FFFF) as u16
528}
529
530#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Node)]
532pub enum Metadata {
533    Namespace(NamespaceMetadata),
534    UdlFile(UdlFile),
535    Func(FnMetadata),
536    Object(ObjectMetadata),
537    CallbackInterface(CallbackInterfaceMetadata),
538    Record(RecordMetadata),
539    Enum(EnumMetadata),
540    Constructor(ConstructorMetadata),
541    Method(MethodMetadata),
542    TraitMethod(TraitMethodMetadata),
543    CustomType(CustomTypeMetadata),
544    UniffiTrait(UniffiTraitMetadata),
545    ObjectTraitImpl(ObjectTraitImplMetadata),
546}
547
548impl Metadata {
549    pub fn read(data: &[u8]) -> anyhow::Result<Self> {
550        read_metadata(data)
551    }
552
553    pub fn module_path(&self) -> &str {
554        match self {
555            Metadata::Namespace(meta) => &meta.crate_name,
556            Metadata::UdlFile(meta) => &meta.module_path,
557            Metadata::Func(meta) => &meta.module_path,
558            Metadata::Constructor(meta) => &meta.module_path,
559            Metadata::Method(meta) => &meta.module_path,
560            Metadata::Record(meta) => &meta.module_path,
561            Metadata::Enum(meta) => &meta.module_path,
562            Metadata::Object(meta) => &meta.module_path,
563            Metadata::CallbackInterface(meta) => &meta.module_path,
564            Metadata::TraitMethod(meta) => &meta.module_path,
565            Metadata::CustomType(meta) => &meta.module_path,
566            Metadata::UniffiTrait(meta) => meta.module_path(),
567            Metadata::ObjectTraitImpl(t) => t.ty.module_path().expect("type has no module"),
568        }
569    }
570}
571
572impl From<NamespaceMetadata> for Metadata {
573    fn from(value: NamespaceMetadata) -> Metadata {
574        Self::Namespace(value)
575    }
576}
577
578impl From<UdlFile> for Metadata {
579    fn from(value: UdlFile) -> Metadata {
580        Self::UdlFile(value)
581    }
582}
583
584impl From<FnMetadata> for Metadata {
585    fn from(value: FnMetadata) -> Metadata {
586        Self::Func(value)
587    }
588}
589
590impl From<ConstructorMetadata> for Metadata {
591    fn from(c: ConstructorMetadata) -> Self {
592        Self::Constructor(c)
593    }
594}
595
596impl From<MethodMetadata> for Metadata {
597    fn from(m: MethodMetadata) -> Self {
598        Self::Method(m)
599    }
600}
601
602impl From<RecordMetadata> for Metadata {
603    fn from(r: RecordMetadata) -> Self {
604        Self::Record(r)
605    }
606}
607
608impl From<EnumMetadata> for Metadata {
609    fn from(e: EnumMetadata) -> Self {
610        Self::Enum(e)
611    }
612}
613
614impl From<ObjectMetadata> for Metadata {
615    fn from(v: ObjectMetadata) -> Self {
616        Self::Object(v)
617    }
618}
619
620impl From<CallbackInterfaceMetadata> for Metadata {
621    fn from(v: CallbackInterfaceMetadata) -> Self {
622        Self::CallbackInterface(v)
623    }
624}
625
626impl From<TraitMethodMetadata> for Metadata {
627    fn from(v: TraitMethodMetadata) -> Self {
628        Self::TraitMethod(v)
629    }
630}
631
632impl From<CustomTypeMetadata> for Metadata {
633    fn from(v: CustomTypeMetadata) -> Self {
634        Self::CustomType(v)
635    }
636}
637
638impl From<UniffiTraitMetadata> for Metadata {
639    fn from(v: UniffiTraitMetadata) -> Self {
640        Self::UniffiTrait(v)
641    }
642}
643
644impl From<ObjectTraitImplMetadata> for Metadata {
645    fn from(t: ObjectTraitImplMetadata) -> Self {
646        Self::ObjectTraitImpl(t)
647    }
648}