139 lines
3.6 KiB
TypeScript
Raw Normal View History

2019-04-10 17:12:25 +03:00
const RESPONSE_SIZE_BYTES = 4;
2019-04-09 12:37:21 +03:00
/**
2019-04-09 15:59:59 +03:00
* Reads array of bytes from a given `ptr` that has to have `len` bytes size.
*
2019-04-09 12:37:21 +03:00
*/
2019-04-09 16:59:12 +03:00
export function readRequestBytes(ptr: i32, size: i32): Uint8Array {
2019-04-09 12:37:21 +03:00
let bb: Uint8Array = new Uint8Array(size);
for (let i = 0; i < size; i++) {
bb[i] = load<u8>(ptr + i)
}
2019-08-12 19:29:06 +03:00
__free(changetype<usize>(ptr));
2019-04-10 17:12:25 +03:00
2019-04-09 12:37:21 +03:00
return bb;
}
2019-04-09 15:59:59 +03:00
/**
* Reads string from a given `ptr` that has to have `len` bytes size.
*
*/
2019-04-09 16:59:12 +03:00
export function readRequestString(ptr: i32, size: i32): string {
2019-04-09 12:37:21 +03:00
let bb = readRequestBytes(ptr, size);
2019-08-12 19:29:06 +03:00
let request = String.UTF8.decode(bb.buffer);
__free(changetype<usize>(bb));
2019-04-10 19:28:34 +03:00
return request
2019-04-09 12:37:21 +03:00
}
2019-04-09 15:59:59 +03:00
/**
2019-04-10 17:18:59 +03:00
* Allocates 'RESPONSE_SIZE_BYTES + response.len()' bytes and writes length of the response as little
* endianes RESPONSE_SIZE_BYTES bytes and then writes content of 'response'. So the final layout of
* the response in memory is following:
2019-04-09 15:59:59 +03:00
*
* | array_length: RESPONSE_SIZE_BYTES bytes (little-endian) | array: $array_length bytes |
*
2019-04-10 17:18:59 +03:00
* This function should normally be used for returning response of `invoke` function. Vm wrapper
* expects response in this format.
2019-04-09 15:59:59 +03:00
*
* @return response pointer
*/
2019-04-10 17:12:25 +03:00
export function writeResponseBytes(response: Uint8Array): i32 {
let len: i32 = response.length;
2019-08-12 19:29:06 +03:00
let addr = __alloc(len + RESPONSE_SIZE_BYTES, 1);
2019-04-10 17:12:25 +03:00
for (let i = 0; i < RESPONSE_SIZE_BYTES; i++) {
2019-04-09 12:37:21 +03:00
let b: u8 = (len >> i * 8) as u8 & 0xFF;
store<u8>(addr + i, b);
}
2019-04-10 17:12:25 +03:00
let responseAddr = addr + RESPONSE_SIZE_BYTES;
2019-04-09 12:37:21 +03:00
for (let i = 0; i < len; i++) {
2019-04-10 17:12:25 +03:00
let b: u8 = response[i];
2019-04-09 12:37:21 +03:00
store<u8>(responseAddr + i, b);
}
2019-08-12 19:29:06 +03:00
__free(changetype<usize>(response.buffer));
__free(changetype<usize>(response));
2019-04-09 12:37:21 +03:00
return addr;
}
2019-04-09 15:59:59 +03:00
/**
* Converts response to bytes and put it to the memory.
* @see `writeResponseBytes`
* @param response
*/
2019-04-09 16:59:12 +03:00
export function writeResponseString(response: string): i32 {
let strLen: i32 = response.length;
2019-08-12 19:29:06 +03:00
let addr = __alloc(strLen + RESPONSE_SIZE_BYTES, 1);
2019-04-10 17:12:25 +03:00
for (let i = 0; i < RESPONSE_SIZE_BYTES; i++) {
2019-04-09 12:37:21 +03:00
let b: u8 = (strLen >> i * 8) as u8 & 0xFF;
store<u8>(addr + i, b);
}
2019-04-10 17:12:25 +03:00
let strAddr = addr + RESPONSE_SIZE_BYTES;
2019-04-09 12:37:21 +03:00
for (let i = 0; i < strLen; i++) {
let b: u8 = response.charCodeAt(i) as u8;
store<u8>(strAddr + i, b);
}
return addr;
}
2019-04-09 15:59:59 +03:00
/**
* Reads request as a string, handles a request and returns pointer on a response.
*
*/
2019-04-09 16:59:12 +03:00
export function stringHandler(ptr: i32, size: i32, handler: (request: string) => string): i32 {
2019-04-09 12:37:21 +03:00
let strRequest = readRequestString(ptr, size);
2019-04-10 17:18:59 +03:00
let response = handler(strRequest);
2019-04-09 12:37:21 +03:00
2019-04-10 17:18:59 +03:00
let responseAddr = writeResponseString(response);
2019-08-12 19:29:06 +03:00
__free(ptr);
__free(changetype<usize>(strRequest));
__free(changetype<usize>(response));
2019-04-09 12:37:21 +03:00
return responseAddr;
}
2019-04-09 16:13:52 +03:00
/**
* Reads request as a string, handles a request and returns pointer on a response.
* Logs request and response.
*
*/
2019-04-09 17:14:03 +03:00
export function loggedStringHandler(ptr: i32, size: i32, handler: (request: string) => string, log: (msg: string) => void): i32 {
2019-04-09 16:13:52 +03:00
let strRequest = readRequestString(ptr, size);
log("Request: " + strRequest);
2019-04-10 17:18:59 +03:00
let response = handler(strRequest);
2019-04-09 16:13:52 +03:00
2019-04-10 17:18:59 +03:00
let responseAddr = writeResponseString(response);
2019-08-12 19:29:06 +03:00
__free(ptr);
__free(changetype<usize>(strRequest));
2019-04-09 16:13:52 +03:00
2019-04-10 17:18:59 +03:00
log("Response: " + response);
2019-04-09 16:13:52 +03:00
2019-08-12 19:29:06 +03:00
__free(changetype<usize>(response));
2019-04-10 19:28:34 +03:00
2019-04-09 16:13:52 +03:00
return responseAddr;
}
2019-04-09 15:59:59 +03:00
/**
* Reads request as bytes, handles a request and returns pointer on a response.
*
*/
2019-04-09 17:14:03 +03:00
export function bytesHandler(ptr: i32, size: i32, handler: (request: Uint8Array) => Uint8Array): i32 {
2019-04-09 12:37:21 +03:00
let bytesRequest = readRequestBytes(ptr, size);
2019-04-10 17:18:59 +03:00
let response = handler(bytesRequest);
2019-04-09 12:37:21 +03:00
2019-04-10 17:18:59 +03:00
let responseAddr = writeResponseBytes(response);
2019-08-12 19:29:06 +03:00
__free(ptr);
__free(changetype<usize>(bytesRequest));
2019-04-09 12:37:21 +03:00
return responseAddr;
}