# flare.grpc.reflection

> A module of flare_mlake's API.

``flare.grpc.reflection`` -- gRPC server reflection (v1alpha).

Server reflection lets a client (``grpcurl``, ``grpc_cli``, Postman)
discover what a server exposes without a local ``.proto``. The service
is ``grpc.reflection.v1alpha.ServerReflection`` with one bidi-streaming
method ``ServerReflectionInfo`` -- each request message asks one of:

* ``list_services`` (field 7): "what services do you serve?"
* ``file_by_filename`` (field 3) / ``file_containing_symbol``
  (field 4): "give me the descriptor for X".

This module ships the wire codec for the request / response messages
and a :class:`ReflectionService` that answers ``list_services`` from a
registered service-name list and ``file_by_filename`` /
``file_containing_symbol`` from a registered ``FileDescriptorProto``
registry (the blobs ``tests/tools/proto_gen.py`` emits per ``.proto`` file).
Lookups that miss return ``NOT_FOUND``. As a result ``grpcurl list``,
``grpcurl describe``, and reflection-driven calls all work once the
generated descriptors are registered.

``ServerReflectionInfo`` is bidi-streaming;
:class:`ReflectionBidiHandler` adapts :meth:`ReflectionService.answer`
onto the :trait:`flare.grpc.GrpcBidiStreaming` server trait, so it is
mountable via ``GrpcBidiService(ReflectionBidiHandler(svc))``.

References:
- https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1alpha/reflection.proto

## Structs

### `ReflectionRequest`

```mojo
struct ReflectionRequest
```

Decoded ``ServerReflectionRequest`` -- which oneof arm is set plus its string argument.

``kind`` is the oneof field number (one of the ``REFLECT_*``
constants) or ``0`` when none of the recognised arms were present.
``arg`` carries the string payload for the string-valued arms
(``list_services`` / ``file_by_filename`` /
``file_containing_symbol``).

Implements: `Copyable`, `Movable`

Fields:

- `kind: Int`
- `arg: String`

#### `decode`

```mojo
def decode(data: Span[UInt8]) -> Self
```

### `ReflectionService`

```mojo
struct ReflectionService
```

Answers ``ServerReflectionInfo`` requests.

Register every gRPC service path (``package.Service``) for
``list_services``; register a serialized ``FileDescriptorProto`` per
``.proto`` file (from :func:`tools.proto_gen` output) with its symbol
names for ``file_by_filename`` / ``file_containing_symbol``. Lookups
that miss return ``NOT_FOUND``.

Implements: `Copyable`, `Movable`

Fields:

- `services: List[String]`
- `descriptors: Dict[String, List[UInt8]]`: Maps each filename to its serialized FileDescriptorProto bytes.
- `symbol_index: Dict[String, String]`: Maps each fully-qualified symbol (``pkg.Service`` / ``pkg.Message``) to the filename whose descriptor defines it.

#### `__init__`

```mojo
def __init__(out self)
```

#### `copy`

```mojo
def copy(self) -> Self
```

#### `register`

```mojo
def register(mut self, name: String)
```

Add a fully-qualified service name (``package.Service``).

#### `register_descriptor`

```mojo
def register_descriptor(mut self, filename: String, var descriptor: List[UInt8], symbols: List[String])
```

Register a serialized ``FileDescriptorProto`` under ``filename`` and index every ``symbols`` entry (service / message fully-qualified names) to it for ``file_containing_symbol``.

#### `answer`

```mojo
def answer(self, request_bytes: Span[UInt8]) -> List[UInt8]
```

Decode one ``ServerReflectionRequest`` and encode the matching ``ServerReflectionResponse`` bytes.

``list_services`` names every registered service.
``file_by_filename`` / ``file_containing_symbol`` return the
registered ``FileDescriptorProto`` (``NOT_FOUND`` on a miss). An
unrecognised arm returns ``UNIMPLEMENTED``.

### `ReflectionBidiHandler`

```mojo
struct ReflectionBidiHandler
```

Bidi adapter that runs every inbound ``ServerReflectionRequest`` through :meth:`ReflectionService.answer`, framing each response as its own LPM frame. Mount via ``GrpcBidiService(ReflectionBidiHandler(svc))`` on ``/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo``.

Implements: `Copyable`, `GrpcBidiStreaming`, `Movable`

Fields:

- `service: ReflectionService`

#### `serve_bidi`

```mojo
def serve_bidi(mut self, ctx: GrpcCallContext, messages: List[List[UInt8]]) -> GrpcServerStreamReply
```

## Aliases

### `REFLECT_FILE_BY_FILENAME`

```mojo
comptime REFLECT_FILE_BY_FILENAME = Int(3)
```

### `REFLECT_FILE_CONTAINING_SYMBOL`

```mojo
comptime REFLECT_FILE_CONTAINING_SYMBOL = Int(4)
```

### `REFLECT_LIST_SERVICES`

```mojo
comptime REFLECT_LIST_SERVICES = Int(7)
```

### `REFLECT_FILE_DESCRIPTOR_RESPONSE`

```mojo
comptime REFLECT_FILE_DESCRIPTOR_RESPONSE = Int(4)
```

### `REFLECT_LIST_SERVICES_RESPONSE`

```mojo
comptime REFLECT_LIST_SERVICES_RESPONSE = Int(6)
```

### `REFLECT_ERROR_RESPONSE`

```mojo
comptime REFLECT_ERROR_RESPONSE = Int(7)
```
