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

Commit 9c62ccb0 authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 7085169 from 4595d8df to sc-release

Change-Id: I77d05006e71076130bf87cb975279e74be0975e5
parents cac88853 4595d8df
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -37,6 +37,11 @@ pub enum Error {
  InvalidPacketError
}

pub trait Packet {
  fn to_bytes(self) -> Bytes;
  fn to_vec(self) -> Vec<u8>;
}

)";
}

+11 −8
Original line number Diff line number Diff line
@@ -1041,22 +1041,25 @@ void PacketDef::GenRustAccessStructImpls(std::ostream& s) const {
    s << "}";
  }

  s << "impl " << name_ << "Packet {";
  if (parent_ == nullptr) {
    s << "pub fn parse(bytes: &[u8]) -> Result<Self> { ";
    s << "Ok(Self::new(Arc::new(" << name_ << "Data::parse(bytes)?)))";
    s << "}";
  }
  s << "impl Packet for " << name_ << "Packet {";
  auto root = GetRootDef();
  auto root_accessor = util::CamelCaseToUnderScore(root->name_);

  s << "pub fn to_bytes(self) -> Bytes {";
  s << "fn to_bytes(self) -> Bytes {";
  s << " let mut buffer = BytesMut::new();";
  s << " self." << root_accessor << ".write_to(&mut buffer);";
  s << " buffer.freeze()";
  s << "}\n";

  s << "pub fn to_vec(self) -> Vec<u8> { self.to_bytes().to_vec() }\n";
  s << "fn to_vec(self) -> Vec<u8> { self.to_bytes().to_vec() }\n";
  s << "}";

  s << "impl " << name_ << "Packet {";
  if (parent_ == nullptr) {
    s << "pub fn parse(bytes: &[u8]) -> Result<Self> { ";
    s << "Ok(Self::new(Arc::new(" << name_ << "Data::parse(bytes)?)))";
    s << "}";
  }

  if (!children_.empty()) {
    s << " pub fn specialize(&self) -> " << name_ << "Child {";
+18 −0
Original line number Diff line number Diff line
rust_library {
    name: "libbt_facade_helpers",
    defaults: ["gd_rust_defaults"],
    crate_name: "bt_facade_helpers",
    srcs: ["src/lib.rs"],
    edition: "2018",
    rustlibs: [
        "libbt_facade_proto",
        "libbt_packets",
        "libbytes",
        "libfutures",
        "libgrpcio",
        "libtokio",
        "libprotobuf",
        "liblog_rust",
        "libcxx",
    ],
}
+67 −0
Original line number Diff line number Diff line
//! common facade & shim helpers

use bt_facade_proto::common::Data;
use bt_packets::hci::Packet;
use futures::sink::SinkExt;
use grpcio::*;
use std::sync::Arc;
use tokio::runtime::Runtime;
use tokio::sync::mpsc::Receiver;
use tokio::sync::Mutex;

/// Wrapper so we can invoke callbacks
pub trait U8SliceRunnable {
    /// Do the thing
    fn run(&self, data: &[u8]);
}

/// Helper for interfacing channels with shim or gRPC boundaries
#[derive(Clone)]
pub struct RxAdapter<T> {
    rx: Arc<Mutex<Receiver<T>>>,
    running: bool,
}

impl<T: 'static + Packet + Send> RxAdapter<T> {
    /// New, from an unwrapped receiver
    pub fn new(rx: Receiver<T>) -> Self {
        Self::from_arc(Arc::new(Mutex::new(rx)))
    }

    /// New, from an already arc mutexed receiver
    pub fn from_arc(rx: Arc<Mutex<Receiver<T>>>) -> Self {
        Self { rx, running: false }
    }

    /// Stream out the channel over the provided sink
    pub fn stream_grpc(&mut self, ctx: RpcContext<'_>, mut sink: ServerStreamingSink<Data>) {
        assert!(!self.running);
        self.running = true;

        let clone_rx = self.rx.clone();
        ctx.spawn(async move {
            while let Some(payload) = clone_rx.lock().await.recv().await {
                let mut data = Data::default();
                data.set_payload(payload.to_vec());
                sink.send((data, WriteFlags::default())).await.unwrap();
            }
        });
    }

    /// Stream out the channel over the provided shim runnable
    pub fn stream_runnable<R: 'static + U8SliceRunnable + Send>(
        &mut self,
        rt: &Arc<Runtime>,
        runnable: R,
    ) {
        assert!(!self.running);
        self.running = true;

        let clone_rx = self.rx.clone();
        rt.spawn(async move {
            while let Some(payload) = clone_rx.lock().await.recv().await {
                runnable.run(&payload.to_bytes());
            }
        });
    }
}
+69 −22
Original line number Diff line number Diff line
@@ -5,7 +5,10 @@ use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::parse::{Parse, ParseStream, Result};
use syn::punctuated::Punctuated;
use syn::{braced, parse, parse_macro_input, FnArg, Ident, ItemFn, Token, Type, DeriveInput, Path};
use syn::{
    braced, parse, parse_macro_input, DeriveInput, Fields, FnArg, Ident, ItemFn, ItemStruct, Path,
    Token, Type,
};

