# 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 { 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::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 { 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`.