Translate asset and material parity tests
Some checks failed
Rust API gates / api-gates (push) Has been cancelled

This commit is contained in:
2026-08-08 15:29:02 +02:00
parent 069e6366b2
commit 9eb4345750
15 changed files with 3735 additions and 3093 deletions

View File

@@ -51,6 +51,8 @@ pub enum Error {
ArgumentNull,
/// An argument value or length was invalid.
Argument,
/// The requested operation was not valid in the object's current state.
InvalidOperation,
/// An index or destination buffer boundary was exceeded.
IndexOutOfRange,
/// An operation observed a requested cancellation.
@@ -63,7 +65,11 @@ impl Error {
pub const fn csharp_member(self) -> Option<&'static str> {
match self {
Self::NotImplemented(error) => Some(error.csharp_member()),
Self::ArgumentNull | Self::Argument | Self::IndexOutOfRange | Self::Cancelled => None,
Self::ArgumentNull
| Self::Argument
| Self::InvalidOperation
| Self::IndexOutOfRange
| Self::Cancelled => None,
}
}
}
@@ -80,6 +86,7 @@ impl fmt::Display for Error {
Self::NotImplemented(error) => error.fmt(formatter),
Self::ArgumentNull => formatter.write_str("required argument was null"),
Self::Argument => formatter.write_str("argument was invalid"),
Self::InvalidOperation => formatter.write_str("operation was invalid for this state"),
Self::IndexOutOfRange => formatter.write_str("index was out of range"),
Self::Cancelled => formatter.write_str("operation was cancelled"),
}
@@ -152,5 +159,9 @@ mod tests {
.expect("placeholder panic must retain its visible marker");
assert_eq!(message, &format!("{PANIC_PREFIX}{MEMBER}"));
assert!(not_implemented::<()>(MEMBER).is_err());
assert_eq!(
Error::InvalidOperation.to_string(),
"operation was invalid for this state"
);
}
}

View File

@@ -0,0 +1,92 @@
// The upstream tests reach the internal OarFile.LoadTerrain member via reflection.
// Keep the equivalent Rust seam private to the owning crate.
// BSD-3-Clause source (see LICENSE.md): LibreMetaverse.Tests/OarFileTerrainTests.cs
// SHA-256: 19c42f7f132b97dc1667208f1e9b49df8ff6db96265c22b1c1ef5498e3c5c75d
#![allow(clippy::float_cmp)]
use crate::Error;
use crate::assets::OarFile;
use std::sync::{Arc, Mutex};
type Terrain = Vec<Vec<f32>>;
type TerrainLoaded = Box<dyn Fn(Terrain, i64, i64) + Send + Sync>;
impl OarFile {
fn load_terrain(
_file_path: &str,
_data: Vec<u8>,
_callback: TerrainLoaded,
_bytes_read: i64,
_total_bytes: i64,
) -> Result<bool, Error> {
libremetaverse_types::not_implemented(
"M:LibreMetaverse.Assets.OarFile.LoadTerrain(System.String,System.Byte[],LibreMetaverse.Assets.OarFile.TerrainLoadedCallback,System.Int64,System.Int64)",
)
}
}
fn raw_terrain(side: usize, fill: f32) -> Vec<u8> {
fill.to_le_bytes().repeat(side * side)
}
fn invoke_load_terrain(file_path: &str, data: Vec<u8>) -> (bool, Option<Terrain>) {
let captured = Arc::new(Mutex::new(None));
let callback_capture = Arc::clone(&captured);
let total_bytes = i64::try_from(data.len()).expect("terrain byte count fits i64");
let loaded = OarFile::load_terrain(
file_path,
data,
Box::new(move |terrain, _, _| {
*callback_capture.lock().expect("terrain capture") = Some(terrain);
}),
0,
total_bytes,
)
.expect("OarFile.LoadTerrain");
let terrain = captured.lock().expect("terrain capture").take();
(loaded, terrain)
}
// Fixture SHA-256: fcdd41fbadfe6a69d9687b3777692c2de82c831856fa8bcef978c3c17b0117fa
// parity-case: LibreMetaverse.Tests/OarFileTerrainTests.cs::OarFileTerrainTests.LoadTerrain_StandardRegion_Loads256x256::test c4e3a994baf06b0106a6614e9c3efbcc27e45ff1725f5470d2db6ded1fff6014 translated
#[test]
fn load_standard_region_terrain() {
let (loaded, terrain) = invoke_load_terrain("terrains/region.r32", raw_terrain(256, 21.0));
assert!(loaded);
let terrain = terrain.expect("terrain callback");
assert_eq!(terrain.len(), 256);
assert!(terrain.iter().all(|row| row.len() == 256));
assert_eq!(terrain[0][0], 21.0);
}
// Fixture SHA-256: c07500b6f966d65dda9261e3e701fb5bb13e31239ff3a89d74c0046d0ba4ec12
// parity-case: LibreMetaverse.Tests/OarFileTerrainTests.cs::OarFileTerrainTests.LoadTerrain_Varregion_Loads512x512::test 4820338f10acbb4987e26992d7a7957be58ab6bc548674bf18943ef312962894 translated
#[test]
fn load_varregion_terrain() {
let (loaded, terrain) = invoke_load_terrain("terrains/megaregion.f32", raw_terrain(512, 30.0));
assert!(loaded);
let terrain = terrain.expect("terrain callback");
assert_eq!(terrain.len(), 512);
assert!(terrain.iter().all(|row| row.len() == 512));
}
// Fixture SHA-256: 2dc88437e482fdaa5613df885d49c2b19bd623ecfc387a72338d2367d4b3b451
// parity-case: LibreMetaverse.Tests/OarFileTerrainTests.cs::OarFileTerrainTests.LoadTerrain_WrongByteCount_FailsGracefully::test ff6fb4feb2773c93397d412d0ecf6aef1f3636e823dabb729a7a6cbe94d1513f translated
#[test]
fn reject_terrain_with_wrong_byte_count() {
let (loaded, terrain) =
invoke_load_terrain("terrains/broken.r32", vec![0; 256_usize * 256 * 4 + 3]);
assert!(!loaded);
assert!(terrain.is_none());
}
// Fixture SHA-256: 9b94b83334ada38b48b53f19ef2c45abc9f84fb723564671290a556f75d6fdc8
// parity-case: LibreMetaverse.Tests/OarFileTerrainTests.cs::OarFileTerrainTests.LoadTerrain_NonSquarePostCount_FailsGracefully::test 218754e53232cd10318668c70b94ae9d7d541d09598b0490082e023e76d6045f translated
#[test]
fn reject_terrain_with_non_square_post_count() {
let (loaded, terrain) =
invoke_load_terrain("terrains/nonsquare.r32", vec![0; 257_usize * 256 * 4]);
assert!(!loaded);
assert!(terrain.is_none());
}

