# flare.io.buf_reader

> A module of flare_mlake's API.

Buffered reader for stream I/O.

Wraps any type that implements the ``Readable`` trait and provides
line-oriented reading (``readline``, ``read_until``, ``read_exact``).
All reads go through an internal buffer so that the underlying stream is
called as infrequently as possible.

Example:
    ```mojo
    from flare.tcp import TcpStream
    from flare.io import BufReader

    var stream = TcpStream.connect("example.com", 80)
    var reader = BufReader(stream^)
    var line = reader.readline() # Read one HTTP header line
    ```

## Structs

### `BufReader`

```mojo
struct BufReader[S: Readable]
```

A buffered byte reader wrapping any ``Readable`` stream.

Reduces the number of syscalls by reading ahead into an internal
buffer and serving ``readline`` / ``read_until`` / ``read_exact``
from that buffer.

Fields:
    _stream: The underlying stream (owned).
    _buf: Internal ring buffer.
    _pos: Byte offset of the next unread byte in ``_buf``.
    _len: Number of valid bytes in ``_buf`` starting at ``_pos``.

Example:
```mojo
from flare.tcp import TcpStream
from flare.io import BufReader

var s = TcpStream.connect("example.com", 80)
var r = BufReader(s^)
s.write_all("GET / HTTP/1.0\r\nHost: example.com\r\n\r\n".as_bytes())
while True:
    var line = r.readline()
    if len(line) == 0:
        break
    print(line)
```

Parameters:

- `S`: Any type implementing the ``Readable`` trait (e.g. ``TcpStream``).

Implements: `Movable`

#### `__init__`

```mojo
def __init__(out self, var stream: S, capacity: Int = Int(8192))
```

Wrap ``stream`` with a read buffer of ``capacity`` bytes.

Args:

- `stream`: The underlying ``Readable`` stream (ownership taken).
- `capacity`: Internal buffer size in bytes (default 8192).

#### `readline`

```mojo
def readline(mut self) -> String
```

Read one line terminated by ``\n`` (LF) from the stream.

The newline character is stripped from the returned string.
``\r\n`` (CRLF) is also handled — the ``\r`` is stripped too.

Example:
```mojo
var line = reader.readline() # e.g. "HTTP/1.1 200 OK"
```

Raises: NetworkError: On any I/O error.

#### `read_until`

```mojo
def read_until(mut self, delimiter: UInt8) -> String
```

Read bytes until ``delimiter`` is encountered.

The delimiter itself is consumed but not included in the result.

Example:
```mojo
var field = reader.read_until(ord(","))
```

Args:

- `delimiter`: The byte value to stop at.

Raises: NetworkError: On any I/O error.

#### `read_exact`

```mojo
def read_exact(mut self, n: Int) -> List[UInt8]
```

Read exactly ``n`` bytes from the stream.

Loops until ``n`` bytes have been accumulated or EOF/error.

Example:
```mojo
var header = reader.read_exact(4)
```

Args:

- `n`: Number of bytes to read.

Raises: NetworkError: If EOF is reached before ``n`` bytes are available.

## Traits

### `Readable`

```mojo
undefined
```

A byte stream that can be read into a mutable buffer.

Extends ``Movable`` so that streams can be transferred into ``BufReader``.
Implementors must provide ``read`` — all other helpers (``read_exact``,
etc.) are layered on top by ``BufReader``.

Example:
    ```mojo
    struct MyStream(Readable):
        def read(mut self, buf: Pointer[UInt8, _], size: Int) raises -> Int:
            ...
    ```

Implements: `Movable`

#### `read`

```mojo
def read(mut self, buf: Pointer[UInt8], size: Int) -> Int
```

Read up to ``size`` bytes into the buffer at ``buf``.

Args:

- `buf`: Destination pointer. The caller must own at least ``size``
      bytes of initialised storage at this address.
- `size`: Maximum number of bytes to read.

Raises: NetworkError: On any I/O error.
