1extern crate rmp_serde as rmps;
2use rmps::{Deserializer, Serializer};
3use serde::{Deserialize, Serialize};
4use std::io::Cursor;
5
6#[cfg(feature = "guest")]
7extern crate wapc_guest as guest;
8#[cfg(feature = "guest")]
9use guest::prelude::*;
10
11#[cfg(feature = "guest")]
12pub struct Host {
13 binding: String,
14}
15
16#[cfg(feature = "guest")]
17impl Default for Host {
18 fn default() -> Self {
19 Host {
20 binding: "default".to_string(),
21 }
22 }
23}
24
25#[cfg(feature = "guest")]
27pub fn host(binding: &str) -> Host {
28 Host {
29 binding: binding.to_string(),
30 }
31}
32
33#[cfg(feature = "guest")]
35pub fn default() -> Host {
36 Host::default()
37}
38
39#[cfg(feature = "guest")]
40impl Host {
41 pub fn create_container(&self, id: String) -> HandlerResult<Container> {
43 let input_args = CreateContainerArgs { id };
44 host_call(
45 &self.binding,
46 "wasmcloud:blobstore",
47 "CreateContainer",
48 &serialize(input_args)?,
49 )
50 .map(|vec| {
51 let resp = deserialize::<Container>(vec.as_ref()).unwrap();
52 resp
53 })
54 .map_err(|e| e.into())
55 }
56 pub fn remove_container(&self, id: String) -> HandlerResult<BlobstoreResult> {
58 let input_args = RemoveContainerArgs { id };
59 host_call(
60 &self.binding,
61 "wasmcloud:blobstore",
62 "RemoveContainer",
63 &serialize(input_args)?,
64 )
65 .map(|vec| {
66 let resp = deserialize::<BlobstoreResult>(vec.as_ref()).unwrap();
67 resp
68 })
69 .map_err(|e| e.into())
70 }
71 pub fn remove_object(
73 &self,
74 id: String,
75 container_id: String,
76 ) -> HandlerResult<BlobstoreResult> {
77 let input_args = RemoveObjectArgs { id, container_id };
78 host_call(
79 &self.binding,
80 "wasmcloud:blobstore",
81 "RemoveObject",
82 &serialize(input_args)?,
83 )
84 .map(|vec| {
85 let resp = deserialize::<BlobstoreResult>(vec.as_ref()).unwrap();
86 resp
87 })
88 .map_err(|e| e.into())
89 }
90 pub fn list_objects(&self, container_id: String) -> HandlerResult<BlobList> {
92 let input_args = ListObjectsArgs { container_id };
93 host_call(
94 &self.binding,
95 "wasmcloud:blobstore",
96 "ListObjects",
97 &serialize(input_args)?,
98 )
99 .map(|vec| {
100 let resp = deserialize::<BlobList>(vec.as_ref()).unwrap();
101 resp
102 })
103 .map_err(|e| e.into())
104 }
105 pub fn upload_chunk(&self, chunk: FileChunk) -> HandlerResult<BlobstoreResult> {
109 let input_args = UploadChunkArgs { chunk };
110 host_call(
111 &self.binding,
112 "wasmcloud:blobstore",
113 "UploadChunk",
114 &serialize(input_args)?,
115 )
116 .map(|vec| {
117 let resp = deserialize::<BlobstoreResult>(vec.as_ref()).unwrap();
118 resp
119 })
120 .map_err(|e| e.into())
121 }
122 pub fn start_download(
125 &self,
126 blob_id: String,
127 container_id: String,
128 chunk_size: u64,
129 context: Option<String>,
130 ) -> HandlerResult<BlobstoreResult> {
131 let input_args = StartDownloadArgs {
132 blob_id,
133 container_id,
134 chunk_size,
135 context,
136 };
137 host_call(
138 &self.binding,
139 "wasmcloud:blobstore",
140 "StartDownload",
141 &serialize(input_args)?,
142 )
143 .map(|vec| {
144 let resp = deserialize::<BlobstoreResult>(vec.as_ref()).unwrap();
145 resp
146 })
147 .map_err(|e| e.into())
148 }
149 pub fn start_upload(&self, chunk: FileChunk) -> HandlerResult<BlobstoreResult> {
152 let input_args = StartUploadArgs { chunk };
153 host_call(
154 &self.binding,
155 "wasmcloud:blobstore",
156 "StartUpload",
157 &serialize(input_args)?,
158 )
159 .map(|vec| {
160 let resp = deserialize::<BlobstoreResult>(vec.as_ref()).unwrap();
161 resp
162 })
163 .map_err(|e| e.into())
164 }
165 pub fn get_object_info(&self, blob_id: String, container_id: String) -> HandlerResult<Blob> {
167 let input_args = GetObjectInfoArgs {
168 blob_id,
169 container_id,
170 };
171 host_call(
172 &self.binding,
173 "wasmcloud:blobstore",
174 "GetObjectInfo",
175 &serialize(input_args)?,
176 )
177 .map(|vec| {
178 let resp = deserialize::<Blob>(vec.as_ref()).unwrap();
179 resp
180 })
181 .map_err(|e| e.into())
182 }
183}
184
185#[cfg(feature = "guest")]
186pub struct Handlers {}
187
188#[cfg(feature = "guest")]
189impl Handlers {
190 pub fn register_receive_chunk(f: fn(FileChunk) -> HandlerResult<()>) {
193 *RECEIVE_CHUNK.write().unwrap() = Some(f);
194 register_function(&"ReceiveChunk", receive_chunk_wrapper);
195 }
196}
197
198#[cfg(feature = "guest")]
199lazy_static::lazy_static! {
200static ref RECEIVE_CHUNK: std::sync::RwLock<Option<fn(FileChunk) -> HandlerResult<()>>> = std::sync::RwLock::new(None);
201}
202
203#[cfg(feature = "guest")]
204fn receive_chunk_wrapper(input_payload: &[u8]) -> CallResult {
205 let input = deserialize::<ReceiveChunkArgs>(input_payload)?;
206 let lock = RECEIVE_CHUNK.read().unwrap().unwrap();
207 let result = lock(input.chunk)?;
208 serialize(result)
209}
210
211#[derive(Debug, PartialEq, Deserialize, Serialize, Default, Clone)]
212pub struct CreateContainerArgs {
213 #[serde(rename = "id")]
214 pub id: String,
215}
216
217#[derive(Debug, PartialEq, Deserialize, Serialize, Default, Clone)]
218pub struct RemoveContainerArgs {
219 #[serde(rename = "id")]
220 pub id: String,
221}
222
223#[derive(Debug, PartialEq, Deserialize, Serialize, Default, Clone)]
224pub struct RemoveObjectArgs {
225 #[serde(rename = "id")]
226 pub id: String,
227 #[serde(rename = "container_id")]
228 pub container_id: String,
229}
230
231#[derive(Debug, PartialEq, Deserialize, Serialize, Default, Clone)]
232pub struct ListObjectsArgs {
233 #[serde(rename = "container_id")]
234 pub container_id: String,
235}
236
237#[derive(Debug, PartialEq, Deserialize, Serialize, Default, Clone)]
238pub struct UploadChunkArgs {
239 #[serde(rename = "chunk")]
240 pub chunk: FileChunk,
241}
242
243#[derive(Debug, PartialEq, Deserialize, Serialize, Default, Clone)]
244pub struct StartDownloadArgs {
245 #[serde(rename = "blob_id")]
246 pub blob_id: String,
247 #[serde(rename = "container_id")]
248 pub container_id: String,
249 #[serde(rename = "chunk_size")]
250 pub chunk_size: u64,
251 #[serde(rename = "context")]
252 pub context: Option<String>,
253}
254
255#[derive(Debug, PartialEq, Deserialize, Serialize, Default, Clone)]
256pub struct StartUploadArgs {
257 #[serde(rename = "chunk")]
258 pub chunk: FileChunk,
259}
260
261#[derive(Debug, PartialEq, Deserialize, Serialize, Default, Clone)]
262pub struct GetObjectInfoArgs {
263 #[serde(rename = "blob_id")]
264 pub blob_id: String,
265 #[serde(rename = "container_id")]
266 pub container_id: String,
267}
268
269#[derive(Debug, PartialEq, Deserialize, Serialize, Default, Clone)]
270pub struct ReceiveChunkArgs {
271 #[serde(rename = "chunk")]
272 pub chunk: FileChunk,
273}
274
275#[derive(Debug, PartialEq, Deserialize, Serialize, Default, Clone)]
279pub struct FileChunk {
280 #[serde(rename = "sequenceNo")]
281 pub sequence_no: u64,
282 #[serde(rename = "container")]
283 pub container: Container,
284 #[serde(rename = "id")]
285 pub id: String,
286 #[serde(rename = "totalBytes")]
287 pub total_bytes: u64,
288 #[serde(rename = "chunkSize")]
289 pub chunk_size: u64,
290 #[serde(rename = "context")]
291 pub context: Option<String>,
292 #[serde(with = "serde_bytes")]
293 #[serde(rename = "chunkBytes")]
294 pub chunk_bytes: Vec<u8>,
295}
296
297#[derive(Debug, PartialEq, Deserialize, Serialize, Default, Clone)]
300pub struct Container {
301 #[serde(rename = "id")]
302 pub id: String,
303}
304
305#[derive(Debug, PartialEq, Deserialize, Serialize, Default, Clone)]
307pub struct ContainerList {
308 #[serde(rename = "containers")]
309 pub containers: Vec<Container>,
310}
311
312#[derive(Debug, PartialEq, Deserialize, Serialize, Default, Clone)]
315pub struct Blob {
316 #[serde(rename = "id")]
317 pub id: String,
318 #[serde(rename = "container")]
319 pub container: Container,
320 #[serde(rename = "byteSize")]
321 pub byte_size: u64,
322}
323
324#[derive(Debug, PartialEq, Deserialize, Serialize, Default, Clone)]
326pub struct BlobList {
327 #[serde(rename = "blobs")]
328 pub blobs: Vec<Blob>,
329}
330
331#[derive(Debug, PartialEq, Deserialize, Serialize, Default, Clone)]
332pub struct Transfer {
333 #[serde(rename = "blobId")]
334 pub blob_id: String,
335 #[serde(rename = "container")]
336 pub container: Container,
337 #[serde(rename = "chunkSize")]
338 pub chunk_size: u64,
339 #[serde(rename = "totalSize")]
340 pub total_size: u64,
341 #[serde(rename = "totalChunks")]
342 pub total_chunks: u64,
343 #[serde(rename = "context")]
344 pub context: Option<String>,
345}
346
347#[derive(Debug, PartialEq, Deserialize, Serialize, Default, Clone)]
349pub struct BlobstoreResult {
350 #[serde(rename = "success")]
351 pub success: bool,
352 #[serde(rename = "error")]
353 pub error: Option<String>,
354}
355
356pub fn serialize<T>(
360 item: T,
361) -> ::std::result::Result<Vec<u8>, Box<dyn std::error::Error + Send + Sync>>
362where
363 T: Serialize,
364{
365 let mut buf = Vec::new();
366 item.serialize(&mut Serializer::new(&mut buf).with_struct_map())?;
367 Ok(buf)
368}
369
370pub fn deserialize<'de, T: Deserialize<'de>>(
374 buf: &[u8],
375) -> ::std::result::Result<T, Box<dyn std::error::Error + Send + Sync>> {
376 let mut de = Deserializer::new(Cursor::new(buf));
377 match Deserialize::deserialize(&mut de) {
378 Ok(t) => Ok(t),
379 Err(e) => Err(format!("Failed to de-serialize: {}", e).into()),
380 }
381}