bcs_stream - [mainnet]
This module enables the deserialization of BCS-formatted byte arrays into Move primitive types. Deserialization Strategies:
use 0x1::error;use 0x1::from_bcs;use 0x1::string;use 0x1::vector;
Constants
The data does not fit the expected format.
const EMALFORMED_DATA: u64 = 1;
There are not enough bytes to deserialize for the given type.
const EOUT_OF_BYTES: u64 = 2;
Structs
BCSStream
struct BCSStream has drop
Fields
-
data: vector<u8>
- Byte buffer containing the serialized data.
-
cur: u64
- Cursor indicating the current position in the byte buffer.
Functions
new
Constructs a new BCSStream instance from the provided byte array.
public fun new(data: vector<u8>): bcs_stream::BCSStream
Implementation
public fun new(data: vector<u8>): BCSStream { BCSStream { data, cur: 0, }}
deserialize_uleb128
Deserializes a ULEB128-encoded integer from the stream. In the BCS format, lengths of vectors are represented using ULEB128 encoding.
public fun deserialize_uleb128(stream: &mut bcs_stream::BCSStream): u64
Implementation
public fun deserialize_uleb128(stream: &mut BCSStream): u64 { let res = 0; let shift = 0;
while (stream.cur < vector::length(&stream.data)) { let byte = *vector::borrow(&stream.data, stream.cur); stream.cur = stream.cur + 1;
let val = ((byte & 0x7f) as u64); if (((val << shift) >> shift) != val) { abort error::invalid_argument(EMALFORMED_DATA) }; res = res | (val << shift);
if ((byte & 0x80) == 0) { if (shift > 0 && val == 0) { abort error::invalid_argument(EMALFORMED_DATA) }; return res };
shift = shift + 7; if (shift > 64) { abort error::invalid_argument(EMALFORMED_DATA) }; };
abort error::out_of_range(EOUT_OF_BYTES)}
deserialize_bool
Deserializes a bool
value from the stream.
public fun deserialize_bool(stream: &mut bcs_stream::BCSStream): bool
Implementation
public fun deserialize_bool(stream: &mut BCSStream): bool { assert!(stream.cur < vector::length(&stream.data), error::out_of_range(EOUT_OF_BYTES)); let byte = *vector::borrow(&stream.data, stream.cur); stream.cur = stream.cur + 1; if (byte == 0) { false } else if (byte == 1) { true } else { abort error::invalid_argument(EMALFORMED_DATA) }}
deserialize_address
Deserializes an address
value from the stream.
32-byte address
values are serialized using little-endian byte order.
This function utilizes the to_address
function from the aptos_std::from_bcs
module,
because the Move type system does not permit per-byte referencing of addresses.
public fun deserialize_address(stream: &mut bcs_stream::BCSStream): address
Implementation
public fun deserialize_address(stream: &mut BCSStream): address { let data = &stream.data; let cur = stream.cur;
assert!(cur + 32 <= vector::length(data), error::out_of_range(EOUT_OF_BYTES)); let res = from_bcs::to_address(vector::slice(data, cur, cur + 32));
stream.cur = cur + 32; res}
deserialize_u8
Deserializes a u8
value from the stream.
1-byte u8
values are serialized using little-endian byte order.
public fun deserialize_u8(stream: &mut bcs_stream::BCSStream): u8
Implementation
public fun deserialize_u8(stream: &mut BCSStream): u8 { let data = &stream.data; let cur = stream.cur;
assert!(cur < vector::length(data), error::out_of_range(EOUT_OF_BYTES));
let res = *vector::borrow(data, cur);
stream.cur = cur + 1; res}
deserialize_u16
Deserializes a u16
value from the stream.
2-byte u16
values are serialized using little-endian byte order.
public fun deserialize_u16(stream: &mut bcs_stream::BCSStream): u16
Implementation
public fun deserialize_u16(stream: &mut BCSStream): u16 { let data = &stream.data; let cur = stream.cur;
assert!(cur + 2 <= vector::length(data), error::out_of_range(EOUT_OF_BYTES)); let res = (*vector::borrow(data, cur) as u16) | ((*vector::borrow(data, cur + 1) as u16) << 8) ;
stream.cur = stream.cur + 2; res}
deserialize_u32
Deserializes a u32
value from the stream.
4-byte u32
values are serialized using little-endian byte order.
public fun deserialize_u32(stream: &mut bcs_stream::BCSStream): u32
Implementation
public fun deserialize_u32(stream: &mut BCSStream): u32 { let data = &stream.data; let cur = stream.cur;
assert!(cur + 4 <= vector::length(data), error::out_of_range(EOUT_OF_BYTES)); let res = (*vector::borrow(data, cur) as u32) | ((*vector::borrow(data, cur + 1) as u32) << 8) | ((*vector::borrow(data, cur + 2) as u32) << 16) | ((*vector::borrow(data, cur + 3) as u32) << 24) ;
stream.cur = stream.cur + 4; res}
deserialize_u64
Deserializes a u64
value from the stream.
8-byte u64
values are serialized using little-endian byte order.
public fun deserialize_u64(stream: &mut bcs_stream::BCSStream): u64
Implementation
public fun deserialize_u64(stream: &mut BCSStream): u64 { let data = &stream.data; let cur = stream.cur;
assert!(cur + 8 <= vector::length(data), error::out_of_range(EOUT_OF_BYTES)); let res = (*vector::borrow(data, cur) as u64) | ((*vector::borrow(data, cur + 1) as u64) << 8) | ((*vector::borrow(data, cur + 2) as u64) << 16) | ((*vector::borrow(data, cur + 3) as u64) << 24) | ((*vector::borrow(data, cur + 4) as u64) << 32) | ((*vector::borrow(data, cur + 5) as u64) << 40) | ((*vector::borrow(data, cur + 6) as u64) << 48) | ((*vector::borrow(data, cur + 7) as u64) << 56) ;
stream.cur = stream.cur + 8; res}
deserialize_u128
Deserializes a u128
value from the stream.
16-byte u128
values are serialized using little-endian byte order.
public fun deserialize_u128(stream: &mut bcs_stream::BCSStream): u128
Implementation
public fun deserialize_u128(stream: &mut BCSStream): u128 { let data = &stream.data; let cur = stream.cur;
assert!(cur + 16 <= vector::length(data), error::out_of_range(EOUT_OF_BYTES)); let res = (*vector::borrow(data, cur) as u128) | ((*vector::borrow(data, cur + 1) as u128) << 8) | ((*vector::borrow(data, cur + 2) as u128) << 16) | ((*vector::borrow(data, cur + 3) as u128) << 24) | ((*vector::borrow(data, cur + 4) as u128) << 32) | ((*vector::borrow(data, cur + 5) as u128) << 40) | ((*vector::borrow(data, cur + 6) as u128) << 48) | ((*vector::borrow(data, cur + 7) as u128) << 56) | ((*vector::borrow(data, cur + 8) as u128) << 64) | ((*vector::borrow(data, cur + 9) as u128) << 72) | ((*vector::borrow(data, cur + 10) as u128) << 80) | ((*vector::borrow(data, cur + 11) as u128) << 88) | ((*vector::borrow(data, cur + 12) as u128) << 96) | ((*vector::borrow(data, cur + 13) as u128) << 104) | ((*vector::borrow(data, cur + 14) as u128) << 112) | ((*vector::borrow(data, cur + 15) as u128) << 120) ;
stream.cur = stream.cur + 16; res}
deserialize_u256
Deserializes a u256
value from the stream.
32-byte u256
values are serialized using little-endian byte order.
public fun deserialize_u256(stream: &mut bcs_stream::BCSStream): u256
Implementation
public fun deserialize_u256(stream: &mut BCSStream): u256 { let data = &stream.data; let cur = stream.cur;
assert!(cur + 32 <= vector::length(data), error::out_of_range(EOUT_OF_BYTES)); let res = (*vector::borrow(data, cur) as u256) | ((*vector::borrow(data, cur + 1) as u256) << 8) | ((*vector::borrow(data, cur + 2) as u256) << 16) | ((*vector::borrow(data, cur + 3) as u256) << 24) | ((*vector::borrow(data, cur + 4) as u256) << 32) | ((*vector::borrow(data, cur + 5) as u256) << 40) | ((*vector::borrow(data, cur + 6) as u256) << 48) | ((*vector::borrow(data, cur + 7) as u256) << 56) | ((*vector::borrow(data, cur + 8) as u256) << 64) | ((*vector::borrow(data, cur + 9) as u256) << 72) | ((*vector::borrow(data, cur + 10) as u256) << 80) | ((*vector::borrow(data, cur + 11) as u256) << 88) | ((*vector::borrow(data, cur + 12) as u256) << 96) | ((*vector::borrow(data, cur + 13) as u256) << 104) | ((*vector::borrow(data, cur + 14) as u256) << 112) | ((*vector::borrow(data, cur + 15) as u256) << 120) | ((*vector::borrow(data, cur + 16) as u256) << 128) | ((*vector::borrow(data, cur + 17) as u256) << 136) | ((*vector::borrow(data, cur + 18) as u256) << 144) | ((*vector::borrow(data, cur + 19) as u256) << 152) | ((*vector::borrow(data, cur + 20) as u256) << 160) | ((*vector::borrow(data, cur + 21) as u256) << 168) | ((*vector::borrow(data, cur + 22) as u256) << 176) | ((*vector::borrow(data, cur + 23) as u256) << 184) | ((*vector::borrow(data, cur + 24) as u256) << 192) | ((*vector::borrow(data, cur + 25) as u256) << 200) | ((*vector::borrow(data, cur + 26) as u256) << 208) | ((*vector::borrow(data, cur + 27) as u256) << 216) | ((*vector::borrow(data, cur + 28) as u256) << 224) | ((*vector::borrow(data, cur + 29) as u256) << 232) | ((*vector::borrow(data, cur + 30) as u256) << 240) | ((*vector::borrow(data, cur + 31) as u256) << 248) ;
stream.cur = stream.cur + 32; res}
deserialize_u256_entry
Deserializes a u256
value from the stream.
public entry fun deserialize_u256_entry(data: vector<u8>, cursor: u64)
Implementation
public entry fun deserialize_u256_entry(data: vector<u8>, cursor: u64) { let stream = BCSStream { data: data, cur: cursor, }; deserialize_u256(&mut stream);}
deserialize_vector
Deserializes an array of BCS deserializable elements from the stream.
First, reads the length of the vector, which is in uleb128 format.
After determining the length, it then reads the contents of the vector.
The elem_deserializer
lambda expression is used sequentially to deserialize each element of the vector.
public fun deserialize_vector<E>(stream: &mut bcs_stream::BCSStream, elem_deserializer: |&mut bcs_stream::BCSStream|E): vector<E>
Implementation
public inline fun deserialize_vector<E>(stream: &mut BCSStream, elem_deserializer: |&mut BCSStream| E): vector<E> { let len = deserialize_uleb128(stream); let v = vector::empty();
let i = 0; while (i < len) { vector::push_back(&mut v, elem_deserializer(stream)); i = i + 1; };
v}
deserialize_string
Deserializes utf-8 String
from the stream.
First, reads the length of the String, which is in uleb128 format.
After determining the length, it then reads the contents of the String.
public fun deserialize_string(stream: &mut bcs_stream::BCSStream): string::String
Implementation
public fun deserialize_string(stream: &mut BCSStream): String { let len = deserialize_uleb128(stream); let data = &stream.data; let cur = stream.cur;
assert!(cur + len <= vector::length(data), error::out_of_range(EOUT_OF_BYTES));
let res = string::utf8(vector::slice(data, cur, cur + len)); stream.cur = cur + len;
res}
deserialize_option
Deserializes Option
from the stream.
First, reads a single byte representing the presence (0x01) or absence (0x00) of data.
After determining the presence of data, it then reads the actual data if present.
The elem_deserializer
lambda expression is used to deserialize the element contained within the Option
.
public fun deserialize_option<E>(stream: &mut bcs_stream::BCSStream, elem_deserializer: |&mut bcs_stream::BCSStream|E): option::Option<E>
Implementation
public inline fun deserialize_option<E>(stream: &mut BCSStream, elem_deserializer: |&mut BCSStream| E): Option<E> { let is_data = deserialize_bool(stream); if (is_data) { option::some(elem_deserializer(stream)) } else { option::none() }}
Specification
pragma verify = false;