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}