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 FatalError = 1,
22 FunctionResult = 2,
23 Log = 3,
24
25 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 StoragePut = 2001,
42 StorageGet = 2002,
43 StorageDelete = 2003,
44 StorageList = 2004,
45
46 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 FatalError(FatalError<'a>),
80 FunctionResult(FunctionResult<'a>),
81 Log(Log<'a>),
82
83 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 StoragePut(StoragePut<'a>),
100 StorageGet(StorageGet<'a>),
101 StorageDelete(StorageDelete<'a>),
102 StorageList(StorageList<'a>),
103
104 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}