Pure parser for single TLCP server lines (CR-LF already stripped).
Tag dispatch is one function head per tag on a binary prefix — the line is
never split just to identify the tag. Each tag has a fixed argument count,
so splitting is bounded and the unsplit remainder is the last argument,
which is how literal commas in trailing arguments survive. Arguments are
percent-decoded, except the field payload of U, which has its own
second-level syntax and is handed to Lightstreamer.Protocol.Update raw.
Returned sub-binaries reference the parent line; callers retaining values
past the current frame must :binary.copy/1 at the point of retention.
Summary
Functions
Parses one server line into a tagged tuple.
Types
@type t() :: {:conok, session_id :: binary(), request_limit :: non_neg_integer(), keepalive_millis :: non_neg_integer(), control_link :: binary()} | {:conerr, code :: integer(), message :: binary()} | {:end, code :: integer(), message :: binary()} | {:loop, expected_delay_millis :: non_neg_integer()} | :wsok | {:reqok, req_id :: pos_integer()} | {:reqerr, req_id :: pos_integer(), code :: integer(), message :: binary()} | {:subok, sub_id :: pos_integer(), num_items :: pos_integer(), num_fields :: pos_integer()} | {:conf, sub_id :: pos_integer(), max_frequency :: :unlimited | float(), :filtered | :unfiltered} | {:unsub, sub_id :: pos_integer()} | {:u, sub_id :: pos_integer(), item_index :: pos_integer(), raw_fields :: binary()} | {:eos, sub_id :: pos_integer(), item_index :: pos_integer()} | {:cs, sub_id :: pos_integer(), item_index :: pos_integer()} | {:ov, sub_id :: pos_integer(), item_index :: pos_integer(), lost :: pos_integer()} | :probe | :noop | {:prog, count :: non_neg_integer()} | {:servname, binary()} | {:clientip, binary()} | {:cons, :unlimited | float()} | {:sync, seconds :: non_neg_integer()} | {:unknown, binary()}
One parsed server line.
Functions
Parses one server line into a tagged tuple.
Unknown tags pass through as {:unknown, line} for forward compatibility.
Examples
iex> Lightstreamer.Protocol.Frame.parse("CONOK,Sid123,50000,5000,*")
{:conok, "Sid123", 50000, 5000, "*"}
iex> Lightstreamer.Protocol.Frame.parse("U,3,1,20:00:33|3.04|#|$")
{:u, 3, 1, "20:00:33|3.04|#|$"}
iex> Lightstreamer.Protocol.Frame.parse("PROBE")
:probe