feat(src): Add real and working support for results
Every `Result` is now -- on demand -- instantiated (i.e. the generic types are replaced with the concretely specified ones). And can thus simply be exported to c.
This commit is contained in:
parent
4b7cd3a0b7
commit
a669f399a8
|
@ -25,7 +25,7 @@ use crate::parser::command_spec::{Attribute, DocIdentifier, Enumeration};
|
||||||
impl Enumeration {
|
impl Enumeration {
|
||||||
pub fn to_auxiliary_c(&self) -> String {
|
pub fn to_auxiliary_c(&self) -> String {
|
||||||
let doc_comments: String = Attribute::to_auxiliary_c_merged(&self.attributes);
|
let doc_comments: String = Attribute::to_auxiliary_c_merged(&self.attributes);
|
||||||
let ident = &self.identifier.to_auxiliary_c();
|
let ident = &self.identifier.to_auxiliary_c(&[]);
|
||||||
let states = self
|
let states = self
|
||||||
.states
|
.states
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -24,15 +24,12 @@ use convert_case::{Case, Casing};
|
||||||
use proc_macro2::TokenStream as TokenStream2;
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
|
||||||
use crate::parser::command_spec::{Identifier, Variant};
|
use crate::parser::command_spec::{Identifier, Type, Variant};
|
||||||
|
|
||||||
mod doc_identifier;
|
mod doc_identifier;
|
||||||
|
|
||||||
//
|
|
||||||
// pub use doc_identifier::*;
|
|
||||||
|
|
||||||
impl Identifier {
|
impl Identifier {
|
||||||
pub fn to_auxiliary_c(&self) -> TokenStream2 {
|
pub fn to_auxiliary_c(&self, generic_args: &[Type]) -> TokenStream2 {
|
||||||
let ident = self.to_rust_pascalized();
|
let ident = self.to_rust_pascalized();
|
||||||
match &self.variant {
|
match &self.variant {
|
||||||
Variant::Structure { .. } => {
|
Variant::Structure { .. } => {
|
||||||
|
@ -46,10 +43,17 @@ impl Identifier {
|
||||||
enum #ident
|
enum #ident
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Variant::Result { .. } => {
|
||||||
|
let ident = Type::mangle_result_name(generic_args);
|
||||||
|
quote! {
|
||||||
|
struct #ident
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Variant::Primitive => match self.name.to_case(Case::Snake).as_str() {
|
Variant::Primitive => match self.name.to_case(Case::Snake).as_str() {
|
||||||
"string" => {
|
"string" => {
|
||||||
quote! {
|
quote! {
|
||||||
const char*
|
const char *
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Unsigned
|
// Unsigned
|
||||||
|
@ -65,14 +69,15 @@ impl Identifier {
|
||||||
// Float
|
// Float
|
||||||
"f_32" => quote! { float },
|
"f_32" => quote! { float },
|
||||||
"f_64" => quote! { double },
|
"f_64" => quote! { double },
|
||||||
// Other (not yet imlemented)
|
|
||||||
|
// Others (not yet imlemented)
|
||||||
// ("Option", 1),
|
// ("Option", 1),
|
||||||
// ("Vec", 1),
|
// ("Vec", 1),
|
||||||
// ("Result", 2),
|
|
||||||
other => {
|
other => {
|
||||||
todo!("'{}' is not yet supported", other)
|
todo!("'{}' is not yet supported", other)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
other => {
|
other => {
|
||||||
unimplemented!("{:#?}", other)
|
unimplemented!("{:#?}", other)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ use proc_macro2::TokenStream as TokenStream2;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
use crate::parser::command_spec::{
|
use crate::parser::command_spec::{
|
||||||
Attribute, Enumeration, Function, Identifier, Namespace, Structure,
|
Attribute, Enumeration, Function, Identifier, Namespace, Structure, Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Namespace {
|
impl Namespace {
|
||||||
|
@ -44,6 +44,12 @@ impl Namespace {
|
||||||
.map(Enumeration::to_auxiliary_c)
|
.map(Enumeration::to_auxiliary_c)
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join("\n");
|
.join("\n");
|
||||||
|
let results: String = self
|
||||||
|
.select_types_pred(|(ident, _generics)| ident.name.as_str() == "Result")
|
||||||
|
.iter()
|
||||||
|
.map(|(_, generics)| Type::to_auxilary_c_result(generics).to_string())
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join("\n");
|
||||||
let functions: String = self
|
let functions: String = self
|
||||||
.functions
|
.functions
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -56,7 +62,7 @@ impl Namespace {
|
||||||
.map(|nasp| nasp.to_auxiliary_c(&nasps))
|
.map(|nasp| nasp.to_auxiliary_c(&nasps))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
format! {"{}\n{}\n{}\n{}", enumerations, structures, functions, namespaces}
|
format! {"{}\n{}\n{}\n{}\n{}", enumerations, structures, results, functions, namespaces}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_auxiliary_c_full_struct_init(&self, namespaces: &Vec<&Identifier>) -> TokenStream2 {
|
pub fn to_auxiliary_c_full_struct_init(&self, namespaces: &Vec<&Identifier>) -> TokenStream2 {
|
||||||
|
|
|
@ -25,7 +25,7 @@ use crate::parser::command_spec::{Attribute, DocNamedType, Structure};
|
||||||
impl Structure {
|
impl Structure {
|
||||||
pub fn to_auxiliary_c(&self) -> String {
|
pub fn to_auxiliary_c(&self) -> String {
|
||||||
let doc_comments: String = Attribute::to_auxiliary_c_merged(&self.attributes);
|
let doc_comments: String = Attribute::to_auxiliary_c_merged(&self.attributes);
|
||||||
let ident = self.identifier.to_auxiliary_c();
|
let ident = self.identifier.to_auxiliary_c(&[]);
|
||||||
let contents = self
|
let contents = self
|
||||||
.contents
|
.contents
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -36,9 +36,9 @@ impl Type {
|
||||||
match self {
|
match self {
|
||||||
Type::Typical {
|
Type::Typical {
|
||||||
identifier,
|
identifier,
|
||||||
generic_args: _,
|
generic_args,
|
||||||
} => {
|
} => {
|
||||||
let ident = identifier.to_auxiliary_c();
|
let ident = identifier.to_auxiliary_c(generic_args);
|
||||||
let output = if is_output {
|
let output = if is_output {
|
||||||
quote! {
|
quote! {
|
||||||
*
|
*
|
||||||
|
@ -78,4 +78,21 @@ impl Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_auxilary_c_result(generic_args: &[Type]) -> TokenStream2 {
|
||||||
|
let ident = Type::mangle_result_name(&generic_args);
|
||||||
|
|
||||||
|
let generic_one = generic_args[0].to_auxiliary_c(false, None);
|
||||||
|
let generic_two = generic_args[1].to_auxiliary_c(false, None);
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
struct #ident {
|
||||||
|
enum ResultTag tag;
|
||||||
|
union {
|
||||||
|
#generic_one ok;
|
||||||
|
#generic_two err;
|
||||||
|
} value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,12 +20,14 @@
|
||||||
* If not, see <https://www.gnu.org/licenses/>.
|
* If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use std::iter;
|
||||||
|
|
||||||
use proc_macro2::TokenStream as TokenStream2;
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
macros::config::trixy::TrixyConfig,
|
macros::config::trixy::TrixyConfig,
|
||||||
parser::command_spec::{Enumeration, Identifier, Namespace, Structure},
|
parser::command_spec::{Enumeration, Identifier, Namespace, Structure, Type},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Namespace {
|
impl Namespace {
|
||||||
|
@ -48,11 +50,20 @@ impl Namespace {
|
||||||
let enumerations: TokenStream2 = self.enumerations.iter().map(Enumeration::to_c).collect();
|
let enumerations: TokenStream2 = self.enumerations.iter().map(Enumeration::to_c).collect();
|
||||||
|
|
||||||
let callback_function = format_ident!("{}", config.callback_function);
|
let callback_function = format_ident!("{}", config.callback_function);
|
||||||
|
|
||||||
|
let all_results_types: TokenStream2 = self
|
||||||
|
.select_types_pred(|(identifier, _generic_args)| identifier.name.as_str() == "Result")
|
||||||
|
.iter()
|
||||||
|
.map(|(_, generics)| Type::to_c_result(&generics))
|
||||||
|
.collect();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
pub mod #ident {
|
pub mod #ident {
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use crate :: #callback_function;
|
use crate :: #callback_function;
|
||||||
|
|
||||||
|
#all_results_types
|
||||||
|
|
||||||
#enumerations
|
#enumerations
|
||||||
#structures
|
#structures
|
||||||
#additional_functions
|
#additional_functions
|
||||||
|
@ -60,4 +71,81 @@ impl Namespace {
|
||||||
#functions
|
#functions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get all the types used in this namespaces that conform to the predicate.
|
||||||
|
/// The predicate get's the identifier of a type and the generic arguments passed.
|
||||||
|
pub fn select_types_pred(
|
||||||
|
&self,
|
||||||
|
pred: fn(&(Identifier, Vec<Type>)) -> bool,
|
||||||
|
) -> Vec<(Identifier, Vec<Type>)> {
|
||||||
|
fn filter_type(ty: &Type) -> Vec<(Identifier, Vec<Type>)> {
|
||||||
|
match ty {
|
||||||
|
Type::Typical {
|
||||||
|
identifier,
|
||||||
|
generic_args,
|
||||||
|
} => {
|
||||||
|
let mut output = vec![];
|
||||||
|
output.extend(generic_args.iter().map(|ga| filter_type(ga)).flatten());
|
||||||
|
output.push((identifier.to_owned(), generic_args.to_owned()));
|
||||||
|
// Stop recursion and return
|
||||||
|
output
|
||||||
|
}
|
||||||
|
Type::Function { inputs, output } => {
|
||||||
|
let mut full_output = vec![];
|
||||||
|
full_output.extend(
|
||||||
|
inputs
|
||||||
|
.iter()
|
||||||
|
.map(|na| &na.r#type)
|
||||||
|
.map(|ty| filter_type(&ty))
|
||||||
|
.flatten(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(out) = output {
|
||||||
|
full_output.extend(filter_type(out))
|
||||||
|
}
|
||||||
|
|
||||||
|
full_output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let all_types = self.collect_types();
|
||||||
|
|
||||||
|
let all_result_types: Vec<_> = all_types
|
||||||
|
.iter()
|
||||||
|
.map(|r#type| filter_type(r#type))
|
||||||
|
.flatten()
|
||||||
|
.filter(pred)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
all_result_types
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Collect a vector of all types used in this namespace
|
||||||
|
pub fn collect_types(&self) -> Vec<Type> {
|
||||||
|
let structures_types = self
|
||||||
|
.structures
|
||||||
|
.iter()
|
||||||
|
.map(|st| st.contents.iter().map(|dc| dc.r#type.clone()))
|
||||||
|
.flatten();
|
||||||
|
|
||||||
|
self.functions
|
||||||
|
.iter()
|
||||||
|
.map(|r#fn| {
|
||||||
|
r#fn.inputs
|
||||||
|
.iter()
|
||||||
|
.map(|nt| Some(nt.r#type.clone()))
|
||||||
|
.chain({
|
||||||
|
if let Some(output) = &r#fn.output {
|
||||||
|
iter::once(Some(output.clone()))
|
||||||
|
} else {
|
||||||
|
iter::once(None)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter_map(|x| x)
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
.chain(structures_types)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use proc_macro2::TokenStream as TokenStream2;
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
use quote::quote;
|
use quote::{format_ident, quote};
|
||||||
|
use syn::Ident;
|
||||||
|
|
||||||
use crate::parser::command_spec::{Identifier, NamedType, Type};
|
use crate::parser::command_spec::{Identifier, NamedType, Type};
|
||||||
|
|
||||||
|
@ -39,10 +40,84 @@ impl Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn mangle_result_name(generic_args: &[Type]) -> Ident {
|
||||||
|
assert_eq!(generic_args.len(), 2);
|
||||||
|
|
||||||
|
format_ident!(
|
||||||
|
"result_{}_{}",
|
||||||
|
generic_args[0].to_string(),
|
||||||
|
generic_args[1].to_string()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn to_c_function(inputs: &[NamedType], output: &Option<Box<Type>>) -> TokenStream2 {
|
pub fn to_c_function(inputs: &[NamedType], output: &Option<Box<Type>>) -> TokenStream2 {
|
||||||
Type::to_rust_function(&inputs, &output)
|
Type::to_rust_function(&inputs, &output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_c_result(generic_args: &[Type]) -> TokenStream2 {
|
||||||
|
assert_eq!(generic_args.len(), 2);
|
||||||
|
let first_generic = generic_args[0].to_c();
|
||||||
|
let second_generic = generic_args[1].to_c();
|
||||||
|
|
||||||
|
let ident = Type::mangle_result_name(&generic_args);
|
||||||
|
let value_ident = format_ident!("{}_value", ident);
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub union #value_ident {
|
||||||
|
ok: std::mem::ManuallyDrop<#first_generic>,
|
||||||
|
err: std::mem::ManuallyDrop<#second_generic>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct #ident {
|
||||||
|
tag: trixy::types::ResultTag,
|
||||||
|
value: #value_ident,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for #ident {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self.tag {
|
||||||
|
trixy::types::ResultTag::Ok => write!(f, "{:?}", unsafe { &self.value.ok }),
|
||||||
|
trixy::types::ResultTag::Err => write!(f, "{:?}", unsafe { &self.value.err }),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl trixy::types::traits::convert_trait::Convertible
|
||||||
|
for crate::OurResult<#first_generic, #second_generic>
|
||||||
|
{
|
||||||
|
type Ptr = #ident;
|
||||||
|
|
||||||
|
fn into_ptr(self) -> Self::Ptr {
|
||||||
|
if self.value.is_ok() {
|
||||||
|
Self::Ptr {
|
||||||
|
tag: trixy::types::ResultTag::Ok,
|
||||||
|
value: #value_ident {
|
||||||
|
ok: std::mem::ManuallyDrop::new(self.value.expect("Is ok")),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Self::Ptr {
|
||||||
|
tag: trixy::types::ResultTag::Err,
|
||||||
|
value: #value_ident {
|
||||||
|
err: std::mem::ManuallyDrop::new(self.value.expect_err("Is err")),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_ptr(_ptr: Self::Ptr) -> Result<Self, trixy::types::error::TypeConversionError> {
|
||||||
|
unreachable!("This should probably not be called?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn to_c_typical(identifier: &Identifier, generic_args: &Vec<Type>) -> TokenStream2 {
|
fn to_c_typical(identifier: &Identifier, generic_args: &Vec<Type>) -> TokenStream2 {
|
||||||
let trixy_build_in_types: Vec<&str> = crate::types::BASE_TYPES
|
let trixy_build_in_types: Vec<&str> = crate::types::BASE_TYPES
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -75,7 +150,7 @@ impl Type {
|
||||||
#nasp_path #ident
|
#nasp_path #ident
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debug_assert_eq!(trixy_build_in_types.len(), 1);
|
assert_eq!(trixy_build_in_types.len(), 1);
|
||||||
|
|
||||||
let type_name = trixy_build_in_types
|
let type_name = trixy_build_in_types
|
||||||
.first()
|
.first()
|
||||||
|
@ -83,11 +158,28 @@ impl Type {
|
||||||
|
|
||||||
match *type_name {
|
match *type_name {
|
||||||
"Result" => {
|
"Result" => {
|
||||||
let ident_ok = &generic_args.first().expect("This is a result").to_c();
|
assert_eq!(generic_args.len(), 2);
|
||||||
let ident_err = &generic_args.last().expect("This is a result").to_c();
|
|
||||||
|
let namespaces_path = &identifier.variant.to_c_path();
|
||||||
|
let nasp_path = if namespaces_path.is_empty() {
|
||||||
|
quote! {
|
||||||
|
crate ::
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let path = namespaces_path;
|
||||||
|
quote! {
|
||||||
|
#path ::
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let ident = format_ident!(
|
||||||
|
"result_{}_{}",
|
||||||
|
generic_args[0].to_string(),
|
||||||
|
generic_args[1].to_string()
|
||||||
|
);
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
// eg: <Result<TrainedDog, TrainingMistake> as Convertible>::Ptr,
|
#nasp_path #ident
|
||||||
<Result<#ident_ok, #ident_err> as Convertible>::Ptr
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"Option" => {
|
"Option" => {
|
||||||
|
|
|
@ -45,13 +45,12 @@ impl Variant {
|
||||||
|
|
||||||
let main_namespace;
|
let main_namespace;
|
||||||
match self {
|
match self {
|
||||||
Variant::Structure { namespace } => {
|
Variant::Structure { namespace }
|
||||||
|
| Variant::Enumeration { namespace }
|
||||||
|
| Variant::Result { namespace } => {
|
||||||
main_namespace = mangle_namespace_name(namespace);
|
main_namespace = mangle_namespace_name(namespace);
|
||||||
}
|
}
|
||||||
Variant::Enumeration { namespace } => {
|
other => unreachable!("This should never be called on '{:#?}'", other),
|
||||||
main_namespace = mangle_namespace_name(namespace);
|
|
||||||
}
|
|
||||||
_ => unreachable!("This should never be called"),
|
|
||||||
}
|
}
|
||||||
Namespace::to_rust_path_owned(&main_namespace[..])
|
Namespace::to_rust_path_owned(&main_namespace[..])
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,10 +36,23 @@ pub fn generate(trixy: &CommandSpec, config: &TrixyConfig) -> String {
|
||||||
format!(
|
format!(
|
||||||
"\
|
"\
|
||||||
/* C API */\n\
|
/* C API */\n\
|
||||||
|
// Workaround rust rules when implementing a foreign trait on a foreign type
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct OurResult<T, E> {{
|
||||||
|
value: Result<T, E>,
|
||||||
|
}}
|
||||||
|
|
||||||
|
impl<T, E> From<Result<T, E>> for OurResult<T, E> {{
|
||||||
|
fn from(value: Result<T, E>) -> Self {{
|
||||||
|
Self {{ value }}
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
/* The real C API */\n\
|
||||||
{}",
|
{}",
|
||||||
rust_code
|
rust_code
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function generates the main c API provided by Trixy.
|
/// This function generates the main c API provided by Trixy.
|
||||||
/// This works for example like this:
|
/// This works for example like this:
|
||||||
/// Turning this:
|
/// Turning this:
|
||||||
|
|
|
@ -36,9 +36,14 @@ pub enum Variant {
|
||||||
Enumeration {
|
Enumeration {
|
||||||
namespace: Vec<Identifier>,
|
namespace: Vec<Identifier>,
|
||||||
},
|
},
|
||||||
|
Result {
|
||||||
|
namespace: Vec<Identifier>,
|
||||||
|
},
|
||||||
|
|
||||||
Namespace,
|
Namespace,
|
||||||
/// The first (implicit) namespace, containing everything
|
/// The first (implicit) namespace, containing everything
|
||||||
RootNamespace,
|
RootNamespace,
|
||||||
|
|
||||||
Function,
|
Function,
|
||||||
Primitive,
|
Primitive,
|
||||||
NamedType,
|
NamedType,
|
||||||
|
@ -59,7 +64,7 @@ impl Variant {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
pub struct Namespace {
|
pub struct Namespace {
|
||||||
pub name: Identifier,
|
pub name: Identifier,
|
||||||
|
|
||||||
|
@ -89,21 +94,21 @@ impl From<Namespace> for CommandSpec {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
pub struct Structure {
|
pub struct Structure {
|
||||||
pub identifier: Identifier,
|
pub identifier: Identifier,
|
||||||
pub contents: Vec<DocNamedType>,
|
pub contents: Vec<DocNamedType>,
|
||||||
pub attributes: Vec<Attribute>,
|
pub attributes: Vec<Attribute>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
pub struct Enumeration {
|
pub struct Enumeration {
|
||||||
pub identifier: Identifier,
|
pub identifier: Identifier,
|
||||||
pub states: Vec<DocIdentifier>,
|
pub states: Vec<DocIdentifier>,
|
||||||
pub attributes: Vec<Attribute>,
|
pub attributes: Vec<Attribute>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
pub identifier: Identifier,
|
pub identifier: Identifier,
|
||||||
pub inputs: Vec<NamedType>,
|
pub inputs: Vec<NamedType>,
|
||||||
|
@ -206,7 +211,7 @@ pub struct NamedType {
|
||||||
pub r#type: Type,
|
pub r#type: Type,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
pub struct DocNamedType {
|
pub struct DocNamedType {
|
||||||
pub name: Identifier,
|
pub name: Identifier,
|
||||||
pub r#type: Type,
|
pub r#type: Type,
|
||||||
|
|
|
@ -159,7 +159,7 @@ impl Parser {
|
||||||
|
|
||||||
let mut functions = vec![];
|
let mut functions = vec![];
|
||||||
for function in namespace.functions {
|
for function in namespace.functions {
|
||||||
functions.push(self.process_function(function)?);
|
functions.push(self.process_function(function, &previous_namespaces)?);
|
||||||
}
|
}
|
||||||
let mut namespaces = vec![];
|
let mut namespaces = vec![];
|
||||||
for namespace in namespace.namespaces {
|
for namespace in namespace.namespaces {
|
||||||
|
@ -187,14 +187,15 @@ impl Parser {
|
||||||
fn process_function(
|
fn process_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut function: UncheckedFunction,
|
mut function: UncheckedFunction,
|
||||||
|
parent_namespaces: &Vec<Identifier>,
|
||||||
) -> Result<Function, ParsingError> {
|
) -> Result<Function, ParsingError> {
|
||||||
let identifier = mem::take(&mut function.identifier.kind).to_identifier(Variant::Function);
|
let identifier = mem::take(&mut function.identifier.kind).to_identifier(Variant::Function);
|
||||||
let mut inputs = vec![];
|
let mut inputs = vec![];
|
||||||
for input in function.inputs {
|
for input in function.inputs {
|
||||||
inputs.push(self.process_named_type(input)?);
|
inputs.push(self.process_named_type(input, parent_namespaces)?);
|
||||||
}
|
}
|
||||||
let output = if let Some(r#type) = function.output {
|
let output = if let Some(r#type) = function.output {
|
||||||
Some(self.process_type(r#type)?)
|
Some(self.process_type(r#type, parent_namespaces)?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -269,7 +270,7 @@ impl Parser {
|
||||||
});
|
});
|
||||||
let mut contents = vec![];
|
let mut contents = vec![];
|
||||||
for named_type in structure.contents {
|
for named_type in structure.contents {
|
||||||
contents.push(self.process_doc_named_type(named_type)?);
|
contents.push(self.process_doc_named_type(named_type, parent_namespaces)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Structure {
|
Ok(Structure {
|
||||||
|
@ -282,19 +283,21 @@ impl Parser {
|
||||||
fn process_named_type(
|
fn process_named_type(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut named_type: UncheckedNamedType,
|
mut named_type: UncheckedNamedType,
|
||||||
|
parent_namespaces: &Vec<Identifier>,
|
||||||
) -> Result<NamedType, ParsingError> {
|
) -> Result<NamedType, ParsingError> {
|
||||||
let name: Identifier =
|
let name: Identifier =
|
||||||
mem::take(&mut named_type.name.kind).to_identifier(Variant::NamedType);
|
mem::take(&mut named_type.name.kind).to_identifier(Variant::NamedType);
|
||||||
let r#type: Type = self.process_type(named_type.r#type)?;
|
let r#type: Type = self.process_type(named_type.r#type, parent_namespaces)?;
|
||||||
Ok(NamedType { name, r#type })
|
Ok(NamedType { name, r#type })
|
||||||
}
|
}
|
||||||
fn process_doc_named_type(
|
fn process_doc_named_type(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut doc_named_type: UncheckedDocNamedType,
|
mut doc_named_type: UncheckedDocNamedType,
|
||||||
|
parent_namespaces: &Vec<Identifier>,
|
||||||
) -> Result<DocNamedType, ParsingError> {
|
) -> Result<DocNamedType, ParsingError> {
|
||||||
let name: Identifier =
|
let name: Identifier =
|
||||||
mem::take(&mut doc_named_type.name.kind).to_identifier(Variant::DocNamedType);
|
mem::take(&mut doc_named_type.name.kind).to_identifier(Variant::DocNamedType);
|
||||||
let r#type: Type = self.process_type(doc_named_type.r#type)?;
|
let r#type: Type = self.process_type(doc_named_type.r#type, parent_namespaces)?;
|
||||||
Ok(DocNamedType {
|
Ok(DocNamedType {
|
||||||
name,
|
name,
|
||||||
r#type,
|
r#type,
|
||||||
|
@ -302,14 +305,18 @@ impl Parser {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_type(&mut self, r#type: UncheckedType) -> Result<Type, ParsingError> {
|
fn process_type(
|
||||||
|
&mut self,
|
||||||
|
r#type: UncheckedType,
|
||||||
|
parent_namespaces: &Vec<Identifier>,
|
||||||
|
) -> Result<Type, ParsingError> {
|
||||||
match r#type {
|
match r#type {
|
||||||
UncheckedType::Typical {
|
UncheckedType::Typical {
|
||||||
identifier,
|
identifier,
|
||||||
generic_args,
|
generic_args,
|
||||||
} => self.process_typical_type(identifier, generic_args),
|
} => self.process_typical_type(identifier, generic_args, parent_namespaces),
|
||||||
UncheckedType::Function { inputs, output } => {
|
UncheckedType::Function { inputs, output } => {
|
||||||
self.process_function_type(inputs, output)
|
self.process_function_type(inputs, output, parent_namespaces)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -318,6 +325,7 @@ impl Parser {
|
||||||
&mut self,
|
&mut self,
|
||||||
mut type_identifier: Token,
|
mut type_identifier: Token,
|
||||||
generic_args: Vec<UncheckedType>,
|
generic_args: Vec<UncheckedType>,
|
||||||
|
parent_namespaces: &Vec<Identifier>,
|
||||||
) -> Result<Type, ParsingError> {
|
) -> Result<Type, ParsingError> {
|
||||||
fn match_to_vector_struct(matches: Vec<&UncheckedStructure>) -> Vec<Identifier> {
|
fn match_to_vector_struct(matches: Vec<&UncheckedStructure>) -> Vec<Identifier> {
|
||||||
matches
|
matches
|
||||||
|
@ -401,7 +409,13 @@ impl Parser {
|
||||||
.iter()
|
.iter()
|
||||||
.any(|(ident, _)| ident == &identifier.name)
|
.any(|(ident, _)| ident == &identifier.name)
|
||||||
{
|
{
|
||||||
variant = Variant::Primitive;
|
if &identifier.name == "Result" {
|
||||||
|
variant = Variant::Result {
|
||||||
|
namespace: parent_namespaces.clone(),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
variant = Variant::Primitive;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(ParsingError::TypeNotDeclared {
|
return Err(ParsingError::TypeNotDeclared {
|
||||||
r#type: identifier,
|
r#type: identifier,
|
||||||
|
@ -461,7 +475,7 @@ impl Parser {
|
||||||
|
|
||||||
let mut new_generic_args: Vec<checked::Type> = vec![];
|
let mut new_generic_args: Vec<checked::Type> = vec![];
|
||||||
for generic_arg in generic_args {
|
for generic_arg in generic_args {
|
||||||
new_generic_args.push(self.process_type(generic_arg)?);
|
new_generic_args.push(self.process_type(generic_arg, parent_namespaces)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Type::Typical {
|
Ok(Type::Typical {
|
||||||
|
@ -473,15 +487,16 @@ impl Parser {
|
||||||
&mut self,
|
&mut self,
|
||||||
inputs: Vec<UncheckedNamedType>,
|
inputs: Vec<UncheckedNamedType>,
|
||||||
output: Option<Box<UncheckedType>>,
|
output: Option<Box<UncheckedType>>,
|
||||||
|
parent_namespaces: &Vec<Identifier>,
|
||||||
) -> Result<Type, ParsingError> {
|
) -> Result<Type, ParsingError> {
|
||||||
let inputs = inputs
|
let inputs = inputs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|input| self.process_named_type(input))
|
.map(|input| self.process_named_type(input, parent_namespaces))
|
||||||
.collect::<Result<Vec<NamedType>, ParsingError>>()?;
|
.collect::<Result<Vec<NamedType>, ParsingError>>()?;
|
||||||
|
|
||||||
let mut new_output = None;
|
let mut new_output = None;
|
||||||
if let Some(output) = output {
|
if let Some(output) = output {
|
||||||
new_output = Some(Box::new(self.process_type(*output)?));
|
new_output = Some(Box::new(self.process_type(*output, parent_namespaces)?));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Type::Function {
|
Ok(Type::Function {
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 - 2024:
|
||||||
|
* The Trinitrix Project <soispha@vhack.eu, antifallobst@systemausfall.org>
|
||||||
|
* SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* This file is part of the Trixy crate for Trinitrix.
|
||||||
|
*
|
||||||
|
* Trixy is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the Lesser GNU General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* and the Lesser GNU General Public License along with this program.
|
||||||
|
* If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TRIXY_RESULT_H
|
||||||
|
#define TRIXY_RESULT_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A rust-like result type
|
||||||
|
*
|
||||||
|
* @detail
|
||||||
|
* This macro effectively generates a type name from the two generic
|
||||||
|
* parameters. The generated type name is always globally unique.
|
||||||
|
*/
|
||||||
|
#define Result(ok, err) struct result_##ok##_##err
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The possibly states of a Result.
|
||||||
|
*/
|
||||||
|
enum ResultTag
|
||||||
|
{
|
||||||
|
OK,
|
||||||
|
ERR,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TRIXY_RESULT_H
|
|
@ -40,7 +40,7 @@ macro_rules! header {
|
||||||
// NOTE: Every type here must have the [`Convertible`] implemented on it (@soispha)
|
// NOTE: Every type here must have the [`Convertible`] implemented on it (@soispha)
|
||||||
// And be added to the `convert/c/auxiliary/idendentifier/mod.rs` file
|
// And be added to the `convert/c/auxiliary/idendentifier/mod.rs` file
|
||||||
// And add it to the types list (`./types_list.rs`)
|
// And add it to the types list (`./types_list.rs`)
|
||||||
pub const BASE_TYPES: [(&'static std::primitive::str, usize); 11] = [
|
pub const BASE_TYPES: [(&'static std::primitive::str, usize); 12] = [
|
||||||
// Unsigned
|
// Unsigned
|
||||||
("u8", 0),
|
("u8", 0),
|
||||||
("u16", 0),
|
("u16", 0),
|
||||||
|
@ -56,15 +56,19 @@ pub const BASE_TYPES: [(&'static std::primitive::str, usize); 11] = [
|
||||||
("f64", 0),
|
("f64", 0),
|
||||||
// Other
|
// Other
|
||||||
("String", 0),
|
("String", 0),
|
||||||
|
("Result", 2),
|
||||||
// FIXME(@soispha): These work, but the generated code is not really ideal <2024-03-26>
|
// FIXME(@soispha): These work, but the generated code is not really ideal <2024-03-26>
|
||||||
// ("Option", 1),
|
// ("Option", 1),
|
||||||
// ("Vec", 1),
|
// ("Vec", 1),
|
||||||
// ("Result", 2),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/// The first value is the file name, the second it's contents
|
/// The first value is the file name, the second it's contents
|
||||||
pub const C_TYPE_HEADER: [(&'static std::primitive::str, &'static std::primitive::str); 3] =
|
pub const C_TYPE_HEADER: [(&'static std::primitive::str, &'static std::primitive::str); 4] = [
|
||||||
[header!("errno.h"), header!("string.h"), header!("vec.h")];
|
header!("errno.h"),
|
||||||
|
header!("string.h"),
|
||||||
|
header!("vec.h"),
|
||||||
|
header!("result.h"),
|
||||||
|
];
|
||||||
|
|
||||||
pub fn header_names() -> std::string::String {
|
pub fn header_names() -> std::string::String {
|
||||||
C_TYPE_HEADER
|
C_TYPE_HEADER
|
||||||
|
|
|
@ -129,121 +129,93 @@ pub extern "C" fn string_free(ptr: *const c_char) {
|
||||||
CString::drop_ptr(ptr);
|
CString::drop_ptr(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Convertible> Convertible for Option<T> {
|
// impl<T: Convertible> Convertible for Option<T> {
|
||||||
type Ptr = *const <T as Convertible>::Ptr;
|
// type Ptr = *const <T as Convertible>::Ptr;
|
||||||
|
//
|
||||||
|
// fn into_ptr(self) -> Self::Ptr {
|
||||||
|
// if let Some(inner) = self {
|
||||||
|
// &inner.into_ptr()
|
||||||
|
// } else {
|
||||||
|
// ptr::null()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fn from_ptr(_: Self::Ptr) -> Result<Self, error::TypeConversionError> {
|
||||||
|
// warn!(
|
||||||
|
// "
|
||||||
|
// This should never be called, as this option type resolves
|
||||||
|
// to a null pointer or to a pointer to the real value
|
||||||
|
// (e. g. a `crate::Vec<T>`)
|
||||||
|
// "
|
||||||
|
// );
|
||||||
|
// Ok(Option::default())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
fn into_ptr(self) -> Self::Ptr {
|
// impl<T: Convertible> Convertible for Vec<T> {
|
||||||
if let Some(inner) = self {
|
// type Ptr = crate::types::Vec<<T as Convertible>::Ptr>;
|
||||||
&inner.into_ptr()
|
//
|
||||||
} else {
|
// fn into_ptr(self) -> Self::Ptr {
|
||||||
ptr::null()
|
// let data_vec: Vec<_> = self.into_iter().map(|val| val.into_ptr()).collect();
|
||||||
}
|
// let data_vec = ManuallyDrop::new(data_vec);
|
||||||
}
|
// Self::Ptr {
|
||||||
|
// data: data_vec.as_ptr(),
|
||||||
fn from_ptr(_: Self::Ptr) -> Result<Self, error::TypeConversionError> {
|
// length: data_vec.len(),
|
||||||
warn!(
|
// capacity: data_vec.capacity(),
|
||||||
"
|
// }
|
||||||
This should never be called, as this option type resolves
|
// }
|
||||||
to a null pointer or to a pointer to the real value
|
//
|
||||||
(e. g. a `crate::Vec<T>`)
|
// fn from_ptr(ptr: Self::Ptr) -> Result<Self, error::TypeConversionError> {
|
||||||
"
|
// if ptr.data.is_null() {
|
||||||
);
|
// return Err(TypeConversionError::NullPointer);
|
||||||
Ok(Option::default())
|
// }
|
||||||
}
|
// // TODO(@soispha): Add this, when this feature is stable <2024-02-17>
|
||||||
}
|
// // if !ptr.data.is_aligned() {
|
||||||
|
// // return Err(TypeConversionError::NotAligned);
|
||||||
impl<T: Convertible, E: Error> Convertible for Result<T, E> {
|
// // }
|
||||||
type Ptr = *const <T as Convertible>::Ptr;
|
// let base_vec = unsafe {
|
||||||
|
// // SAFETY:
|
||||||
fn into_ptr(self) -> Self::Ptr {
|
// // We simply hope that c treated our vector as read-only and didn't modify it.
|
||||||
match self {
|
// // See the SAFETY section of the String implementation for more detail.
|
||||||
Ok(ok) => &ok.into_ptr(),
|
// Vec::from_raw_parts(
|
||||||
Err(err) => {
|
// ptr.data as *mut <T as Convertible>::Ptr,
|
||||||
errno::set(TypeConversionError::ResultWasErr {
|
// ptr.length,
|
||||||
original_message: err.to_string(),
|
// ptr.capacity,
|
||||||
});
|
// )
|
||||||
ptr::null()
|
// };
|
||||||
}
|
//
|
||||||
}
|
// let vec: Vec<_> = base_vec
|
||||||
}
|
// .into_iter()
|
||||||
|
// .map(|val| <T as Convertible>::from_ptr(val))
|
||||||
fn from_ptr(_: Self::Ptr) -> Result<Self, error::TypeConversionError> {
|
// .collect::<Result<Vec<_>, _>>()?;
|
||||||
warn!(
|
// Ok(vec)
|
||||||
"
|
// }
|
||||||
This should never be called, as this result type resolves
|
// }
|
||||||
to a null pointer (and a set error) or to a pointer to
|
//
|
||||||
the real value (e. g. a `crate::Vec<T>`)
|
// macro_rules! make_vec_free {
|
||||||
"
|
// ($value:ident, $name:ident) => {
|
||||||
);
|
// #[no_mangle]
|
||||||
todo!()
|
// pub extern "C" fn $name(ptr: crate::types::Vec<<$value as Convertible>::Ptr>) {
|
||||||
// Ok(Result::Ok(T::default()))
|
// Vec::<$value>::drop_ptr(ptr);
|
||||||
}
|
// }
|
||||||
}
|
// };
|
||||||
|
// }
|
||||||
impl<T: Convertible> Convertible for Vec<T> {
|
//
|
||||||
type Ptr = crate::types::Vec<<T as Convertible>::Ptr>;
|
// // Unsigned
|
||||||
|
// make_vec_free!(u8, vec_free_u8);
|
||||||
fn into_ptr(self) -> Self::Ptr {
|
// make_vec_free!(u16, vec_free_u16);
|
||||||
let data_vec: Vec<_> = self.into_iter().map(|val| val.into_ptr()).collect();
|
// make_vec_free!(u32, vec_free_u32);
|
||||||
let data_vec = ManuallyDrop::new(data_vec);
|
// make_vec_free!(u64, vec_free_u64);
|
||||||
Self::Ptr {
|
// // Signed
|
||||||
data: data_vec.as_ptr(),
|
// make_vec_free!(i8, vec_free_i8);
|
||||||
length: data_vec.len(),
|
// make_vec_free!(i16, vec_free_i16);
|
||||||
capacity: data_vec.capacity(),
|
// make_vec_free!(i32, vec_free_i32);
|
||||||
}
|
// make_vec_free!(i64, vec_free_i64);
|
||||||
}
|
// // Float
|
||||||
|
// make_vec_free!(f32, vec_free_f32);
|
||||||
fn from_ptr(ptr: Self::Ptr) -> Result<Self, error::TypeConversionError> {
|
// make_vec_free!(f64, vec_free_f64);
|
||||||
if ptr.data.is_null() {
|
// // Other
|
||||||
return Err(TypeConversionError::NullPointer);
|
// make_vec_free!(String, vec_free_String);
|
||||||
}
|
|
||||||
// TODO(@soispha): Add this, when this feature is stable <2024-02-17>
|
|
||||||
// if !ptr.data.is_aligned() {
|
|
||||||
// return Err(TypeConversionError::NotAligned);
|
|
||||||
// }
|
|
||||||
let base_vec = unsafe {
|
|
||||||
// SAFETY:
|
|
||||||
// We simply hope that c treated our vector as read-only and didn't modify it.
|
|
||||||
// See the SAFETY section of the String implementation for more detail.
|
|
||||||
Vec::from_raw_parts(
|
|
||||||
ptr.data as *mut <T as Convertible>::Ptr,
|
|
||||||
ptr.length,
|
|
||||||
ptr.capacity,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
let vec: Vec<_> = base_vec
|
|
||||||
.into_iter()
|
|
||||||
.map(|val| <T as Convertible>::from_ptr(val))
|
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
|
||||||
Ok(vec)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! make_vec_free {
|
|
||||||
($value:ident, $name:ident) => {
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn $name(ptr: crate::types::Vec<<$value as Convertible>::Ptr>) {
|
|
||||||
Vec::<$value>::drop_ptr(ptr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unsigned
|
|
||||||
make_vec_free!(u8, vec_free_u8);
|
|
||||||
make_vec_free!(u16, vec_free_u16);
|
|
||||||
make_vec_free!(u32, vec_free_u32);
|
|
||||||
make_vec_free!(u64, vec_free_u64);
|
|
||||||
// Signed
|
|
||||||
make_vec_free!(i8, vec_free_i8);
|
|
||||||
make_vec_free!(i16, vec_free_i16);
|
|
||||||
make_vec_free!(i32, vec_free_i32);
|
|
||||||
make_vec_free!(i64, vec_free_i64);
|
|
||||||
// Float
|
|
||||||
make_vec_free!(f32, vec_free_f32);
|
|
||||||
make_vec_free!(f64, vec_free_f64);
|
|
||||||
// Other
|
|
||||||
make_vec_free!(String, vec_free_String);
|
|
||||||
|
|
||||||
// FIXME(@soispha): Find a way to support these <2024-02-27>
|
// FIXME(@soispha): Find a way to support these <2024-02-27>
|
||||||
// make_vec_free!(Option<?>, vec_free_Option);
|
// make_vec_free!(Option<?>, vec_free_Option);
|
||||||
|
|
|
@ -23,24 +23,30 @@
|
||||||
// NOTE(@soispha): All types specified here *MUST* be include in the BASE_TYPES constant, otherwise
|
// NOTE(@soispha): All types specified here *MUST* be include in the BASE_TYPES constant, otherwise
|
||||||
// they are not usable from Trixy code <2023-12-25>
|
// they are not usable from Trixy code <2023-12-25>
|
||||||
|
|
||||||
// NOTE(@soispha): All types added here must also have an added free impl for the vector type (./traits/convert_trait.rs) <2024-02-27>
|
|
||||||
|
|
||||||
use std::ffi::c_char;
|
use std::ffi::c_char;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct String(pub(crate) *const c_char);
|
pub struct String(pub(crate) *const c_char);
|
||||||
|
|
||||||
|
/// The tag used to tag the c result Enumerations
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Vec<T> {
|
pub enum ResultTag {
|
||||||
/// You should cast this value to it's supposed type (readable from the Trixy api definition
|
Ok,
|
||||||
/// file)
|
Err,
|
||||||
pub(crate) data: *const T,
|
|
||||||
pub(crate) length: usize,
|
|
||||||
pub(crate) capacity: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #[derive(Debug)]
|
||||||
|
// #[repr(C)]
|
||||||
|
// pub struct Vec<T> {
|
||||||
|
// /// You should cast this value to it's supposed type (readable from the Trixy api definition
|
||||||
|
// /// file)
|
||||||
|
// pub(crate) data: *const T,
|
||||||
|
// pub(crate) length: usize,
|
||||||
|
// pub(crate) capacity: usize,
|
||||||
|
// }
|
||||||
|
|
||||||
// Unsigned
|
// Unsigned
|
||||||
pub use std::primitive::u16;
|
pub use std::primitive::u16;
|
||||||
pub use std::primitive::u32;
|
pub use std::primitive::u32;
|
||||||
|
|
Reference in New Issue