pub fn wrap_function(foreign_fn: &ForeignItemFn) -> proc_macro2::TokenStream {
    //  println!("foreign_fn: {:#?}", foreign_fn);
    let sig = &foreign_fn.sig;  //  Get the function signature
    //  Contains `#[doc] ... pub fn ...`
    let foreign_item_tokens = quote! { #foreign_fn };
    //  println!("foreign_item_tokens: {:#?}", foreign_item_tokens.to_string());

    //  Get the function name, with and without namespace (`os_task_init` vs `task_init`)
    let transformed_fname = transform_function_name(&sig.ident);
    let TransformedFunctionName{ 
        ident: fname,
        token: fname_token, 
        without_namespace_token: fname_without_namespace_token, .. 
    } = transformed_fname;

    //  If function name is not whitelisted, return the extern tokens without wrapping.
    if !function_is_whitelisted(&fname) { 
        return quote! { extern "C" { #foreign_item_tokens } }
    }

    //  Move the `#[doc]` attributes out from the extern and into the top level.
    //  TODO: Accumulate doc in attrs and rename args.
    let attrs = &foreign_fn.attrs;
    let mut doc_tokens = proc_macro2::TokenStream::new();
    for attr in attrs {
        //  println!("attr: {:#?}", quote! { #attr }.to_string());
        let attr_span = attr.span();
        let tokens = quote_spanned!(attr_span => #attr);
        doc_tokens.extend(tokens);
    }

    //  Get the extern declaration without the doc attributes.
    //  let extern_decl = foreign_fn.decl;
    //  let extern_decl_span = &foreign_fn.span();
    //  let extern_decl_tokens = quote_spanned!(extern_decl_span => #extern_decl);

    //  Transform the return type.
    let transformed_ret = transform_return_type(&sig.output);
    let TransformedReturnType{ 
        declare_result_tokens, get_result_tokens, return_result_tokens, .. 
    } = transformed_ret;

    //  Get the function args and transform each arg into 3 forms:
    //  (1) Wrap Declaration: How the arg type is exposed via the wrapper
    //  (2) Validation Stmt: To validate each arg if needed, e.g. check strings are null-terminated
    //  (3) Call Expr: Inside the wrapper, call the Mynewt API with type casting
    let args = &sig.inputs;
    let transformed_args = transform_arg_list(args);

    //  For all args, collect the tokens for the Wrap, Validation and Call forms.
    let wrap_tokens = collect_wrap(&transformed_args);
    let validation_tokens = collect_validation(&transformed_args);
    let call_tokens = collect_call(&transformed_args);

    //  Compose the wrapper code as tokens.
    let expanded = quote! {
        //  "----------Insert Doc: `#[doc]`----------";
        #doc_tokens
        //  "----------Insert Func Name: `pub fn task_init() -> ... {`----------";
        pub fn #fname_without_namespace_token(
            //  "----------Insert Wrapped Decl----------";
            #wrap_tokens
            /* Like this:
                t: Out<os_task>,  //  Previously: *mut os_task
                name: &Strn,      //  Previously: *const ::cty::c_char
                func: os_task_func_t,
                arg: Ptr,         //  Previously: *mut ::cty::c_void
                prio: u8,
                sanity_itvl: os_time_t,
                stack_bottom: Out<[os_stack_t]>,  //  Previously: *mut os_stack_t
                stack_size: usize,                //  Previously: u16 */
        ) -> #declare_result_tokens {             //  e.g. MynewtResult<()> or MynewtResult<* mut os_eventq>
            "----------Insert Extern Decl: `extern C { pub fn ... }`----------";
            extern "C" { #foreign_item_tokens }
            "----------Insert Validation: `Strn::validate_bytestr(name.bytestr)`----------";
            #validation_tokens
            unsafe {
                "----------Insert Call: `let result_value = os_task_init(`----------";
                #get_result_tokens #fname_token(
                    //  "----------Insert Call Expr----------";
                    #call_tokens
                    /* Like this:
                        t,
                        name.bytestr.as_ptr() as *const ::cty::c_char,  //  Converted to pointer
                        func,
                        arg,
                        prio,
                        sanity_itvl,
                        stack_bottom.as_ptr() as *mut os_stack_t,  //  Converted to pointer
                        stack_size as u16  */
                );
                "----------Insert Result: `Ok(Strn::from_cstr(result_value))`----------";
                #return_result_tokens
            }
        }
    };
    expanded
}
/// Return the safe wrapper tokens for the extern function
Return the safe wrapper tokens for the extern function
Return the safe wrapper tokens for the extern function
pub fn wrap_function(foreign_fn: &ForeignItemFn) -> proc_macro2::TokenStream {
    //  println!("foreign_fn: {:#?}", foreign_fn);
    let sig = &foreign_fn.sig;  //  Get the function signature
    //  Contains `#[doc] ... pub fn ...`
    let foreign_item_tokens = quote! { #foreign_fn };
    //  println!("foreign_item_tokens: {:#?}", foreign_item_tokens.to_string());
    //  Get the function name, with and without namespace (`os_task_init` vs `task_init`)
    let transformed_fname = transform_function_name(&sig.ident);
    let TransformedFunctionName{ 
        ident: fname,
        token: fname_token, 
        without_namespace_token: fname_without_namespace_token, .. 
    } = transformed_fname;
    //  If function name is not whitelisted, return the extern tokens without wrapping.
    if !function_is_whitelisted(&fname) { 
        return quote! { extern "C" { #foreign_item_tokens } }
    }
    //  Move the `#[doc]` attributes out from the extern and into the top level.
    //  TODO: Accumulate doc in attrs and rename args.
    let attrs = &foreign_fn.attrs;
    let mut doc_tokens = proc_macro2::TokenStream::new();
    for attr in attrs {
        //  println!("attr: {:#?}", quote! { #attr }.to_string());
        let attr_span = attr.span();
        let tokens = quote_spanned!(attr_span => #attr);
        doc_tokens.extend(tokens);
    }
    //  Get the extern declaration without the doc attributes.
    //  let extern_decl = foreign_fn.decl;
    //  let extern_decl_span = &foreign_fn.span();
    //  let extern_decl_tokens = quote_spanned!(extern_decl_span => #extern_decl);
    //  Transform the return type.
    let transformed_ret = transform_return_type(&sig.output);
    let TransformedReturnType{ 
        declare_result_tokens, get_result_tokens, return_result_tokens, .. 
    } = transformed_ret;
    //  Get the function args and transform each arg into 3 forms:
    //  (1) Wrap Declaration: How the arg type is exposed via the wrapper
    //  (2) Validation Stmt: To validate each arg if needed, e.g. check strings are null-terminated
    //  (3) Call Expr: Inside the wrapper, call the Mynewt API with type casting
    let args = &sig.inputs;
    let transformed_args = transform_arg_list(args);
    //  For all args, collect the tokens for the Wrap, Validation and Call forms.
    let wrap_tokens = collect_wrap(&transformed_args);
    let validation_tokens = collect_validation(&transformed_args);
    let call_tokens = collect_call(&transformed_args);
    //  Compose the wrapper code as tokens.
    let expanded = quote! {
        //  "----------Insert Doc: `#[doc]`----------";
        #doc_tokens
        //  "----------Insert Func Name: `pub fn task_init() -> ... {`----------";
        pub fn #fname_without_namespace_token(
            //  "----------Insert Wrapped Decl----------";
            #wrap_tokens
            /* Like this:
                t: Out<os_task>,  //  Previously: *mut os_task
                name: &Strn,      //  Previously: *const ::cty::c_char
                func: os_task_func_t,
                arg: Ptr,         //  Previously: *mut ::cty::c_void
                prio: u8,
                sanity_itvl: os_time_t,
                stack_bottom: Out<[os_stack_t]>,  //  Previously: *mut os_stack_t
                stack_size: usize,                //  Previously: u16 */
        ) -> #declare_result_tokens {             //  e.g. MynewtResult<()> or MynewtResult<* mut os_eventq>
            "----------Insert Extern Decl: `extern C { pub fn ... }`----------";
            extern "C" { #foreign_item_tokens }
            "----------Insert Validation: `Strn::validate_bytestr(name.bytestr)`----------";
            #validation_tokens
            unsafe {
                "----------Insert Call: `let result_value = os_task_init(`----------";
                #get_result_tokens #fname_token(
                    //  "----------Insert Call Expr----------";
                    #call_tokens
                    /* Like this:
                        t,
                        name.bytestr.as_ptr() as *const ::cty::c_char,  //  Converted to pointer
                        func,
                        arg,
                        prio,
                        sanity_itvl,
                        stack_bottom.as_ptr() as *mut os_stack_t,  //  Converted to pointer
                        stack_size as u16  */
                );
                "----------Insert Result: `Ok(Strn::from_cstr(result_value))`----------";
                #return_result_tokens
            }
        }
    };
    expanded
}
pub fn wrap_function ( foreign_fn : & ForeignItemFn ) -> proc_macro2 :: TokenStream { //  println!("foreign_fn: {:#?}", foreign_fn); let sig = & foreign_fn . sig ; //  Get the function signature //  Contains `#[doc] ... pub fn ...` let foreign_item_tokens = quote ! { foreign_fn } ; //  println!("foreign_item_tokens: {:#?}", foreign_item_tokens.to_string()); //  Get the function name, with and without namespace (`os_task_init` vs `task_init`) let transformed_fname = transform_function_name ( & sig . ident ) ; let TransformedFunctionName { ident : fname , token : fname_token , without_namespace_token : fname_without_namespace_token , .. } = transformed_fname ; //  If function name is not whitelisted, return the extern tokens without wrapping. if ! function_is_whitelisted ( & fname ) { return quote ! { extern " " { foreign_item_tokens } } } //  Move the `#[doc]` attributes out from the extern and into the top level. //  TODO: Accumulate doc in attrs and rename args. let attrs = & foreign_fn . attrs ; let mut doc_tokens = proc_macro2 :: TokenStream :: new ( ) ; for attr in attrs { //  println!("attr: {:#?}", quote! { #attr }.to_string()); let attr_span = attr . span ( ) ; let tokens = quote_spanned ! ( attr_span attr ) ; doc_tokens . extend ( tokens ) ; } //  Get the extern declaration without the doc attributes. //  let extern_decl = foreign_fn.decl; //  let extern_decl_span = &foreign_fn.span(); //  let extern_decl_tokens = quote_spanned!(extern_decl_span => #extern_decl); //  Transform the return type. let transformed_ret = transform_return_type ( & sig . output ) ; let TransformedReturnType { declare_result_tokens , get_result_tokens , return_result_tokens , .. } = transformed_ret ; //  Get the function args and transform each arg into 3 forms: //  (1) Wrap Declaration: How the arg type is exposed via the wrapper //  (2) Validation Stmt: To validate each arg if needed, e.g. check strings are null-terminated //  (3) Call Expr: Inside the wrapper, call the Mynewt API with type casting let args = & sig . inputs ; let transformed_args = transform_arg_list ( args ) ; //  For all args, collect the tokens for the Wrap, Validation and Call forms. let wrap_tokens = collect_wrap ( & transformed_args ) ; let validation_tokens = collect_validation ( & transformed_args ) ; let call_tokens = collect_call ( & transformed_args ) ; //  Compose the wrapper code as tokens. let expanded = quote ! { //  "----------Insert Doc: `#[doc]`----------"; doc_tokens //  "----------Insert Func Name: `pub fn task_init() -> ... {`----------"; pub fn fname_without_namespace_token ( //  "----------Insert Wrapped Decl----------"; wrap_tokens /* Like this:
                t: Out<os_task>,  //  Previously: *mut os_task
                name: &Strn,      //  Previously: *const ::cty::c_char
                func: os_task_func_t,
                arg: Ptr,         //  Previously: *mut ::cty::c_void
                prio: u8,
                sanity_itvl: os_time_t,
                stack_bottom: Out<[os_stack_t]>,  //  Previously: *mut os_stack_t
                stack_size: usize,                //  Previously: u16 */ ) declare_result_tokens { //  e.g. MynewtResult<()> or MynewtResult<* mut os_eventq> " " extern " " { foreign_item_tokens } " " validation_tokens unsafe { " " get_result_tokens fname_token ( //  "----------Insert Call Expr----------"; call_tokens /* Like this:
                        t,
                        name.bytestr.as_ptr() as *const ::cty::c_char,  //  Converted to pointer
                        func,
                        arg,
                        prio,
                        sanity_itvl,
                        stack_bottom.as_ptr() as *mut os_stack_t,  //  Converted to pointer
                        stack_size as u16  */ ) " " return_result_tokens } } } ; expanded }
Return the safe wrapper tokens for the extern function
Return the safe wrapper tokens for the extern function
foreign_fn
&ForeignItemFn
foreign_fn
&ForeignItemFn