Skip to main content

k3_wasm_sdk/
lib.rs

1pub mod http;
2pub mod ipfs;
3pub mod kv;
4pub mod sc;
5pub mod sxt;
6pub mod stellar;
7
8use core::panic;
9use std::str::FromStr;
10
11pub use dotenvy;
12pub use web3;
13
14use bytecodec::{
15    bytes::{BytesEncoder, RemainingBytesDecoder},
16    io::{IoDecodeExt, IoEncodeExt},
17    Encode,
18};
19use httpcodec::{BodyDecoder, BodyEncoder, RequestDecoder, ResponseEncoder};
20
21#[no_mangle]
22pub static mut ENV_VAR_PTR: *const u8 = std::ptr::null();
23
24#[no_mangle]
25pub static mut ENV_VAR_LEN: usize = 0;
26
27#[no_mangle]
28pub static mut RES_PTR: *const u8 = std::ptr::null();
29
30/// requires define_k3_write_inputs macro
31pub fn get_args(arg_ptr: *const u8, arg_len: usize) -> String {
32    let arg_str = unsafe {
33        if arg_ptr.is_null() {
34            panic!("ARG_PTR must be set.");
35        }
36
37        let json_bytes = std::slice::from_raw_parts(arg_ptr, arg_len);
38        std::str::from_utf8_unchecked(json_bytes)
39    };
40    arg_str.to_string()
41}
42
43pub fn set_env_context() {
44    let env_var_bytes = unsafe {
45        if ENV_VAR_PTR.is_null() {
46            panic!("ENV_VAR_PTR must be set")
47        }
48        std::slice::from_raw_parts(ENV_VAR_PTR, ENV_VAR_LEN)
49    };
50
51    dotenvy::from_read_override(env_var_bytes).unwrap();
52}
53
54pub fn encode_response(res: http::Response<Vec<u8>>) -> u32 {
55    let (parts, body) = res.into_parts();
56    let version = if parts.version == http::Version::HTTP_10 {
57        httpcodec::HttpVersion::V1_0
58    } else if parts.version == http::Version::HTTP_11 {
59        httpcodec::HttpVersion::V1_1
60    } else {
61        panic!("Only HTTP 1.0 and 1.1 are supported")
62    };
63    let mut enc_res = unsafe {
64        httpcodec::Response::new(
65            version,
66            httpcodec::StatusCode::new_unchecked(parts.status.as_u16()),
67            httpcodec::ReasonPhrase::new_unchecked(parts.status.canonical_reason().unwrap_or("")),
68            body,
69        )
70    };
71    let mut enc_headers = enc_res.header_mut();
72    for header in parts.headers {
73        let name = header
74            .0
75            .map(|name| name.to_string())
76            .unwrap_or("".to_string());
77        let value = header.1.to_str().unwrap();
78        enc_headers.add_field(unsafe { httpcodec::HeaderField::new_unchecked(&name, value) });
79    }
80
81    let mut encoder = ResponseEncoder::<BodyEncoder<BytesEncoder>>::default();
82    encoder.start_encoding(enc_res).unwrap();
83    let mut res_buf = Vec::new();
84    encoder.encode_all(&mut res_buf).unwrap();
85    let mut res_buf_with_len = (res_buf.len() as u32).to_le_bytes().to_vec();
86    res_buf_with_len.append(&mut res_buf);
87    let ptr = res_buf_with_len.as_ptr();
88    std::mem::forget(res_buf_with_len);
89    ptr as u32
90}
91
92pub fn request_from_raw_parts(req_ptr: u32, req_len: u32) -> http::Request<Vec<u8>> {
93    let req_buf = unsafe { std::slice::from_raw_parts(req_ptr as *const u8, req_len as usize) };
94    let mut decoder = RequestDecoder::<BodyDecoder<RemainingBytesDecoder>>::default();
95    let dec_req = decoder.decode_exact(req_buf).unwrap();
96    let mut req = http::Request::builder()
97        .version(match dec_req.http_version() {
98            httpcodec::HttpVersion::V1_0 => http::Version::HTTP_10,
99            httpcodec::HttpVersion::V1_1 => http::Version::HTTP_11,
100        })
101        .method(http::Method::from_str(dec_req.method().as_str()).unwrap())
102        .uri(http::Uri::from_str(dec_req.request_target().as_str()).unwrap());
103    for header in dec_req.header().fields() {
104        req = req.header(header.name(), header.value());
105    }
106
107    let req = req.body(dec_req.into_body()).unwrap();
108    req
109}