musdk_common/
outgoing_message.rs

1pub mod db;
2pub mod storage;
3
4use std::{
5    borrow::Cow,
6    io::{Read, Write},
7};
8
9use borsh::{BorshDeserialize, BorshSerialize};
10use num_derive::FromPrimitive;
11use num_traits::FromPrimitive;
12
13use crate::{function::*, http_client::Request as HttpRequest};
14use db::*;
15use storage::*;
16
17#[derive(FromPrimitive)]
18#[repr(u16)]
19pub enum OutgoingMessageKind {
20    // Runtime messages
21    FatalError = 1,
22    FunctionResult = 2,
23    Log = 3,
24
25    // DB messages
26    Put = 1001,
27    Get = 1002,
28    Delete = 1003,
29    DeleteByPrefix = 1004,
30    Scan = 1005,
31    ScanKeys = 1006,
32    TableList = 1007,
33    BatchPut = 1008,
34    BatchGet = 1009,
35    BatchDelete = 1010,
36    BatchScan = 1011,
37    BatchScanKeys = 1012,
38    CompareAndSwap = 1013,
39
40    // Storage messages
41    StoragePut = 2001,
42    StorageGet = 2002,
43    StorageDelete = 2003,
44    StorageList = 2004,
45
46    // Http Client
47    HttpRequest = 3001,
48}
49
50#[derive(Debug, BorshDeserialize, BorshSerialize)]
51pub struct FatalError<'a> {
52    pub error: Cow<'a, str>,
53}
54
55#[derive(Debug, BorshDeserialize, BorshSerialize)]
56pub struct FunctionResult<'a> {
57    pub response: Response<'a>,
58}
59
60#[derive(Debug, BorshDeserialize, BorshSerialize)]
61pub struct Log<'a> {
62    pub body: Cow<'a, str>,
63    pub level: LogLevel,
64}
65
66#[repr(u8)]
67#[derive(Debug, FromPrimitive, BorshDeserialize, BorshSerialize)]
68pub enum LogLevel {
69    Error = 0,
70    Warn = 1,
71    Info = 2,
72    Debug = 3,
73    Trace = 4,
74}
75
76#[derive(Debug)]
77pub enum OutgoingMessage<'a> {
78    // Runtime messages
79    FatalError(FatalError<'a>),
80    FunctionResult(FunctionResult<'a>),
81    Log(Log<'a>),
82
83    // DB messages
84    Put(Put<'a>),
85    Get(Get<'a>),
86    Delete(Delete<'a>),
87    DeleteByPrefix(DeleteByPrefix<'a>),
88    Scan(Scan<'a>),
89    ScanKeys(ScanKeys<'a>),
90    TableList(TableList<'a>),
91    BatchPut(BatchPut<'a>),
92    BatchGet(BatchGet<'a>),
93    BatchDelete(BatchDelete<'a>),
94    BatchScan(BatchScan<'a>),
95    BatchScanKeys(BatchScanKeys<'a>),
96    CompareAndSwap(CompareAndSwap<'a>),
97
98    // Storage messages
99    StoragePut(StoragePut<'a>),
100    StorageGet(StorageGet<'a>),
101    StorageDelete(StorageDelete<'a>),
102    StorageList(StorageList<'a>),
103
104    // Http Client
105    HttpRequest(HttpRequest<'a>),
106}
107
108macro_rules! read_cases {
109    ($kind: ident, $reader: ident, [$($case: ident),+]) => {
110        match OutgoingMessageKind::from_u16($kind) {
111            $(Some(OutgoingMessageKind::$case) => {
112                let message: $case<'static> = BorshDeserialize::deserialize_reader($reader)?;
113                Ok(Self::$case(message))
114            })+
115
116            None => Err(
117                std::io::Error::new(
118                    std::io::ErrorKind::InvalidData,
119                    format!("Unknown outgoing message code: {}", $kind)
120                )
121            ),
122        }
123    };
124}
125
126macro_rules! write_cases {
127    ($self: ident, $writer: ident, [$($case: ident),+]) => {
128        match $self {
129            $(OutgoingMessage::$case(x) => {
130                (OutgoingMessageKind::$case as u16).serialize($writer)?;
131                x.serialize($writer)?;
132            })+
133        }
134    };
135}
136
137impl<'a> OutgoingMessage<'a> {
138    pub fn read(reader: &mut impl Read) -> std::io::Result<Self> {
139        let kind: u16 = BorshDeserialize::deserialize_reader(reader)?;
140
141        read_cases!(
142            kind,
143            reader,
144            [
145                FatalError,
146                FunctionResult,
147                Log,
148                Put,
149                Get,
150                Delete,
151                DeleteByPrefix,
152                Scan,
153                ScanKeys,
154                TableList,
155                BatchPut,
156                BatchGet,
157                BatchDelete,
158                BatchScan,
159                BatchScanKeys,
160                CompareAndSwap,
161                StoragePut,
162                StorageGet,
163                StorageDelete,
164                StorageList,
165                HttpRequest
166            ]
167        )
168    }
169
170    pub fn write(&self, writer: &mut impl Write) -> std::io::Result<()> {
171        write_cases!(
172            self,
173            writer,
174            [
175                FatalError,
176                FunctionResult,
177                Log,
178                Put,
179                Get,
180                Delete,
181                DeleteByPrefix,
182                Scan,
183                ScanKeys,
184                TableList,
185                BatchPut,
186                BatchGet,
187                BatchDelete,
188                BatchScan,
189                BatchScanKeys,
190                CompareAndSwap,
191                StoragePut,
192                StorageGet,
193                StorageDelete,
194                StorageList,
195                HttpRequest
196            ]
197        );
198
199        Ok(())
200    }
201}