1
//! Transaction-domain natives. Wraps `server::command::{CreateTransaction,
2
//! ListTransactions, GetTransaction, UpdateTransaction, DeleteTransaction}`.
3

            
4
mod logical_common;
5
mod parse;
6
mod render;
7
mod run;
8
mod run_logical;
9

            
10
#[cfg(test)]
11
mod tests;
12
#[cfg(test)]
13
mod tests_get_transaction;
14
#[cfg(test)]
15
mod tests_logical;
16
#[cfg(test)]
17
mod tests_logical_update;
18
#[cfg(test)]
19
mod tests_parse;
20

            
21
use scripting::runtime::{alloc_string_ref, read_string_arg};
22
use wasmtime::{ArrayRef, Caller, Linker, Rooted, StructRef};
23

            
24
use crate::session::SessionData;
25

            
26
use render::alloc_transaction_chain;
27
use run::{
28
    run_create_transaction, run_delete_transaction, run_get_transaction,
29
    run_get_transaction_detail, run_get_transaction_tag, run_list_transactions,
30
    run_set_transaction_tag, run_update_transaction,
31
};
32
use run_logical::{run_create_transaction_logical, run_update_transaction_logical};
33

            
34
pub const REGISTERED_COMMANDS: &[&str] = &[
35
    "create-transaction",
36
    "create-transaction-logical",
37
    "list-transactions",
38
    "get-transaction",
39
    "get-transaction-detail",
40
    "update-transaction",
41
    "update-transaction-logical",
42
    "delete-transaction",
43
    "set-transaction-tag",
44
    "get-transaction-tag",
45
];
46

            
47
5909
pub fn register(linker: &mut Linker<SessionData>) -> wasmtime::Result<()> {
48
5909
    register_readonly(linker)?;
49
5909
    register_mutators(linker)?;
50
5909
    Ok(())
51
5909
}
52

            
53
6045
pub fn register_readonly(linker: &mut Linker<SessionData>) -> wasmtime::Result<()> {
54
6045
    linker.func_wrap_async(
55
6045
        "nomi",
56
6045
        "transaction_list_transactions",
57
        |mut caller: Caller<'_, SessionData>,
58
         (account_arg,): (Option<Rooted<ArrayRef>>,)|
59
         -> Box<
60
            dyn std::future::Future<Output = wasmtime::Result<Option<Rooted<StructRef>>>> + Send,
61
175
        > {
62
175
            Box::new(async move {
63
175
                let user_id = caller.data().ctx().user_id;
64
175
                let account_str = read_string_arg(&mut caller, account_arg)?;
65
175
                let result = run_list_transactions(user_id, account_str).await?;
66
175
                alloc_transaction_chain(&mut caller, result).await
67
175
            })
68
175
        },
69
    )?;
70
6045
    linker.func_wrap_async(
71
6045
        "nomi",
72
6045
        "transaction_get_transaction",
73
        |mut caller: Caller<'_, SessionData>,
74
         (id_arg,): (Option<Rooted<ArrayRef>>,)|
75
         -> Box<
76
            dyn std::future::Future<Output = wasmtime::Result<Option<Rooted<StructRef>>>> + Send,
77
50
        > {
78
50
            Box::new(async move {
79
50
                let user_id = caller.data().ctx().user_id;
80
50
                let id = read_string_arg(&mut caller, id_arg)?;
81
50
                run_get_transaction(&mut caller, user_id, id).await
82
50
            })
83
50
        },
84
    )?;
85
6045
    linker.func_wrap_async(
86
6045
        "nomi",
87
6045
        "transaction_get_transaction_detail",
88
        |mut caller: Caller<'_, SessionData>,
89
         (id_arg,): (Option<Rooted<ArrayRef>>,)|
90
         -> Box<
91
            dyn std::future::Future<Output = wasmtime::Result<Option<Rooted<ArrayRef>>>> + Send,
92
        > {
93
            Box::new(async move {
94
                let user_id = caller.data().ctx().user_id;
95
                let id = read_string_arg(&mut caller, id_arg)?;
96
                let plist = run_get_transaction_detail(user_id, id).await?;
97
                Ok(match plist {
98
                    Some(s) => Some(alloc_string_ref(&mut caller, s.as_bytes())?),
99
                    None => None,
100
                })
101
            })
102
        },
103
    )?;
104
6045
    linker.func_wrap_async(
105
6045
        "nomi",
106
6045
        "transaction_get_transaction_tag",
107
        |mut caller: Caller<'_, SessionData>,
108
         (id_arg, name_arg): (Option<Rooted<ArrayRef>>, Option<Rooted<ArrayRef>>)|
109
         -> Box<
110
            dyn std::future::Future<Output = wasmtime::Result<Option<Rooted<ArrayRef>>>> + Send,
111
        > {
112
            Box::new(async move {
113
                let user_id = caller.data().ctx().user_id;
114
                let id = read_string_arg(&mut caller, id_arg)?;
115
                let name = read_string_arg(&mut caller, name_arg)?;
116
                let value = run_get_transaction_tag(user_id, id, name).await?;
117
                Ok(Some(alloc_string_ref(&mut caller, value.as_bytes())?))
118
            })
119
        },
120
    )?;
121
6045
    Ok(())
122
6045
}
123

            
124
5909
pub fn register_mutators(linker: &mut Linker<SessionData>) -> wasmtime::Result<()> {
125
5909
    linker.func_wrap_async(
126
5909
        "nomi",
127
5909
        "transaction_delete_transaction",
128
        |mut caller: Caller<'_, SessionData>,
129
         (id_arg,): (Option<Rooted<ArrayRef>>,)|
130
50
         -> Box<dyn std::future::Future<Output = wasmtime::Result<i32>> + Send> {
131
50
            Box::new(async move {
132
50
                let user_id = caller.data().ctx().user_id;
133
50
                let id = read_string_arg(&mut caller, id_arg)?;
134
50
                run_delete_transaction(user_id, id).await
135
50
            })
136
50
        },
137
    )?;
138
5909
    linker.func_wrap_async(
139
5909
        "nomi",
140
5909
        "transaction_create_transaction",
141
        |mut caller: Caller<'_, SessionData>,
142
         (payload_arg,): (Option<Rooted<ArrayRef>>,)|
143
         -> Box<
144
            dyn std::future::Future<Output = wasmtime::Result<Option<Rooted<ArrayRef>>>> + Send,
145
700
        > {
146
700
            Box::new(async move {
147
700
                let user_id = caller.data().ctx().user_id;
148
700
                let payload = read_string_arg(&mut caller, payload_arg)?;
149
700
                let id = run_create_transaction(user_id, payload).await?;
150
700
                Ok(Some(alloc_string_ref(&mut caller, id.as_bytes())?))
151
700
            })
152
700
        },
153
    )?;
154
5909
    linker.func_wrap_async(
155
5909
        "nomi",
156
5909
        "transaction_create_transaction_logical",
157
        |mut caller: Caller<'_, SessionData>,
158
         (payload_arg,): (Option<Rooted<ArrayRef>>,)|
159
         -> Box<
160
            dyn std::future::Future<Output = wasmtime::Result<Option<Rooted<ArrayRef>>>> + Send,
161
100
        > {
162
100
            Box::new(async move {
163
100
                let user_id = caller.data().ctx().user_id;
164
100
                let payload = read_string_arg(&mut caller, payload_arg)?;
165
100
                let id = run_create_transaction_logical(user_id, payload).await?;
166
100
                Ok(Some(alloc_string_ref(&mut caller, id.as_bytes())?))
167
100
            })
168
100
        },
169
    )?;
170
5909
    linker.func_wrap_async(
171
5909
        "nomi",
172
5909
        "transaction_update_transaction",
173
        |mut caller: Caller<'_, SessionData>,
174
         (payload_arg,): (Option<Rooted<ArrayRef>>,)|
175
         -> Box<
176
            dyn std::future::Future<Output = wasmtime::Result<Option<Rooted<ArrayRef>>>> + Send,
177
25
        > {
178
25
            Box::new(async move {
179
25
                let user_id = caller.data().ctx().user_id;
180
25
                let payload = read_string_arg(&mut caller, payload_arg)?;
181
25
                let id = run_update_transaction(user_id, payload).await?;
182
                Ok(Some(alloc_string_ref(&mut caller, id.as_bytes())?))
183
25
            })
184
25
        },
185
    )?;
186
5909
    linker.func_wrap_async(
187
5909
        "nomi",
188
5909
        "transaction_update_transaction_logical",
189
        |mut caller: Caller<'_, SessionData>,
190
         (payload_arg,): (Option<Rooted<ArrayRef>>,)|
191
         -> Box<
192
            dyn std::future::Future<Output = wasmtime::Result<Option<Rooted<ArrayRef>>>> + Send,
193
25
        > {
194
25
            Box::new(async move {
195
25
                let user_id = caller.data().ctx().user_id;
196
25
                let payload = read_string_arg(&mut caller, payload_arg)?;
197
25
                let id = run_update_transaction_logical(user_id, payload).await?;
198
25
                Ok(Some(alloc_string_ref(&mut caller, id.as_bytes())?))
199
25
            })
200
25
        },
201
    )?;
202
5909
    linker.func_wrap_async(
203
5909
        "nomi",
204
5909
        "transaction_set_transaction_tag",
205
        |mut caller: Caller<'_, SessionData>,
206
         (id_arg, name_arg, value_arg): super::StringArgTriple|
207
25
         -> Box<dyn std::future::Future<Output = wasmtime::Result<i32>> + Send> {
208
25
            Box::new(async move {
209
25
                let user_id = caller.data().ctx().user_id;
210
25
                let id = read_string_arg(&mut caller, id_arg)?;
211
25
                let name = read_string_arg(&mut caller, name_arg)?;
212
25
                let value = read_string_arg(&mut caller, value_arg)?;
213
25
                run_set_transaction_tag(user_id, id, name, value).await
214
25
            })
215
25
        },
216
    )?;
217
5909
    Ok(())
218
5909
}