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
7433
pub fn register(linker: &mut Linker<SessionData>) -> wasmtime::Result<()> {
48
7433
    register_readonly(linker)?;
49
7433
    register_mutators(linker)?;
50
7433
    Ok(())
51
7433
}
52

            
53
7573
pub fn register_readonly(linker: &mut Linker<SessionData>) -> wasmtime::Result<()> {
54
7573
    linker.func_wrap_async(
55
7573
        "nomi",
56
7573
        "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
182
        > {
62
182
            Box::new(async move {
63
182
                let user_id = caller.data().ctx().user_id;
64
182
                let account_str = read_string_arg(&mut caller, account_arg)?;
65
182
                let result = run_list_transactions(user_id, account_str).await?;
66
182
                alloc_transaction_chain(&mut caller, result).await
67
182
            })
68
182
        },
69
    )?;
70
7573
    linker.func_wrap_async(
71
7573
        "nomi",
72
7573
        "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
52
        > {
78
52
            Box::new(async move {
79
52
                let user_id = caller.data().ctx().user_id;
80
52
                let id = read_string_arg(&mut caller, id_arg)?;
81
52
                run_get_transaction(&mut caller, user_id, id).await
82
52
            })
83
52
        },
84
    )?;
85
7573
    linker.func_wrap_async(
86
7573
        "nomi",
87
7573
        "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
7573
    linker.func_wrap_async(
105
7573
        "nomi",
106
7573
        "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
7573
    Ok(())
122
7573
}
123

            
124
7433
pub fn register_mutators(linker: &mut Linker<SessionData>) -> wasmtime::Result<()> {
125
7433
    linker.func_wrap_async(
126
7433
        "nomi",
127
7433
        "transaction_delete_transaction",
128
        |mut caller: Caller<'_, SessionData>,
129
         (id_arg,): (Option<Rooted<ArrayRef>>,)|
130
52
         -> Box<dyn std::future::Future<Output = wasmtime::Result<i32>> + Send> {
131
52
            Box::new(async move {
132
52
                let user_id = caller.data().ctx().user_id;
133
52
                let id = read_string_arg(&mut caller, id_arg)?;
134
52
                run_delete_transaction(user_id, id).await
135
52
            })
136
52
        },
137
    )?;
138
7433
    linker.func_wrap_async(
139
7433
        "nomi",
140
7433
        "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
728
        > {
146
728
            Box::new(async move {
147
728
                let user_id = caller.data().ctx().user_id;
148
728
                let payload = read_string_arg(&mut caller, payload_arg)?;
149
728
                let id = run_create_transaction(user_id, payload).await?;
150
728
                Ok(Some(alloc_string_ref(&mut caller, id.as_bytes())?))
151
728
            })
152
728
        },
153
    )?;
154
7433
    linker.func_wrap_async(
155
7433
        "nomi",
156
7433
        "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
104
        > {
162
104
            Box::new(async move {
163
104
                let user_id = caller.data().ctx().user_id;
164
104
                let payload = read_string_arg(&mut caller, payload_arg)?;
165
104
                let id = run_create_transaction_logical(user_id, payload).await?;
166
104
                Ok(Some(alloc_string_ref(&mut caller, id.as_bytes())?))
167
104
            })
168
104
        },
169
    )?;
170
7433
    linker.func_wrap_async(
171
7433
        "nomi",
172
7433
        "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
26
        > {
178
26
            Box::new(async move {
179
26
                let user_id = caller.data().ctx().user_id;
180
26
                let payload = read_string_arg(&mut caller, payload_arg)?;
181
26
                let id = run_update_transaction(user_id, payload).await?;
182
                Ok(Some(alloc_string_ref(&mut caller, id.as_bytes())?))
183
26
            })
184
26
        },
185
    )?;
186
7433
    linker.func_wrap_async(
187
7433
        "nomi",
188
7433
        "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
26
        > {
194
26
            Box::new(async move {
195
26
                let user_id = caller.data().ctx().user_id;
196
26
                let payload = read_string_arg(&mut caller, payload_arg)?;
197
26
                let id = run_update_transaction_logical(user_id, payload).await?;
198
26
                Ok(Some(alloc_string_ref(&mut caller, id.as_bytes())?))
199
26
            })
200
26
        },
201
    )?;
202
7433
    linker.func_wrap_async(
203
7433
        "nomi",
204
7433
        "transaction_set_transaction_tag",
205
        |mut caller: Caller<'_, SessionData>,
206
         (id_arg, name_arg, value_arg): super::StringArgTriple|
207
26
         -> Box<dyn std::future::Future<Output = wasmtime::Result<i32>> + Send> {
208
26
            Box::new(async move {
209
26
                let user_id = caller.data().ctx().user_id;
210
26
                let id = read_string_arg(&mut caller, id_arg)?;
211
26
                let name = read_string_arg(&mut caller, name_arg)?;
212
26
                let value = read_string_arg(&mut caller, value_arg)?;
213
26
                run_set_transaction_tag(user_id, id, name, value).await
214
26
            })
215
26
        },
216
    )?;
217
7433
    Ok(())
218
7433
}