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

Commit a327d905 authored by Abhishek Pandit-Subedi's avatar Abhishek Pandit-Subedi
Browse files

floss: Update cb_variant to consume values

To keep callback enum variants clean, introduce a consuming conversion
in the cb_variant! macro. This is useful when converting a pointer
+ size into a vector.

Example:

enum Foo {
  Bar(Vec<u32>),
}

cb_variant!(FooCb, bar_cb -> Foo::Bar, *const u32, usize -> _, {
  let _0 = ptr_to_vec(_0, _1);
});

Bug: 216384386
Tag: #floss
Test: Build on ChromeOS
Change-Id: I3c110bbaf5120730b589dd3efa4b952e41d7291a
parent 83a3fa87
Loading
Loading
Loading
Loading
+37 −11
Original line number Original line Diff line number Diff line
@@ -11,7 +11,7 @@ use syn::{parse_macro_input, Block, Ident, Path, Stmt, Token, Type};
struct CbVariant {
struct CbVariant {
    dispatcher: Type,
    dispatcher: Type,
    fn_pair: (Ident, Path),
    fn_pair: (Ident, Path),
    arg_pairs: Vec<(Type, Type)>,
    arg_pairs: Vec<(Type, Option<Type>)>,
    stmts: Vec<Stmt>,
    stmts: Vec<Stmt>,
}
}


@@ -26,7 +26,7 @@ impl Parse for CbVariant {
        input.parse::<Token![->]>()?;
        input.parse::<Token![->]>()?;
        let rpath: Path = input.parse()?;
        let rpath: Path = input.parse()?;


        let mut arg_pairs: Vec<(Type, Type)> = Vec::new();
        let mut arg_pairs: Vec<(Type, Option<Type>)> = Vec::new();
        let mut stmts: Vec<Stmt> = Vec::new();
        let mut stmts: Vec<Stmt> = Vec::new();


        while input.peek(Token![,]) {
        while input.peek(Token![,]) {
@@ -48,11 +48,19 @@ impl Parse for CbVariant {
                // Discard ->
                // Discard ->
                input.parse::<Token![->]>()?;
                input.parse::<Token![->]>()?;


                // Try to parse Token![_]. If that works, we will
                // consume this value and not pass it forward.
                // Otherwise, try to parse as syn::Type and pass forward for
                // conversion.
                if input.peek(Token![_]) {
                    input.parse::<Token![_]>()?;
                    arg_pairs.push((start_type, None));
                } else {
                    let end_type: Type = input.parse()?;
                    let end_type: Type = input.parse()?;

                    arg_pairs.push((start_type, Some(end_type)));
                arg_pairs.push((start_type, end_type))
                }
            } else {
            } else {
                arg_pairs.push((start_type.clone(), start_type));
                arg_pairs.push((start_type.clone(), Some(start_type)));
            }
            }
        }
        }


@@ -69,6 +77,18 @@ impl Parse for CbVariant {
///         // Statements (maybe converting types)
///         // Statements (maybe converting types)
///         // Args in order will be _0, _1, etc.
///         // Args in order will be _0, _1, etc.
///     })
///     })
///
///     args can do conversions inline as well. In order for conversions to work, the relevant
///     From<T> trait should also be implemented.
///
///     Example:
///         u32 -> BtStatus (requires impl From<u32> for BtStatus)
///
///     To consume a value during conversion, you can use `Type -> _`. This is useful when you want
///     to convert a pointer + size into a single Vec (i.e. using ptr_to_vec).
///
///     Example:
///         u32 -> _
pub fn cb_variant(input: TokenStream) -> TokenStream {
pub fn cb_variant(input: TokenStream) -> TokenStream {
    let parsed_cptr = parse_macro_input!(input as CbVariant);
    let parsed_cptr = parse_macro_input!(input as CbVariant);


@@ -81,13 +101,19 @@ pub fn cb_variant(input: TokenStream) -> TokenStream {
        let ident = format_ident!("_{}", i);
        let ident = format_ident!("_{}", i);
        params.extend(quote! { #ident: #start, });
        params.extend(quote! { #ident: #start, });


        match end {
            Some(v) => {
                // Argument needs an into translation if it doesn't match the start
                // Argument needs an into translation if it doesn't match the start
        if start != end {
                if start != v {
                    args.extend(quote! { #end::from(#ident), });
                    args.extend(quote! { #end::from(#ident), });
                } else {
                } else {
                    args.extend(quote! {#ident,});
                    args.extend(quote! {#ident,});
                }
                }
            }
            }
            // If there's no end type, just consume it instead.
            None => (),
        }
    }


    let mut stmts = proc_macro2::TokenStream::new();
    let mut stmts = proc_macro2::TokenStream::new();
    for stmt in parsed_cptr.stmts {
    for stmt in parsed_cptr.stmts {