# `Lightstreamer.Protocol.Frame`
[🔗](https://github.com/ktec/lightstreamer/blob/v0.1.0/lib/lightstreamer/protocol/frame.ex#L1)

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.

# `t`

```elixir
@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.

# `parse`

```elixir
@spec parse(binary()) :: t()
```

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

---

*Consult [api-reference.md](api-reference.md) for complete listing*
