Complete native extension milestone gate (#84)
Some checks failed
Native code generation / deterministic (push) Has been cancelled
Some checks failed
Native code generation / deterministic (push) Has been cancelled
This commit is contained in:
@@ -104,6 +104,10 @@ jobs:
|
||||
OPENJPEG_PREFIX: /tmp/metacrate-openjpeg-${{ github.run_id }}
|
||||
PKG_CONFIG_PATH: /tmp/metacrate-openjpeg-${{ github.run_id }}/lib/pkgconfig
|
||||
LD_LIBRARY_PATH: /tmp/metacrate-openjpeg-${{ github.run_id }}/lib
|
||||
CARGO_BUILD_JOBS: 1
|
||||
CARGO_INCREMENTAL: 0
|
||||
CARGO_PROFILE_DEV_DEBUG: 0
|
||||
CARGO_PROFILE_TEST_DEBUG: 0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
@@ -15,8 +15,12 @@ on:
|
||||
- "tools/check_milestone_10_issue_81.py"
|
||||
- "tools/check_milestone_10_issue_82.py"
|
||||
- "tools/check_milestone_10_issue_83.py"
|
||||
- "tools/check_milestone_10.py"
|
||||
- "tools/test_milestone_10.py"
|
||||
- "tools/generate_lsl_tables.py"
|
||||
- "codegen/inputs/lsl_tools_grammar.json"
|
||||
- "docs/extension-milestone-gate.md"
|
||||
- "api/SHIM-COVERAGE.md"
|
||||
- "**/*.rs"
|
||||
- "**/Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
@@ -34,8 +38,12 @@ on:
|
||||
- "tools/check_milestone_10_issue_81.py"
|
||||
- "tools/check_milestone_10_issue_82.py"
|
||||
- "tools/check_milestone_10_issue_83.py"
|
||||
- "tools/check_milestone_10.py"
|
||||
- "tools/test_milestone_10.py"
|
||||
- "tools/generate_lsl_tables.py"
|
||||
- "codegen/inputs/lsl_tools_grammar.json"
|
||||
- "docs/extension-milestone-gate.md"
|
||||
- "api/SHIM-COVERAGE.md"
|
||||
- "**/*.rs"
|
||||
- "**/Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
@@ -48,11 +56,15 @@ jobs:
|
||||
OPENJPEG_PREFIX: /tmp/metacrate-openjpeg-${{ github.run_id }}
|
||||
PKG_CONFIG_PATH: /tmp/metacrate-openjpeg-${{ github.run_id }}/lib/pkgconfig
|
||||
LD_LIBRARY_PATH: /tmp/metacrate-openjpeg-${{ github.run_id }}/lib
|
||||
CARGO_BUILD_JOBS: 1
|
||||
CARGO_INCREMENTAL: 0
|
||||
CARGO_PROFILE_DEV_DEBUG: 0
|
||||
CARGO_PROFILE_TEST_DEBUG: 0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
components: rustfmt
|
||||
components: rustfmt, clippy
|
||||
- name: Install audited OpenJPEG 2.5.4
|
||||
run: |
|
||||
sudo apt-get update
|
||||
@@ -80,7 +92,16 @@ jobs:
|
||||
python3 tools/check_milestone_10_issue_82.py
|
||||
python3 tools/check_milestone_10_issue_83.py
|
||||
python3 tools/generate_lsl_tables.py --check
|
||||
python3 tools/check_milestone_10.py
|
||||
- name: Test the complete native world milestone
|
||||
run: python3 tools/test_milestone_09.py
|
||||
- name: Test the complete native extension milestone
|
||||
run: python3 tools/test_milestone_10.py
|
||||
- name: Compile every workspace target with bounded memory
|
||||
run: cargo check --workspace --all-targets --locked -j 1
|
||||
- name: Lint every native extension target with bounded memory
|
||||
run: cargo clippy -p libremetaverse-rendering-simple -p libremetaverse-rendering-mesh-foundry -p libremetaverse-rlv -p libremetaverse-lsl-tools --all-targets --locked -j 1 -- -D warnings
|
||||
- name: Document every native extension crate
|
||||
env:
|
||||
RUSTDOCFLAGS: -D warnings
|
||||
run: cargo doc -p libremetaverse-rendering-simple -p libremetaverse-rendering-mesh-foundry -p libremetaverse-rlv -p libremetaverse-lsl-tools --no-deps --locked -j 1
|
||||
|
||||
@@ -9,7 +9,7 @@ Generated by `python3 tools/generate_api_shims.py`; do not edit by hand.
|
||||
| `LibreMetaverse.Imaging.Skia` | 1 | 3 | native implementation: 1 type / 3 members; no generated shims remain |
|
||||
| `LibreMetaverse.LslTools` | 164 | 768 | native implementation: 164 types / 768 members; no generated shims remain |
|
||||
| `LibreMetaverse.PrimMesher` | 17 | 207 | native implementation: 15 types / 200 members; remaining surface is callable failure-only shims |
|
||||
| `LibreMetaverse.RLV` | 28 | 499 | native implementation: 17 types / 200 members; remaining surface is callable failure-only shims |
|
||||
| `LibreMetaverse.RLV` | 28 | 499 | native implementation: 28 types / 499 members; no generated shims remain |
|
||||
| `LibreMetaverse.Rendering.MeshFoundry` | 1 | 14 | native implementation: 1 type / 14 members; no generated shims remain |
|
||||
| `LibreMetaverse.Rendering.Simple` | 1 | 6 | native implementation: 1 type / 6 members; no generated shims remain |
|
||||
| `LibreMetaverse.StructuredData` | 16 | 295 | native implementation: 16 types / 295 members; no generated shims remain |
|
||||
|
||||
@@ -131,188 +131,90 @@ pub trait IRlvActionCallbacks: Send + Sync {
|
||||
factor: f32,
|
||||
delta: f32,
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>
|
||||
{
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvActionCallbacks.AdjustHeightAsync(System.Single,System.Single,System.Single,System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvActionCallbacks.AttachAsync(System.Collections.Generic.IReadOnlyList{LibreMetaverse.RLV.AttachmentRequest},System.Threading.CancellationToken)`.
|
||||
fn attach(
|
||||
&self,
|
||||
items_to_attach: Vec<libremetaverse_rlv::AttachmentRequest>,
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>
|
||||
{
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvActionCallbacks.AttachAsync(System.Collections.Generic.IReadOnlyList{LibreMetaverse.RLV.AttachmentRequest},System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvActionCallbacks.DetachAsync(System.Collections.Generic.IReadOnlyList{System.Guid},System.Threading.CancellationToken)`.
|
||||
fn detach(
|
||||
&self,
|
||||
item_ids: Vec<libremetaverse_types::compat::Guid>,
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>
|
||||
{
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvActionCallbacks.DetachAsync(System.Collections.Generic.IReadOnlyList{System.Guid},System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvActionCallbacks.RemOutfitAsync(System.Collections.Generic.IReadOnlyList{System.Guid},System.Threading.CancellationToken)`.
|
||||
fn rem_outfit(
|
||||
&self,
|
||||
item_ids: Vec<libremetaverse_types::compat::Guid>,
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>
|
||||
{
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvActionCallbacks.RemOutfitAsync(System.Collections.Generic.IReadOnlyList{System.Guid},System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvActionCallbacks.SendInstantMessageAsync(System.Guid,System.String,System.Threading.CancellationToken)`.
|
||||
fn send_instant_message(
|
||||
&self,
|
||||
target_user: libremetaverse_types::compat::Guid,
|
||||
message: String,
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>
|
||||
{
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvActionCallbacks.SendInstantMessageAsync(System.Guid,System.String,System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvActionCallbacks.SendReplyAsync(System.Int32,System.String,System.Threading.CancellationToken)`.
|
||||
fn send_reply(
|
||||
&self,
|
||||
channel: i32,
|
||||
message: String,
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>
|
||||
{
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvActionCallbacks.SendReplyAsync(System.Int32,System.String,System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvActionCallbacks.SetCamFOVAsync(System.Single,System.Threading.CancellationToken)`.
|
||||
fn set_cam_fov(
|
||||
&self,
|
||||
fov_in_radians: f32,
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>
|
||||
{
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvActionCallbacks.SetCamFOVAsync(System.Single,System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvActionCallbacks.SetDebugAsync(System.String,System.String,System.Threading.CancellationToken)`.
|
||||
fn set_debug(
|
||||
&self,
|
||||
setting_name: String,
|
||||
setting_value: String,
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>
|
||||
{
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvActionCallbacks.SetDebugAsync(System.String,System.String,System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvActionCallbacks.SetEnvAsync(System.String,System.String,System.Threading.CancellationToken)`.
|
||||
fn set_env(
|
||||
&self,
|
||||
setting_name: String,
|
||||
setting_value: String,
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>
|
||||
{
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvActionCallbacks.SetEnvAsync(System.String,System.String,System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvActionCallbacks.SetGroupAsync(System.Guid,System.String,System.Threading.CancellationToken)`.
|
||||
fn set_group_with_guid_string_cancellation_token(
|
||||
&self,
|
||||
group_id: libremetaverse_types::compat::Guid,
|
||||
role_name: Option<String>,
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>
|
||||
{
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvActionCallbacks.SetGroupAsync(System.Guid,System.String,System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvActionCallbacks.SetGroupAsync(System.String,System.String,System.Threading.CancellationToken)`.
|
||||
fn set_group_with_string_string_cancellation_token(
|
||||
&self,
|
||||
group_name: String,
|
||||
role_name: Option<String>,
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>
|
||||
{
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvActionCallbacks.SetGroupAsync(System.String,System.String,System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvActionCallbacks.SetRotAsync(System.Single,System.Threading.CancellationToken)`.
|
||||
fn set_rot(
|
||||
&self,
|
||||
angle_in_radians: f32,
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>
|
||||
{
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvActionCallbacks.SetRotAsync(System.Single,System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvActionCallbacks.SitAsync(System.Guid,System.Threading.CancellationToken)`.
|
||||
fn sit(
|
||||
&self,
|
||||
target: libremetaverse_types::compat::Guid,
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>
|
||||
{
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvActionCallbacks.SitAsync(System.Guid,System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvActionCallbacks.SitGroundAsync(System.Threading.CancellationToken)`.
|
||||
fn sit_ground(
|
||||
&self,
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>
|
||||
{
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvActionCallbacks.SitGroundAsync(System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvActionCallbacks.TpToAsync(System.Single,System.Single,System.Single,System.String,System.Nullable{System.Single},System.Threading.CancellationToken)`.
|
||||
fn tp_to(
|
||||
&self,
|
||||
@@ -322,26 +224,12 @@ pub trait IRlvActionCallbacks: Send + Sync {
|
||||
region_name: Option<String>,
|
||||
lookat: Option<Option<f32>>,
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>
|
||||
{
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvActionCallbacks.TpToAsync(System.Single,System.Single,System.Single,System.String,System.Nullable{System.Single},System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvActionCallbacks.UnsitAsync(System.Threading.CancellationToken)`.
|
||||
fn unsit(
|
||||
&self,
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>
|
||||
{
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvActionCallbacks.UnsitAsync(System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), crate::Error>> + Send + '_>>;
|
||||
}
|
||||
|
||||
/// C# type: `T:LibreMetaverse.RLV.IRlvQueryCallbacks`.
|
||||
@@ -350,40 +238,20 @@ pub trait IRlvQueryCallbacks: Send + Sync {
|
||||
fn is_sitting(
|
||||
&self,
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<bool, crate::Error>> + Send + '_>>
|
||||
{
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvQueryCallbacks.IsSittingAsync(System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<bool, crate::Error>> + Send + '_>>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvQueryCallbacks.ObjectExistsAsync(System.Guid,System.Threading.CancellationToken)`.
|
||||
fn object_exists(
|
||||
&self,
|
||||
object_id: libremetaverse_types::compat::Guid,
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<bool, crate::Error>> + Send + '_>>
|
||||
{
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvQueryCallbacks.ObjectExistsAsync(System.Guid,System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<bool, crate::Error>> + Send + '_>>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvQueryCallbacks.TryGetActiveGroupNameAsync(System.Threading.CancellationToken)`.
|
||||
fn try_get_active_group_name(
|
||||
&self,
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<
|
||||
Box<dyn std::future::Future<Output = Result<(bool, String), crate::Error>> + Send + '_>,
|
||||
> {
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvQueryCallbacks.TryGetActiveGroupNameAsync(System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvQueryCallbacks.TryGetCameraSettingsAsync(System.Threading.CancellationToken)`.
|
||||
fn try_get_camera_settings(
|
||||
&self,
|
||||
@@ -398,13 +266,7 @@ pub trait IRlvQueryCallbacks: Send + Sync {
|
||||
> + Send
|
||||
+ '_,
|
||||
>,
|
||||
> {
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvQueryCallbacks.TryGetCameraSettingsAsync(System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvQueryCallbacks.TryGetDebugSettingValueAsync(System.String,System.Threading.CancellationToken)`.
|
||||
fn try_get_debug_setting_value(
|
||||
&self,
|
||||
@@ -412,13 +274,7 @@ pub trait IRlvQueryCallbacks: Send + Sync {
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<
|
||||
Box<dyn std::future::Future<Output = Result<(bool, String), crate::Error>> + Send + '_>,
|
||||
> {
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvQueryCallbacks.TryGetDebugSettingValueAsync(System.String,System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvQueryCallbacks.TryGetEnvironmentSettingValueAsync(System.String,System.Threading.CancellationToken)`.
|
||||
fn try_get_environment_setting_value(
|
||||
&self,
|
||||
@@ -426,13 +282,7 @@ pub trait IRlvQueryCallbacks: Send + Sync {
|
||||
cancellation_token: libremetaverse_types::compat::CancellationToken,
|
||||
) -> std::pin::Pin<
|
||||
Box<dyn std::future::Future<Output = Result<(bool, String), crate::Error>> + Send + '_>,
|
||||
> {
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvQueryCallbacks.TryGetEnvironmentSettingValueAsync(System.String,System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvQueryCallbacks.TryGetInventoryMapAsync(System.Threading.CancellationToken)`.
|
||||
fn try_get_inventory_map(
|
||||
&self,
|
||||
@@ -444,13 +294,7 @@ pub trait IRlvQueryCallbacks: Send + Sync {
|
||||
> + Send
|
||||
+ '_,
|
||||
>,
|
||||
> {
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvQueryCallbacks.TryGetInventoryMapAsync(System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
>;
|
||||
/// C# member: `M:LibreMetaverse.RLV.IRlvQueryCallbacks.TryGetSitIdAsync(System.Threading.CancellationToken)`.
|
||||
fn try_get_sit_id(
|
||||
&self,
|
||||
@@ -462,13 +306,7 @@ pub trait IRlvQueryCallbacks: Send + Sync {
|
||||
> + Send
|
||||
+ '_,
|
||||
>,
|
||||
> {
|
||||
Box::pin(async {
|
||||
libremetaverse_types::not_implemented(
|
||||
"M:LibreMetaverse.RLV.IRlvQueryCallbacks.TryGetSitIdAsync(System.Threading.CancellationToken)",
|
||||
)
|
||||
})
|
||||
}
|
||||
>;
|
||||
}
|
||||
|
||||
/// C# type: `T:LibreMetaverse.RLV.InventoryMap`.
|
||||
|
||||
113
docs/extension-milestone-gate.md
Normal file
113
docs/extension-milestone-gate.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# 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`.
|
||||
@@ -67,10 +67,7 @@ fn extension_flows_have_typed_callable_signatures() {
|
||||
#[test]
|
||||
fn extension_constructors_have_expected_native_or_failure_behavior() {
|
||||
assert!(YyParser::new().is_ok());
|
||||
assert_eq!(
|
||||
member_id(RlvActionCallbacksDefault::new()),
|
||||
"M:LibreMetaverse.RLV.RlvActionCallbacksDefault.#ctor"
|
||||
);
|
||||
assert!(RlvActionCallbacksDefault::new().is_ok());
|
||||
assert_eq!(
|
||||
member_id(TCPPipe::new()),
|
||||
"M:LibreMetaverse.Voice.Vivox.TCPPipe.#ctor"
|
||||
|
||||
80
tests/compat/tests/milestone_10_integration.rs
Normal file
80
tests/compat/tests/milestone_10_integration.rs
Normal file
@@ -0,0 +1,80 @@
|
||||
//! Milestone 10 integration coverage across core primitives and native extensions.
|
||||
|
||||
use libremetaverse::rendering::{DetailLevel, SimpleMesh};
|
||||
use libremetaverse::{Primitive, PrimitiveConstructionData};
|
||||
use libremetaverse_compat_tests::block_on;
|
||||
use libremetaverse_compat_tests::rlv_support::RlvHarness;
|
||||
use libremetaverse_lsl_tools::{Lexer, Parser, generated_lexer, generated_parser};
|
||||
use libremetaverse_rendering_mesh_foundry::MeshFoundry;
|
||||
use libremetaverse_rendering_simple::SimpleRenderer;
|
||||
use libremetaverse_types::{HoleType, PCode, PathCurve, ProfileCurve};
|
||||
|
||||
fn world_primitive() -> Primitive {
|
||||
let mut primitive = Primitive::new_with_constructor().expect("Primitive constructor");
|
||||
let mut construction = PrimitiveConstructionData::new_with_constructor()
|
||||
.expect("PrimitiveConstructionData constructor");
|
||||
construction.p_code = PCode::Prim;
|
||||
construction.path_curve = PathCurve::Line;
|
||||
construction.set_profile_curve_with_property(ProfileCurve::Square);
|
||||
construction.set_profile_hole(HoleType::Same);
|
||||
construction.path_scale_x = 1.0;
|
||||
construction.path_scale_y = 1.0;
|
||||
construction.path_end = 1.0;
|
||||
construction.profile_end = 1.0;
|
||||
construction.path_revolutions = 1.0;
|
||||
primitive.prim_data = construction;
|
||||
primitive
|
||||
}
|
||||
|
||||
fn mesh_signature(mesh: &SimpleMesh) -> u64 {
|
||||
let mut hash = 0xcbf2_9ce4_8422_2325_u64;
|
||||
for vertex in &mesh.vertices {
|
||||
for value in [
|
||||
vertex.position.x,
|
||||
vertex.position.y,
|
||||
vertex.position.z,
|
||||
vertex.normal.x,
|
||||
vertex.normal.y,
|
||||
vertex.normal.z,
|
||||
vertex.tex_coord.x,
|
||||
vertex.tex_coord.y,
|
||||
] {
|
||||
hash = (hash ^ u64::from(value.to_bits())).wrapping_mul(0x0000_0100_0000_01b3);
|
||||
}
|
||||
}
|
||||
hash
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn native_extensions_consume_core_models_and_preserve_service_state() {
|
||||
let primitive = world_primitive();
|
||||
let simple = SimpleRenderer::new()
|
||||
.expect("simple renderer")
|
||||
.generate_simple_mesh(primitive.clone(), DetailLevel::High)
|
||||
.expect("simple mesh");
|
||||
let foundry = MeshFoundry::new()
|
||||
.expect("mesh foundry")
|
||||
.generate_simple_mesh(primitive, DetailLevel::High)
|
||||
.expect("foundry mesh")
|
||||
.expect("legacy primitive is renderable");
|
||||
assert_eq!(simple.vertices.len(), foundry.vertices.len());
|
||||
assert_eq!(mesh_signature(&simple), mesh_signature(&foundry));
|
||||
assert_eq!(simple.indices, foundry.indices);
|
||||
|
||||
let lexer = Lexer::new(generated_lexer().expect("generated lexer")).expect("lexer");
|
||||
let mut parser =
|
||||
Parser::new(generated_parser().expect("generated parser"), lexer).expect("parser");
|
||||
let symbol = parser
|
||||
.parse_with_string("Widget(value;):base(new Child[])".to_owned())
|
||||
.expect("generated class body");
|
||||
assert_eq!(
|
||||
(symbol.yyname(), symbol.yynum()),
|
||||
("ClassBody".to_owned(), 19)
|
||||
);
|
||||
|
||||
let rlv = RlvHarness::new().expect("RLV service");
|
||||
assert!(block_on(rlv.process("@fly=n")).expect("add restriction"));
|
||||
assert!(!rlv.service.permissions().can_fly().expect("permission"));
|
||||
assert!(block_on(rlv.process("@fly=y")).expect("remove restriction"));
|
||||
assert!(rlv.service.permissions().can_fly().expect("permission"));
|
||||
}
|
||||
252
tools/check_milestone_10.py
Normal file
252
tools/check_milestone_10.py
Normal file
@@ -0,0 +1,252 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Audit the complete native rendering, RLV, and LSL milestone boundary."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import generate_api_shims
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
ASSEMBLIES = {
|
||||
"LibreMetaverse.Rendering.Simple": (1, 6),
|
||||
"LibreMetaverse.Rendering.MeshFoundry": (1, 14),
|
||||
"LibreMetaverse.RLV": (28, 499),
|
||||
"LibreMetaverse.LslTools": (164, 768),
|
||||
}
|
||||
CRATES = (
|
||||
"libremetaverse-rendering-simple",
|
||||
"libremetaverse-rendering-mesh-foundry",
|
||||
"libremetaverse-rlv",
|
||||
"libremetaverse-lsl-tools",
|
||||
)
|
||||
RLV_GENERATED_TYPES = {
|
||||
"T:LibreMetaverse.RLV.IRlvActionCallbacks",
|
||||
"T:LibreMetaverse.RLV.IRlvQueryCallbacks",
|
||||
"T:LibreMetaverse.RLV.RlvAttachmentPoint",
|
||||
"T:LibreMetaverse.RLV.RlvGestureState",
|
||||
"T:LibreMetaverse.RLV.RlvGetDebugType",
|
||||
"T:LibreMetaverse.RLV.RlvGetEnvType",
|
||||
"T:LibreMetaverse.RLV.RlvPermissionsService.HoverTextLocation",
|
||||
"T:LibreMetaverse.RLV.RlvPermissionsService.ObjectLocation",
|
||||
"T:LibreMetaverse.RLV.RlvPermissionsService.TouchLocation",
|
||||
"T:LibreMetaverse.RLV.RlvRestrictionType",
|
||||
"T:LibreMetaverse.RLV.RlvWearableType",
|
||||
}
|
||||
STUB_RE = re.compile(
|
||||
r"\b(?:not_implemented|unimplemented_api)\b|\b(?:todo|unimplemented)!\s*\("
|
||||
)
|
||||
PLATFORM_RE = re.compile(r"unsafe\s*\{|unsafe\s+impl|target_os\s*=\s*\"macos\"")
|
||||
|
||||
|
||||
def require_markers(path: Path, markers: tuple[str, ...]) -> None:
|
||||
text = path.read_text()
|
||||
missing = [marker for marker in markers if marker not in text]
|
||||
if missing:
|
||||
raise SystemExit(f"{path}: audit evidence missing: " + ", ".join(missing))
|
||||
|
||||
|
||||
def catalog_assemblies() -> dict[str, dict]:
|
||||
catalog = json.loads((ROOT / "api" / "public-api.json").read_text())
|
||||
return {assembly["identity"]["name"]: assembly for assembly in catalog["assemblies"]}
|
||||
|
||||
|
||||
def member_is_native(item: dict, member: dict) -> bool:
|
||||
doc_id = item["doc_id"]
|
||||
return (
|
||||
doc_id in generate_api_shims.NATIVE_TYPES
|
||||
or doc_id in generate_api_shims.NATIVE_GENERATED_TYPES
|
||||
or (
|
||||
doc_id in generate_api_shims.NATIVE_DECLARATIONS
|
||||
and member["kind"] in {"field", "constant"}
|
||||
)
|
||||
or generate_api_shims.native_member_body(member["doc_id"]) is not None
|
||||
)
|
||||
|
||||
|
||||
def check_catalog_ownership() -> None:
|
||||
assemblies = catalog_assemblies()
|
||||
native_types = (
|
||||
set(generate_api_shims.NATIVE_TYPES)
|
||||
| set(generate_api_shims.NATIVE_DECLARATIONS)
|
||||
| set(generate_api_shims.NATIVE_GENERATED_TYPES)
|
||||
)
|
||||
for name, expected in ASSEMBLIES.items():
|
||||
assembly = assemblies[name]
|
||||
actual = (
|
||||
len(assembly["types"]),
|
||||
sum(len(item["members"]) for item in assembly["types"]),
|
||||
)
|
||||
if actual != expected:
|
||||
raise SystemExit(f"{name}: expected catalog counts {expected}, found {actual}")
|
||||
missing_types = [
|
||||
item["doc_id"] for item in assembly["types"] if item["doc_id"] not in native_types
|
||||
]
|
||||
missing_members = [
|
||||
member["doc_id"]
|
||||
for item in assembly["types"]
|
||||
for member in item["members"]
|
||||
if not member_is_native(item, member)
|
||||
]
|
||||
if missing_types or missing_members:
|
||||
raise SystemExit(
|
||||
f"{name}: non-native types={missing_types}, members={missing_members}"
|
||||
)
|
||||
if generate_api_shims.NATIVE_GENERATED_TYPES != RLV_GENERATED_TYPES:
|
||||
raise SystemExit("milestone 10 generated-native RLV declaration set changed")
|
||||
|
||||
|
||||
def check_sources_and_manifests() -> None:
|
||||
offenders: list[str] = []
|
||||
platform_offenders: list[str] = []
|
||||
for crate in CRATES:
|
||||
crate_root = ROOT / "crates" / crate
|
||||
manifest = (crate_root / "Cargo.toml").read_text()
|
||||
if "[features]" in manifest:
|
||||
raise SystemExit(f"{crate}: native implementation must be active without a feature")
|
||||
if re.search(r"\b(?:dotnet|csc|mcs)\b", manifest, re.IGNORECASE):
|
||||
raise SystemExit(f"{crate}: manifest depends on a C#/.NET tool")
|
||||
for source in (crate_root / "src").glob("*.rs"):
|
||||
text = source.read_text()
|
||||
if STUB_RE.search(text):
|
||||
offenders.append(str(source.relative_to(ROOT)))
|
||||
if PLATFORM_RE.search(text):
|
||||
platform_offenders.append(str(source.relative_to(ROOT)))
|
||||
if offenders:
|
||||
raise SystemExit("milestone 10 owned Rust stubs remain: " + ", ".join(offenders))
|
||||
if platform_offenders:
|
||||
raise SystemExit(
|
||||
"milestone 10 unsafe or macOS-only sources remain: "
|
||||
+ ", ".join(platform_offenders)
|
||||
)
|
||||
|
||||
|
||||
def check_parity() -> None:
|
||||
catalog = json.loads((ROOT / "tests" / "upstream-tests.json").read_text())
|
||||
related = [
|
||||
test
|
||||
for test in catalog["tests"]
|
||||
if test["source"].startswith("LibreMetaverse.Tests/RLV/")
|
||||
or test["source"].startswith("LibreMetaverse.Rendering.Tests/")
|
||||
]
|
||||
if len(related) != 691:
|
||||
raise SystemExit(f"milestone 10 expected 691 upstream parity cases, found {len(related)}")
|
||||
bad = [
|
||||
test["id"]
|
||||
for test in related
|
||||
if test["status"] != "translated" or test.get("semantic_review") != "reviewed"
|
||||
]
|
||||
if bad:
|
||||
raise SystemExit("milestone 10 parity cases are not reviewed: " + ", ".join(bad))
|
||||
missing = sorted(
|
||||
{
|
||||
test["rust_file"]
|
||||
for test in related
|
||||
if not (ROOT / test["rust_file"]).is_file()
|
||||
}
|
||||
)
|
||||
if missing:
|
||||
raise SystemExit("milestone 10 translated files are missing: " + ", ".join(missing))
|
||||
|
||||
|
||||
def check_contract_evidence() -> None:
|
||||
require_markers(
|
||||
ROOT / "crates" / "libremetaverse-rendering-simple" / "src" / "simple_renderer.rs",
|
||||
("MAX_FACE_VERTICES", "checked_add", "u16::try_from"),
|
||||
)
|
||||
require_markers(
|
||||
ROOT / "crates" / "libremetaverse-rendering-mesh-foundry" / "src" / "mesh_foundry.rs",
|
||||
("MAX_ASSET_BYTES", "MAX_TOTAL_VERTICES", "MAX_JOINTS", "checked_add"),
|
||||
)
|
||||
require_markers(
|
||||
ROOT / "crates" / "libremetaverse-rlv" / "src" / "service.rs",
|
||||
(
|
||||
"MAX_RLV_MESSAGE_BYTES",
|
||||
"MAX_RLV_COMMANDS",
|
||||
"Arc<dyn IRlvQueryCallbacks>",
|
||||
"Arc<dyn IRlvActionCallbacks>",
|
||||
"throw_if_cancellation_requested",
|
||||
),
|
||||
)
|
||||
require_markers(
|
||||
ROOT / "crates" / "libremetaverse-lsl-tools" / "src" / "parser.rs",
|
||||
("MAX_PARSER_STATES", "MAX_PARSER_STACK", "MAX_PARSER_STEPS", "MAX_RECOVERY_ERRORS"),
|
||||
)
|
||||
require_markers(
|
||||
ROOT / "crates" / "libremetaverse-lsl-tools" / "src" / "lexer.rs",
|
||||
("MAX_SOURCE_UNITS", "MAX_TOKEN_UNITS"),
|
||||
)
|
||||
require_markers(
|
||||
ROOT / "tests" / "compat" / "tests" / "milestone_10_integration.rs",
|
||||
(
|
||||
"native_extensions_consume_core_models_and_preserve_service_state",
|
||||
"SimpleRenderer",
|
||||
"MeshFoundry",
|
||||
"generated_parser",
|
||||
"RlvHarness",
|
||||
),
|
||||
)
|
||||
require_markers(
|
||||
ROOT / "docs" / "extension-milestone-gate.md",
|
||||
(
|
||||
"Choosing an extension",
|
||||
"Rendering migration",
|
||||
"RLV host integration and teardown",
|
||||
"LSL tooling migration",
|
||||
"194 types",
|
||||
"1,287 members",
|
||||
"tools/test_milestone_10.py",
|
||||
"ubuntu-latest",
|
||||
),
|
||||
)
|
||||
require_markers(
|
||||
ROOT / "api" / "SHIM-COVERAGE.md",
|
||||
tuple(
|
||||
f"`{name}` | {types} | {members} | native implementation"
|
||||
for name, (types, members) in ASSEMBLIES.items()
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def check_generation_and_ci() -> None:
|
||||
subprocess.run(
|
||||
["python3", "tools/generate_rust_mapping.py", "--check"], cwd=ROOT, check=True
|
||||
)
|
||||
subprocess.run(
|
||||
["python3", "tools/generate_api_shims.py", "--check"], cwd=ROOT, check=True
|
||||
)
|
||||
subprocess.run(
|
||||
["python3", "tools/generate_lsl_tables.py", "--check"], cwd=ROOT, check=True
|
||||
)
|
||||
workflow = ROOT / ".gitea" / "workflows" / "rust-workspace.yml"
|
||||
require_markers(
|
||||
workflow,
|
||||
(
|
||||
"python3 tools/check_milestone_10.py",
|
||||
"python3 tools/test_milestone_10.py",
|
||||
"runs-on: ubuntu-latest",
|
||||
),
|
||||
)
|
||||
if re.search(r"runs-on:\s*(?:macos|windows)", workflow.read_text(), re.IGNORECASE):
|
||||
raise SystemExit("milestone 10 workflow is not ubuntu-only")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
check_catalog_ownership()
|
||||
check_sources_and_manifests()
|
||||
check_parity()
|
||||
check_contract_evidence()
|
||||
check_generation_and_ci()
|
||||
print(
|
||||
"milestone 10 audit: 194 types and 1,287 members are native; no owned "
|
||||
"stubs remain; bounds, callback teardown, 691 reviewed parity cases, "
|
||||
"integration, migration docs, deterministic generation, and ubuntu-only CI are present"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -132,7 +132,7 @@ def main() -> None:
|
||||
raise SystemExit(f"issue 81 expected 27 focused fixtures, found {test_count}")
|
||||
require_markers(DOC, (
|
||||
"UTF-16 code-unit offsets", "maximum munch", "structured `Diagnostic`",
|
||||
"64 Mi UTF-16", "16 Mi units", "Lexer::iter", "27 focused",
|
||||
"64 Mi UTF-16", "16 Mi units", "Lexer::iter", "46 focused",
|
||||
"No C#, .NET runtime", "ubuntu-latest",
|
||||
))
|
||||
require_markers(WORKFLOW, ("python3 tools/check_milestone_10_issue_81.py",))
|
||||
|
||||
@@ -122,7 +122,7 @@ def main() -> None:
|
||||
require_markers(EXTENSION_TESTS, ("assert!(YyParser::new().is_ok())",))
|
||||
require_markers(DOC, (
|
||||
"canonical LR(0)", "deterministic LALR(1)", "Shift/reduce conflicts",
|
||||
"nonassociative", "1,048,576", "16,777,216", "37 focused",
|
||||
"nonassociative", "1,048,576", "16,777,216", "46 focused",
|
||||
"issue 83", "ubuntu-latest",
|
||||
))
|
||||
require_markers(WORKFLOW, ("python3 tools/check_milestone_10_issue_82.py",))
|
||||
|
||||
@@ -601,6 +601,26 @@ NATIVE_DECLARATIONS = {
|
||||
"T:LibreMetaverse.Rendering.MeshFoundry": "crate::mesh_foundry::MeshFoundry",
|
||||
}
|
||||
|
||||
# Catalog declarations which are themselves complete native Rust. Unlike
|
||||
# NATIVE_TYPES, these types intentionally remain in generated.rs: the RLV
|
||||
# enums are closed value tables and the callback interfaces are Rust traits
|
||||
# whose required methods are implemented by the host and default adapters.
|
||||
# Keeping this set explicit lets coverage distinguish concrete generated code
|
||||
# from a callable failure-only compatibility shell.
|
||||
NATIVE_GENERATED_TYPES = {
|
||||
"T:LibreMetaverse.RLV.IRlvActionCallbacks",
|
||||
"T:LibreMetaverse.RLV.IRlvQueryCallbacks",
|
||||
"T:LibreMetaverse.RLV.RlvAttachmentPoint",
|
||||
"T:LibreMetaverse.RLV.RlvGestureState",
|
||||
"T:LibreMetaverse.RLV.RlvGetDebugType",
|
||||
"T:LibreMetaverse.RLV.RlvGetEnvType",
|
||||
"T:LibreMetaverse.RLV.RlvPermissionsService.HoverTextLocation",
|
||||
"T:LibreMetaverse.RLV.RlvPermissionsService.ObjectLocation",
|
||||
"T:LibreMetaverse.RLV.RlvPermissionsService.TouchLocation",
|
||||
"T:LibreMetaverse.RLV.RlvRestrictionType",
|
||||
"T:LibreMetaverse.RLV.RlvWearableType",
|
||||
}
|
||||
|
||||
NATIVE_MEMBER_BODIES = {
|
||||
"M:LibreMetaverse.RLV.RlvCommon.TryGetAttachmentPointFromItemName(System.String,System.Nullable{LibreMetaverse.RLV.RlvAttachmentPoint}@)":
|
||||
"Self::native_try_get_attachment_point_from_item_name(item_name, attachment_point)",
|
||||
@@ -3523,9 +3543,18 @@ def native_member_body(member_id: str) -> str | None:
|
||||
return None
|
||||
|
||||
|
||||
def render_body(signature: str, member_id: str, error_model: str, asyncness: str, trait: bool) -> str:
|
||||
def render_body(
|
||||
signature: str,
|
||||
member_id: str,
|
||||
error_model: str,
|
||||
asyncness: str,
|
||||
trait: bool,
|
||||
required_trait_method: bool = False,
|
||||
) -> str:
|
||||
if trait:
|
||||
signature = signature.removeprefix("pub ")
|
||||
if required_trait_method:
|
||||
return f" {signature};"
|
||||
if body := native_member_body(member_id):
|
||||
if any(f"LibreMetaverse.{owner}." in member_id for owner in CLIENT_CORE_NATIVE_OWNERS):
|
||||
marker = " /* native client-core implementation */"
|
||||
@@ -3647,6 +3676,7 @@ def render_type(item: dict, type_row: dict, member_rows: dict[str, dict[str, str
|
||||
row["error_model"],
|
||||
row["asyncness"],
|
||||
trait,
|
||||
trait and item["doc_id"] in NATIVE_GENERATED_TYPES,
|
||||
)
|
||||
)
|
||||
lines.append("}")
|
||||
@@ -3844,7 +3874,9 @@ def coverage_report(catalog: dict, coverage: dict[str, tuple[int, int, bool]]) -
|
||||
native_type_ids = {
|
||||
item["doc_id"]
|
||||
for item in assembly["types"]
|
||||
if item["doc_id"] in NATIVE_TYPES or item["doc_id"] in NATIVE_DECLARATIONS
|
||||
if item["doc_id"] in NATIVE_TYPES
|
||||
or item["doc_id"] in NATIVE_DECLARATIONS
|
||||
or item["doc_id"] in NATIVE_GENERATED_TYPES
|
||||
or (name == "LibreMetaverse.Types" and item["kind"] == "enum")
|
||||
}
|
||||
native_member_ids = {
|
||||
@@ -3852,6 +3884,7 @@ def coverage_report(catalog: dict, coverage: dict[str, tuple[int, int, bool]]) -
|
||||
for item in assembly["types"]
|
||||
for member in item["members"]
|
||||
if item["doc_id"] in NATIVE_TYPES
|
||||
or item["doc_id"] in NATIVE_GENERATED_TYPES
|
||||
or (name == "LibreMetaverse.Types" and item["kind"] == "enum")
|
||||
or (
|
||||
item["doc_id"] in NATIVE_DECLARATIONS
|
||||
|
||||
@@ -960,7 +960,10 @@ def function_bodies(text: str) -> list[str]:
|
||||
|
||||
|
||||
def validate_generated_shims() -> None:
|
||||
for path in sorted((ROOT / "crates").glob("*/src/generated*.rs")):
|
||||
# Only generated.rs files are callable compatibility shim targets.
|
||||
# Deterministic native artifacts such as LSL generated_tables.rs contain
|
||||
# ordinary successful functions and are validated by their own generator.
|
||||
for path in sorted((ROOT / "crates").glob("*/src/generated.rs")):
|
||||
text = path.read_text()
|
||||
default_types = set(
|
||||
re.findall(
|
||||
|
||||
77
tools/test_milestone_10.py
Normal file
77
tools/test_milestone_10.py
Normal file
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Run only tests owned by the rendering, RLV, and LSL milestone."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
ENV = os.environ.copy()
|
||||
ENV.setdefault("CARGO_BUILD_JOBS", "1")
|
||||
ENV.setdefault("CARGO_INCREMENTAL", "0")
|
||||
ENV.setdefault("CARGO_PROFILE_DEV_DEBUG", "0")
|
||||
ENV.setdefault("CARGO_PROFILE_TEST_DEBUG", "0")
|
||||
ENV.pop("RUN_LIVE_TESTS", None)
|
||||
|
||||
|
||||
def run(command: list[str]) -> None:
|
||||
print("+", " ".join(command), flush=True)
|
||||
subprocess.run(command, cwd=ROOT, env=ENV, check=True)
|
||||
|
||||
|
||||
run(
|
||||
[
|
||||
"cargo",
|
||||
"test",
|
||||
"-p",
|
||||
"libremetaverse-rendering-simple",
|
||||
"-p",
|
||||
"libremetaverse-rendering-mesh-foundry",
|
||||
"-p",
|
||||
"libremetaverse-rlv",
|
||||
"-p",
|
||||
"libremetaverse-lsl-tools",
|
||||
"--locked",
|
||||
"-j",
|
||||
"1",
|
||||
]
|
||||
)
|
||||
|
||||
catalog = json.loads((ROOT / "tests" / "upstream-tests.json").read_text())
|
||||
rlv_targets = sorted(
|
||||
{
|
||||
Path(test["rust_file"]).stem
|
||||
for test in catalog["tests"]
|
||||
if test["source"].startswith("LibreMetaverse.Tests/RLV/")
|
||||
}
|
||||
)
|
||||
if len(rlv_targets) != 24:
|
||||
raise SystemExit(f"milestone 10 expected 24 RLV test targets, found {rlv_targets}")
|
||||
|
||||
compat = ["cargo", "test", "-p", "libremetaverse-compat-tests"]
|
||||
for target in (
|
||||
"imaging_meshing_semantics",
|
||||
"rendering_shims",
|
||||
"extension_shims",
|
||||
"milestone_10_integration",
|
||||
*rlv_targets,
|
||||
):
|
||||
compat.extend(("--test", target))
|
||||
compat.extend(("--locked", "-j", "1"))
|
||||
run(compat)
|
||||
|
||||
run(
|
||||
[
|
||||
"cargo",
|
||||
"check",
|
||||
"--manifest-path",
|
||||
"tests/api-compile/Cargo.toml",
|
||||
"--locked",
|
||||
"-j",
|
||||
"1",
|
||||
]
|
||||
)
|
||||
Reference in New Issue
Block a user