//! Cross-platform renderer discovery without CLR assembly loading. use std::path::Path; use crate::Error; use crate::rendering::IRendering; const BUILTIN_SIMPLE: &str = "builtin:simple"; pub(crate) fn list_renderers(path: &str) -> Result, Error> { let directory = Path::new(path); if !directory.is_dir() { return Err(Error::Argument); } let mut renderers = vec![BUILTIN_SIMPLE.to_owned()]; let entries = std::fs::read_dir(directory).map_err(|_| Error::Argument)?; for entry in entries { let entry = entry.map_err(|_| Error::Argument)?; let file_type = entry.file_type().map_err(|_| Error::Argument)?; if !file_type.is_file() { continue; } let name = entry.file_name(); let name = name.to_string_lossy().to_ascii_lowercase(); if is_simple_artifact(&name) { renderers.push(entry.path().to_string_lossy().into_owned()); } } renderers.sort(); renderers.dedup(); Ok(renderers) } pub(crate) fn load_renderer(filename: &str) -> Result, Error> { let normalized = Path::new(filename) .file_name() .and_then(|name| name.to_str()) .unwrap_or(filename) .to_ascii_lowercase(); if filename.eq_ignore_ascii_case(BUILTIN_SIMPLE) || filename.eq_ignore_ascii_case("simple") || filename.eq_ignore_ascii_case("LibreMetaverse.Rendering.Simple") || is_simple_artifact(&normalized) { return Ok(Box::new( crate::builtin_simple_renderer::SimpleRenderer::native_new()?, )); } Err(Error::Rendering { source: libremetaverse_types::UUID::zero(), context: "unknown or unsupported renderer", }) } fn is_simple_artifact(name: &str) -> bool { name.contains("libremetaverse_rendering_simple") || name.contains("libremetaverse-rendering-simple") || name.contains("libremetaverse.rendering.simple") } #[cfg(test)] mod tests { use super::*; #[test] fn built_in_renderer_is_discoverable_and_constructible() { let renderers = list_renderers(env!("CARGO_MANIFEST_DIR")).unwrap(); assert!(renderers.iter().any(|name| name == BUILTIN_SIMPLE)); let renderer = load_renderer(BUILTIN_SIMPLE).unwrap(); let mut vertices = Vec::new(); renderer .transform_tex_coords( &mut vertices, libremetaverse_types::Vector3::zero(), crate::PrimitiveTextureEntryFace::new(None).unwrap(), libremetaverse_types::Vector3::one(), ) .unwrap(); } #[test] fn discovery_recognizes_platform_artifact_names() { assert!(is_simple_artifact("liblibremetaverse_rendering_simple.so")); assert!(is_simple_artifact("libremetaverse_rendering_simple.dll")); assert!(is_simple_artifact( "liblibremetaverse_rendering_simple.dylib" )); } }