# Rendering, RLV, and LSL extension gate

Milestone 10 replaces the pinned rendering, Restrained Love Viewer, and LSL
tooling assemblies with native Rust. The four extension crates are normal
workspace dependencies with no opt-in compatibility feature: adding one of
them selects its Rust implementation on every supported platform. None loads
a CLR assembly, starts a .NET process, or delegates to a platform-only API.

## Choosing an extension

| Previous C# assembly | Rust crate | Primary entry points |
| --- | --- | --- |
| `LibreMetaverse.Rendering.Simple` | `libremetaverse-rendering-simple` | `SimpleRenderer`, `IRendering` |
| `LibreMetaverse.Rendering.MeshFoundry` | `libremetaverse-rendering-mesh-foundry` | `MeshFoundry`, `IRendering`, `MeshFaceAux` |
| `LibreMetaverse.RLV` | `libremetaverse-rlv` | `RlvService`, `RlvPermissionsService`, callback traits |
| `LibreMetaverse.LslTools` | `libremetaverse-lsl-tools` | `Lexer`, `Parser`, `Grammar`, generated tables |

The mapped PascalCase C# surface remains represented in the API ledger, while
the callable Rust names follow the workspace's snake-case mapping. New code
should use owned Rust values and `Result` instead of nullable CLR containers or
exceptions. `api/SHIM-COVERAGE.md` is generated evidence that all 194 types and
1,287 members in these four assemblies are native; the milestone audit rejects
an owned `not_implemented`, `unimplemented_api`, `todo!`, or `unimplemented!`.

## Rendering migration

Both renderers consume the native core `Primitive` and common `IRendering`
types. Use `SimpleRenderer` for prim and decoded sculpt geometry. Use
`MeshFoundry` when an LLSD mesh asset, skin weights, secondary UVs, tangents,
terrain, or physics hulls are required. Both keep coordinates prim-local; the
world service remains responsible for object transforms, asset retrieval, and
scene ownership.

```rust,no_run
use libremetaverse::Primitive;
use libremetaverse::rendering::{DetailLevel, IRendering};
use libremetaverse_rendering_simple::SimpleRenderer;

fn render(primitive: Primitive) -> Result<usize, libremetaverse_types::Error> {
    let renderer = SimpleRenderer::new()?;
    Ok(renderer
        .generate_simple_mesh(primitive, DetailLevel::High)?
        .indices
        .len())
}
```

Inputs are bounded before allocation: a face stays in the 16-bit index domain,
and MeshFoundry caps encoded/decompressed assets, sections, total geometry,
joints, and convex data. Rendering is deterministic and performs no network,
GPU, window-system, or callback work.

## RLV host integration and teardown

`RlvService` separates deterministic protocol/state handling from world side
effects. A host implements every required method of `IRlvQueryCallbacks` and
`IRlvActionCallbacks`, then passes owned trait objects to `RlvService::new`.
There are no generated fallback methods: an incomplete adapter fails to
compile. `RlvCallbacksDefault` and `RlvActionCallbacksDefault` are complete,
cancellation-aware adapters for hosts that intentionally use conservative
query values and no-op actions.

```rust,no_run
use libremetaverse_rlv::{RlvActionCallbacksDefault, RlvCallbacksDefault, RlvService};

fn service() -> Result<RlvService, libremetaverse_types::Error> {
    RlvService::new(
        Box::new(RlvCallbacksDefault::new()?),
        Box::new(RlvActionCallbacksDefault::new()?),
        true,
    )
}
```

Core/world adapters should snapshot manager data before returning a future and
perform network actions through the corresponding manager APIs. The RLV crate
releases its locks before awaiting a callback, checks cancellation between
commands, bounds each message to 64 KiB and 128 commands, and never starts a
background task. Drop event `Subscription` guards when a host shuts down; drop
the service and its callback objects after outstanding host futures complete.

## LSL tooling migration

Use `generated_lexer()` and `generated_parser()` for the reviewed checked-in
grammar, or build typed `Dfa` and `Grammar` values for another language. Source
locations use UTF-16 code units to preserve the mapped contract. Generation is
an explicit development operation; parsing never generates or compiles code at
runtime.

```rust,no_run
use libremetaverse_lsl_tools::{Lexer, Parser, generated_lexer, generated_parser};

fn parse(source: String) -> Result<String, libremetaverse_types::Error> {
    let lexer = Lexer::new(generated_lexer()?)?;
    let mut parser = Parser::new(generated_parser()?, lexer)?;
    Ok(parser.parse_with_string(source)?.yyname())
}
```

Source, token, DFA, parser-state, stack, operation, recovery, and generator
sizes have fixed limits. The checked table is reproducible with
`python3 tools/generate_lsl_tables.py --check`; API generation is checked with
`python3 tools/generate_api_shims.py --check`.

## Complete milestone verification

`python3 tools/check_milestone_10.py` audits native ownership, reviewed parity
metadata, deterministic generation, resource limits, integration evidence,
migration documentation, and the ubuntu-only workflow. Run
`python3 tools/test_milestone_10.py` to execute the four crate suites, all 616
reviewed RLV compatibility cases, rendering compatibility, the cross-extension
core/world integration, and the compile-only mapped API fixture. The workflow
runs these gates on `ubuntu-latest`.
