uniffi_bindgen 0.31.1

a multi-language bindings generator for rust (codegen and cli tooling)
Documentation
/* 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 super::*;
use anyhow::bail;

pub fn pass(namespace: &mut Namespace) -> Result<()> {
    // UniFFI contract version function.  This is used to check that there wasn't a breaking
    // change to `uniffi-bindgen`.
    namespace.ffi_uniffi_contract_version = RustFfiFunctionName(format!(
        "ffi_{}_uniffi_contract_version",
        &namespace.crate_name
    ));
    namespace.ffi_definitions.insert(
        FfiFunction {
            name: RustFfiFunctionName(format!(
                "ffi_{}_uniffi_contract_version",
                &namespace.crate_name
            )),
            async_data: None,
            arguments: vec![],
            return_type: FfiReturnType {
                ty: Some(FfiType::UInt32.into()),
            },
            has_rust_call_status_arg: false,
            kind: FfiFunctionKind::UniffiContractVersion,
            ..FfiFunction::default()
        }
        .into(),
    );

    // Checksums, these are used to check that the bindings were built against the same
    // exported interface as the loaded library.
    let mut checksums = vec![];
    // Closure to visit a callable
    let mut visit_callable = |callable: &Callable| {
        let Some(checksum) = callable.checksum else {
            bail!("Checksum not set for {:#?}", callable);
        };
        let fn_name = match &callable.kind {
            CallableKind::Function => {
                uniffi_meta::fn_checksum_symbol_name(&namespace.crate_name, &callable.name)
            }
            CallableKind::Method { self_type } => {
                let name = self_type.ty.name().unwrap();
                uniffi_meta::method_checksum_symbol_name(
                    &namespace.crate_name,
                    name,
                    &callable.name,
                )
            }
            CallableKind::VTableMethod { self_type } => uniffi_meta::method_checksum_symbol_name(
                &namespace.crate_name,
                self_type.ty.name().unwrap(),
                &callable.name,
            ),
            CallableKind::Constructor { self_type, .. } => {
                uniffi_meta::constructor_checksum_symbol_name(
                    &namespace.crate_name,
                    self_type.ty.name().unwrap(),
                    &callable.name,
                )
            }
        };
        checksums.push((
            FfiFunction {
                name: RustFfiFunctionName(fn_name.clone()),
                async_data: None,
                arguments: vec![],
                return_type: FfiReturnType {
                    ty: Some(FfiType::UInt16.into()),
                },
                has_rust_call_status_arg: false,
                kind: FfiFunctionKind::Checksum,
                ..FfiFunction::default()
            },
            checksum,
        ));
        Ok(())
    };
    // Call `visit_callable` for callables that we have checksums for
    // (functions/constructors/methods), but not ones where we don't (VTable methods and UniFFI
    // traits).
    namespace.try_visit(|function: &Function| function.try_visit(&mut visit_callable))?;
    namespace.try_visit(|int: &Interface| {
        for cons in int.constructors.iter() {
            visit_callable(&cons.callable)?;
        }
        for meth in int.methods.iter() {
            visit_callable(&meth.callable)?;
        }
        Ok(())
    })?;

    for (ffi_func, checksum) in checksums {
        namespace.checksums.push(Checksum {
            fn_name: ffi_func.name.clone(),
            checksum,
        });
        namespace
            .ffi_definitions
            .insert(FfiDefinition::RustFunction(ffi_func));
    }
    namespace.correct_contract_version = uniffi_meta::UNIFFI_CONTRACT_VERSION.to_string();
    Ok(())
}