blob: 3695de0997e43aa5639f4836fa65e2be04d87ecb [file] [log] [blame]
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Code to create functions to alloc and free while unitialized.
use syn::{parse_quote, punctuated::Punctuated, token::Comma, FnArg, ReturnType};
use crate::{
conversion::{
api::{Api, ApiName, CppVisibility, FuncToConvert, Provenance, References, TraitSynthesis},
apivec::ApiVec,
},
types::{make_ident, QualifiedName},
};
use super::{
fun::function_wrapper::{CppFunctionBody, CppFunctionKind},
pod::PodPhase,
};
pub(crate) fn create_alloc_and_frees(apis: ApiVec<PodPhase>) -> ApiVec<PodPhase> {
apis.into_iter()
.flat_map(|api| -> Box<dyn Iterator<Item = Api<PodPhase>>> {
match &api {
Api::Struct { name, .. } => {
Box::new(create_alloc_and_free(name.name.clone()).chain(std::iter::once(api)))
}
Api::Subclass { name, .. } => {
Box::new(create_alloc_and_free(name.cpp()).chain(std::iter::once(api)))
}
_ => Box::new(std::iter::once(api)),
}
})
.collect()
}
fn create_alloc_and_free(ty_name: QualifiedName) -> impl Iterator<Item = Api<PodPhase>> {
let typ = ty_name.to_type_path();
let free_inputs: Punctuated<FnArg, Comma> = parse_quote! {
arg0: *mut #typ
};
let alloc_return: ReturnType = parse_quote! {
-> *mut #typ
};
[
(
TraitSynthesis::AllocUninitialized(ty_name.clone()),
get_alloc_name(&ty_name),
Punctuated::new(),
alloc_return,
CppFunctionBody::AllocUninitialized(ty_name.clone()),
),
(
TraitSynthesis::FreeUninitialized(ty_name.clone()),
get_free_name(&ty_name),
free_inputs,
ReturnType::Default,
CppFunctionBody::FreeUninitialized(ty_name.clone()),
),
]
.into_iter()
.map(
move |(synthesis, name, inputs, output, cpp_function_body)| {
let ident = name.get_final_ident();
let api_name = ApiName::new_from_qualified_name(name);
Api::Function {
name: api_name,
fun: Box::new(FuncToConvert {
ident,
doc_attrs: Vec::new(),
inputs,
output,
vis: parse_quote! { pub },
virtualness: crate::conversion::api::Virtualness::None,
cpp_vis: CppVisibility::Public,
special_member: None,
unused_template_param: false,
references: References::default(),
original_name: None,
self_ty: None,
synthesized_this_type: None,
synthetic_cpp: Some((cpp_function_body, CppFunctionKind::Function)),
add_to_trait: Some(synthesis),
is_deleted: false,
provenance: Provenance::SynthesizedOther,
variadic: false,
}),
analysis: (),
}
},
)
}
pub(crate) fn get_alloc_name(ty_name: &QualifiedName) -> QualifiedName {
get_name(ty_name, "alloc")
}
pub(crate) fn get_free_name(ty_name: &QualifiedName) -> QualifiedName {
get_name(ty_name, "free")
}
fn get_name(ty_name: &QualifiedName, label: &str) -> QualifiedName {
let name = format!("{}_{}", ty_name.get_final_item(), label);
let name_id = make_ident(name);
QualifiedName::new(ty_name.get_namespace(), name_id)
}