Brian Silverman | 4e662aa | 2022-05-11 23:10:19 -0700 | [diff] [blame^] | 1 | // Copyright 2022 Google LLC |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
| 4 | // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
| 5 | // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your |
| 6 | // option. This file may not be copied, modified, or distributed |
| 7 | // except according to those terms. |
| 8 | |
| 9 | //! Code to create functions to alloc and free while unitialized. |
| 10 | |
| 11 | use syn::{parse_quote, punctuated::Punctuated, token::Comma, FnArg, ReturnType}; |
| 12 | |
| 13 | use crate::{ |
| 14 | conversion::{ |
| 15 | api::{Api, ApiName, CppVisibility, FuncToConvert, Provenance, References, TraitSynthesis}, |
| 16 | apivec::ApiVec, |
| 17 | }, |
| 18 | types::{make_ident, QualifiedName}, |
| 19 | }; |
| 20 | |
| 21 | use super::{ |
| 22 | fun::function_wrapper::{CppFunctionBody, CppFunctionKind}, |
| 23 | pod::PodPhase, |
| 24 | }; |
| 25 | |
| 26 | pub(crate) fn create_alloc_and_frees(apis: ApiVec<PodPhase>) -> ApiVec<PodPhase> { |
| 27 | apis.into_iter() |
| 28 | .flat_map(|api| -> Box<dyn Iterator<Item = Api<PodPhase>>> { |
| 29 | match &api { |
| 30 | Api::Struct { name, .. } => { |
| 31 | Box::new(create_alloc_and_free(name.name.clone()).chain(std::iter::once(api))) |
| 32 | } |
| 33 | Api::Subclass { name, .. } => { |
| 34 | Box::new(create_alloc_and_free(name.cpp()).chain(std::iter::once(api))) |
| 35 | } |
| 36 | _ => Box::new(std::iter::once(api)), |
| 37 | } |
| 38 | }) |
| 39 | .collect() |
| 40 | } |
| 41 | |
| 42 | fn create_alloc_and_free(ty_name: QualifiedName) -> impl Iterator<Item = Api<PodPhase>> { |
| 43 | let typ = ty_name.to_type_path(); |
| 44 | let free_inputs: Punctuated<FnArg, Comma> = parse_quote! { |
| 45 | arg0: *mut #typ |
| 46 | }; |
| 47 | let alloc_return: ReturnType = parse_quote! { |
| 48 | -> *mut #typ |
| 49 | }; |
| 50 | [ |
| 51 | ( |
| 52 | TraitSynthesis::AllocUninitialized(ty_name.clone()), |
| 53 | get_alloc_name(&ty_name), |
| 54 | Punctuated::new(), |
| 55 | alloc_return, |
| 56 | CppFunctionBody::AllocUninitialized(ty_name.clone()), |
| 57 | ), |
| 58 | ( |
| 59 | TraitSynthesis::FreeUninitialized(ty_name.clone()), |
| 60 | get_free_name(&ty_name), |
| 61 | free_inputs, |
| 62 | ReturnType::Default, |
| 63 | CppFunctionBody::FreeUninitialized(ty_name.clone()), |
| 64 | ), |
| 65 | ] |
| 66 | .into_iter() |
| 67 | .map( |
| 68 | move |(synthesis, name, inputs, output, cpp_function_body)| { |
| 69 | let ident = name.get_final_ident(); |
| 70 | let api_name = ApiName::new_from_qualified_name(name); |
| 71 | Api::Function { |
| 72 | name: api_name, |
| 73 | fun: Box::new(FuncToConvert { |
| 74 | ident, |
| 75 | doc_attrs: Vec::new(), |
| 76 | inputs, |
| 77 | output, |
| 78 | vis: parse_quote! { pub }, |
| 79 | virtualness: crate::conversion::api::Virtualness::None, |
| 80 | cpp_vis: CppVisibility::Public, |
| 81 | special_member: None, |
| 82 | unused_template_param: false, |
| 83 | references: References::default(), |
| 84 | original_name: None, |
| 85 | self_ty: None, |
| 86 | synthesized_this_type: None, |
| 87 | synthetic_cpp: Some((cpp_function_body, CppFunctionKind::Function)), |
| 88 | add_to_trait: Some(synthesis), |
| 89 | is_deleted: false, |
| 90 | provenance: Provenance::SynthesizedOther, |
| 91 | variadic: false, |
| 92 | }), |
| 93 | analysis: (), |
| 94 | } |
| 95 | }, |
| 96 | ) |
| 97 | } |
| 98 | |
| 99 | pub(crate) fn get_alloc_name(ty_name: &QualifiedName) -> QualifiedName { |
| 100 | get_name(ty_name, "alloc") |
| 101 | } |
| 102 | |
| 103 | pub(crate) fn get_free_name(ty_name: &QualifiedName) -> QualifiedName { |
| 104 | get_name(ty_name, "free") |
| 105 | } |
| 106 | |
| 107 | fn get_name(ty_name: &QualifiedName, label: &str) -> QualifiedName { |
| 108 | let name = format!("{}_{}", ty_name.get_final_item(), label); |
| 109 | let name_id = make_ident(name); |
| 110 | QualifiedName::new(ty_name.get_namespace(), name_id) |
| 111 | } |