# `ADS.Symbol`
[🔗](https://github.com/tallakt/yaads/blob/v0.1.0/lib/ads/symbol.ex#L1)

A PLC's description of one of its variables: its name, the name of its type, where it is, and
how big.

A PLC has a table of its symbols when the project is built with symbols, as TwinCAT does by
default. `ADS.Client.symbol/3` asks for one by name (index group `0xF009`), and
`ADS.Client.symbols/2` uploads all of them (`0xF00B`, its size from `0xF00F`). Each is an entry
of variable length:

| Bytes | Field |
|---|---|
| 4 | the entry's length, padding included |
| 4, 4 | index group and offset |
| 4 | size in bytes |
| 4 | ADS data type id (see `ADS.Type.id_name/1`) |
| 4 | flags |
| 2, 2, 2 | lengths of the name, the type and the comment |
| ... | the name, the type and the comment, each with a zero after it |
| 16 | the type's GUID, if flagged (`0x0008`) |
| ... | attributes, if flagged (`0x1000`): a count of 2 bytes, then each with a byte for the length of its name and one for its value, and both with a zero after |

Beckhoff's manuals don't describe this layout, only how to ask for it; it's written here from
general knowledge of the format, not from another implementation's code, and is yet to be
checked against a PLC.

Beckhoff recommends reaching a variable by a handle from its name, as `ADS.Client` does, rather
than by its index group and offset, which change when the program does.

# `t`

```elixir
@type t() :: %ADS.Symbol{
  attributes: %{required(String.t()) =&gt; String.t()},
  comment: String.t(),
  data_type: atom() | non_neg_integer(),
  flags: non_neg_integer(),
  guid: String.t() | nil,
  index_group: ADS.index_group(),
  index_offset: ADS.index_offset(),
  name: String.t(),
  size: non_neg_integer(),
  type: String.t()
}
```

# `decode`

```elixir
@spec decode(binary(), ADS.Codepage.t()) :: {:ok, t()} | :error
```

The symbol entry at the start of the bytes, as in the answer to a request by name; its strings
in UTF-8 if they are, as plain ASCII is, or else in the code page (see `ADS.Codepage`).

# `decode_all`

```elixir
@spec decode_all(binary(), ADS.Codepage.t()) :: {:ok, [t()]} | :error
```

Every symbol entry in the bytes, as uploaded; the strings as for `decode/2`.

# `flags`

```elixir
@spec flags(t()) :: [atom()]
```

The flags of a symbol by name, those that are known: `:persistent`, `:read_only` and so on.

---

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