1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
use super::error::{Error, StorageError, StreamError};
use super::stream::{BaseStream, ReadStream};
use num_traits::FromPrimitive;
use serde::{Deserialize, Serialize};
use serde_json;
use std::collections::HashMap;

/// Response to the [`crate::storage::get`] request.
///
/// [get]: super::storage::get
#[derive(Debug)]
pub struct StorageResponse {
    headers: HashMap<String, String>,
    read_stream: ReadStream,
}

/// Represents the attributes associated with a stored file.
///
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct FileAttributes {
    pub properties: Option<HashMap<String, String>>,
    #[serde(rename = "defaultVersion")]
    pub default_version: Option<String>,
}

impl FileAttributes {
    pub fn new(
        properties: Option<HashMap<String, String>>,
        default_version: Option<String>,
    ) -> Self {
        FileAttributes {
            properties,
            default_version,
        }
    }
    pub fn from_bytes(bytes: Vec<u8>) -> Result<Self, StorageError> {
        let attr: FileAttributes = serde_json::from_slice(&bytes)?;
        Ok(attr)
    }
}

impl StorageResponse {
    pub fn new() -> Result<StorageResponse, StorageError> {
        let headers: HashMap<String, String>;
        headers = match get_all_headers_from_host_streaming(0) {
            Ok(headers) => headers,
            Err(err) => return Err(err),
        };
        let read_sd = match get_read_stream_host_streaming(0) {
            Ok(sd) => sd,
            Err(err) => return Err(err),
        };

        Ok(StorageResponse {
            headers: headers,
            read_stream: BaseStream::new(read_sd),
        })
    }

    /// Returns the metadata associated with the storage object.
    pub fn headers(&self) -> &HashMap<String, String> {
        return &self.headers;
    }

    /// Retrieves the bytes of the storage object.
    pub fn read_body(&mut self) -> Result<Vec<u8>, StreamError> {
        let result = self.read_stream.read_all();
        let closed = self.read_stream.close();

        if result.is_err() {
            return result;
        }

        if closed.is_err() {
            return Err(closed.err().unwrap());
        }

        return result;
    }

    /// Returns the read stream.
    pub fn get_read_stream(&mut self) -> &mut ReadStream {
        return &mut self.read_stream;
    }
}

#[link(wasm_import_module = "storage_response")]
extern "C" {
    fn storage_response_get_headers_streaming(sd: u32, err_ptr: *mut i32) -> i32;
    fn http_storage_response_get_read_stream(
        sd: u32,
        read_sd_ptr: *mut u32,
        err_ptr: *mut i32,
    ) -> i32;
}

/// [`StorageResponsePending`] is a placeholder for the EDJX Object Store's
/// response. It is returned when [`crate::storage::put_streaming`] is called.
/// It is used to retrive a [`StorageResponse`] once it is ready.
pub struct StorageResponsePending {
    sd: u32,
}

impl StorageResponsePending {
    pub fn new(stream_desc: u32) -> Self {
        StorageResponsePending { sd: stream_desc }
    }

    /// This function is used to to retrive a [`StorageResponse`]
    pub fn get_storage_response(&self) -> Result<StorageResponse, StorageError> {
        let headers: HashMap<String, String>;
        headers = match get_all_headers_from_host_streaming(self.sd) {
            Ok(headers) => headers,
            Err(err) => return Err(err),
        };
        let read_sd = match get_read_stream_host_streaming(self.sd) {
            Ok(sd) => sd,
            Err(err) => return Err(err),
        };

        Ok(StorageResponse {
            headers: headers,
            read_stream: BaseStream::new(read_sd),
        })
    }
}

fn get_all_headers_from_host_streaming(sd: u32) -> Result<HashMap<String, String>, StorageError> {
    let mut err: i32 = 0;
    let result_size = unsafe { storage_response_get_headers_streaming(sd, &mut err) };

    if result_size > 0 {
        let result = super::result::get_result_bytes(result_size).unwrap();
        let res: HashMap<String, String> = serde_json::from_slice(&result).unwrap();
        Ok(res)
    } else if result_size == 0 {
        return Ok(HashMap::new());
    } else {
        return Err(StorageError::from(Error::from_i32(err).unwrap()));
    }
}

fn get_read_stream_host_streaming(sd: u32) -> Result<u32, StorageError> {
    let mut err_code: i32 = 0;
    let mut read_sd: u32 = 0;
    let response =
        unsafe { http_storage_response_get_read_stream(sd, &mut read_sd, &mut err_code) };

    if response < 0 {
        Err(StorageError::from(Error::from_i32(err_code).unwrap()))
    } else {
        Ok(read_sd)
    }
}