Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 29c984a4 authored by Hsin-chen Chuang's avatar Hsin-chen Chuang
Browse files

floss: topshim: Add utility for easier sharing types with cxx bridge

Add gen_cxx_extern_trivial macro which generates the type info for cxx
bridge.

Use `namespace` attribute so we don't need to re-define the types in
type_alias.h

Bug: 343675216
Tag: #floss
Test: mmm packages/modules/Bluetooth
Flag: EXEMPT, Floss-only changes
Change-Id: Id177abdb4c4475ab3bdc03864d5f758c2d66150a
parent 545cc3b0
Loading
Loading
Loading
Loading
+0 −42
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef GD_RUST_TOPSHIM_COMMON_TYPE_ALIAS_H
#define GD_RUST_TOPSHIM_COMMON_TYPE_ALIAS_H

/*
 * Declare type aliases in the topshim namespace in this file.
 *
 * The type declarations in cxx bridge blocks are bound to the namespace of the
 * block. Since in topshim we always put the bridge codes in namespace
 * `bluetooth::topshim::rust`, to reuse the existing types in GD it's necessary
 * to define the aliases in the topshim namespace.
 */

#include "types/bluetooth/uuid.h"
#include "types/raw_address.h"

namespace bluetooth {
namespace topshim {
namespace rust {

using RawAddress = ::RawAddress;
using Uuid = ::bluetooth::Uuid;

}  // namespace rust
}  // namespace topshim
}  // namespace bluetooth

#endif  // GD_RUST_TOPSHIM_COMMON_TYPE_ALIAS_H
+78 −0
Original line number Diff line number Diff line
@@ -220,3 +220,81 @@ fn generate_profile_enabled_or_tokenstream(item: TokenStream, attr_string: Strin

    output.into()
}

/// Generate impl cxx::ExternType for the trivial types in bindings.
///
/// This is only needed if they need to be share with the cxx-bridge blocks.
///
/// Usage (assume the C++ type some::ns::sample_t is defined in types/some_samples.h):
/// ```ignore
/// #[gen_cxx_extern_trivial]
/// type SampleType = bindings::some::ns::sample_t;
/// ```
///
/// Which generates the type info below for cxx-bridge:
/// ```ignore
/// unsafe impl cxx::ExternType for SampleType {
///     type Id = cxx::type_id!("some::ns::sample_t");
///     type Kind = cxx::kind::Trivial;
/// }
/// ```
///
/// To use the binding type in a cxx::bridge block, include the header and (optionally) assign
/// the namespace and name for the C++ type.
/// ```ignore
/// #[cxx::bridge]
/// mod ffi {
///     unsafe extern "C++" {
///         include!("types/some_samples.h");
///
///         #[namespace = "some::ns"]
///         #[cxx_name = "sample_t"]
///         type SampleType = super::SampleType;
///     }
/// }
/// ```
#[proc_macro_attribute]
pub fn gen_cxx_extern_trivial(_attr: TokenStream, item: TokenStream) -> TokenStream {
    let input = syn::parse_macro_input!(item as syn::ItemType);

    let ident = input.ident.clone();

    let segs = match *input.ty {
        Type::Path(syn::TypePath {
            qself: None,
            path: Path { leading_colon: None, ref segments },
        }) => segments,
        _ => panic!("Unsupported type"),
    };

    let mut iter = segs.into_iter();

    match iter.next() {
        Some(seg) if seg.ident == "bindings" => {}
        _ => panic!("Unexpected type: Must starts with \"bindings::\""),
    }

    match iter.clone().next() {
        Some(seg) if seg.ident == "root" => {
            // Skip the "root" module in bindings
            iter.next();
        }
        _ => {}
    }

    let cxx_ident = iter.map(|seg| seg.ident.to_string()).collect::<Vec<String>>().join("::");

    if cxx_ident.is_empty() {
        panic!("Empty cxx ident");
    }

    quote! {
        #input

        unsafe impl cxx::ExternType for #ident {
            type Id = cxx::type_id!(#cxx_ident);
            type Kind = cxx::kind::Trivial;
        }
    }
    .into()
}
+15 −18
Original line number Diff line number Diff line
@@ -15,9 +15,7 @@ use std::mem;
use std::os::raw::c_char;
use std::sync::{Arc, Mutex};
use std::vec::Vec;
use topshim_macros::cb_variant;

use cxx::{type_id, ExternType};
use topshim_macros::{cb_variant, gen_cxx_extern_trivial};

#[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
#[repr(u32)]
@@ -418,12 +416,6 @@ pub type BtLocalLeFeatures = bindings::bt_local_le_features_t;
pub type BtPinCode = bindings::bt_pin_code_t;
pub type BtRemoteVersion = bindings::bt_remote_version_t;
pub type BtVendorProductInfo = bindings::bt_vendor_product_info_t;
pub type Uuid = bindings::bluetooth::Uuid;

unsafe impl ExternType for Uuid {
    type Id = type_id!("bluetooth::topshim::rust::Uuid");
    type Kind = cxx::kind::Trivial;
}

impl TryFrom<Uuid> for Vec<u8> {
    type Error = &'static str;
@@ -910,27 +902,30 @@ mod ffi {
    }
}

/// The RawAddress directly exported from the bindings.
/// Generate impl cxx::ExternType for RawAddress and Uuid.
///
/// To make use of RawAddress in cxx::bridge C++ blocks,
/// To make use of RawAddress and Uuid in cxx::bridge C++ blocks,
/// include the following snippet in the ffi module.
/// ```ignore
/// #[cxx::bridge(namespace = bluetooth::topshim::rust)]
/// mod ffi {
///     unsafe extern "C++" {
///         include!("gd/rust/topshim/common/type_alias.h");
///         include!("types/raw_address.h");
///         include!("types/bluetooth/uuid.h");
///
///         #[namespace = ""]
///         type RawAddress = crate::btif::RawAddress;
///
///         #[namespace = "bluetooth"]
///         type Uuid = crate::btif::Uuid;
///     }
///     // Place you shared stuff here.
/// }
/// ```
#[gen_cxx_extern_trivial]
pub type RawAddress = bindings::RawAddress;
pub type OobData = bindings::bt_oob_data_s;

unsafe impl ExternType for RawAddress {
    type Id = type_id!("bluetooth::topshim::rust::RawAddress");
    type Kind = cxx::kind::Trivial;
}
#[gen_cxx_extern_trivial]
pub type Uuid = bindings::bluetooth::Uuid;

impl Hash for RawAddress {
    fn hash<H: Hasher>(&self, state: &mut H) {
@@ -1007,6 +1002,8 @@ impl<'a> Display for DisplayAddress<'a> {
    }
}

pub type OobData = bindings::bt_oob_data_s;

/// An enum representing `bt_callbacks_t` from btif.
#[derive(Clone, Debug)]
pub enum BaseCallbacks {
+2 −1
Original line number Diff line number Diff line
#[cxx::bridge(namespace = bluetooth::topshim::rust)]
mod ffi {
    unsafe extern "C++" {
        include!("gd/rust/topshim/common/type_alias.h");
        include!("types/raw_address.h");
        #[namespace = ""]
        type RawAddress = crate::btif::RawAddress;
    }

+2 −1
Original line number Diff line number Diff line
@@ -6,7 +6,8 @@ use crate::btif::{
#[cxx::bridge(namespace = bluetooth::topshim::rust)]
mod ffi {
    unsafe extern "C++" {
        include!("gd/rust/topshim/common/type_alias.h");
        include!("types/raw_address.h");
        #[namespace = ""]
        type RawAddress = crate::btif::RawAddress;
    }

Loading