Replace the protobuf hex package (agent.pb.ex) and hand-written validator
(validator.ex) with a pure Gleam implementation: wire format primitives,
all 23 message types, encode/decode functions, and validation merged into
decode. Thin Elixir wrappers in agent.ex preserve the existing struct API.
- Wire format: varint, length-delimited, double (IEEE 754 via FFI), tag encode/decode
- Types: all proto3 message types as Gleam custom types with enums and oneof
- Decode: field-level parsing with integrated validation (UUID, IP, hostname, limits)
- Encode: proto3 default omission, bytes_tree concatenation, map/repeated fields
- Wrappers: Elixir structs with encode/decode delegating to Gleam, enum atom conversion
- Remove {:protobuf, "~> 0.12"} dependency
Reviewed-on: graham/towerops-web#104
54 lines
1.6 KiB
Erlang
54 lines
1.6 KiB
Erlang
-module(towerops_proto_wire_ffi).
|
|
-export([encode_double/1, decode_double/1, split_bytes/2,
|
|
bits_append/2, string_to_bits/1,
|
|
int_and/2, int_or/2, shift_left/2, shift_right/2]).
|
|
|
|
%% Encode a float as 8-byte little-endian IEEE 754 double.
|
|
-spec encode_double(float()) -> binary().
|
|
encode_double(Value) ->
|
|
<<Value:64/float-little>>.
|
|
|
|
%% Decode 8 bytes as a little-endian IEEE 754 double.
|
|
-spec decode_double(binary()) -> {ok, float()} | {error, nil}.
|
|
decode_double(<<Value:64/float-little>>) ->
|
|
{ok, Value};
|
|
decode_double(_) ->
|
|
{error, nil}.
|
|
|
|
%% Split a binary into two parts at position Len.
|
|
-spec split_bytes(binary(), non_neg_integer()) -> {ok, {binary(), binary()}} | {error, nil}.
|
|
split_bytes(Data, Len) when byte_size(Data) >= Len ->
|
|
<<Part:Len/binary, Rest/binary>> = Data,
|
|
{ok, {Part, Rest}};
|
|
split_bytes(_, _) ->
|
|
{error, nil}.
|
|
|
|
%% Append two binaries.
|
|
-spec bits_append(binary(), binary()) -> binary().
|
|
bits_append(A, B) ->
|
|
<<A/binary, B/binary>>.
|
|
|
|
%% Convert a string (binary) to bits (identity for BEAM).
|
|
-spec string_to_bits(binary()) -> binary().
|
|
string_to_bits(S) ->
|
|
S.
|
|
|
|
%% Bitwise AND.
|
|
-spec int_and(integer(), integer()) -> integer().
|
|
int_and(A, B) ->
|
|
A band B.
|
|
|
|
%% Bitwise OR.
|
|
-spec int_or(integer(), integer()) -> integer().
|
|
int_or(A, B) ->
|
|
A bor B.
|
|
|
|
%% Bitwise shift left.
|
|
-spec shift_left(integer(), non_neg_integer()) -> integer().
|
|
shift_left(Value, Bits) ->
|
|
Value bsl Bits.
|
|
|
|
%% Bitwise shift right (arithmetic).
|
|
-spec shift_right(integer(), non_neg_integer()) -> integer().
|
|
shift_right(Value, Bits) ->
|
|
Value bsr Bits.
|