Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  lib.rs   Sprache: unbekannt

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

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;

// This needs to match the minor version of the `uniffi` crate.  See
// `docs/uniffi-versioning.md` for details.
//
// Once we get to 1.0, then we'll need to update the scheme to something like 100 + major_version
pub const UNIFFI_CONTRACT_VERSION: u32 = 26;

/// Similar to std::hash::Hash.
///
/// Implementations of this trait are expected to update the hasher state in
/// the same way across platforms. #[derive(Checksum)] will do the right thing.
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)
    }
}

// The namespace of a Component interface.
//
// This is used to match up the macro metadata with the UDL items.
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct NamespaceMetadata {
    pub crate_name: String,
    pub name: String,
}

// UDL file included with `include_scaffolding!()`
//
// This is to find the UDL files in library mode generation
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct UdlFile {
    // The module path specified when the UDL file was parsed.
    pub module_path: String,
    pub namespace: String,
    // the base filename of the udl file - no path, no extension.
    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>,
    pub docstring: Option<String>,
}

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 is_async: bool,
    pub inputs: Vec<FnParamMetadata>,
    pub throws: Option<Type>,
    pub checksum: Option<u16>,
    pub docstring: Option<String>,
}

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, // unused except by rust udl bindgen.
    pub checksum: Option<u16>,
    pub docstring: Option<String>,
}

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,
    // Note: the position of `index` is important since it causes callback interface methods to be
    // ordered correctly in MetadataGroup.items
    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, // unused except by rust udl bindgen.
    pub checksum: Option<u16>,
    pub docstring: Option<String>,
}

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),
    // Integers are represented as the widest representation we can.
    // Number formatting vary with language and radix, so we avoid a lot of parsing and
    // formatting duplication by using only signed and unsigned variants.
    UInt(u64, Radix, Type),
    Int(i64, Radix, Type),
    // Pass the string representation through as typed in the UDL.
    // This avoids a lot of uncertainty around precision and accuracy,
    // though bindings for languages less sophisticated number parsing than WebIDL
    // will have to do extra work.
    Float(String, Type),
    Enum(String, Type),
    EmptySequence,
    EmptyMap,
    None,
    Some { inner: Box<LiteralMetadata> },
}

impl LiteralMetadata {
    pub fn new_uint(v: u64) -> Self {
        LiteralMetadata::UInt(v, Radix::Decimal, Type::UInt64)
    }
    pub fn new_int(v: i64) -> Self {
        LiteralMetadata::Int(v, Radix::Decimal, Type::Int64)
    }
}

// Represent the radix of integer literal values.
// We preserve the radix into the generated bindings for readability reasons.
#[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>,
    pub docstring: Option<String>,
}

#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct FieldMetadata {
    pub name: String,
    pub ty: Type,
    pub default: Option<LiteralMetadata>,
    pub docstring: Option<String>,
}

#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Checksum)]
pub enum EnumShape {
    Enum,
    Error { flat: bool },
}

impl EnumShape {
    pub fn as_u8(&self) -> u8 {
        match self {
            EnumShape::Enum => 0,
            EnumShape::Error { flat: false } => 1,
            EnumShape::Error { flat: true } => 2,
        }
    }

    pub fn from(v: u8) -> anyhow::Result<Self> {
        Ok(match v {
            0 => EnumShape::Enum,
            1 => EnumShape::Error { flat: false },
            2 => EnumShape::Error { flat: true },
            _ => anyhow::bail!("invalid enum shape discriminant {v}"),
        })
    }
}

#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct EnumMetadata {
    pub module_path: String,
    pub name: String,
    pub shape: EnumShape,
    pub variants: Vec<VariantMetadata>,
    pub discr_type: Option<Type>,
    pub non_exhaustive: bool,
    pub docstring: Option<String>,
}

#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct VariantMetadata {
    pub name: String,
    pub discr: Option<LiteralMetadata>,
    pub fields: Vec<FieldMetadata>,
    pub docstring: Option<String>,
}

#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct ObjectMetadata {
    pub module_path: String,
    pub name: String,
    pub imp: types::ObjectImpl,
    pub docstring: Option<String>,
}

#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct CallbackInterfaceMetadata {
    pub module_path: String,
    pub name: String,
    pub docstring: Option<String>,
}

impl ObjectMetadata {
    /// FFI symbol name for the `clone` function for this object.
    ///
    /// This function is used to increment the reference count before lowering an object to pass
    /// back to Rust.
    pub fn clone_ffi_symbol_name(&self) -> String {
        clone_fn_symbol_name(&self.module_path, &self.name)
    }

    /// FFI symbol name for the `free` function for this object.
    ///
    /// This function is used to free the memory used by this object.
    pub fn free_ffi_symbol_name(&self) -> String {
        free_fn_symbol_name(&self.module_path, &self.name)
    }
}

/// The list of traits we support generating helper methods for.
#[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)]
#[derive(Eq, PartialEq, Hash)]
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 struct CustomTypeMetadata {
    pub module_path: String,
    pub name: String,
    pub builtin: Type,
}

/// Returns the last 16 bits of the value's hash as computed with [`SipHasher13`].
///
/// This is used as a safeguard against different UniFFI versions being used for scaffolding and
/// bindings generation.
pub fn checksum<T: Checksum>(val: &T) -> u16 {
    let mut hasher = siphasher::sip::SipHasher13::new();
    val.checksum(&mut hasher);
    (hasher.finish() & 0x000000000000FFFF) as u16
}

/// Enum covering all the possible metadata types
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum Metadata {
    Namespace(NamespaceMetadata),
    UdlFile(UdlFile),
    Func(FnMetadata),
    Object(ObjectMetadata),
    CallbackInterface(CallbackInterfaceMetadata),
    Record(RecordMetadata),
    Enum(EnumMetadata),
    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::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<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)
    }
}

[ Dauer der Verarbeitung: 0.31 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge