Some checks failed
API and SemVer surface / api-surface (push) Failing after 1m34s
Native code generation / deterministic (push) Has been cancelled
Concurrency and resource soak audit / soak (push) Has been cancelled
Documentation / documentation (push) Has been cancelled
performance evidence / audit (push) Has been cancelled
First release candidate / non-fuzz-release-gate (push) Has been cancelled
Release platform and feature matrix / audit (push) Has been cancelled
Release platform and feature matrix / matrix (false, linux-stable-minimal, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (false, macos-stable-portable, x86_64-apple-darwin, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (false, windows-stable-portable, x86_64-pc-windows-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-msrv-portable, x86_64-unknown-linux-gnu, 1.96.0) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-default, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-features, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-release-surface, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Dependency and supply-chain audit / audit (push) Has been cancelled
Native release artifact audit / audit (push) Has been cancelled
Imaging and meshing gate / native (push) Failing after 53s
JPEG 2000 feature / linux (push) Successful in 2m49s
Native Rust workspace compile / compile (push) Failing after 59s
Skia feature / linux (push) Has been cancelled
599 lines
20 KiB
Rust
599 lines
20 KiB
Rust
//! Native Rust grid client corresponding to the main `LibreMetaverse` assembly.
|
|
//!
|
|
//! Start here for login, networking, agents, inventory, assets, appearance,
|
|
//! world, and social APIs. The appended guide covers crate selection, C# name
|
|
//! migration, ownership, cancellation, events, security, and `OpenSim` setup.
|
|
|
|
#![doc = include_str!("../README.md")]
|
|
|
|
extern crate self as libremetaverse;
|
|
|
|
#[rustfmt::skip] // Deterministic machine output is formatted by the pinned generator.
|
|
mod attention_catalog;
|
|
mod agent_manager;
|
|
mod agent_messages;
|
|
mod agent_movement;
|
|
mod animation;
|
|
#[path = "animesh.rs"]
|
|
mod animesh_runtime;
|
|
mod animesh_skinning;
|
|
mod appearance_baker;
|
|
mod appearance_manager;
|
|
mod asset_archive;
|
|
mod asset_cache;
|
|
mod asset_manager;
|
|
mod asset_material;
|
|
mod asset_models;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod asset_prim;
|
|
mod avatar_manager;
|
|
mod avatar_rig;
|
|
mod baking_texture_provider;
|
|
mod bit_pack;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod builtin_simple_renderer;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod callback_runtime;
|
|
mod caps;
|
|
mod caps_http;
|
|
mod client_core;
|
|
mod current_outfit;
|
|
mod download_manager;
|
|
mod environment_manager;
|
|
mod estate_tools;
|
|
mod event_queue;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod event_subscription;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod file_helper;
|
|
mod friends_manager;
|
|
mod gesture;
|
|
mod gltf;
|
|
mod group_manager;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod helpers;
|
|
mod initial_outfit;
|
|
mod inventory;
|
|
mod inventory_ais;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod inventory_exception;
|
|
mod inventory_manager;
|
|
#[rustfmt::skip] // Deterministic machine output is formatted by the pinned generator.
|
|
mod foliage_catalog;
|
|
mod generated;
|
|
#[rustfmt::skip] // Deterministic machine output is formatted by the pinned generator.
|
|
mod genepool_catalog;
|
|
mod j2k;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod linden_mesh;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod logger;
|
|
mod login;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod lsl_syntax;
|
|
#[path = "marketplace.rs"]
|
|
mod marketplace_runtime;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod mesh_asset;
|
|
mod message_codec;
|
|
mod message_decoder;
|
|
mod model_workflow;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod name_value;
|
|
mod network_manager;
|
|
mod object_manager;
|
|
mod object_material;
|
|
mod object_model;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod observable_dictionary;
|
|
#[rustfmt::skip]
|
|
pub mod packet_catalog;
|
|
mod directory_manager;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod disposal_helper;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod dynamic_messages;
|
|
mod grid_manager;
|
|
pub use grid_manager::MapItemData;
|
|
mod interest_list;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod packet_base;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod packet_decoder;
|
|
mod packet_wire;
|
|
mod parcel_manager;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod particle_simulator;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod port_errors;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod position_helper;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod prim_object;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod protocol_manager;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod rendering_binary_reader;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod rendering_loader;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod rendering_metadata;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod repeat;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod service_collection;
|
|
mod sim_stats;
|
|
mod skeleton;
|
|
mod slurl;
|
|
mod sound_manager;
|
|
#[rustfmt::skip] // Deterministic machine output is formatted by the pinned generator.
|
|
mod skeleton_catalog;
|
|
mod targa;
|
|
mod terrain_codec;
|
|
mod terrain_manager;
|
|
mod transfers;
|
|
mod udp_transport;
|
|
mod user_report;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod uuid_formatter;
|
|
#[rustfmt::skip] // Deterministic machine output is formatted by the pinned generator.
|
|
mod visual_catalog;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod avatar_model;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod avatar_physics;
|
|
|
|
#[cfg(test)]
|
|
mod appearance_baker_semantics;
|
|
#[cfg(test)]
|
|
mod asset_archive_semantics;
|
|
#[cfg(test)]
|
|
mod asset_pipeline_semantics;
|
|
#[cfg(test)]
|
|
mod avatar_animesh_semantics;
|
|
#[cfg(test)]
|
|
mod batch_link_internal_semantics;
|
|
#[cfg(test)]
|
|
mod inventory_ais_internal_semantics;
|
|
#[cfg(test)]
|
|
mod world_internal_semantics;
|
|
|
|
type Terrain = Vec<Vec<f32>>;
|
|
type TerrainLoaded = Box<dyn Fn(Terrain, i64, i64) + Send + Sync>;
|
|
|
|
impl assets::OarFile {
|
|
#[allow(dead_code, clippy::needless_pass_by_value)]
|
|
fn load_terrain(
|
|
file_path: &str,
|
|
data: Vec<u8>,
|
|
callback: TerrainLoaded,
|
|
bytes_read: i64,
|
|
total_bytes: i64,
|
|
) -> Result<bool, Error> {
|
|
crate::asset_archive::load_terrain(file_path, &data, callback, bytes_read, total_bytes)
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
impl animesh::AnimationTrack {
|
|
fn new(animation_id: libremetaverse_types::UUID) -> Result<Self, Error> {
|
|
Self::native_new(animation_id)
|
|
}
|
|
|
|
fn decode_rotation(
|
|
value: libremetaverse_types::Vector3,
|
|
) -> Result<libremetaverse_types::Quaternion, Error> {
|
|
Self::native_decode_rotation(value)
|
|
}
|
|
}
|
|
|
|
#[allow(
|
|
clippy::needless_pass_by_value,
|
|
clippy::unnecessary_wraps,
|
|
clippy::unused_self,
|
|
dead_code
|
|
)]
|
|
impl animesh::AnimeshPlayer {
|
|
fn new(object_id: libremetaverse_types::UUID) -> Result<Self, Error> {
|
|
Self::native_new(object_id)
|
|
}
|
|
|
|
fn get_or_add_track(
|
|
&mut self,
|
|
animation_id: libremetaverse_types::UUID,
|
|
) -> Result<std::sync::Arc<animesh::AnimationTrack>, Error> {
|
|
self.native_get_or_add_track(animation_id)
|
|
}
|
|
|
|
fn retain_only(
|
|
&mut self,
|
|
animation_ids: std::collections::HashSet<libremetaverse_types::UUID>,
|
|
) -> Result<(), Error> {
|
|
self.native_retain_only(&animation_ids);
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)] // Internal C# surface consumed by InventoryManager workflows.
|
|
impl InventoryAISClient {
|
|
async fn create_inventory_links(
|
|
&self,
|
|
parent_uuid: libremetaverse_types::UUID,
|
|
new_inventory: libremetaverse_structured_data::OSD,
|
|
cancellation_token: Option<libremetaverse_types::compat::CancellationToken>,
|
|
) -> Result<Vec<InventoryItem>, Error> {
|
|
self.native_create_inventory_links(parent_uuid, new_inventory, cancellation_token)
|
|
.await
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code, clippy::needless_pass_by_value, clippy::unnecessary_wraps)]
|
|
impl NetworkManager {
|
|
fn raise_sim_console_response(
|
|
&self,
|
|
message: messages::linden::SimConsoleResponseMessage,
|
|
simulator: Simulator,
|
|
) -> Result<(), Error> {
|
|
self.dispatch_caps_event("SimConsoleResponse", &message, simulator);
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
impl imaging::Baker {
|
|
fn resize_to_bake_dimensions(
|
|
source: libremetaverse_imaging::ManagedImage,
|
|
width: i32,
|
|
height: i32,
|
|
) -> Result<Option<libremetaverse_imaging::ManagedImage>, Error> {
|
|
crate::appearance_baker::Baker::native_resize_to_bake_dimensions(source, width, height)
|
|
}
|
|
}
|
|
|
|
pub use callback_runtime::{AsyncInvocation, DictionaryCallbackTarget};
|
|
pub use caps_http::CapsHttpLimits;
|
|
pub use client_core::{
|
|
ClientCoreError, ClientLifecycleState, ClientService, GridClientBuilder, ShutdownPhase,
|
|
};
|
|
pub use generated::*;
|
|
pub use libremetaverse_imaging as imaging_abstractions;
|
|
pub use libremetaverse_structured_data as structured_data;
|
|
pub use libremetaverse_types as types;
|
|
pub use libremetaverse_types::Error;
|
|
pub use logger::LoggerCallbackTarget;
|
|
pub use network_manager::SimulatorCollection;
|
|
pub use udp_transport::{
|
|
AgentThrottleSender, UdpPacketHandler, UdpThrottleCategory, UdpTransportConfig,
|
|
UdpTransportError, UdpTransportStats,
|
|
};
|
|
pub use user_report::{UserReport, UserReportService, UserReportType};
|
|
|
|
pub(crate) fn is_offline_fixture_uri(uri: &libremetaverse_types::compat::Uri) -> bool {
|
|
reqwest::Url::parse(&uri.0)
|
|
.ok()
|
|
.and_then(|url| url.host_str().map(str::to_owned))
|
|
.is_some_and(|host| host == "invalid" || host.ends_with(".invalid"))
|
|
}
|
|
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod collada;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod coordinate_frame;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod physics_volume_morphs;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod simulator_data_pool;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod sound_catalog;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod statistics_runtime;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod texture_pipeline;
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the pinned C# API.
|
|
mod threading_runtime;
|
|
|
|
/// Rust object-safe view of the C# `InventoryBase` inheritance hierarchy.
|
|
pub trait InventoryObjectClass: std::any::Any {
|
|
/// Returns the concrete value for exact C# runtime-type checks.
|
|
fn as_any(&self) -> &dyn std::any::Any;
|
|
|
|
/// Returns the shared `InventoryBase` portion of the concrete object.
|
|
fn inventory_base(&self) -> &InventoryBase;
|
|
|
|
/// Returns the shared `InventoryItem` portion for item-derived objects.
|
|
fn inventory_item(&self) -> Option<&InventoryItem> {
|
|
None
|
|
}
|
|
}
|
|
|
|
/// Rust object-safe view of concrete classes derived from C# `InventoryItem`.
|
|
pub trait InventoryItemClass: InventoryObjectClass {}
|
|
|
|
macro_rules! inventory_object_class {
|
|
($type:ty, $base:ident $(.$nested:ident)*) => {
|
|
impl InventoryObjectClass for $type {
|
|
fn as_any(&self) -> &dyn std::any::Any {
|
|
self
|
|
}
|
|
|
|
fn inventory_base(&self) -> &InventoryBase {
|
|
&self.$base$(.$nested)*
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
macro_rules! inventory_item_class {
|
|
($type:ty, $item:ident $(.$nested:ident)*) => {
|
|
impl InventoryObjectClass for $type {
|
|
fn as_any(&self) -> &dyn std::any::Any {
|
|
self
|
|
}
|
|
|
|
fn inventory_base(&self) -> &InventoryBase {
|
|
&self.$item$(.$nested)*.base
|
|
}
|
|
|
|
fn inventory_item(&self) -> Option<&InventoryItem> {
|
|
Some(&self.$item$(.$nested)*)
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
impl InventoryObjectClass for InventoryBase {
|
|
fn as_any(&self) -> &dyn std::any::Any {
|
|
self
|
|
}
|
|
|
|
fn inventory_base(&self) -> &InventoryBase {
|
|
self
|
|
}
|
|
}
|
|
|
|
inventory_object_class!(InventoryFolder, base);
|
|
impl InventoryObjectClass for InventoryItem {
|
|
fn as_any(&self) -> &dyn std::any::Any {
|
|
self
|
|
}
|
|
|
|
fn inventory_base(&self) -> &InventoryBase {
|
|
&self.base
|
|
}
|
|
|
|
fn inventory_item(&self) -> Option<&InventoryItem> {
|
|
Some(self)
|
|
}
|
|
}
|
|
inventory_item_class!(InventoryAnimation, base);
|
|
inventory_item_class!(InventoryAttachment, base);
|
|
inventory_item_class!(InventoryCallingCard, base);
|
|
inventory_item_class!(InventoryCategory, base);
|
|
inventory_item_class!(InventoryGesture, base);
|
|
inventory_item_class!(InventoryLSL, base);
|
|
inventory_item_class!(InventoryLandmark, base);
|
|
inventory_item_class!(InventoryMaterial, base);
|
|
inventory_item_class!(InventoryNotecard, base);
|
|
inventory_item_class!(InventoryObject, base);
|
|
inventory_item_class!(InventorySettings, base);
|
|
inventory_item_class!(InventorySnapshot, base);
|
|
inventory_item_class!(InventorySound, base);
|
|
inventory_item_class!(InventoryTexture, base);
|
|
inventory_item_class!(InventoryWearable, base);
|
|
|
|
impl InventoryItemClass for InventoryItem {}
|
|
impl InventoryItemClass for InventoryAnimation {}
|
|
impl InventoryItemClass for InventoryAttachment {}
|
|
impl InventoryItemClass for InventoryCallingCard {}
|
|
impl InventoryItemClass for InventoryCategory {}
|
|
impl InventoryItemClass for InventoryGesture {}
|
|
impl InventoryItemClass for InventoryLSL {}
|
|
impl InventoryItemClass for InventoryLandmark {}
|
|
impl InventoryItemClass for InventoryMaterial {}
|
|
impl InventoryItemClass for InventoryNotecard {}
|
|
impl InventoryItemClass for InventoryObject {}
|
|
impl InventoryItemClass for InventorySettings {}
|
|
impl InventoryItemClass for InventorySnapshot {}
|
|
impl InventoryItemClass for InventorySound {}
|
|
impl InventoryItemClass for InventoryTexture {}
|
|
impl InventoryItemClass for InventoryWearable {}
|
|
|
|
/// Project-owned boundary types for external `MessagePack` signatures.
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the external API boundary.
|
|
pub mod message_pack {
|
|
use libremetaverse_types::Error;
|
|
|
|
pub trait IMessagePackFormatter<T = ()> {
|
|
fn serialize(
|
|
&self,
|
|
writer: &mut MessagePackWriter,
|
|
value: T,
|
|
options: MessagePackSerializerOptions,
|
|
) -> Result<(), Error>;
|
|
|
|
fn deserialize(
|
|
&mut self,
|
|
reader: &mut MessagePackReader,
|
|
options: MessagePackSerializerOptions,
|
|
) -> Result<T, Error>;
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct MessagePackReader {
|
|
bytes: Vec<u8>,
|
|
position: usize,
|
|
}
|
|
|
|
impl MessagePackReader {
|
|
#[must_use]
|
|
pub fn new(bytes: Vec<u8>) -> Self {
|
|
Self { bytes, position: 0 }
|
|
}
|
|
|
|
pub fn read_bytes(&mut self) -> Result<Option<Vec<u8>>, Error> {
|
|
let marker = *self
|
|
.bytes
|
|
.get(self.position)
|
|
.ok_or(Error::IndexOutOfRange)?;
|
|
self.position += 1;
|
|
if marker == 0xc0 {
|
|
return Ok(None);
|
|
}
|
|
let length = match marker {
|
|
0xc4 => {
|
|
let length = *self
|
|
.bytes
|
|
.get(self.position)
|
|
.ok_or(Error::IndexOutOfRange)?;
|
|
self.position += 1;
|
|
usize::from(length)
|
|
}
|
|
0xc5 => {
|
|
let length = self
|
|
.bytes
|
|
.get(self.position..self.position + 2)
|
|
.ok_or(Error::IndexOutOfRange)?;
|
|
self.position += 2;
|
|
usize::from(u16::from_be_bytes([length[0], length[1]]))
|
|
}
|
|
0xc6 => {
|
|
let length = self
|
|
.bytes
|
|
.get(self.position..self.position + 4)
|
|
.ok_or(Error::IndexOutOfRange)?;
|
|
self.position += 4;
|
|
usize::try_from(u32::from_be_bytes([
|
|
length[0], length[1], length[2], length[3],
|
|
]))
|
|
.map_err(|_| Error::IndexOutOfRange)?
|
|
}
|
|
_ => {
|
|
return Err(Error::Parse {
|
|
position: self.position - 1,
|
|
context: "MessagePack binary marker",
|
|
});
|
|
}
|
|
};
|
|
let end = self
|
|
.position
|
|
.checked_add(length)
|
|
.ok_or(Error::IndexOutOfRange)?;
|
|
let value = self
|
|
.bytes
|
|
.get(self.position..end)
|
|
.ok_or(Error::IndexOutOfRange)?
|
|
.to_vec();
|
|
self.position = end;
|
|
Ok(Some(value))
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Default)]
|
|
pub struct MessagePackSerializerOptions;
|
|
|
|
#[derive(Clone, Debug, Default)]
|
|
pub struct MessagePackWriter {
|
|
bytes: Vec<u8>,
|
|
}
|
|
|
|
impl MessagePackWriter {
|
|
#[must_use]
|
|
pub fn new() -> Self {
|
|
Self::default()
|
|
}
|
|
|
|
pub fn write_bytes(&mut self, value: &[u8]) -> Result<(), Error> {
|
|
match value.len() {
|
|
length if u8::try_from(length).is_ok() => {
|
|
self.bytes.push(0xc4);
|
|
self.bytes.push(length as u8);
|
|
}
|
|
length if u16::try_from(length).is_ok() => {
|
|
self.bytes.push(0xc5);
|
|
self.bytes.extend_from_slice(&(length as u16).to_be_bytes());
|
|
}
|
|
length => {
|
|
self.bytes.push(0xc6);
|
|
let length = u32::try_from(length).map_err(|_| Error::Argument)?;
|
|
self.bytes.extend_from_slice(&length.to_be_bytes());
|
|
}
|
|
}
|
|
self.bytes.extend_from_slice(value);
|
|
Ok(())
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn as_slice(&self) -> &[u8] {
|
|
&self.bytes
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn into_bytes(self) -> Vec<u8> {
|
|
self.bytes
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Project-owned boundary types for external logging signatures.
|
|
#[allow(clippy::all, clippy::pedantic)] // Public shapes mirror the external API boundary.
|
|
pub mod logging {
|
|
use std::sync::Arc;
|
|
|
|
use libremetaverse_types::compat::{Close, ExternalError, Object};
|
|
|
|
pub trait ILogger: Send + Sync {
|
|
fn is_enabled(&self, level: LogLevel) -> bool;
|
|
fn log(
|
|
&self,
|
|
level: LogLevel,
|
|
message: &Object,
|
|
exception: Option<&ExternalError>,
|
|
client_name: Option<&str>,
|
|
);
|
|
fn begin_scope(&self, state: Object) -> Box<dyn Close>;
|
|
}
|
|
|
|
pub trait ILoggerFactory: Send + Sync {
|
|
fn create_logger(&self, name: &str) -> Arc<dyn ILogger>;
|
|
fn shutdown(&self) -> Result<(), ExternalError>;
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
|
pub struct LogLevel(pub i32);
|
|
|
|
impl LogLevel {
|
|
pub const TRACE: Self = Self(0);
|
|
pub const DEBUG: Self = Self(1);
|
|
pub const INFORMATION: Self = Self(2);
|
|
pub const WARNING: Self = Self(3);
|
|
pub const ERROR: Self = Self(4);
|
|
pub const CRITICAL: Self = Self(5);
|
|
pub const NONE: Self = Self(6);
|
|
}
|
|
}
|
|
|
|
/// Project-owned boundary types for external networking signatures.
|
|
pub mod net {
|
|
pub struct RateLimiter;
|
|
pub struct Socket;
|
|
pub struct TcpStream;
|
|
pub struct UdpSocket;
|
|
}
|
|
|
|
/// Project-owned boundary types for external service-collection signatures.
|
|
pub mod services {
|
|
pub use crate::service_collection::{IServiceCollection, ServiceCollection};
|
|
}
|
|
|
|
/// Common behavior for program shims while the network stack is unimplemented.
|
|
pub mod shim {
|
|
use std::process::ExitCode;
|
|
|
|
/// Reports that an upstream sample has a target but no implementation yet.
|
|
#[must_use]
|
|
pub fn pending_program(name: &str) -> ExitCode {
|
|
eprintln!("{name}: LibreMetaverse Rust port is not implemented yet");
|
|
ExitCode::FAILURE
|
|
}
|
|
}
|