# `Unicom360.GSM`
[🔗](https://github.com/TechRode-Solution-Limited/unicom360-elixir/blob/v0.1.0/lib/unicom360/gsm.ex#L1)

Opt-in GSM-7 helpers: the gateway's own answers about an SMS text, before you send it.

The gateway accepts only GSM-7 text (the GSM basic set plus `^{}\[~]|€`, with no form feed),
at most 1,200 characters, and bills `max(1, ceil(length / 160))` units per recipient, where a
CR LF pair counts as one character. The SDK never checks this when sending; these helpers do
it when you ask:

    iex> Unicom360.GSM.gsm7?("Hello €")
    true
    iex> Unicom360.GSM.length("Hi\r\nthere")
    8
    iex> Unicom360.GSM.units(String.duplicate("a", 161))
    2
    iex> Unicom360.GSM.non_gsm_characters("It’s")
    [{"’", 2}]
    iex> Unicom360.GSM.validate_sms("It’s ready")
    [:non_gsm]

Characters are Unicode code points (an emoji is one), not bytes.

# `issue`

```elixir
@type issue() :: :empty | :too_long | :non_gsm
```

A problem `validate_sms/1` reports: `:empty`, `:too_long` or `:non_gsm`.

# `charset`

```elixir
@spec charset() :: String.t()
```

The gateway's GSM-7 character set, as one string.

# `gsm7?`

```elixir
@spec gsm7?(String.t()) :: boolean()
```

Whether every character of `text` is in the gateway's GSM-7 set. `""` is GSM-7.

# `length`

```elixir
@spec length(String.t()) :: non_neg_integer()
```

The length the gateway counts: code points, with each CR LF pair (`"\r\n"`) counted once.

# `max_length`

```elixir
@spec max_length() :: 1200
```

The longest text the gateway accepts, in characters (`1200`).

# `non_gsm_characters`

```elixir
@spec non_gsm_characters(String.t()) :: [{String.t(), non_neg_integer()}]
```

Every character outside the GSM-7 set, in order, as `{character, index}` with `index` the
0-based code point position (here a CR LF pair counts as two).

# `unit_length`

```elixir
@spec unit_length() :: 160
```

The characters per billing unit (`160`).

# `units`

```elixir
@spec units(String.t()) :: pos_integer()
```

The billing units per recipient: `max(1, ceil(length / 160))`. These are not GSM segments.

# `validate_sms`

```elixir
@spec validate_sms(String.t()) :: [issue()]
```

The problems the gateway would refuse `text` for, in this order: `:empty` (empty, or only
spaces, tabs, CR and LF), `:too_long` (more than 1,200 characters), `:non_gsm`. An empty list
means the gateway would accept the text.

---

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