/// Defines a provider function, with generated helper that implicitly fetches argument instances from the registry
#[proc_macro_attribute]
@@ -57,6 +60,7 @@ enum ModuleEntry {
struct ProviderDef {
    ty: Type,
    ident: Ident,
    parts: bool,
}

impl Parse for ModuleDef {
@@ -75,30 +79,34 @@ impl Parse for ModuleDef {
                        panic!("providers specified more than once");
                    }
                    providers = value;
                },
                }
                ModuleEntry::Submodules(value) => {
                    if !submodules.is_empty() {
                        panic!("submodules specified more than once");
                    }
                    submodules = value;
                },
                }
            }
        Ok(ModuleDef {
            name,
            providers,
            submodules,
        })
        }
        Ok(ModuleDef { name, providers, submodules })
    }
}

impl Parse for ProviderDef {
    fn parse(input: ParseStream) -> Result<Self> {
        let parts = input.peek3(Token![=>]);
        if parts {
            match input.parse::<Ident>()?.to_string().as_str() {
                "parts" => {}
                keyword => panic!("expected 'parts', got '{}'", keyword),
            }
        }

        // A provider definition follows this format: <Type> -> <function name>
        let ty = input.parse()?;
        input.parse::<Token![=>]>()?;
        let ident = input.parse()?;
        Ok(ProviderDef { ty, ident })
        Ok(ProviderDef { ty, ident, parts })
    }
}

@@ -108,16 +116,12 @@ impl Parse for ModuleEntry {
            "providers" => {
                let entries;
                braced!(entries in input);
                Ok(ModuleEntry::Providers(
                    entries.parse_terminated(ProviderDef::parse)?,
                ))
                Ok(ModuleEntry::Providers(entries.parse_terminated(ProviderDef::parse)?))
            }
            "submodules" => {
                let entries;
                braced!(entries in input);
                Ok(ModuleEntry::Submodules(
                    entries.parse_terminated(Path::parse)?,
                ))
                Ok(ModuleEntry::Submodules(entries.parse_terminated(Path::parse)?))
            }
            keyword => {
                panic!("unexpected keyword: {}", keyword);
@@ -131,20 +135,30 @@ impl Parse for ModuleEntry {
pub fn module(item: TokenStream) -> TokenStream {
    let module = parse_macro_input!(item as ModuleDef);
    let init_ident = module.name.clone();
    let types = module.providers.iter().map(|p| p.ty.clone());
    let provider_idents = module
        .providers
        .iter()
        .map(|p| format_ident!("__gddi_{}_injected", p.ident.clone()));
    let providers = module.providers.iter();
    let types = providers.clone().map(|p| p.ty.clone());
    let provider_idents =
        providers.clone().map(|p| format_ident!("__gddi_{}_injected", p.ident.clone()));
    let parting_functions = providers.filter_map(|p| match &p.ty {
        Type::Path(ty) if p.parts => Some(format_ident!(
            "__gddi_part_out_{}",
            ty.path.get_ident().unwrap().to_string().to_lowercase()
        )),
        _ => None,
    });
    let submodule_idents = module.submodules.iter();
    let emitted_code = quote! {
        #[doc(hidden)]
        #[allow(missing_docs)]
        pub fn #init_ident(builder: gddi::RegistryBuilder) -> gddi::RegistryBuilder {
            // Register all providers on this module
            builder#(.register_provider::<#types>(Box::new(#provider_idents)))*
            let ret = builder#(.register_provider::<#types>(Box::new(#provider_idents)))*
            // Register all submodules on this module
            #(.register_module(#submodule_idents))*
            #(.register_module(#submodule_idents))*;

            #(let ret = #parting_functions(ret);)*

            ret
        }
    };
    emitted_code.into()
@@ -160,3 +174,36 @@ pub fn derive_nop_stop(item: TokenStream) -> TokenStream {
    };
    emitted_code.into()
}

/// Generates the code necessary to split up a type into its components
#[proc_macro_attribute]
pub fn part_out(_attr: TokenStream, item: TokenStream) -> TokenStream {
    let struct_: ItemStruct = parse(item).expect("can only be applied to struct definitions");
    let struct_ident = struct_.ident.clone();
    let fields = match struct_.fields.clone() {
        Fields::Named(f) => f,
        _ => panic!("can only be applied to structs with named fields"),
    }
    .named;

    let field_names = fields.iter().map(|f| f.ident.clone().expect("field without a name"));
    let field_types = fields.iter().map(|f| f.ty.clone());

    let fn_ident = format_ident!("__gddi_part_out_{}", struct_ident.to_string().to_lowercase());

    let emitted_code = quote! {
        #struct_

        fn #fn_ident(builder: gddi::RegistryBuilder) -> gddi::RegistryBuilder {
            builder#(.register_provider::<#field_types>(Box::new(
                |registry: std::sync::Arc<gddi::Registry>| -> std::pin::Pin<gddi::ProviderFutureBox> {
                    Box::pin(async move {
                        Box::new(async move {
                            registry.get::<#struct_ident>().await.#field_names
                        }) as Box<dyn std::any::Any>
                    })
                })))*
        }
    };
    emitted_code.into()
}
Loading