///|
pub fn decode_feature(
data : Bytes,
header : Header,
limits~ : Limits = Limits::default(),
) -> Feature raise FgbError {
limits.validate()
let payload = sized_payload(data, 0, limits.max_feature_bytes)
if payload.length() + 4 != data.length() {
raise InvalidData(0, "trailing bytes after feature")
}
let table = TableView::root(payload)
if table.reference(2) != 0 {
raise Unsupported("per-feature column schemas")
}
let geometry_at = table.reference(0)
let geometry = if geometry_at == 0 {
None
} else {
Some(
read_geometry(
payload,
geometry_at,
header.geometry_kind,
limits,
1,
Ref(0),
),
)
}
let (properties_at, properties_size) = table.vector(
1,
1,
limits.max_feature_bytes,
)
let properties = decode_properties(
slice_bytes(payload, properties_at, properties_size),
header.columns,
limits~,
)
{ geometry, properties, }
}
///|
pub fn encode_feature(
feature : Feature,
header : Header,
limits~ : Limits = Limits::default(),
) -> Bytes raise FgbError {
limits.validate()
let properties = encode_properties(
feature.properties,
header.columns,
limits~,
)
let b = FbBuilder::new()
let table = b.table(3)
match feature.geometry {
None => ()
Some(g) => {
g.validate(limits~)
if header.geometry_kind != Unknown && header.geometry_kind != g.kind {
raise InvalidArgument("feature geometry conflicts with header type")
}
b.reference(table, 0, write_geometry(b, g))
}
}
if !properties.is_empty() {
let at = b.vector(properties.length(), 1)
b.writer.bytes(properties)
b.reference(table, 1, at)
}
let result = b.finish(table)
enforce(result.length() - 4, limits.max_feature_bytes, "feature bytes")
result
}
///|
pub(all) struct FeatureRecord {
ordinal : Int32
offset : Int32
byte_length : Int32
feature : Feature
} derive(Eq, Debug)
///|
pub fn Feature::property(
self : Feature,
header : Header,
name : String,
) -> Property? {
for i in 0..