core_crypto_macros/entity_derive/
mod.rs

1mod derive_impl;
2mod parse;
3
4use proc_macro2::Ident;
5
6/// Representation of a struct annotated with `#[derive(Entity)]`.
7pub(super) struct KeyStoreEntity {
8    /// Name of the type to implement the trait on
9    struct_name: Ident,
10    /// Database table name
11    collection_name: String,
12    /// The ID column
13    id: IdColumn,
14    /// All other columns
15    columns: Columns,
16    /// Whether to fail on inserting conflicting ids instead of using upsert semantics (default: false)
17    no_upsert: bool,
18}
19
20impl KeyStoreEntity {
21    /// Convert Keystore entity to a flattened version that is more verbose but can be used more easily in `quote!()`.
22    pub(super) fn flatten(self) -> KeyStoreEntityFlattened {
23        let all_columns = self
24            .columns
25            .0
26            .iter()
27            .map(|column| column.name.clone())
28            .collect::<Vec<_>>();
29
30        let blob_columns = self
31            .columns
32            .0
33            .iter()
34            .filter(|column| column.column_type == ColumnType::Bytes)
35            .map(|column| column.name.clone())
36            .collect::<Vec<_>>();
37
38        let optional_blob_columns = self
39            .columns
40            .0
41            .iter()
42            .filter(|column| column.column_type == ColumnType::OptionalBytes)
43            .map(|column| column.name.clone())
44            .collect::<Vec<_>>();
45
46        let all_column_names = all_columns.iter().map(ToString::to_string).collect();
47        let blob_column_names = blob_columns.iter().map(ToString::to_string).collect();
48        let optional_blob_column_names = optional_blob_columns.iter().map(ToString::to_string).collect();
49
50        let id = self.id.name;
51        let id_name = self.id.column_name.unwrap_or_else(|| id.to_string());
52        let id_type = self.id.column_type;
53
54        KeyStoreEntityFlattened {
55            struct_name: self.struct_name,
56            collection_name: self.collection_name,
57            no_upsert: self.no_upsert,
58            id,
59            id_type,
60            id_name,
61            id_transformation: self.id.transformation,
62            all_columns,
63            all_column_names,
64            blob_columns,
65            blob_column_names,
66            optional_blob_columns,
67            optional_blob_column_names,
68        }
69    }
70}
71
72/// Less abstract version of [KeyStoreEntity] that has all the fields flattened
73/// ready for usage in `quote!()`.
74pub(super) struct KeyStoreEntityFlattened {
75    struct_name: Ident,
76    collection_name: String,
77    id: Ident,
78    id_name: String,
79    id_type: IdColumnType,
80    id_transformation: Option<IdTransformation>,
81    all_columns: Vec<Ident>,
82    all_column_names: Vec<String>,
83    blob_columns: Vec<Ident>,
84    blob_column_names: Vec<String>,
85    optional_blob_columns: Vec<Ident>,
86    optional_blob_column_names: Vec<String>,
87    no_upsert: bool,
88}
89
90#[derive(PartialEq, Eq)]
91enum IdColumnType {
92    String,
93    Bytes,
94}
95
96struct IdColumn {
97    name: Ident,
98    column_type: IdColumnType,
99    /// Only present if it differs from the name
100    column_name: Option<String>,
101    /// If the ID cannot be stored as-is because of indexing limitations
102    transformation: Option<IdTransformation>,
103}
104
105enum IdTransformation {
106    Hex,
107    #[expect(dead_code)]
108    Sha256,
109}
110
111struct Columns(Vec<Column>);
112
113struct Column {
114    name: Ident,
115    column_type: ColumnType,
116}
117
118#[derive(PartialEq, Eq)]
119enum ColumnType {
120    String,
121    Bytes,
122    OptionalBytes,
123}