opendp_tooling/
lib.rs

1// logic for the bootstrap macro
2pub mod bootstrap;
3
4// logic for the proven macro
5pub mod proven;
6
7// logic for generating bindings from the core structures below
8pub mod codegen;
9
10#[derive(Debug)]
11pub struct Deprecation {
12    since: String,
13    note: String,
14}
15
16// metadata for each function in a module
17#[derive(Debug)]
18pub struct Function {
19    pub name: String,
20    // plaintext description of the function used to generate documentation
21    pub description: Option<String>,
22    // required feature flags to execute function
23    pub features: Vec<String>,
24    // arguments and generics
25    pub args: Vec<Argument>,
26    // metadata for constructing new types based on existing types or introspection
27    pub derived_types: Vec<Argument>,
28    // metadata for return type
29    pub ret: Argument,
30    // set to true if the first two arguments are input domain and input metric
31    pub supports_partial: bool,
32    // whether to generate FFI
33    pub has_ffi: bool,
34    // deprecation warning if applicable
35    pub deprecation: Option<Deprecation>,
36}
37
38// Metadata for function arguments, derived types and returns.
39#[derive(Debug, Default, Clone)]
40pub struct Argument {
41    // argument name. Optional for return types
42    pub name: Option<String>,
43    // c type to translate to/from for FFI. Optional for derived types
44    pub c_type: Option<String>,
45    // directions to construct a Rust type with generics
46    pub rust_type: Option<TypeRecipe>,
47    // type hint- a more abstract type that all potential arguments inherit from
48    pub hint: Option<String>,
49    // plaintext description of the argument used to generate documentation
50    pub description: Option<String>,
51    // default value for the argument
52    pub default: Option<Value>,
53    // set to true if the argument represents a type
54    pub is_type: bool,
55    // most functions convert c_to_py or py_to_c. Set to true to leave the value as-is
56    // an example usage is slice_as_object,
57    //  to prevent the returned AnyObject from getting converted back to python
58    pub do_not_convert: bool,
59    // when is_type, use this as an example to infer the type
60    pub example: Option<TypeRecipe>,
61}
62
63impl Argument {
64    /// Returns the intersection of leaf names and the provided variables.
65    /// That is, leaf nodes that are variables are considered generics.
66    fn generics(&self, variables: &Vec<String>) -> Vec<String> {
67        variables
68            .iter()
69            .filter(|v| Some(*v) != self.name.as_ref())
70            .cloned()
71            .collect()
72    }
73}
74
75// TypeRecipe contains the metadata to generate code that evaluates to a rust type name
76#[derive(Debug, PartialEq, Clone)]
77pub enum TypeRecipe {
78    // reference an existing type
79    Name(String),
80    // build up a rust type from other rust types
81    Nest {
82        origin: String,
83        args: Vec<TypeRecipe>,
84    },
85    // explicitly absent
86    None,
87    // construct the rust type via function call
88    Function {
89        function: String,
90        params: Vec<TypeRecipe>,
91    },
92}
93
94// holds literal values, like for default
95#[derive(Debug, Default, Clone)]
96pub enum Value {
97    #[default]
98    Null,
99    Bool(bool),
100    String(String),
101    Integer(i64),
102    Float(f64),
103}