///|
pub suberror FgbError {
InvalidData(Int32, String)
Unsupported(String)
LimitExceeded(String)
InvalidArgument(String)
} derive(Debug)
///|
pub(all) struct Limits {
max_header_bytes : Int32
max_feature_bytes : Int32
max_features : Int32
max_columns : Int32
max_coordinates : Int32
max_string_bytes : Int32
max_depth : Int32
max_index_nodes : Int32
max_file_bytes : Int32
} derive(Eq, Debug, ToJson, @json.FromJson)
///|
pub fn Limits::default() -> Limits {
{
max_header_bytes: 1048576,
max_feature_bytes: 16777216,
max_features: 1000000,
max_columns: 1024,
max_coordinates: 1000000,
max_string_bytes: 1048576,
max_depth: 32,
max_index_nodes: 2000000,
max_file_bytes: 1073741824,
}
}
///|
pub fn Limits::validate(self : Limits) -> Unit raise FgbError {
if self.max_header_bytes < 8 || self.max_feature_bytes < 8 {
raise InvalidArgument("buffer limits must be at least 8")
}
if self.max_features < 1 || self.max_columns < 1 {
raise InvalidArgument("feature and column limits must be positive")
}
if self.max_columns > 65536 {
raise InvalidArgument("column limit exceeds unsigned 16-bit keys")
}
if self.max_coordinates < 1 || self.max_string_bytes < 1 {
raise InvalidArgument("coordinate and string limits must be positive")
}
if self.max_depth < 1 || self.max_depth > 256 {
raise InvalidArgument("depth limit must be between 1 and 256")
}
if self.max_index_nodes < 1 || self.max_file_bytes < 12 {
raise InvalidArgument("index and file limits must be positive")
}
}
///|
fn require_range(
data : Bytes,
offset : Int32,
size : Int32,
) -> Unit raise FgbError {
if offset < 0 ||
size < 0 ||
offset > data.length() ||
size > data.length() - offset {
raise InvalidData(offset, "truncated or out-of-range buffer")
}
}
///|
fn checked_add(a : Int32, b : Int32) -> Int32 raise FgbError {
if a < 0 || b < 0 || a > 2147483647 - b {
raise InvalidData(a, "offset addition overflow")
}
a + b
}
///|
fn checked_mul(a : Int32, b : Int32) -> Int32 raise FgbError {
if a < 0 || b < 0 || (b != 0 && a > 2147483647 / b) {
raise InvalidData(a, "size multiplication overflow")
}
a * b
}
///|
fn enforce(value : Int32, limit : Int32, name : String) -> Unit raise FgbError {
if value > limit {
raise LimitExceeded(name)
}
}
///|
fn finite(value : Double) -> Bool {
value == value && value != 1.0 / 0.0 && value != -1.0 / 0.0
}