Current section
Files
Jump to
Current section
Files
src/types/limits.gleam
import gleam/bit_array
import gleam/list
import gleam/option.{type Option, Some, None}
import gleam/result
import util
import types/vector as vector
// https://webassembly.github.io/spec/core/binary/types.html#limits
pub type Limits
{
Limits(min: Int, max: Option(Int))
}
pub fn from_raw_data(at position: Int, from raw_data: BitArray) -> Result(#(Limits, Int), String)
{
// From the spec: "limits are encoded with a preceding flag indicating whether a maximum is present."
use has_max <- result.try(
case bit_array.slice(at: position, from: raw_data, take: 1)
{
Ok(<<0x00>>) -> Ok(False)
Ok(<<0x01>>) -> Ok(True)
Ok(_) | Error(_) -> Error("limits::from_raw_data: can't get has_max flag")
}
)
use #(min, min_word_size) <- result.try(util.decode_u32leb128(at: position + 1, from: raw_data))
let bytes_read = 1 + min_word_size
use maybe_max <- result.try(
case has_max
{
True ->
{
use mx <- result.try(util.decode_u32leb128(at: position + min_word_size + 1, from: raw_data))
Ok(Some(mx))
}
False ->
{
Ok(None)
}
}
)
let bytes_read = case maybe_max
{
Some(#(_, max_word_size)) -> bytes_read + max_word_size
None -> bytes_read
}
case maybe_max
{
Some(#(max, _)) -> Ok(#(Limits(min: min, max: Some(max)), bytes_read))
None -> Ok(#(Limits(min: min, max: None), bytes_read))
}
}
pub fn do_from_vector(at position_accumulator: Int, from vec: vector.Vector, to result_accumulator: List(Limits)) -> Result(#(List(Limits), Int), String)
{
case position_accumulator < vec.length
{
True ->
{
case from_raw_data(at: position_accumulator, from: vec.data)
{
Ok(limit) ->
{
let result_accumulator = list.append(result_accumulator, [limit.0])
do_from_vector(at: position_accumulator + limit.1, from: vec, to: result_accumulator)
}
Error(reason) -> Error(reason)
}
}
False -> Ok(#(result_accumulator, position_accumulator))
}
}
pub fn from_vector(from vec: vector.Vector)
{
do_from_vector(at: 0, from: vec, to: [])
}