View File

@@ -5042,7 +5042,7 @@ impl AssetManager {
libremetaverse_types::unimplemented_api!("E:LibreMetaverse.AssetManager.XferReceived")
}
/// C# member: `M:LibreMetaverse.AssetManager.#ctor(LibreMetaverse.GridClient)`.
pub fn new(client: libremetaverse::GridClient) -> Result<Self, crate::Error> {
pub fn new(client: Option<libremetaverse::GridClient>) -> Result<Self, crate::Error> {
libremetaverse_types::not_implemented(
"M:LibreMetaverse.AssetManager.#ctor(LibreMetaverse.GridClient)",
)
@@ -27523,7 +27523,7 @@ impl TerrainManager {
pub async fn get_terrain_material_overrides(
&self,
cancellation_token: Option<libremetaverse_types::compat::CancellationToken>,
) -> Result<Option<Vec<libremetaverse::assets::AssetMaterial>>, crate::Error> {
) -> Result<Option<Vec<Option<libremetaverse::assets::AssetMaterial>>>, crate::Error> {
libremetaverse_types::not_implemented(
"M:LibreMetaverse.TerrainManager.GetTerrainMaterialOverridesAsync(System.Threading.CancellationToken)",
)
@@ -27531,7 +27531,7 @@ impl TerrainManager {
/// C# member: `M:LibreMetaverse.TerrainManager.SetTerrainMaterialOverridesAsync(LibreMetaverse.Assets.AssetMaterial[],System.Threading.CancellationToken)`.
pub async fn set_terrain_material_overrides(
&self,
overrides: Vec<libremetaverse::assets::AssetMaterial>,
overrides: Vec<Option<libremetaverse::assets::AssetMaterial>>,
cancellation_token: Option<libremetaverse_types::compat::CancellationToken>,
) -> Result<bool, crate::Error> {
libremetaverse_types::not_implemented(
@@ -29804,7 +29804,7 @@ pub mod assets {
}
/// C# member: `M:LibreMetaverse.Assets.AssetMaterial.ApplyOverride(LibreMetaverse.Assets.AssetMaterial)`.
pub fn apply_override(
&self,
&mut self,
override_mat: libremetaverse::assets::AssetMaterial,
) -> Result<(), crate::Error> {
libremetaverse_types::not_implemented(
@@ -29812,11 +29812,11 @@ pub mod assets {
)
}
/// C# member: `M:LibreMetaverse.Assets.AssetMaterial.Decode`.
pub fn decode(&self) -> Result<bool, crate::Error> {
pub fn decode(&mut self) -> Result<bool, crate::Error> {
libremetaverse_types::not_implemented("M:LibreMetaverse.Assets.AssetMaterial.Decode")
}
/// C# member: `M:LibreMetaverse.Assets.AssetMaterial.Encode`.
pub fn encode(&self) -> Result<(), crate::Error> {
pub fn encode(&mut self) -> Result<(), crate::Error> {
libremetaverse_types::not_implemented("M:LibreMetaverse.Assets.AssetMaterial.Encode")
}
/// C# member: `M:LibreMetaverse.Assets.AssetMaterial.FromOverrideOsd(LibreMetaverse.StructuredData.OSDMap)`.
@@ -29829,7 +29829,7 @@ pub mod assets {
}
/// C# member: `M:LibreMetaverse.Assets.AssetMaterial.SetAlphaCutoff(System.Single,System.Boolean)`.
pub fn set_alpha_cutoff_with_single_boolean(
&self,
&mut self,
cutoff: f32,
for_override: Option<bool>,
) -> Result<(), crate::Error> {
@@ -29839,7 +29839,7 @@ pub mod assets {
}
/// C# member: `M:LibreMetaverse.Assets.AssetMaterial.SetAlphaMode(LibreMetaverse.Assets.GltfAlphaMode,System.Boolean)`.
pub fn set_alpha_mode_with_gltf_alpha_mode_boolean(
&self,
&mut self,
mode: libremetaverse::assets::GltfAlphaMode,
for_override: Option<bool>,
) -> Result<(), crate::Error> {
@@ -29849,7 +29849,7 @@ pub mod assets {
}
/// C# member: `M:LibreMetaverse.Assets.AssetMaterial.SetBaseColorFactor(LibreMetaverse.Color4,System.Boolean)`.
pub fn set_base_color_factor_with_color4_boolean(
&self,
&mut self,
color: libremetaverse_types::Color4,
for_override: Option<bool>,
) -> Result<(), crate::Error> {
@@ -29858,14 +29858,14 @@ pub mod assets {
)
}
/// C# member: `M:LibreMetaverse.Assets.AssetMaterial.SetBaseMaterial`.
pub fn set_base_material(&self) -> Result<(), crate::Error> {
pub fn set_base_material(&mut self) -> Result<(), crate::Error> {
libremetaverse_types::not_implemented(
"M:LibreMetaverse.Assets.AssetMaterial.SetBaseMaterial",
)
}
/// C# member: `M:LibreMetaverse.Assets.AssetMaterial.SetDoubleSided(System.Boolean,System.Boolean)`.
pub fn set_double_sided_with_boolean_boolean(
&self,
&mut self,
double_sided: bool,
for_override: Option<bool>,
) -> Result<(), crate::Error> {
@@ -29875,7 +29875,7 @@ pub mod assets {
}
/// C# member: `M:LibreMetaverse.Assets.AssetMaterial.SetEmissiveFactor(LibreMetaverse.Vector3,System.Boolean)`.
pub fn set_emissive_factor_with_vector3_boolean(
&self,
&mut self,
color: libremetaverse_types::Vector3,
for_override: Option<bool>,
) -> Result<(), crate::Error> {
@@ -29885,7 +29885,7 @@ pub mod assets {
}
/// C# member: `M:LibreMetaverse.Assets.AssetMaterial.SetMetallicFactor(System.Single,System.Boolean)`.
pub fn set_metallic_factor_with_single_boolean(
&self,
&mut self,
metallic: f32,
for_override: Option<bool>,
) -> Result<(), crate::Error> {
@@ -29895,7 +29895,7 @@ pub mod assets {
}
/// C# member: `M:LibreMetaverse.Assets.AssetMaterial.SetRoughnessFactor(System.Single,System.Boolean)`.
pub fn set_roughness_factor_with_single_boolean(
&self,
&mut self,
roughness: f32,
for_override: Option<bool>,
) -> Result<(), crate::Error> {
@@ -29905,7 +29905,7 @@ pub mod assets {
}
/// C# member: `M:LibreMetaverse.Assets.AssetMaterial.SetTextureId(System.Int32,LibreMetaverse.UUID,System.Boolean)`.
pub fn set_texture_id(
&self,
&mut self,
slot: i32,
id: libremetaverse_types::UUID,
for_override: Option<bool>,
@@ -29916,7 +29916,7 @@ pub mod assets {
}
/// C# member: `M:LibreMetaverse.Assets.AssetMaterial.SetTextureOffset(System.Int32,LibreMetaverse.Vector2)`.
pub fn set_texture_offset(
&self,
&mut self,
slot: i32,
offset: libremetaverse_types::Vector2,
) -> Result<(), crate::Error> {
@@ -29925,14 +29925,18 @@ pub mod assets {
)
}
/// C# member: `M:LibreMetaverse.Assets.AssetMaterial.SetTextureRotation(System.Int32,System.Single)`.
pub fn set_texture_rotation(&self, slot: i32, rotation: f32) -> Result<(), crate::Error> {
pub fn set_texture_rotation(
&mut self,
slot: i32,
rotation: f32,
) -> Result<(), crate::Error> {
libremetaverse_types::not_implemented(
"M:LibreMetaverse.Assets.AssetMaterial.SetTextureRotation(System.Int32,System.Single)",
)
}
/// C# member: `M:LibreMetaverse.Assets.AssetMaterial.SetTextureScale(System.Int32,LibreMetaverse.Vector2)`.
pub fn set_texture_scale(
&self,
&mut self,
slot: i32,
scale: libremetaverse_types::Vector2,
) -> Result<(), crate::Error> {

View File

@@ -4,6 +4,9 @@ extern crate self as libremetaverse;
mod generated;
#[cfg(test)]
mod asset_archive_semantics;
pub use generated::*;
pub use libremetaverse_imaging as imaging_abstractions;
pub use libremetaverse_structured_data as structured_data;