# Type Casting

RouterOS returns **all** values as plain strings over the API wire.
The `cast` module converts those strings into native Python types.

---

## `cast(value, to)`

```python
from routeros import cast
from datetime import timedelta

# Integers
mtu      = cast("1500", int)          # → 1500
tx_bytes = cast("1048576", int)       # → 1048576

# Floats
load     = cast("0.75", float)        # → 0.75

# Booleans
running  = cast("true", bool)         # → True
disabled = cast("false", bool)        # → False
# Also accepts:  "yes" / "no",  "1" / "0"
enabled  = cast("yes", bool)          # → True

# Timedelta (RouterOS duration format)
uptime   = cast("2d3h4m5s", timedelta)   # timedelta(days=2, hours=3, minutes=4, seconds=5)
lease    = cast("1w", timedelta)         # timedelta(weeks=1)
plain_s  = cast("3600", timedelta)       # timedelta(seconds=3600) – plain int = seconds

# Lists (comma-separated)
dns      = cast("8.8.8.8,8.8.4.4", list)  # → ["8.8.8.8", "8.8.4.4"]

# Bytes (hex with optional : or - separators)
mac      = cast("AA:BB:CC:DD:EE:FF", bytes)  # → b'\xaa\xbb\xcc\xdd\xee\xff'
raw      = cast("deadbeef", bytes)           # → b'\xde\xad\xbe\xef'

# String (identity)
name     = cast("ether1", str)        # → "ether1"
```

---

## `cast_optional(value, to)`

Returns `None` when the value is an empty string `""`.
Useful for RouterOS fields that may be absent.

```python
from routeros import cast_optional

comment = cast_optional("", str)       # → None  (field not set)
mtu     = cast_optional("1500", int)   # → 1500
```

---

## `typed_map(sentence, schema)`

Convert a whole sentence at once using a type schema.
Keys absent from the sentence are **omitted** from the result.

```python
from routeros import typed_map
from datetime import timedelta

row = typed_map(sentence, {
    "name":      str,
    "type":      str,
    "mtu":       int,
    "running":   bool,
    "disabled":  bool,
    "rx-byte":   int,
    "tx-byte":   int,
})

# Safe key access:
print(row.get("mtu", 0))         # 1500
print(row.get("running", False)) # True
```

### Full integration example

```python
import routeros
from routeros import typed_map
from datetime import timedelta

with routeros.dial("192.168.1.1:8728", "admin", "") as c:
    reply = c.run("/interface/print")
    interfaces = [
        typed_map(s, {
            "name":     str,
            "type":     str,
            "mtu":      int,
            "running":  bool,
            "disabled": bool,
            "rx-byte":  int,
            "tx-byte":  int,
        })
        for s in reply.re
    ]
    for iface in interfaces:
        status = "up" if iface.get("running") else "down"
        print(f"{iface['name']:20s} {status:4s} mtu={iface.get('mtu', '?')}")
```

---

## RouterOS Duration Format

RouterOS expresses durations as `[Xw][Xd][Xh][Xm][Xs]`.

| RouterOS string | Python `timedelta` |
|---|---|
| `"30s"` | `timedelta(seconds=30)` |
| `"5m"` | `timedelta(minutes=5)` |
| `"2h30m"` | `timedelta(hours=2, minutes=30)` |
| `"1d"` | `timedelta(days=1)` |
| `"1w"` | `timedelta(weeks=1)` |
| `"1w2d3h4m5s"` | full combination |
| `"3600"` | `timedelta(seconds=3600)` |

---

## Supported Target Types Summary

| `to=` | Input example | Output |
|---|---|---|
| `str` | `"ether1"` | `"ether1"` |
| `int` | `"1500"` | `1500` |
| `float` | `"3.14"` | `3.14` |
| `bool` | `"true"`, `"yes"`, `"1"` | `True` |
| `timedelta` | `"2d3h"` | `timedelta(days=2, hours=3)` |
| `list` | `"8.8.8.8,8.8.4.4"` | `["8.8.8.8", "8.8.4.4"]` |
| `bytes` | `"AA:BB:CC"` | `b'\xaa\xbb\xcc'` |
