diff --git a/Cargo.lock b/Cargo.lock index ac2b8b3..5675f74 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "block-buffer" version = "0.10.4" @@ -11,6 +17,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" +dependencies = [ + "hybrid-array", +] + [[package]] name = "bumpalo" version = "3.20.3" @@ -23,6 +38,30 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + [[package]] name = "crypto-common" version = "0.1.7" @@ -33,14 +72,34 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "hybrid-array", +] + [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", - "crypto-common", + "block-buffer 0.10.4", + "crypto-common 0.1.7", +] + +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.1", + "const-oid", + "crypto-common 0.2.2", ] [[package]] @@ -88,6 +147,15 @@ dependencies = [ "r-efi", ] +[[package]] +name = "hybrid-array" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b" +dependencies = [ + "typenum", +] + [[package]] name = "js-sys" version = "0.3.104" @@ -211,8 +279,11 @@ dependencies = [ name = "libremetaverse-types" version = "0.0.1" dependencies = [ + "base64", "getrandom", "md-5", + "sha1", + "sha2", "stats_alloc", "uuid", ] @@ -251,7 +322,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ "cfg-if", - "digest", + "digest 0.10.7", ] [[package]] @@ -296,6 +367,28 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" +[[package]] +name = "sha1" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "digest 0.11.3", +] + [[package]] name = "slab" version = "0.4.12" diff --git a/README.md b/README.md index 386818f..9beecde 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,12 @@ byte encodings are explicitly little-endian and do not depend on host architecture. Matrix4 preserves LibreMetaverse's row-major storage, row-vector transform direction, and translation in the fourth row; quaternion components are stored as `(x, y, z, w)` and products use the reference Hamilton-product -direction. The remaining Types surfaces stay visibly failure-only until their -owning milestone issues are completed. +direction. All Types enum discriminants retain their C# widths, extensible +protocol flags preserve unknown bits, and the native conversion layer covers +numeric and floating-point byte order, UTF-8 +and hex text, hashes and PBKDF2, timestamps, IP addresses, region handles, enum +metadata, and cross-platform OS detection. The remaining Types collections, +caches, and token bucket stay visibly failure-only until their owning milestone +issue is completed. The controlled audit aggregates every expected failure by standardized C# member ID and rejects unrelated fixture, assertion, compile, or symbol errors. diff --git a/api/RUST-MAPPING.tsv b/api/RUST-MAPPING.tsv index 556bad6..a36cc81 100644 --- a/api/RUST-MAPPING.tsv +++ b/api/RUST-MAPPING.tsv @@ -25125,13 +25125,13 @@ M:LibreMetaverse.Utils.CopyBytes(System.Byte[]) method System.Byte[] LibreMetave M:LibreMetaverse.Utils.DateTimeToUnixTime(System.DateTime) method System.UInt32 LibreMetaverse.Utils.DateTimeToUnixTime(System.DateTime time) libremetaverse-types libremetaverse_types::Utils::date_time_to_unix_time pub fn date_time_to_unix_time(time: std::time::SystemTime) -> Result owned sync Result<_, crate::Error> direct_snake_case method mapped M:LibreMetaverse.Utils.Distance(System.Single,System.Single) method System.Single LibreMetaverse.Utils.Distance(System.Single value1, System.Single value2) libremetaverse-types libremetaverse_types::Utils::distance pub fn distance(value1: f32, value2: f32) -> Result owned,owned sync Result<_, crate::Error> direct_snake_case method mapped M:LibreMetaverse.Utils.DoubleToBytes(System.Double) method System.Byte[] LibreMetaverse.Utils.DoubleToBytes(System.Double value) libremetaverse-types libremetaverse_types::Utils::double_to_bytes_with_double pub fn double_to_bytes_with_double(value: f64) -> Result, crate::Error> owned sync Result<_, crate::Error> descriptive_overload_name method mapped -M:LibreMetaverse.Utils.DoubleToBytes(System.Double,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.DoubleToBytes(System.Double value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::double_to_bytes_with_double_bytes_int32 pub fn double_to_bytes_with_double_bytes_int32(value: f64, dest: Vec, pos: i32) -> Result<(), crate::Error> owned,owned,owned sync Result<_, crate::Error> descriptive_overload_name method mapped +M:LibreMetaverse.Utils.DoubleToBytes(System.Double,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.DoubleToBytes(System.Double value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::double_to_bytes_with_double_bytes_int32 pub fn double_to_bytes_with_double_bytes_int32(value: f64, dest: &mut [u8], pos: i32) -> Result<(), crate::Error> owned,mutable_borrow,owned sync Result<_, crate::Error> descriptive_overload_name method mapped M:LibreMetaverse.Utils.DoubleToBytesBig(System.Double) method System.Byte[] LibreMetaverse.Utils.DoubleToBytesBig(System.Double value) libremetaverse-types libremetaverse_types::Utils::double_to_bytes_big pub fn double_to_bytes_big(value: f64) -> Result, crate::Error> owned sync Result<_, crate::Error> direct_snake_case method mapped M:LibreMetaverse.Utils.EnumToText(System.Enum) method System.String LibreMetaverse.Utils.EnumToText(System.Enum value) libremetaverse-types libremetaverse_types::Utils::enum_to_text pub fn enum_to_text(value: libremetaverse_types::compat::EnumValue) -> Result owned sync Result<_, crate::Error> direct_snake_case method mapped -M:LibreMetaverse.Utils.EnumTryParse``1(System.String,``0@) method System.Boolean LibreMetaverse.Utils.EnumTryParse(System.String strType, out T& result) libremetaverse-types libremetaverse_types::Utils::enum_try_parse pub fn enum_try_parse(str_type: String, result: &mut Option) -> Result owned,mutable_output sync Result<_, crate::Error> direct_snake_case method mapped +M:LibreMetaverse.Utils.EnumTryParse``1(System.String,``0@) method System.Boolean LibreMetaverse.Utils.EnumTryParse(System.String strType, out T& result) libremetaverse-types libremetaverse_types::Utils::enum_try_parse pub fn enum_try_parse(str_type: String, result: &mut Option) -> Result owned,mutable_borrow sync Result<_, crate::Error> direct_snake_case method mapped M:LibreMetaverse.Utils.FloatToByte(System.Single,System.Single,System.Single) method System.Byte LibreMetaverse.Utils.FloatToByte(System.Single val, System.Single lower, System.Single upper) libremetaverse-types libremetaverse_types::Utils::float_to_byte pub fn float_to_byte(val: f32, lower: f32, upper: f32) -> Result owned,owned,owned sync Result<_, crate::Error> direct_snake_case method mapped M:LibreMetaverse.Utils.FloatToBytes(System.Single) method System.Byte[] LibreMetaverse.Utils.FloatToBytes(System.Single value) libremetaverse-types libremetaverse_types::Utils::float_to_bytes_with_single pub fn float_to_bytes_with_single(value: f32) -> Result, crate::Error> owned sync Result<_, crate::Error> descriptive_overload_name method mapped -M:LibreMetaverse.Utils.FloatToBytes(System.Single,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.FloatToBytes(System.Single value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::float_to_bytes_with_single_bytes_int32 pub fn float_to_bytes_with_single_bytes_int32(value: f32, dest: Vec, pos: i32) -> Result<(), crate::Error> owned,owned,owned sync Result<_, crate::Error> descriptive_overload_name method mapped +M:LibreMetaverse.Utils.FloatToBytes(System.Single,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.FloatToBytes(System.Single value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::float_to_bytes_with_single_bytes_int32 pub fn float_to_bytes_with_single_bytes_int32(value: f32, dest: &mut [u8], pos: i32) -> Result<(), crate::Error> owned,mutable_borrow,owned sync Result<_, crate::Error> descriptive_overload_name method mapped M:LibreMetaverse.Utils.FloatToUInt16(System.Single,System.Single,System.Single) method System.UInt16 LibreMetaverse.Utils.FloatToUInt16(System.Single value, System.Single lower, System.Single upper) libremetaverse-types libremetaverse_types::Utils::float_to_u_int16 pub fn float_to_u_int16(value: f32, lower: f32, upper: f32) -> Result owned,owned,owned sync Result<_, crate::Error> direct_snake_case method mapped M:LibreMetaverse.Utils.FolderTypeToString(LibreMetaverse.FolderType) method System.String LibreMetaverse.Utils.FolderTypeToString(LibreMetaverse.FolderType type) libremetaverse-types libremetaverse_types::Utils::folder_type_to_string pub fn folder_type_to_string(type_: libremetaverse_types::FolderType) -> Result owned sync Result<_, crate::Error> direct_snake_case method mapped M:LibreMetaverse.Utils.GetRunningPlatform method LibreMetaverse.Utils.Platform LibreMetaverse.Utils.GetRunningPlatform() libremetaverse-types libremetaverse_types::Utils::get_running_platform pub fn get_running_platform() -> Result none sync Result<_, crate::Error> direct_snake_case method mapped @@ -25142,11 +25142,11 @@ M:LibreMetaverse.Utils.HexStringToBytes(System.String,System.Boolean) method Sys M:LibreMetaverse.Utils.HostnameToIPv4(System.String) method System.Net.IPAddress LibreMetaverse.Utils.HostnameToIPv4(System.String hostname) libremetaverse-types libremetaverse_types::Utils::hostname_to_i_pv4 pub fn hostname_to_i_pv4(hostname: String) -> Result, crate::Error> owned sync Result<_, crate::Error> direct_snake_case method mapped M:LibreMetaverse.Utils.IPToUInt(System.Net.IPAddress) method System.UInt32 LibreMetaverse.Utils.IPToUInt(System.Net.IPAddress address) libremetaverse-types libremetaverse_types::Utils::ip_to_u_int pub fn ip_to_u_int(address: std::net::IpAddr) -> Result owned sync Result<_, crate::Error> direct_snake_case method mapped M:LibreMetaverse.Utils.Int16ToBytes(System.Int16) method System.Byte[] LibreMetaverse.Utils.Int16ToBytes(System.Int16 value) libremetaverse-types libremetaverse_types::Utils::int16_to_bytes_with_int16 pub fn int16_to_bytes_with_int16(value: i16) -> Result, crate::Error> owned sync Result<_, crate::Error> descriptive_overload_name method mapped -M:LibreMetaverse.Utils.Int16ToBytes(System.Int16,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.Int16ToBytes(System.Int16 value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::int16_to_bytes_with_int16_bytes_int32 pub fn int16_to_bytes_with_int16_bytes_int32(value: i16, dest: Vec, pos: i32) -> Result<(), crate::Error> owned,owned,owned sync Result<_, crate::Error> descriptive_overload_name method mapped +M:LibreMetaverse.Utils.Int16ToBytes(System.Int16,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.Int16ToBytes(System.Int16 value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::int16_to_bytes_with_int16_bytes_int32 pub fn int16_to_bytes_with_int16_bytes_int32(value: i16, dest: &mut [u8], pos: i32) -> Result<(), crate::Error> owned,mutable_borrow,owned sync Result<_, crate::Error> descriptive_overload_name method mapped M:LibreMetaverse.Utils.Int64ToBytes(System.Int64) method System.Byte[] LibreMetaverse.Utils.Int64ToBytes(System.Int64 value) libremetaverse-types libremetaverse_types::Utils::int64_to_bytes_with_int64 pub fn int64_to_bytes_with_int64(value: i64) -> Result, crate::Error> owned sync Result<_, crate::Error> descriptive_overload_name method mapped -M:LibreMetaverse.Utils.Int64ToBytes(System.Int64,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.Int64ToBytes(System.Int64 value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::int64_to_bytes_with_int64_bytes_int32 pub fn int64_to_bytes_with_int64_bytes_int32(value: i64, dest: Vec, pos: i32) -> Result<(), crate::Error> owned,owned,owned sync Result<_, crate::Error> descriptive_overload_name method mapped +M:LibreMetaverse.Utils.Int64ToBytes(System.Int64,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.Int64ToBytes(System.Int64 value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::int64_to_bytes_with_int64_bytes_int32 pub fn int64_to_bytes_with_int64_bytes_int32(value: i64, dest: &mut [u8], pos: i32) -> Result<(), crate::Error> owned,mutable_borrow,owned sync Result<_, crate::Error> descriptive_overload_name method mapped M:LibreMetaverse.Utils.IntToBytes(System.Int32) method System.Byte[] LibreMetaverse.Utils.IntToBytes(System.Int32 value) libremetaverse-types libremetaverse_types::Utils::int_to_bytes_with_int32 pub fn int_to_bytes_with_int32(value: i32) -> Result, crate::Error> owned sync Result<_, crate::Error> descriptive_overload_name method mapped -M:LibreMetaverse.Utils.IntToBytes(System.Int32,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.IntToBytes(System.Int32 value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::int_to_bytes_with_int32_bytes_int32 pub fn int_to_bytes_with_int32_bytes_int32(value: i32, dest: Vec, pos: i32) -> Result<(), crate::Error> owned,owned,owned sync Result<_, crate::Error> descriptive_overload_name method mapped +M:LibreMetaverse.Utils.IntToBytes(System.Int32,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.IntToBytes(System.Int32 value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::int_to_bytes_with_int32_bytes_int32 pub fn int_to_bytes_with_int32_bytes_int32(value: i32, dest: &mut [u8], pos: i32) -> Result<(), crate::Error> owned,mutable_borrow,owned sync Result<_, crate::Error> descriptive_overload_name method mapped M:LibreMetaverse.Utils.IntToBytesBig(System.Int32) method System.Byte[] LibreMetaverse.Utils.IntToBytesBig(System.Int32 value) libremetaverse-types libremetaverse_types::Utils::int_to_bytes_big pub fn int_to_bytes_big(value: i32) -> Result, crate::Error> owned sync Result<_, crate::Error> direct_snake_case method mapped M:LibreMetaverse.Utils.InventoryTypeToString(LibreMetaverse.InventoryType) method System.String LibreMetaverse.Utils.InventoryTypeToString(LibreMetaverse.InventoryType type) libremetaverse-types libremetaverse_types::Utils::inventory_type_to_string pub fn inventory_type_to_string(type_: libremetaverse_types::InventoryType) -> Result owned sync Result<_, crate::Error> direct_snake_case method mapped M:LibreMetaverse.Utils.IsFinite(System.Double) method System.Boolean LibreMetaverse.Utils.IsFinite(System.Double value) libremetaverse-types libremetaverse_types::Utils::is_finite_with_double pub fn is_finite_with_double(value: f64) -> Result owned sync Result<_, crate::Error> descriptive_overload_name method mapped @@ -25183,17 +25183,17 @@ M:LibreMetaverse.Utils.TryParseDouble(System.String,System.Double@) method Syste M:LibreMetaverse.Utils.TryParseHex(System.String,System.UInt32@) method System.Boolean LibreMetaverse.Utils.TryParseHex(System.String s, out System.UInt32& result) libremetaverse-types libremetaverse_types::Utils::try_parse_hex pub fn try_parse_hex(s: String, result: &mut u32) -> bool owned,mutable_output sync infallible_placeholder direct_snake_case method mapped M:LibreMetaverse.Utils.TryParseSingle(System.String,System.Single@) method System.Boolean LibreMetaverse.Utils.TryParseSingle(System.String s, out System.Single& result) libremetaverse-types libremetaverse_types::Utils::try_parse_single pub fn try_parse_single(s: String, result: &mut f32) -> bool owned,mutable_output sync infallible_placeholder direct_snake_case method mapped M:LibreMetaverse.Utils.UInt16ToBytes(System.UInt16) method System.Byte[] LibreMetaverse.Utils.UInt16ToBytes(System.UInt16 value) libremetaverse-types libremetaverse_types::Utils::u_int16_to_bytes_with_u_int16 pub fn u_int16_to_bytes_with_u_int16(value: u16) -> Result, crate::Error> owned sync Result<_, crate::Error> descriptive_overload_name method mapped -M:LibreMetaverse.Utils.UInt16ToBytes(System.UInt16,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.UInt16ToBytes(System.UInt16 value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::u_int16_to_bytes_with_u_int16_bytes_int32 pub fn u_int16_to_bytes_with_u_int16_bytes_int32(value: u16, dest: Vec, pos: i32) -> Result<(), crate::Error> owned,owned,owned sync Result<_, crate::Error> descriptive_overload_name method mapped -M:LibreMetaverse.Utils.UInt16ToBytesBig(System.UInt16,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.UInt16ToBytesBig(System.UInt16 value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::u_int16_to_bytes_big pub fn u_int16_to_bytes_big(value: u16, dest: Vec, pos: i32) -> Result<(), crate::Error> owned,owned,owned sync Result<_, crate::Error> direct_snake_case method mapped +M:LibreMetaverse.Utils.UInt16ToBytes(System.UInt16,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.UInt16ToBytes(System.UInt16 value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::u_int16_to_bytes_with_u_int16_bytes_int32 pub fn u_int16_to_bytes_with_u_int16_bytes_int32(value: u16, dest: &mut [u8], pos: i32) -> Result<(), crate::Error> owned,mutable_borrow,owned sync Result<_, crate::Error> descriptive_overload_name method mapped +M:LibreMetaverse.Utils.UInt16ToBytesBig(System.UInt16,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.UInt16ToBytesBig(System.UInt16 value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::u_int16_to_bytes_big pub fn u_int16_to_bytes_big(value: u16, dest: &mut [u8], pos: i32) -> Result<(), crate::Error> owned,mutable_borrow,owned sync Result<_, crate::Error> direct_snake_case method mapped M:LibreMetaverse.Utils.UInt16ToFloat(System.Byte[],System.Int32,System.Single,System.Single) method System.Single LibreMetaverse.Utils.UInt16ToFloat(System.Byte[] bytes, System.Int32 pos, System.Single lower, System.Single upper) libremetaverse-types libremetaverse_types::Utils::u_int16_to_float_with_bytes_int32_single_single pub fn u_int16_to_float_with_bytes_int32_single_single(bytes: Vec, pos: i32, lower: f32, upper: f32) -> Result owned,owned,owned,owned sync Result<_, crate::Error> descriptive_overload_name method mapped M:LibreMetaverse.Utils.UInt16ToFloat(System.UInt16,System.Single,System.Single) method System.Single LibreMetaverse.Utils.UInt16ToFloat(System.UInt16 val, System.Single lower, System.Single upper) libremetaverse-types libremetaverse_types::Utils::u_int16_to_float_with_u_int16_single_single pub fn u_int16_to_float_with_u_int16_single_single(val: u16, lower: f32, upper: f32) -> Result owned,owned,owned sync Result<_, crate::Error> descriptive_overload_name method mapped M:LibreMetaverse.Utils.UInt64ToBytes(System.UInt64) method System.Byte[] LibreMetaverse.Utils.UInt64ToBytes(System.UInt64 value) libremetaverse-types libremetaverse_types::Utils::u_int64_to_bytes_with_u_int64 pub fn u_int64_to_bytes_with_u_int64(value: u64) -> Result, crate::Error> owned sync Result<_, crate::Error> descriptive_overload_name method mapped -M:LibreMetaverse.Utils.UInt64ToBytes(System.UInt64,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.UInt64ToBytes(System.UInt64 value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::u_int64_to_bytes_with_u_int64_bytes_int32 pub fn u_int64_to_bytes_with_u_int64_bytes_int32(value: u64, dest: Vec, pos: i32) -> Result<(), crate::Error> owned,owned,owned sync Result<_, crate::Error> descriptive_overload_name method mapped +M:LibreMetaverse.Utils.UInt64ToBytes(System.UInt64,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.UInt64ToBytes(System.UInt64 value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::u_int64_to_bytes_with_u_int64_bytes_int32 pub fn u_int64_to_bytes_with_u_int64_bytes_int32(value: u64, dest: &mut [u8], pos: i32) -> Result<(), crate::Error> owned,mutable_borrow,owned sync Result<_, crate::Error> descriptive_overload_name method mapped M:LibreMetaverse.Utils.UInt64ToBytesBig(System.UInt64) method System.Byte[] LibreMetaverse.Utils.UInt64ToBytesBig(System.UInt64 value) libremetaverse-types libremetaverse_types::Utils::u_int64_to_bytes_big_with_u_int64 pub fn u_int64_to_bytes_big_with_u_int64(value: u64) -> Result, crate::Error> owned sync Result<_, crate::Error> descriptive_overload_name method mapped -M:LibreMetaverse.Utils.UInt64ToBytesBig(System.UInt64,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.UInt64ToBytesBig(System.UInt64 value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::u_int64_to_bytes_big_with_u_int64_bytes_int32 pub fn u_int64_to_bytes_big_with_u_int64_bytes_int32(value: u64, dest: Vec, pos: i32) -> Result<(), crate::Error> owned,owned,owned sync Result<_, crate::Error> descriptive_overload_name method mapped +M:LibreMetaverse.Utils.UInt64ToBytesBig(System.UInt64,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.UInt64ToBytesBig(System.UInt64 value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::u_int64_to_bytes_big_with_u_int64_bytes_int32 pub fn u_int64_to_bytes_big_with_u_int64_bytes_int32(value: u64, dest: &mut [u8], pos: i32) -> Result<(), crate::Error> owned,mutable_borrow,owned sync Result<_, crate::Error> descriptive_overload_name method mapped M:LibreMetaverse.Utils.UIntToBytes(System.UInt32) method System.Byte[] LibreMetaverse.Utils.UIntToBytes(System.UInt32 value) libremetaverse-types libremetaverse_types::Utils::u_int_to_bytes_with_u_int32 pub fn u_int_to_bytes_with_u_int32(value: u32) -> Result, crate::Error> owned sync Result<_, crate::Error> descriptive_overload_name method mapped -M:LibreMetaverse.Utils.UIntToBytes(System.UInt32,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.UIntToBytes(System.UInt32 value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::u_int_to_bytes_with_u_int32_bytes_int32 pub fn u_int_to_bytes_with_u_int32_bytes_int32(value: u32, dest: Vec, pos: i32) -> Result<(), crate::Error> owned,owned,owned sync Result<_, crate::Error> descriptive_overload_name method mapped -M:LibreMetaverse.Utils.UIntToBytesBig(System.UInt32,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.UIntToBytesBig(System.UInt32 value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::u_int_to_bytes_big pub fn u_int_to_bytes_big(value: u32, dest: Vec, pos: i32) -> Result<(), crate::Error> owned,owned,owned sync Result<_, crate::Error> direct_snake_case method mapped +M:LibreMetaverse.Utils.UIntToBytes(System.UInt32,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.UIntToBytes(System.UInt32 value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::u_int_to_bytes_with_u_int32_bytes_int32 pub fn u_int_to_bytes_with_u_int32_bytes_int32(value: u32, dest: &mut [u8], pos: i32) -> Result<(), crate::Error> owned,mutable_borrow,owned sync Result<_, crate::Error> descriptive_overload_name method mapped +M:LibreMetaverse.Utils.UIntToBytesBig(System.UInt32,System.Byte[],System.Int32) method System.Void LibreMetaverse.Utils.UIntToBytesBig(System.UInt32 value, System.Byte[] dest, System.Int32 pos) libremetaverse-types libremetaverse_types::Utils::u_int_to_bytes_big pub fn u_int_to_bytes_big(value: u32, dest: &mut [u8], pos: i32) -> Result<(), crate::Error> owned,mutable_borrow,owned sync Result<_, crate::Error> direct_snake_case method mapped M:LibreMetaverse.Utils.UIntToHexString(System.UInt32) method System.String LibreMetaverse.Utils.UIntToHexString(System.UInt32 i) libremetaverse-types libremetaverse_types::Utils::u_int_to_hex_string pub fn u_int_to_hex_string(i: u32) -> Result owned sync Result<_, crate::Error> direct_snake_case method mapped M:LibreMetaverse.Utils.UIntsToLong(System.UInt32,System.UInt32) method System.UInt64 LibreMetaverse.Utils.UIntsToLong(System.UInt32 a, System.UInt32 b) libremetaverse-types libremetaverse_types::Utils::u_ints_to_long pub fn u_ints_to_long(a: u32, b: u32) -> Result owned,owned sync Result<_, crate::Error> direct_snake_case method mapped M:LibreMetaverse.Utils.UnixTimeToDateTime(System.Int32) method System.DateTime LibreMetaverse.Utils.UnixTimeToDateTime(System.Int32 timestamp) libremetaverse-types libremetaverse_types::Utils::unix_time_to_date_time_with_int32 pub fn unix_time_to_date_time_with_int32(timestamp: i32) -> Result owned sync Result<_, crate::Error> descriptive_overload_name method mapped diff --git a/api/SHIM-COVERAGE.md b/api/SHIM-COVERAGE.md index 8212751..25be668 100644 --- a/api/SHIM-COVERAGE.md +++ b/api/SHIM-COVERAGE.md @@ -13,7 +13,7 @@ Generated by `python3 tools/generate_api_shims.py`; do not edit by hand. | `LibreMetaverse.Rendering.MeshFoundry` | 1 | 14 | callable failure-only shim | | `LibreMetaverse.Rendering.Simple` | 1 | 6 | callable failure-only shim | | `LibreMetaverse.StructuredData` | 16 | 295 | callable failure-only shim | -| `LibreMetaverse.Types` | 45 | 942 | native implementation: 10 types / 419 members; remaining surface is callable failure-only shims | +| `LibreMetaverse.Types` | 45 | 942 | native implementation: 35 types / 821 members; remaining surface is callable failure-only shims | | `LibreMetaverse.Utilities` | 3 | 13 | callable failure-only shim | | `LibreMetaverse.Voice.Vivox` | 64 | 531 | callable failure-only shim | | `LibreMetaverse.Voice.WebRTC` | 12 | 210 | callable failure-only shim | diff --git a/crates/libremetaverse-types/Cargo.toml b/crates/libremetaverse-types/Cargo.toml index 48379dc..0d5a319 100644 --- a/crates/libremetaverse-types/Cargo.toml +++ b/crates/libremetaverse-types/Cargo.toml @@ -11,8 +11,11 @@ description = "Core value-type shims for the MetaCrate LibreMetaverse rewrite" workspace = true [dependencies] +base64 = "0.22" getrandom = "0.4" md-5 = "0.10" +sha1 = "0.10" +sha2 = "0.11" uuid = { version = "1.18", features = ["v4"] } [dev-dependencies] diff --git a/crates/libremetaverse-types/src/compat.rs b/crates/libremetaverse-types/src/compat.rs index 97a857c..9f3923d 100644 --- a/crates/libremetaverse-types/src/compat.rs +++ b/crates/libremetaverse-types/src/compat.rs @@ -135,8 +135,12 @@ pub struct CultureInfo(pub String); #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct ExternalError(pub String); +/// Type-erased enum name and optional [`crate::EnumInfoAttribute`] text. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct EnumValue(pub i64); +pub struct EnumValue { + pub(crate) name: &'static str, + pub(crate) text: Option<&'static str>, +} #[derive(Clone, Debug, Eq, PartialEq)] pub struct ArrayList(pub Vec); diff --git a/crates/libremetaverse-types/src/enum_compat.rs b/crates/libremetaverse-types/src/enum_compat.rs new file mode 100644 index 0000000..148b6e1 --- /dev/null +++ b/crates/libremetaverse-types/src/enum_compat.rs @@ -0,0 +1,418 @@ +//! Native enum metadata, parsing, and flag operations. + +#![allow(clippy::missing_errors_doc)] // Result shapes are fixed by the public compatibility map. +#![allow(clippy::must_use_candidate)] // Attributes are not part of the mapped C# surface. + +use crate::compat::EnumValue; + +/// Metadata needed to reproduce the reflection-based C# enum helpers. +pub trait EnumValueMetadata: Copy + Sized { + /// Parses a named value using the C# helper's case-insensitive comparison. + fn parse_name(name: &str) -> Option; + + /// Returns the C# identifier for this value, when it is named. + fn variant_name(self) -> Option<&'static str>; + + /// Returns the value's `EnumInfoAttribute.Text`, when present. + fn enum_text(self) -> Option<&'static str> { + None + } +} + +/// C# enum presentation metadata. +#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)] +pub struct EnumInfoAttribute { + /// Text used when presenting the enum to a user. + pub text: String, +} + +impl EnumInfoAttribute { + /// Creates an attribute with empty presentation text. + pub fn new_with_constructor() -> Result { + Ok(Self::default()) + } + + /// Creates an attribute with the supplied presentation text. + pub fn new_with_string(text: String) -> Result { + Ok(Self { text }) + } +} + +/// Reflection-free equivalent of the C# enum metadata extension. +pub struct EnumInfoExtensions; + +impl EnumInfoExtensions { + /// Returns attached presentation text, or an empty string when absent. + pub fn get_text(value: EnumValue) -> Result { + Ok(value.text.unwrap_or_default().to_owned()) + } +} + +macro_rules! impl_enum_metadata { + ($ty:ty; $($variant:ident $(=> $text:literal)?),+ $(,)?) => { + impl EnumValueMetadata for $ty { + fn parse_name(name: &str) -> Option { + $(if name.eq_ignore_ascii_case(stringify!($variant)) { + return Some(Self::$variant); + })+ + None + } + + fn variant_name(self) -> Option<&'static str> { + Some(match self { $(Self::$variant => stringify!($variant),)+ }) + } + + #[allow(unreachable_patterns)] + fn enum_text(self) -> Option<&'static str> { + match self { + $($(Self::$variant => Some($text),)?)+ + _ => None, + } + } + } + + impl From<$ty> for EnumValue { + fn from(value: $ty) -> Self { + Self { + name: value.variant_name().unwrap_or_default(), + text: value.enum_text(), + } + } + } + }; +} + +impl_enum_metadata!(crate::AssetType; + Animation => "animatn", Bodypart => "bodypart", CallingCard => "callcard", + Clothing => "clothing", Folder => "category", Gesture => "gesture", + ImageJPEG => "jpeg", ImageTGA => "img_tga", LSLBytecode => "lslbyte", + LSLText => "lsltext", Landmark => "landmark", Link => "link", + LinkFolder => "link_f", Material => "material", Mesh => "mesh", + Notecard => "notecard", Object => "object", Person => "person", + Script => "script", Settings => "settings", Simstate => "simstate", + Sound => "sound", SoundWAV => "snd_wav", Texture => "texture", + TextureTGA => "txtr_tga", Unknown => "invalid", Widget => "widget"); + +impl_enum_metadata!(crate::FolderType; + Animation => "Animations", BasicRoot => "Basic Root", BodyPart => "Body Parts", + CallingCard => "Calling Cards", Clothing => "Clothing", + CurrentOutfit => "Current Outfit", EnsembleEnd, EnsembleStart, + Favorites => "Favorites", Gesture => "Gestures", Inbox => "Received Items", + LSLText => "Scripts", Landmark => "Landmarks", LostAndFound => "Lost And Found", + MarketplaceListings => "Marketplace Listings", MarketplaceStock => "New Stock", + MarketplaceVersion => "Marketplace Version", Material => "Material", Mesh => "Meshes", + MyOutfits => "My Outfits", None, Notecard => "Notecards", Object => "Objects", + OldRoot, Outbox => "Merchant Outbox", Outfit => "New Outfit", + Root => "My Inventory", Settings => "Settings", Snapshot => "Photo Album", + Sound => "Sounds", Suitcase => "Suitcase", Texture => "Textures", Trash => "Trash"); + +impl_enum_metadata!(crate::WearableType; + Alpha => "Alpha", Eyes => "Eyes", Gloves => "Gloves", Hair => "Hair", + Invalid => "Invalid", Jacket => "Jacket", Pants => "Pants", Physics => "Physics", + Shape => "Shape", Shirt => "Shirt", Shoes => "Shoes", Skin => "Skin", + Skirt => "Skirt", Socks => "Socks", Tattoo => "Tattoo", + Underpants => "Underpants", Undershirt => "Undershirt", Universal => "Universal"); + +impl_enum_metadata!(crate::AttachmentPoint; + AltLeftEar => "Alt Left Ear", AltLeftEye => "Alt Left Eye", + AltRightEar => "Alt Right Ear", AltRightEye => "Alt Right Eye", Chest => "Chest", + Chin => "Chin", Default => "Default", Groin => "Groin", HUDBottom => "HUD Bottom", + HUDBottomLeft => "HUD Bottom Left", HUDBottomRight => "HUD Bottom Right", + HUDCenter => "HUD Center 1", HUDCenter2 => "HUD Center 2", HUDTop => "HUD Top Center", + HUDTopLeft => "HUD Top Left", HUDTopRight => "HUD Top Right", Jaw => "Jaw", + LeftEar => "Left Ear", LeftEyeball => "Left Eye", LeftFoot => "Left Foot", + LeftForearm => "Left Lower Arm", LeftHand => "Left Hand", + LeftHandRing => "Left Ring Finger", LeftHindFoot => "Left Hind Foot", + LeftHip => "Left Hip", LeftLowerLeg => "Left Lower Leg", LeftPec => "Left Pec", + LeftShoulder => "Left Shoulder", LeftUpperArm => "Left Upper Arm", + LeftUpperLeg => "Left Upper Leg", LeftWing => "Left Wing", Mouth => "Mouth", + Neck => "Neck", Nose => "Nose", Pelvis => "Pelvis", RightEar => "Right Ear", + RightEyeball => "Right Eye", RightFoot => "Right Foot", + RightForearm => "Right Lower Arm", RightHand => "Right Hand", + RightHandRing => "Right Ring Finger", RightHindFoot => "Right Hind Foot", + RightHip => "Right Hip", RightLowerLeg => "Right Lower Leg", RightPec => "Right Pec", + RightShoulder => "Right Shoulder", RightUpperArm => "Right Upper Arm", + RightUpperLeg => "Right Upper Leg", RightWing => "Right Wing", + Root => "Avatar Center", Skull => "Head", Spine => "Back", Stomach => "Belly", + TailBase => "Tail Base", TailTip => "Tail Tip", Tongue => "Tongue"); + +impl_enum_metadata!(crate::ClickAction; Buy, OpenMedia, OpenTask, Pay, PlayMedia, Sit, Touch); +impl_enum_metadata!(crate::FaceType; InnerSide, OuterSide0, OuterSide1, OuterSide2, OuterSide3, PathBegin, PathEnd, ProfileBegin, ProfileEnd); +impl_enum_metadata!(crate::JointType; Hinge, Invalid, Point); +impl_enum_metadata!(crate::Material; Flesh, Glass, Light, Metal, Plastic, Rubber, Stone, Wood); +impl_enum_metadata!(crate::ObjectCategory; Group, Invalid, None, Other, Owner, Selected, Temporary); +impl_enum_metadata!(crate::PCode; Avatar, Grass, NewTree, None, ParticleSystem, Prim, Tree); +impl_enum_metadata!(crate::PathCurve; Circle, Circle2, Flexible, Line, Test); +impl_enum_metadata!(crate::PhysicsShapeType; ConvexHull, None, Prim); +impl_enum_metadata!(crate::PrimType; Box, Cylinder, Mesh, Prism, Ring, Sculpt, Sphere, Torus, Tube, Unknown); +impl_enum_metadata!(crate::ProfileCurve; Circle, EqualTriangle, HalfCircle, IsoTriangle, RightTriangle, Square); +impl_enum_metadata!(crate::SaleType; Contents, Copy, Not, Original); +impl_enum_metadata!(crate::SculptType; Cylinder, Invert, Mesh, Mirror, None, Plane, Sphere, Torus); +impl_enum_metadata!(crate::UtilsPlatform; Linux, OSX, Unknown, Windows, WindowsCE); + +macro_rules! impl_raw_enum_metadata { + ($ty:ty; $($name:literal => $constant:ident),+ $(,)?) => { + impl EnumValueMetadata for $ty { + fn parse_name(name: &str) -> Option { + $(if name.eq_ignore_ascii_case($name) { return Some(Self::$constant); })+ + None + } + + fn variant_name(self) -> Option<&'static str> { + $(if self == Self::$constant { return Some($name); })+ + None + } + } + + impl From<$ty> for EnumValue { + fn from(value: $ty) -> Self { + Self { name: value.variant_name().unwrap_or_default(), text: None } + } + } + }; +} + +impl_raw_enum_metadata!(crate::HoleType; + "Circle" => Circle, "Same" => Same, "Square" => Square, "Triangle" => Triangle); +impl_raw_enum_metadata!(crate::InventoryType; + "Animation" => ANIMATION, "Attachment" => ATTACHMENT, "CallingCard" => CALLING_CARD, + "Category" => CATEGORY, "Gesture" => GESTURE, "LSL" => LSL, + "Landmark" => LANDMARK, "Material" => MATERIAL, "Mesh" => MESH, + "Notecard" => NOTECARD, "Object" => OBJECT, "RootCategory" => ROOT_CATEGORY, + "Settings" => SETTINGS, "Snapshot" => SNAPSHOT, "Sound" => SOUND, + "Texture" => TEXTURE, "Unknown" => UNKNOWN, "Wearable" => WEARABLE); +impl_raw_enum_metadata!(crate::ExtraParamType; + "ExtendedMesh" => EXTENDED_MESH, "Flexible" => FLEXIBLE, "Light" => LIGHT, + "LightImage" => LIGHT_IMAGE, "Mesh" => MESH, "ReflectionProbe" => REFLECTION_PROBE, + "RenderMaterial" => RENDER_MATERIAL, "Sculpt" => SCULPT); +impl_raw_enum_metadata!(crate::PrimFlags; + "AllowInventoryDrop" => ALLOW_INVENTORY_DROP, "AnimSource" => ANIM_SOURCE, + "CameraDecoupled" => CAMERA_DECOUPLED, "CameraSource" => CAMERA_SOURCE, + "CastShadows" => CAST_SHADOWS, "CreateSelected" => CREATE_SELECTED, + "DieAtEdge" => DIE_AT_EDGE, "Flying" => FLYING, "InventoryEmpty" => INVENTORY_EMPTY, + "JointHinge" => JOINT_HINGE, "JointLP2P" => JOINT_LP2_P, "JointP2P" => JOINT_P2_P, + "JointWheel" => JOINT_WHEEL, "Money" => MONEY, "None" => NONE, + "ObjectAnyOwner" => OBJECT_ANY_OWNER, "ObjectCopy" => OBJECT_COPY, + "ObjectGroupOwned" => OBJECT_GROUP_OWNED, "ObjectModify" => OBJECT_MODIFY, + "ObjectMove" => OBJECT_MOVE, "ObjectOwnerModify" => OBJECT_OWNER_MODIFY, + "ObjectTransfer" => OBJECT_TRANSFER, "ObjectYouOfficer" => OBJECT_YOU_OFFICER, + "ObjectYouOwner" => OBJECT_YOU_OWNER, "Phantom" => PHANTOM, "Physics" => PHYSICS, + "ReturnAtEdge" => RETURN_AT_EDGE, "Sandbox" => SANDBOX, "Scripted" => SCRIPTED, + "Temporary" => TEMPORARY, "TemporaryOnRez" => TEMPORARY_ON_REZ, + "Touch" => TOUCH, "ZlibCompressed" => ZLIB_COMPRESSED); +impl_raw_enum_metadata!(crate::SoundFlags; + "Loop" => LOOP_, "None" => NONE, "Queue" => QUEUE, "Stop" => STOP, + "SyncMaster" => SYNC_MASTER, "SyncPending" => SYNC_PENDING, "SyncSlave" => SYNC_SLAVE); + +macro_rules! impl_flag_ops { + ($ty:ty, $raw:ty) => { + impl $ty { + /// Returns every known and unknown protocol bit. + #[must_use] + pub const fn bits(self) -> $raw { + self.0 + } + + /// Constructs flags without discarding future protocol bits. + #[must_use] + pub const fn from_bits_retain(bits: $raw) -> Self { + Self(bits) + } + + /// Returns whether all supplied bits are present. + #[must_use] + pub const fn contains(self, other: Self) -> bool { + self.0 & other.0 == other.0 + } + + /// Returns whether any supplied bit is present. + #[must_use] + pub const fn intersects(self, other: Self) -> bool { + self.0 & other.0 != 0 + } + + /// Returns whether no bits are set. + #[must_use] + pub const fn is_empty(self) -> bool { + self.0 == 0 + } + } + + impl std::ops::BitOr for $ty { + type Output = Self; + fn bitor(self, rhs: Self) -> Self { + Self(self.0 | rhs.0) + } + } + impl std::ops::BitAnd for $ty { + type Output = Self; + fn bitand(self, rhs: Self) -> Self { + Self(self.0 & rhs.0) + } + } + impl std::ops::BitXor for $ty { + type Output = Self; + fn bitxor(self, rhs: Self) -> Self { + Self(self.0 ^ rhs.0) + } + } + impl std::ops::Not for $ty { + type Output = Self; + fn not(self) -> Self { + Self(!self.0) + } + } + impl std::ops::BitOrAssign for $ty { + fn bitor_assign(&mut self, rhs: Self) { + self.0 |= rhs.0; + } + } + impl std::ops::BitAndAssign for $ty { + fn bitand_assign(&mut self, rhs: Self) { + self.0 &= rhs.0; + } + } + impl std::ops::BitXorAssign for $ty { + fn bitxor_assign(&mut self, rhs: Self) { + self.0 ^= rhs.0; + } + } + }; +} + +impl_flag_ops!(crate::ExtraParamType, u16); +impl_flag_ops!(crate::PrimFlags, u32); +impl_flag_ops!(crate::SoundFlags, u8); + +impl crate::HoleType { + /// Returns the raw protocol value. + #[must_use] + pub const fn raw(self) -> u8 { + self.0 + } + + /// Retains a raw value, including extensions unknown to this version. + #[must_use] + pub const fn from_raw(value: u8) -> Self { + Self(value) + } +} + +impl crate::InventoryType { + /// Returns the raw protocol value. + #[must_use] + pub const fn raw(self) -> i8 { + self.0 + } + + /// Retains a raw value, including extensions unknown to this version. + #[must_use] + pub const fn from_raw(value: i8) -> Self { + Self(value) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + AssetType, AttachmentPoint, ClickAction, ExtraParamType, FaceType, FolderType, HoleType, + InventoryType, JointType, Material, ObjectCategory, PCode, PathCurve, PhysicsShapeType, + PrimFlags, PrimType, ProfileCurve, SaleType, SculptType, SoundFlags, UtilsPlatform, + WearableType, + }; + + #[test] + fn discriminants_and_unknown_flag_bits_round_trip() { + assert_eq!(AssetType::Material as i8, 57); + assert_eq!(AttachmentPoint::RightHindFoot as u8, 55); + assert_eq!(std::mem::size_of::(), 4); + let future = PrimFlags::from_bits_retain(0x0000_0001 | 0x0000_0800); + assert!(future.contains(PrimFlags::PHYSICS)); + assert_eq!(future.bits(), 0x0000_0801); + assert_eq!((SoundFlags::LOOP_ | SoundFlags::QUEUE).bits(), 0x11); + assert_eq!(SoundFlags::from_bits_retain(0x80).bits(), 0x80); + assert_eq!(ExtraParamType::from_bits_retain(0x8000).bits(), 0x8000); + assert_eq!(HoleType::from_raw(0x40).raw(), 0x40); + assert_eq!(InventoryType::from_raw(120).raw(), 120); + } + + #[test] + fn every_enum_uses_the_golden_underlying_width() { + assert_eq!(std::mem::size_of::(), 1); + assert_eq!(std::mem::size_of::(), 1); + assert_eq!(std::mem::size_of::(), 1); + assert_eq!(std::mem::size_of::(), 2); + assert_eq!(std::mem::size_of::(), 2); + assert_eq!(std::mem::size_of::(), 1); + assert_eq!(std::mem::size_of::(), 1); + assert_eq!(std::mem::size_of::(), 1); + assert_eq!(std::mem::size_of::(), 1); + assert_eq!(std::mem::size_of::(), 1); + assert_eq!(std::mem::size_of::(), 4); + assert_eq!(std::mem::size_of::(), 1); + assert_eq!(std::mem::size_of::(), 1); + assert_eq!(std::mem::size_of::(), 1); + assert_eq!(std::mem::size_of::(), 4); + assert_eq!(std::mem::size_of::(), 4); + assert_eq!(std::mem::size_of::(), 1); + assert_eq!(std::mem::size_of::(), 1); + assert_eq!(std::mem::size_of::(), 1); + assert_eq!(std::mem::size_of::(), 1); + assert_eq!(std::mem::size_of::(), 4); + assert_eq!(std::mem::size_of::(), 1); + + let all_prim_flags = PrimFlags::PHYSICS + | PrimFlags::CREATE_SELECTED + | PrimFlags::OBJECT_MODIFY + | PrimFlags::OBJECT_COPY + | PrimFlags::OBJECT_ANY_OWNER + | PrimFlags::OBJECT_YOU_OWNER + | PrimFlags::SCRIPTED + | PrimFlags::TOUCH + | PrimFlags::OBJECT_MOVE + | PrimFlags::MONEY + | PrimFlags::PHANTOM + | PrimFlags::INVENTORY_EMPTY + | PrimFlags::JOINT_HINGE + | PrimFlags::JOINT_P2_P + | PrimFlags::JOINT_LP2_P + | PrimFlags::JOINT_WHEEL + | PrimFlags::ALLOW_INVENTORY_DROP + | PrimFlags::OBJECT_TRANSFER + | PrimFlags::OBJECT_GROUP_OWNED + | PrimFlags::OBJECT_YOU_OFFICER + | PrimFlags::CAMERA_DECOUPLED + | PrimFlags::ANIM_SOURCE + | PrimFlags::CAMERA_SOURCE + | PrimFlags::CAST_SHADOWS + | PrimFlags::DIE_AT_EDGE + | PrimFlags::RETURN_AT_EDGE + | PrimFlags::SANDBOX + | PrimFlags::FLYING + | PrimFlags::OBJECT_OWNER_MODIFY + | PrimFlags::TEMPORARY_ON_REZ + | PrimFlags::TEMPORARY + | PrimFlags::ZLIB_COMPRESSED; + assert_eq!(all_prim_flags.bits(), u32::MAX); + let all_sound_flags = SoundFlags::LOOP_ + | SoundFlags::SYNC_MASTER + | SoundFlags::SYNC_SLAVE + | SoundFlags::SYNC_PENDING + | SoundFlags::QUEUE + | SoundFlags::STOP; + assert_eq!(all_sound_flags.bits(), 0x3f); + } + + #[test] + fn metadata_and_case_insensitive_parsing_match_csharp() { + assert_eq!(AssetType::parse_name("lsltEXt"), Some(AssetType::LSLText)); + let value: EnumValue = AssetType::LSLText.into(); + assert_eq!( + EnumInfoExtensions::get_text(value), + Ok("lsltext".to_owned()) + ); + let value: EnumValue = AttachmentPoint::Skull.into(); + assert_eq!(EnumInfoExtensions::get_text(value), Ok("Head".to_owned())); + } +} diff --git a/crates/libremetaverse-types/src/generated.rs b/crates/libremetaverse-types/src/generated.rs index 6ebb310..28366d1 100644 --- a/crates/libremetaverse-types/src/generated.rs +++ b/crates/libremetaverse-types/src/generated.rs @@ -567,35 +567,14 @@ impl libremetaverse_types::ICacheDictionaryRemovalStrategy } /// C# type: `T:LibreMetaverse.EnumInfoAttribute`. -pub struct EnumInfoAttribute { - /// C# member: `F:LibreMetaverse.EnumInfoAttribute.Text`. - pub text: String, -} -impl EnumInfoAttribute { - /// C# member: `M:LibreMetaverse.EnumInfoAttribute.#ctor`. - pub fn new_with_constructor() -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.EnumInfoAttribute.#ctor") - } - /// C# member: `M:LibreMetaverse.EnumInfoAttribute.#ctor(System.String)`. - pub fn new_with_string(text: String) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.EnumInfoAttribute.#ctor(System.String)", - ) - } -} +/// C# member: `F:LibreMetaverse.EnumInfoAttribute.Text`. +/// C# member: `M:LibreMetaverse.EnumInfoAttribute.#ctor`. +/// C# member: `M:LibreMetaverse.EnumInfoAttribute.#ctor(System.String)`. +pub use crate::enum_compat::EnumInfoAttribute; /// C# type: `T:LibreMetaverse.EnumInfoExtensions`. -pub struct EnumInfoExtensions; -impl EnumInfoExtensions { - /// C# member: `M:LibreMetaverse.EnumInfoExtensions.GetText(System.Enum)`. - pub fn get_text( - value: libremetaverse_types::compat::EnumValue, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.EnumInfoExtensions.GetText(System.Enum)", - ) - } -} +/// C# member: `M:LibreMetaverse.EnumInfoExtensions.GetText(System.Enum)`. +pub use crate::enum_compat::EnumInfoExtensions; /// C# type: `T:LibreMetaverse.ExpiringCache`2`. pub struct ExpiringCache { @@ -1802,719 +1781,122 @@ impl TokenBucket { pub use crate::uuid::UUID; /// C# type: `T:LibreMetaverse.Utils`. -pub struct Utils; -impl Utils { - /// C# member: `F:LibreMetaverse.Utils.DEG_TO_RAD`. - pub const DEG_TO_RAD: f32 = 0.017453292; - /// C# member: `F:LibreMetaverse.Utils.E`. - pub const E: f32 = 2.7182817; - /// C# member: `F:LibreMetaverse.Utils.EmptyBytes`. - pub fn empty_bytes() -> Vec { - libremetaverse_types::unimplemented_api!("F:LibreMetaverse.Utils.EmptyBytes") - } - /// C# member: `F:LibreMetaverse.Utils.EnUsCulture`. - pub fn en_us_culture() -> libremetaverse_types::compat::CultureInfo { - libremetaverse_types::unimplemented_api!("F:LibreMetaverse.Utils.EnUsCulture") - } - /// C# member: `F:LibreMetaverse.Utils.Epoch`. - pub fn epoch() -> std::time::SystemTime { - libremetaverse_types::unimplemented_api!("F:LibreMetaverse.Utils.Epoch") - } - /// C# member: `F:LibreMetaverse.Utils.InternStrings`. - pub fn intern_strings() -> bool { - libremetaverse_types::unimplemented_api!("F:LibreMetaverse.Utils.InternStrings") - } - /// C# member: `F:LibreMetaverse.Utils.LOG10E`. - pub const LOG10_E: f32 = 0.4342945; - /// C# member: `F:LibreMetaverse.Utils.LOG2E`. - pub const LOG2_E: f32 = 1.442695; - /// C# member: `F:LibreMetaverse.Utils.PI`. - pub const PI: f32 = 3.1415927; - /// C# member: `F:LibreMetaverse.Utils.PI_OVER_FOUR`. - pub const PI_OVER_FOUR: f32 = 0.7853982; - /// C# member: `F:LibreMetaverse.Utils.PI_OVER_TWO`. - pub const PI_OVER_TWO: f32 = 1.5707964; - /// C# member: `F:LibreMetaverse.Utils.RAD_TO_DEG`. - pub const RAD_TO_DEG: f32 = 57.29578; - /// C# member: `F:LibreMetaverse.Utils.TWO_PI`. - pub const TWO_PI: f32 = 6.2831855; - /// C# member: `M:LibreMetaverse.Utils.AssetTypeToString(LibreMetaverse.AssetType)`. - pub fn asset_type_to_string( - type_: libremetaverse_types::AssetType, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.AssetTypeToString(LibreMetaverse.AssetType)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.ByteToFloat(System.Byte,System.Single,System.Single)`. - pub fn byte_to_float_with_byte_single_single( - val: u8, - lower: f32, - upper: f32, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.ByteToFloat(System.Byte,System.Single,System.Single)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.ByteToFloat(System.Byte[],System.Int32,System.Single,System.Single)`. - pub fn byte_to_float_with_bytes_int32_single_single( - bytes: Vec, - pos: i32, - lower: f32, - upper: f32, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.ByteToFloat(System.Byte[],System.Int32,System.Single,System.Single)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.BytesToDouble(System.Byte[],System.Int32)`. - pub fn bytes_to_double(bytes: Vec, pos: i32) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.BytesToDouble(System.Byte[],System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.BytesToFloat(System.Byte[],System.Int32)`. - pub fn bytes_to_float(bytes: Vec, pos: i32) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.BytesToFloat(System.Byte[],System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.BytesToHexString(System.Byte[],System.Int32,System.String)`. - pub fn bytes_to_hex_string_with_bytes_int32_string( - bytes: Vec, - length: i32, - field_name: Option, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.BytesToHexString(System.Byte[],System.Int32,System.String)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.BytesToHexString(System.Byte[],System.String)`. - pub fn bytes_to_hex_string_with_bytes_string( - bytes: Vec, - field_name: String, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.BytesToHexString(System.Byte[],System.String)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.BytesToInt(System.Byte[])`. - pub fn bytes_to_int_with_bytes(bytes: Vec) -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.BytesToInt(System.Byte[])") - } - /// C# member: `M:LibreMetaverse.Utils.BytesToInt(System.Byte[],System.Int32)`. - pub fn bytes_to_int_with_bytes_int32(bytes: Vec, pos: i32) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.BytesToInt(System.Byte[],System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.BytesToInt16(System.Byte[])`. - pub fn bytes_to_int16_with_bytes(bytes: Vec) -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.BytesToInt16(System.Byte[])") - } - /// C# member: `M:LibreMetaverse.Utils.BytesToInt16(System.Byte[],System.Int32)`. - pub fn bytes_to_int16_with_bytes_int32(bytes: Vec, pos: i32) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.BytesToInt16(System.Byte[],System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.BytesToInt64(System.Byte[])`. - pub fn bytes_to_int64_with_bytes(bytes: Vec) -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.BytesToInt64(System.Byte[])") - } - /// C# member: `M:LibreMetaverse.Utils.BytesToInt64(System.Byte[],System.Int32)`. - pub fn bytes_to_int64_with_bytes_int32(bytes: Vec, pos: i32) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.BytesToInt64(System.Byte[],System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.BytesToString(System.Byte[])`. - pub fn bytes_to_string_with_bytes(bytes: Vec) -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.BytesToString(System.Byte[])") - } - /// C# member: `M:LibreMetaverse.Utils.BytesToString(System.Byte[],System.Int32,System.Int32)`. - pub fn bytes_to_string_with_bytes_int32_int32( - bytes: Vec, - index: i32, - count: i32, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.BytesToString(System.Byte[],System.Int32,System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.BytesToUInt(System.Byte[])`. - pub fn bytes_to_u_int_with_bytes(bytes: Vec) -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.BytesToUInt(System.Byte[])") - } - /// C# member: `M:LibreMetaverse.Utils.BytesToUInt(System.Byte[],System.Int32)`. - pub fn bytes_to_u_int_with_bytes_int32(bytes: Vec, pos: i32) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.BytesToUInt(System.Byte[],System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.BytesToUInt16(System.Byte[])`. - pub fn bytes_to_u_int16_with_bytes(bytes: Vec) -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.BytesToUInt16(System.Byte[])") - } - /// C# member: `M:LibreMetaverse.Utils.BytesToUInt16(System.Byte[],System.Int32)`. - pub fn bytes_to_u_int16_with_bytes_int32( - bytes: Vec, - pos: i32, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.BytesToUInt16(System.Byte[],System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.BytesToUInt64(System.Byte[])`. - pub fn bytes_to_u_int64(bytes: Vec) -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.BytesToUInt64(System.Byte[])") - } - /// C# member: `M:LibreMetaverse.Utils.Clamp(System.Double,System.Double,System.Double)`. - pub fn clamp_with_double_double_double( - value: f64, - min: f64, - max: f64, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.Clamp(System.Double,System.Double,System.Double)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.Clamp(System.Int32,System.Int32,System.Int32)`. - pub fn clamp_with_int32_int32_int32( - value: i32, - min: i32, - max: i32, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.Clamp(System.Int32,System.Int32,System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.Clamp(System.Single,System.Single,System.Single)`. - pub fn clamp_with_single_single_single( - value: f32, - min: f32, - max: f32, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.Clamp(System.Single,System.Single,System.Single)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.CopyBytes(System.Byte[])`. - pub fn copy_bytes(bytes: Option>) -> Result>, crate::Error> { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.CopyBytes(System.Byte[])") - } - /// C# member: `M:LibreMetaverse.Utils.DateTimeToUnixTime(System.DateTime)`. - pub fn date_time_to_unix_time(time: std::time::SystemTime) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.DateTimeToUnixTime(System.DateTime)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.Distance(System.Single,System.Single)`. - pub fn distance(value1: f32, value2: f32) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.Distance(System.Single,System.Single)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.DoubleToBytes(System.Double)`. - pub fn double_to_bytes_with_double(value: f64) -> Result, crate::Error> { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.DoubleToBytes(System.Double)") - } - /// C# member: `M:LibreMetaverse.Utils.DoubleToBytes(System.Double,System.Byte[],System.Int32)`. - pub fn double_to_bytes_with_double_bytes_int32( - value: f64, - dest: Vec, - pos: i32, - ) -> Result<(), crate::Error> { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.DoubleToBytes(System.Double,System.Byte[],System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.DoubleToBytesBig(System.Double)`. - pub fn double_to_bytes_big(value: f64) -> Result, crate::Error> { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.DoubleToBytesBig(System.Double)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.EnumToText(System.Enum)`. - pub fn enum_to_text( - value: libremetaverse_types::compat::EnumValue, - ) -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.EnumToText(System.Enum)") - } - /// C# member: `M:LibreMetaverse.Utils.EnumTryParse``1(System.String,``0@)`. - pub fn enum_try_parse( - str_type: String, - result: &mut Option, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.EnumTryParse``1(System.String,``0@)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.FloatToByte(System.Single,System.Single,System.Single)`. - pub fn float_to_byte(val: f32, lower: f32, upper: f32) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.FloatToByte(System.Single,System.Single,System.Single)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.FloatToBytes(System.Single)`. - pub fn float_to_bytes_with_single(value: f32) -> Result, crate::Error> { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.FloatToBytes(System.Single)") - } - /// C# member: `M:LibreMetaverse.Utils.FloatToBytes(System.Single,System.Byte[],System.Int32)`. - pub fn float_to_bytes_with_single_bytes_int32( - value: f32, - dest: Vec, - pos: i32, - ) -> Result<(), crate::Error> { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.FloatToBytes(System.Single,System.Byte[],System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.FloatToUInt16(System.Single,System.Single,System.Single)`. - pub fn float_to_u_int16(value: f32, lower: f32, upper: f32) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.FloatToUInt16(System.Single,System.Single,System.Single)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.FolderTypeToString(LibreMetaverse.FolderType)`. - pub fn folder_type_to_string( - type_: libremetaverse_types::FolderType, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.FolderTypeToString(LibreMetaverse.FolderType)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.GetRunningPlatform`. - pub fn get_running_platform() -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.GetRunningPlatform") - } - /// C# member: `M:LibreMetaverse.Utils.GetUnixTime`. - pub fn get_unix_time() -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.GetUnixTime") - } - /// C# member: `M:LibreMetaverse.Utils.Hermite(System.Double,System.Double,System.Double,System.Double,System.Double)`. - pub fn hermite_with_double_double_double_double_double( - value1: f64, - tangent1: f64, - value2: f64, - tangent2: f64, - amount: f64, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.Hermite(System.Double,System.Double,System.Double,System.Double,System.Double)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.Hermite(System.Single,System.Single,System.Single,System.Single,System.Single)`. - pub fn hermite_with_single_single_single_single_single( - value1: f32, - tangent1: f32, - value2: f32, - tangent2: f32, - amount: f32, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.Hermite(System.Single,System.Single,System.Single,System.Single,System.Single)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.HexStringToBytes(System.String,System.Boolean)`. - pub fn hex_string_to_bytes( - hex_string: String, - handle_dirty: bool, - ) -> Result, crate::Error> { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.HexStringToBytes(System.String,System.Boolean)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.HostnameToIPv4(System.String)`. - pub fn hostname_to_i_pv4(hostname: String) -> Result, crate::Error> { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.HostnameToIPv4(System.String)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.IPToUInt(System.Net.IPAddress)`. - pub fn ip_to_u_int(address: std::net::IpAddr) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.IPToUInt(System.Net.IPAddress)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.Int16ToBytes(System.Int16)`. - pub fn int16_to_bytes_with_int16(value: i16) -> Result, crate::Error> { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.Int16ToBytes(System.Int16)") - } - /// C# member: `M:LibreMetaverse.Utils.Int16ToBytes(System.Int16,System.Byte[],System.Int32)`. - pub fn int16_to_bytes_with_int16_bytes_int32( - value: i16, - dest: Vec, - pos: i32, - ) -> Result<(), crate::Error> { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.Int16ToBytes(System.Int16,System.Byte[],System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.Int64ToBytes(System.Int64)`. - pub fn int64_to_bytes_with_int64(value: i64) -> Result, crate::Error> { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.Int64ToBytes(System.Int64)") - } - /// C# member: `M:LibreMetaverse.Utils.Int64ToBytes(System.Int64,System.Byte[],System.Int32)`. - pub fn int64_to_bytes_with_int64_bytes_int32( - value: i64, - dest: Vec, - pos: i32, - ) -> Result<(), crate::Error> { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.Int64ToBytes(System.Int64,System.Byte[],System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.IntToBytes(System.Int32)`. - pub fn int_to_bytes_with_int32(value: i32) -> Result, crate::Error> { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.IntToBytes(System.Int32)") - } - /// C# member: `M:LibreMetaverse.Utils.IntToBytes(System.Int32,System.Byte[],System.Int32)`. - pub fn int_to_bytes_with_int32_bytes_int32( - value: i32, - dest: Vec, - pos: i32, - ) -> Result<(), crate::Error> { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.IntToBytes(System.Int32,System.Byte[],System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.IntToBytesBig(System.Int32)`. - pub fn int_to_bytes_big(value: i32) -> Result, crate::Error> { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.IntToBytesBig(System.Int32)") - } - /// C# member: `M:LibreMetaverse.Utils.InventoryTypeToString(LibreMetaverse.InventoryType)`. - pub fn inventory_type_to_string( - type_: libremetaverse_types::InventoryType, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.InventoryTypeToString(LibreMetaverse.InventoryType)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.IsFinite(System.Double)`. - pub fn is_finite_with_double(value: f64) -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.IsFinite(System.Double)") - } - /// C# member: `M:LibreMetaverse.Utils.IsFinite(System.Single)`. - pub fn is_finite_with_single(value: f32) -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.IsFinite(System.Single)") - } - /// C# member: `M:LibreMetaverse.Utils.Lerp(System.Double,System.Double,System.Double)`. - pub fn lerp_with_double_double_double( - value1: f64, - value2: f64, - amount: f64, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.Lerp(System.Double,System.Double,System.Double)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.Lerp(System.Single,System.Single,System.Single)`. - pub fn lerp_with_single_single_single( - value1: f32, - value2: f32, - amount: f32, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.Lerp(System.Single,System.Single,System.Single)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.LongToUInts(System.UInt64,System.UInt32@,System.UInt32@)`. - pub fn long_to_u_ints(a: u64, b: &mut u32, c: &mut u32) -> Result<(), crate::Error> { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.LongToUInts(System.UInt64,System.UInt32@,System.UInt32@)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.MD5(System.Byte[])`. - pub fn md5_with_bytes(data: Vec) -> Result, crate::Error> { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.MD5(System.Byte[])") - } - /// C# member: `M:LibreMetaverse.Utils.MD5(System.String)`. - pub fn md5_with_string(str: String) -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.MD5(System.String)") - } - /// C# member: `M:LibreMetaverse.Utils.MD5String(System.String)`. - pub fn md5_string(value: String) -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.MD5String(System.String)") - } - /// C# member: `M:LibreMetaverse.Utils.PBKDF2(System.String)`. - pub fn pbkdf2(str: String) -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.PBKDF2(System.String)") - } - /// C# member: `M:LibreMetaverse.Utils.RandomDouble`. - pub fn random_double() -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.RandomDouble") - } - /// C# member: `M:LibreMetaverse.Utils.ReadDoubleLittleEndian(System.Byte[],System.Int32)`. - pub fn read_double_little_endian(src: &[u8], pos: i32) -> Result { - crate::byte_order::read_double_little_endian(src, pos) - } - /// C# member: `M:LibreMetaverse.Utils.ReadSingleLittleEndian(System.Byte[],System.Int32)`. - pub fn read_single_little_endian(src: &[u8], pos: i32) -> Result { - crate::byte_order::read_single_little_endian(src, pos) - } - /// C# member: `M:LibreMetaverse.Utils.Round(System.Single)`. - pub fn round(val: f32) -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.Round(System.Single)") - } - /// C# member: `M:LibreMetaverse.Utils.SHA1(System.Byte[])`. - pub fn sha1(data: Vec) -> Result, crate::Error> { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.SHA1(System.Byte[])") - } - /// C# member: `M:LibreMetaverse.Utils.SHA1String(System.String)`. - pub fn sha1_string(value: String) -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.SHA1String(System.String)") - } - /// C# member: `M:LibreMetaverse.Utils.SHA256(System.Byte[])`. - pub fn sha256(data: Vec) -> Result, crate::Error> { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.SHA256(System.Byte[])") - } - /// C# member: `M:LibreMetaverse.Utils.SHA256String(System.String)`. - pub fn sha256_string(value: String) -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.SHA256String(System.String)") - } - /// C# member: `M:LibreMetaverse.Utils.SaleTypeToString(LibreMetaverse.SaleType)`. - pub fn sale_type_to_string( - type_: libremetaverse_types::SaleType, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.SaleTypeToString(LibreMetaverse.SaleType)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.SmoothStep(System.Double,System.Double,System.Double)`. - pub fn smooth_step_with_double_double_double( - value1: f64, - value2: f64, - amount: f64, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.SmoothStep(System.Double,System.Double,System.Double)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.SmoothStep(System.Single,System.Single,System.Single)`. - pub fn smooth_step_with_single_single_single( - value1: f32, - value2: f32, - amount: f32, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.SmoothStep(System.Single,System.Single,System.Single)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.StringToAssetType(System.String)`. - pub fn string_to_asset_type( - type_: String, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.StringToAssetType(System.String)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.StringToAttachmentPoint(System.String)`. - pub fn string_to_attachment_point( - value: String, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.StringToAttachmentPoint(System.String)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.StringToBytes(System.String)`. - pub fn string_to_bytes(str: String) -> Result, crate::Error> { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.StringToBytes(System.String)") - } - /// C# member: `M:LibreMetaverse.Utils.StringToFolderType(System.String)`. - pub fn string_to_folder_type( - type_: String, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.StringToFolderType(System.String)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.StringToInventoryType(System.String)`. - pub fn string_to_inventory_type( - type_: String, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.StringToInventoryType(System.String)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.StringToSaleType(System.String)`. - pub fn string_to_sale_type( - value: String, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.StringToSaleType(System.String)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.SwapWords(System.Byte)`. - pub fn swap_words(value: u8) -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.SwapWords(System.Byte)") - } - /// C# member: `M:LibreMetaverse.Utils.Swap``1(``0@,``0@)`. - pub fn swap(lhs: &mut Option, rhs: &mut Option) -> Result<(), crate::Error> { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.Swap``1(``0@,``0@)") - } - /// C# member: `M:LibreMetaverse.Utils.ToDegrees(System.Single)`. - pub fn to_degrees(radians: f32) -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.ToDegrees(System.Single)") - } - /// C# member: `M:LibreMetaverse.Utils.ToRadians(System.Single)`. - pub fn to_radians(degrees: f32) -> Result { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.ToRadians(System.Single)") - } - /// C# member: `M:LibreMetaverse.Utils.TryParseDouble(System.String,System.Double@)`. - pub fn try_parse_double(s: String, result: &mut f64) -> bool { - libremetaverse_types::unimplemented_api!( - "M:LibreMetaverse.Utils.TryParseDouble(System.String,System.Double@)" - ) - } - /// C# member: `M:LibreMetaverse.Utils.TryParseHex(System.String,System.UInt32@)`. - pub fn try_parse_hex(s: String, result: &mut u32) -> bool { - libremetaverse_types::unimplemented_api!( - "M:LibreMetaverse.Utils.TryParseHex(System.String,System.UInt32@)" - ) - } - /// C# member: `M:LibreMetaverse.Utils.TryParseSingle(System.String,System.Single@)`. - pub fn try_parse_single(s: String, result: &mut f32) -> bool { - libremetaverse_types::unimplemented_api!( - "M:LibreMetaverse.Utils.TryParseSingle(System.String,System.Single@)" - ) - } - /// C# member: `M:LibreMetaverse.Utils.UInt16ToBytes(System.UInt16)`. - pub fn u_int16_to_bytes_with_u_int16(value: u16) -> Result, crate::Error> { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.UInt16ToBytes(System.UInt16)") - } - /// C# member: `M:LibreMetaverse.Utils.UInt16ToBytes(System.UInt16,System.Byte[],System.Int32)`. - pub fn u_int16_to_bytes_with_u_int16_bytes_int32( - value: u16, - dest: Vec, - pos: i32, - ) -> Result<(), crate::Error> { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.UInt16ToBytes(System.UInt16,System.Byte[],System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.UInt16ToBytesBig(System.UInt16,System.Byte[],System.Int32)`. - pub fn u_int16_to_bytes_big(value: u16, dest: Vec, pos: i32) -> Result<(), crate::Error> { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.UInt16ToBytesBig(System.UInt16,System.Byte[],System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.UInt16ToFloat(System.Byte[],System.Int32,System.Single,System.Single)`. - pub fn u_int16_to_float_with_bytes_int32_single_single( - bytes: Vec, - pos: i32, - lower: f32, - upper: f32, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.UInt16ToFloat(System.Byte[],System.Int32,System.Single,System.Single)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.UInt16ToFloat(System.UInt16,System.Single,System.Single)`. - pub fn u_int16_to_float_with_u_int16_single_single( - val: u16, - lower: f32, - upper: f32, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.UInt16ToFloat(System.UInt16,System.Single,System.Single)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.UInt64ToBytes(System.UInt64)`. - pub fn u_int64_to_bytes_with_u_int64(value: u64) -> Result, crate::Error> { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.UInt64ToBytes(System.UInt64)") - } - /// C# member: `M:LibreMetaverse.Utils.UInt64ToBytes(System.UInt64,System.Byte[],System.Int32)`. - pub fn u_int64_to_bytes_with_u_int64_bytes_int32( - value: u64, - dest: Vec, - pos: i32, - ) -> Result<(), crate::Error> { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.UInt64ToBytes(System.UInt64,System.Byte[],System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.UInt64ToBytesBig(System.UInt64)`. - pub fn u_int64_to_bytes_big_with_u_int64(value: u64) -> Result, crate::Error> { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.UInt64ToBytesBig(System.UInt64)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.UInt64ToBytesBig(System.UInt64,System.Byte[],System.Int32)`. - pub fn u_int64_to_bytes_big_with_u_int64_bytes_int32( - value: u64, - dest: Vec, - pos: i32, - ) -> Result<(), crate::Error> { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.UInt64ToBytesBig(System.UInt64,System.Byte[],System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.UIntToBytes(System.UInt32)`. - pub fn u_int_to_bytes_with_u_int32(value: u32) -> Result, crate::Error> { - libremetaverse_types::not_implemented("M:LibreMetaverse.Utils.UIntToBytes(System.UInt32)") - } - /// C# member: `M:LibreMetaverse.Utils.UIntToBytes(System.UInt32,System.Byte[],System.Int32)`. - pub fn u_int_to_bytes_with_u_int32_bytes_int32( - value: u32, - dest: Vec, - pos: i32, - ) -> Result<(), crate::Error> { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.UIntToBytes(System.UInt32,System.Byte[],System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.UIntToBytesBig(System.UInt32,System.Byte[],System.Int32)`. - pub fn u_int_to_bytes_big(value: u32, dest: Vec, pos: i32) -> Result<(), crate::Error> { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.UIntToBytesBig(System.UInt32,System.Byte[],System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.UIntToHexString(System.UInt32)`. - pub fn u_int_to_hex_string(i: u32) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.UIntToHexString(System.UInt32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.UIntsToLong(System.UInt32,System.UInt32)`. - pub fn u_ints_to_long(a: u32, b: u32) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.UIntsToLong(System.UInt32,System.UInt32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.UnixTimeToDateTime(System.Int32)`. - pub fn unix_time_to_date_time_with_int32( - timestamp: i32, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.UnixTimeToDateTime(System.Int32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.UnixTimeToDateTime(System.UInt32)`. - pub fn unix_time_to_date_time_with_u_int32( - timestamp: u32, - ) -> Result { - libremetaverse_types::not_implemented( - "M:LibreMetaverse.Utils.UnixTimeToDateTime(System.UInt32)", - ) - } - /// C# member: `M:LibreMetaverse.Utils.WriteDoubleLittleEndian(System.Byte[],System.Int32,System.Double)`. - pub fn write_double_little_endian( - dest: &mut [u8], - pos: i32, - value: f64, - ) -> Result<(), crate::Error> { - crate::byte_order::write_double_little_endian(dest, pos, value) - } - /// C# member: `M:LibreMetaverse.Utils.WriteSingleLittleEndian(System.Byte[],System.Int32,System.Single)`. - pub fn write_single_little_endian( - dest: &mut [u8], - pos: i32, - value: f32, - ) -> Result<(), crate::Error> { - crate::byte_order::write_single_little_endian(dest, pos, value) - } -} +/// C# member: `F:LibreMetaverse.Utils.DEG_TO_RAD`. +/// C# member: `F:LibreMetaverse.Utils.E`. +/// C# member: `F:LibreMetaverse.Utils.EmptyBytes`. +/// C# member: `F:LibreMetaverse.Utils.EnUsCulture`. +/// C# member: `F:LibreMetaverse.Utils.Epoch`. +/// C# member: `F:LibreMetaverse.Utils.InternStrings`. +/// C# member: `F:LibreMetaverse.Utils.LOG10E`. +/// C# member: `F:LibreMetaverse.Utils.LOG2E`. +/// C# member: `F:LibreMetaverse.Utils.PI`. +/// C# member: `F:LibreMetaverse.Utils.PI_OVER_FOUR`. +/// C# member: `F:LibreMetaverse.Utils.PI_OVER_TWO`. +/// C# member: `F:LibreMetaverse.Utils.RAD_TO_DEG`. +/// C# member: `F:LibreMetaverse.Utils.TWO_PI`. +/// C# member: `M:LibreMetaverse.Utils.AssetTypeToString(LibreMetaverse.AssetType)`. +/// C# member: `M:LibreMetaverse.Utils.ByteToFloat(System.Byte,System.Single,System.Single)`. +/// C# member: `M:LibreMetaverse.Utils.ByteToFloat(System.Byte[],System.Int32,System.Single,System.Single)`. +/// C# member: `M:LibreMetaverse.Utils.BytesToDouble(System.Byte[],System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.BytesToFloat(System.Byte[],System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.BytesToHexString(System.Byte[],System.Int32,System.String)`. +/// C# member: `M:LibreMetaverse.Utils.BytesToHexString(System.Byte[],System.String)`. +/// C# member: `M:LibreMetaverse.Utils.BytesToInt(System.Byte[])`. +/// C# member: `M:LibreMetaverse.Utils.BytesToInt(System.Byte[],System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.BytesToInt16(System.Byte[])`. +/// C# member: `M:LibreMetaverse.Utils.BytesToInt16(System.Byte[],System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.BytesToInt64(System.Byte[])`. +/// C# member: `M:LibreMetaverse.Utils.BytesToInt64(System.Byte[],System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.BytesToString(System.Byte[])`. +/// C# member: `M:LibreMetaverse.Utils.BytesToString(System.Byte[],System.Int32,System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.BytesToUInt(System.Byte[])`. +/// C# member: `M:LibreMetaverse.Utils.BytesToUInt(System.Byte[],System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.BytesToUInt16(System.Byte[])`. +/// C# member: `M:LibreMetaverse.Utils.BytesToUInt16(System.Byte[],System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.BytesToUInt64(System.Byte[])`. +/// C# member: `M:LibreMetaverse.Utils.Clamp(System.Double,System.Double,System.Double)`. +/// C# member: `M:LibreMetaverse.Utils.Clamp(System.Int32,System.Int32,System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.Clamp(System.Single,System.Single,System.Single)`. +/// C# member: `M:LibreMetaverse.Utils.CopyBytes(System.Byte[])`. +/// C# member: `M:LibreMetaverse.Utils.DateTimeToUnixTime(System.DateTime)`. +/// C# member: `M:LibreMetaverse.Utils.Distance(System.Single,System.Single)`. +/// C# member: `M:LibreMetaverse.Utils.DoubleToBytes(System.Double)`. +/// C# member: `M:LibreMetaverse.Utils.DoubleToBytes(System.Double,System.Byte[],System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.DoubleToBytesBig(System.Double)`. +/// C# member: `M:LibreMetaverse.Utils.EnumToText(System.Enum)`. +/// C# member: `M:LibreMetaverse.Utils.EnumTryParse``1(System.String,``0@)`. +/// C# member: `M:LibreMetaverse.Utils.FloatToByte(System.Single,System.Single,System.Single)`. +/// C# member: `M:LibreMetaverse.Utils.FloatToBytes(System.Single)`. +/// C# member: `M:LibreMetaverse.Utils.FloatToBytes(System.Single,System.Byte[],System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.FloatToUInt16(System.Single,System.Single,System.Single)`. +/// C# member: `M:LibreMetaverse.Utils.FolderTypeToString(LibreMetaverse.FolderType)`. +/// C# member: `M:LibreMetaverse.Utils.GetRunningPlatform`. +/// C# member: `M:LibreMetaverse.Utils.GetUnixTime`. +/// C# member: `M:LibreMetaverse.Utils.Hermite(System.Double,System.Double,System.Double,System.Double,System.Double)`. +/// C# member: `M:LibreMetaverse.Utils.Hermite(System.Single,System.Single,System.Single,System.Single,System.Single)`. +/// C# member: `M:LibreMetaverse.Utils.HexStringToBytes(System.String,System.Boolean)`. +/// C# member: `M:LibreMetaverse.Utils.HostnameToIPv4(System.String)`. +/// C# member: `M:LibreMetaverse.Utils.IPToUInt(System.Net.IPAddress)`. +/// C# member: `M:LibreMetaverse.Utils.Int16ToBytes(System.Int16)`. +/// C# member: `M:LibreMetaverse.Utils.Int16ToBytes(System.Int16,System.Byte[],System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.Int64ToBytes(System.Int64)`. +/// C# member: `M:LibreMetaverse.Utils.Int64ToBytes(System.Int64,System.Byte[],System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.IntToBytes(System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.IntToBytes(System.Int32,System.Byte[],System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.IntToBytesBig(System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.InventoryTypeToString(LibreMetaverse.InventoryType)`. +/// C# member: `M:LibreMetaverse.Utils.IsFinite(System.Double)`. +/// C# member: `M:LibreMetaverse.Utils.IsFinite(System.Single)`. +/// C# member: `M:LibreMetaverse.Utils.Lerp(System.Double,System.Double,System.Double)`. +/// C# member: `M:LibreMetaverse.Utils.Lerp(System.Single,System.Single,System.Single)`. +/// C# member: `M:LibreMetaverse.Utils.LongToUInts(System.UInt64,System.UInt32@,System.UInt32@)`. +/// C# member: `M:LibreMetaverse.Utils.MD5(System.Byte[])`. +/// C# member: `M:LibreMetaverse.Utils.MD5(System.String)`. +/// C# member: `M:LibreMetaverse.Utils.MD5String(System.String)`. +/// C# member: `M:LibreMetaverse.Utils.PBKDF2(System.String)`. +/// C# member: `M:LibreMetaverse.Utils.RandomDouble`. +/// C# member: `M:LibreMetaverse.Utils.ReadDoubleLittleEndian(System.Byte[],System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.ReadSingleLittleEndian(System.Byte[],System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.Round(System.Single)`. +/// C# member: `M:LibreMetaverse.Utils.SHA1(System.Byte[])`. +/// C# member: `M:LibreMetaverse.Utils.SHA1String(System.String)`. +/// C# member: `M:LibreMetaverse.Utils.SHA256(System.Byte[])`. +/// C# member: `M:LibreMetaverse.Utils.SHA256String(System.String)`. +/// C# member: `M:LibreMetaverse.Utils.SaleTypeToString(LibreMetaverse.SaleType)`. +/// C# member: `M:LibreMetaverse.Utils.SmoothStep(System.Double,System.Double,System.Double)`. +/// C# member: `M:LibreMetaverse.Utils.SmoothStep(System.Single,System.Single,System.Single)`. +/// C# member: `M:LibreMetaverse.Utils.StringToAssetType(System.String)`. +/// C# member: `M:LibreMetaverse.Utils.StringToAttachmentPoint(System.String)`. +/// C# member: `M:LibreMetaverse.Utils.StringToBytes(System.String)`. +/// C# member: `M:LibreMetaverse.Utils.StringToFolderType(System.String)`. +/// C# member: `M:LibreMetaverse.Utils.StringToInventoryType(System.String)`. +/// C# member: `M:LibreMetaverse.Utils.StringToSaleType(System.String)`. +/// C# member: `M:LibreMetaverse.Utils.SwapWords(System.Byte)`. +/// C# member: `M:LibreMetaverse.Utils.Swap``1(``0@,``0@)`. +/// C# member: `M:LibreMetaverse.Utils.ToDegrees(System.Single)`. +/// C# member: `M:LibreMetaverse.Utils.ToRadians(System.Single)`. +/// C# member: `M:LibreMetaverse.Utils.TryParseDouble(System.String,System.Double@)`. +/// C# member: `M:LibreMetaverse.Utils.TryParseHex(System.String,System.UInt32@)`. +/// C# member: `M:LibreMetaverse.Utils.TryParseSingle(System.String,System.Single@)`. +/// C# member: `M:LibreMetaverse.Utils.UInt16ToBytes(System.UInt16)`. +/// C# member: `M:LibreMetaverse.Utils.UInt16ToBytes(System.UInt16,System.Byte[],System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.UInt16ToBytesBig(System.UInt16,System.Byte[],System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.UInt16ToFloat(System.Byte[],System.Int32,System.Single,System.Single)`. +/// C# member: `M:LibreMetaverse.Utils.UInt16ToFloat(System.UInt16,System.Single,System.Single)`. +/// C# member: `M:LibreMetaverse.Utils.UInt64ToBytes(System.UInt64)`. +/// C# member: `M:LibreMetaverse.Utils.UInt64ToBytes(System.UInt64,System.Byte[],System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.UInt64ToBytesBig(System.UInt64)`. +/// C# member: `M:LibreMetaverse.Utils.UInt64ToBytesBig(System.UInt64,System.Byte[],System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.UIntToBytes(System.UInt32)`. +/// C# member: `M:LibreMetaverse.Utils.UIntToBytes(System.UInt32,System.Byte[],System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.UIntToBytesBig(System.UInt32,System.Byte[],System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.UIntToHexString(System.UInt32)`. +/// C# member: `M:LibreMetaverse.Utils.UIntsToLong(System.UInt32,System.UInt32)`. +/// C# member: `M:LibreMetaverse.Utils.UnixTimeToDateTime(System.Int32)`. +/// C# member: `M:LibreMetaverse.Utils.UnixTimeToDateTime(System.UInt32)`. +/// C# member: `M:LibreMetaverse.Utils.WriteDoubleLittleEndian(System.Byte[],System.Int32,System.Double)`. +/// C# member: `M:LibreMetaverse.Utils.WriteSingleLittleEndian(System.Byte[],System.Int32,System.Single)`. +pub use crate::utils::Utils; /// C# type: `T:LibreMetaverse.Utils.Platform`. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] diff --git a/crates/libremetaverse-types/src/lib.rs b/crates/libremetaverse-types/src/lib.rs index 25d8849..76a9b73 100644 --- a/crates/libremetaverse-types/src/lib.rs +++ b/crates/libremetaverse-types/src/lib.rs @@ -6,12 +6,15 @@ mod byte_order; mod color4; pub mod compat; mod crc32; +mod enum_compat; mod generated; mod geometry; mod math_compat; pub mod shim; +mod utils; mod uuid; mod vectors; +pub use enum_compat::EnumValueMetadata; pub use generated::*; pub use shim::{Error, NotImplemented, not_implemented}; diff --git a/crates/libremetaverse-types/src/shim.rs b/crates/libremetaverse-types/src/shim.rs index 8ede15e..bfab496 100644 --- a/crates/libremetaverse-types/src/shim.rs +++ b/crates/libremetaverse-types/src/shim.rs @@ -59,6 +59,8 @@ pub enum Error { Cancelled, /// An HTTP request completed with an unsuccessful response. HttpRequest, + /// A host lookup or socket operation failed. + Socket, } impl Error { @@ -72,7 +74,8 @@ impl Error { | Self::InvalidOperation | Self::IndexOutOfRange | Self::Cancelled - | Self::HttpRequest => None, + | Self::HttpRequest + | Self::Socket => None, } } } @@ -95,6 +98,7 @@ impl fmt::Display for Error { Self::IndexOutOfRange => formatter.write_str("index was out of range"), Self::Cancelled => formatter.write_str("operation was cancelled"), Self::HttpRequest => formatter.write_str("HTTP request failed"), + Self::Socket => formatter.write_str("socket operation failed"), } } } diff --git a/crates/libremetaverse-types/src/utils.rs b/crates/libremetaverse-types/src/utils.rs new file mode 100644 index 0000000..698833e --- /dev/null +++ b/crates/libremetaverse-types/src/utils.rs @@ -0,0 +1,1111 @@ +//! Native protocol conversion and utility helpers. + +#![allow(clippy::approx_constant)] // Decimal constants exactly preserve the reference protocol API. +#![allow(clippy::cast_lossless)] // Explicit casts document the C# underlying enum widths. +#![allow(clippy::cast_possible_truncation)] // C# numeric conversions deliberately narrow and wrap. +#![allow(clippy::cast_possible_wrap)] // C# time conversions deliberately reinterpret overflow. +#![allow(clippy::cast_precision_loss)] // Random.NextDouble-style construction uses 53 random bits. +#![allow(clippy::cast_sign_loss)] // C# signed timestamp overload casts to uint before conversion. +#![allow(clippy::float_cmp)] // Exact Hermite endpoints are required reference behavior. +#![allow(clippy::missing_errors_doc)] // Result shapes are fixed by the public compatibility map. +#![allow(clippy::must_use_candidate)] // Attributes are not part of the mapped C# surface. +#![allow(clippy::needless_pass_by_value)] // Owned parameters preserve the generated API mapping. + +use std::net::{IpAddr, ToSocketAddrs}; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; + +use base64::Engine as _; +use md5::{Digest as _, Md5}; +use sha1::Sha1; +use sha2::{Digest as _, Sha256}; + +use crate::compat::{CultureInfo, EnumValue}; +use crate::{ + AssetType, AttachmentPoint, EnumValueMetadata, FolderType, InventoryType, SaleType, + UtilsPlatform, +}; + +const ASSET_TYPE_NAMES: [&str; 50] = [ + "texture", "sound", "callcard", "landmark", "script", "clothing", "object", "notecard", + "category", "", "lsltext", "lslbyte", "txtr_tga", "bodypart", "", "", "", "snd_wav", "img_tga", + "jpeg", "animatn", "gesture", "simstate", "", "link", "link_f", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "mesh", +]; + +const FOLDER_TYPE_NAMES: [&str; 55] = [ + "texture", "sound", "callcard", "landmark", "", "clothing", "object", "notecard", "root_inv", + "", "lsltext", "", "", "bodypart", "trash", "snapshot", "lstndfnd", "", "", "", "animatn", + "gesture", "", "favorite", "", "", "ensemble", "ensemble", "ensemble", "ensemble", "ensemble", + "ensemble", "ensemble", "ensemble", "ensemble", "ensemble", "ensemble", "ensemble", "ensemble", + "ensemble", "ensemble", "ensemble", "ensemble", "ensemble", "ensemble", "ensemble", "current", + "outfit", "my_otfts", "mesh", "inbox", "outbox", "basic_rt", "merchant", "stock", +]; + +const INVENTORY_TYPE_NAMES: [&str; 23] = [ + "texture", + "sound", + "callcard", + "landmark", + "", + "", + "object", + "notecard", + "category", + "root", + "script", + "", + "", + "", + "", + "snapshot", + "", + "attach", + "wearable", + "animation", + "gesture", + "", + "mesh", +]; +const SALE_TYPE_NAMES: [&str; 4] = ["not", "orig", "copy", "cntn"]; +const ATTACHMENT_POINT_NAMES: [&str; 56] = [ + "", + "ATTACH_CHEST", + "ATTACH_HEAD", + "ATTACH_LSHOULDER", + "ATTACH_RSHOULDER", + "ATTACH_LHAND", + "ATTACH_RHAND", + "ATTACH_LFOOT", + "ATTACH_RFOOT", + "ATTACH_BACK", + "ATTACH_PELVIS", + "ATTACH_MOUTH", + "ATTACH_CHIN", + "ATTACH_LEAR", + "ATTACH_REAR", + "ATTACH_LEYE", + "ATTACH_REYE", + "ATTACH_NOSE", + "ATTACH_RUARM", + "ATTACH_RLARM", + "ATTACH_LUARM", + "ATTACH_LLARM", + "ATTACH_RHIP", + "ATTACH_RULEG", + "ATTACH_RLLEG", + "ATTACH_LHIP", + "ATTACH_LULEG", + "ATTACH_LLLEG", + "ATTACH_BELLY", + "ATTACH_RPEC", + "ATTACH_LPEC", + "ATTACH_HUD_CENTER_2", + "ATTACH_HUD_TOP_RIGHT", + "ATTACH_HUD_TOP_CENTER", + "ATTACH_HUD_TOP_LEFT", + "ATTACH_HUD_CENTER_1", + "ATTACH_HUD_BOTTOM_LEFT", + "ATTACH_HUD_BOTTOM", + "ATTACH_HUD_BOTTOM_RIGHT", + "ATTACH_NECK", + "ATTACH_AVATAR_CENTER", + "ATTACH_LHAND_RING1", + "ATTACH_RHAND_RING1", + "ATTACH_TAIL_BASE", + "ATTACH_TAIL_TIP", + "ATTACH_LWING", + "ATTACH_RWING", + "ATTACH_FACE_JAW", + "ATTACH_FACE_LEAR", + "ATTACH_FACE_REAR", + "ATTACH_FACE_LEYE", + "ATTACH_FACE_REYE", + "ATTACH_FACE_TONGUE", + "ATTACH_GROIN", + "ATTACH_HIND_LFOOT", + "ATTACH_HIND_RFOOT", +]; + +/// Cross-platform native implementation of the C# `Utils` API. +pub struct Utils; + +impl Utils { + pub const E: f32 = std::f32::consts::E; + pub const LOG10_E: f32 = 0.434_294_5; + pub const LOG2_E: f32 = std::f32::consts::LOG2_E; + pub const PI: f32 = std::f32::consts::PI; + pub const TWO_PI: f32 = std::f32::consts::TAU; + pub const PI_OVER_TWO: f32 = std::f32::consts::FRAC_PI_2; + pub const PI_OVER_FOUR: f32 = std::f32::consts::FRAC_PI_4; + pub const DEG_TO_RAD: f32 = std::f32::consts::PI / 180.0; + pub const RAD_TO_DEG: f32 = 180.0 / std::f32::consts::PI; + + #[must_use] + pub fn en_us_culture() -> CultureInfo { + CultureInfo("en-us".to_owned()) + } + #[must_use] + pub fn epoch() -> SystemTime { + UNIX_EPOCH + } + #[must_use] + pub fn empty_bytes() -> Vec { + Vec::new() + } + #[must_use] + pub const fn intern_strings() -> bool { + false + } + + pub fn clamp_with_single_single_single( + mut value: f32, + min: f32, + max: f32, + ) -> Result { + if value > max { + value = max; + } + if value < min { + value = min; + } + Ok(value) + } + pub fn clamp_with_double_double_double( + mut value: f64, + min: f64, + max: f64, + ) -> Result { + if value > max { + value = max; + } + if value < min { + value = min; + } + Ok(value) + } + pub fn clamp_with_int32_int32_int32( + mut value: i32, + min: i32, + max: i32, + ) -> Result { + if value > max { + value = max; + } + if value < min { + value = min; + } + Ok(value) + } + pub fn round(val: f32) -> Result { + Ok((val + 0.5).floor() as i32) + } + pub fn is_finite_with_single(value: f32) -> Result { + Ok(value.is_finite()) + } + pub fn is_finite_with_double(value: f64) -> Result { + Ok(value.is_finite()) + } + pub fn distance(value1: f32, value2: f32) -> Result { + Ok((value1 - value2).abs()) + } + + pub fn hermite_with_single_single_single_single_single( + value1: f32, + tangent1: f32, + value2: f32, + tangent2: f32, + amount: f32, + ) -> Result { + Ok(hermite_f64( + f64::from(value1), + f64::from(tangent1), + f64::from(value2), + f64::from(tangent2), + f64::from(amount), + ) as f32) + } + pub fn hermite_with_double_double_double_double_double( + value1: f64, + tangent1: f64, + value2: f64, + tangent2: f64, + amount: f64, + ) -> Result { + Ok(hermite_f64(value1, tangent1, value2, tangent2, amount)) + } + pub fn lerp_with_single_single_single( + value1: f32, + value2: f32, + amount: f32, + ) -> Result { + Ok(value1 + (value2 - value1) * amount) + } + pub fn lerp_with_double_double_double( + value1: f64, + value2: f64, + amount: f64, + ) -> Result { + Ok(value1 + (value2 - value1) * amount) + } + pub fn smooth_step_with_single_single_single( + value1: f32, + value2: f32, + amount: f32, + ) -> Result { + let amount = Self::clamp_with_single_single_single(amount, 0.0, 1.0)?; + Self::hermite_with_single_single_single_single_single(value1, 0.0, value2, 0.0, amount) + } + pub fn smooth_step_with_double_double_double( + value1: f64, + value2: f64, + amount: f64, + ) -> Result { + let amount = Self::clamp_with_double_double_double(amount, 0.0, 1.0)?; + Self::hermite_with_double_double_double_double_double(value1, 0.0, value2, 0.0, amount) + } + pub fn to_degrees(radians: f32) -> Result { + Ok((f64::from(radians) * 57.295_779_513_082_32) as f32) + } + pub fn to_radians(degrees: f32) -> Result { + Ok((f64::from(degrees) * 0.017_453_292_519_943_295) as f32) + } + + pub fn md5_with_bytes(data: Vec) -> Result, crate::Error> { + Ok(Md5::digest(data).to_vec()) + } + pub fn md5_with_string(str: String) -> Result { + Ok(format!("$1${:x}", Md5::digest(str.as_bytes()))) + } + pub fn md5_string(value: String) -> Result { + Ok(format!("{:x}", Md5::digest(value.as_bytes()))) + } + pub fn sha1(data: Vec) -> Result, crate::Error> { + Ok(Sha1::digest(data).to_vec()) + } + pub fn sha1_string(value: String) -> Result { + Ok(lower_hex(&Sha1::digest(value.as_bytes()))) + } + pub fn sha256(data: Vec) -> Result, crate::Error> { + Ok(Sha256::digest(data).to_vec()) + } + pub fn sha256_string(value: String) -> Result { + Ok(lower_hex(&Sha256::digest(value.as_bytes()))) + } + pub fn pbkdf2(str: String) -> Result { + let mut salt = [0_u8; 32]; + getrandom::fill(&mut salt).map_err(|_| crate::Error::InvalidOperation)?; + let hash = pbkdf2_sha1(str.as_bytes(), &salt, 10_000); + let engine = base64::engine::general_purpose::STANDARD; + Ok(format!("{}|{}", engine.encode(salt), engine.encode(hash))) + } + pub fn random_double() -> Result { + let mut bytes = [0_u8; 8]; + getrandom::fill(&mut bytes).map_err(|_| crate::Error::InvalidOperation)?; + Ok(((u64::from_le_bytes(bytes) >> 11) as f64) / ((1_u64 << 53) as f64)) + } + + pub fn get_running_platform() -> Result { + #[cfg(target_os = "windows")] + { + return Ok(UtilsPlatform::Windows); + } + #[cfg(target_os = "macos")] + { + return Ok(UtilsPlatform::OSX); + } + #[cfg(target_os = "linux")] + { + return Ok(UtilsPlatform::Linux); + } + #[allow(unreachable_code)] + Ok(UtilsPlatform::Unknown) + } + + pub fn read_single_little_endian(src: &[u8], pos: i32) -> Result { + crate::byte_order::read_single_little_endian(src, pos) + } + pub fn write_single_little_endian( + dest: &mut [u8], + pos: i32, + value: f32, + ) -> Result<(), crate::Error> { + crate::byte_order::write_single_little_endian(dest, pos, value) + } + pub fn read_double_little_endian(src: &[u8], pos: i32) -> Result { + crate::byte_order::read_double_little_endian(src, pos) + } + pub fn write_double_little_endian( + dest: &mut [u8], + pos: i32, + value: f64, + ) -> Result<(), crate::Error> { + crate::byte_order::write_double_little_endian(dest, pos, value) + } + + pub fn bytes_to_int16_with_bytes(bytes: Vec) -> Result { + Self::bytes_to_int16_with_bytes_int32(bytes, 0) + } + pub fn bytes_to_int16_with_bytes_int32(bytes: Vec, pos: i32) -> Result { + Ok(read_or_zero::<2>(&bytes, pos)?.map_or(0, i16::from_le_bytes)) + } + pub fn bytes_to_int_with_bytes(bytes: Vec) -> Result { + Self::bytes_to_int_with_bytes_int32(bytes, 0) + } + pub fn bytes_to_int_with_bytes_int32(bytes: Vec, pos: i32) -> Result { + Ok(read_or_zero::<4>(&bytes, pos)?.map_or(0, i32::from_le_bytes)) + } + pub fn bytes_to_int64_with_bytes(bytes: Vec) -> Result { + Self::bytes_to_int64_with_bytes_int32(bytes, 0) + } + pub fn bytes_to_int64_with_bytes_int32(bytes: Vec, pos: i32) -> Result { + Ok(read_or_zero::<8>(&bytes, pos)?.map_or(0, i64::from_le_bytes)) + } + pub fn bytes_to_u_int16_with_bytes(bytes: Vec) -> Result { + Self::bytes_to_u_int16_with_bytes_int32(bytes, 0) + } + pub fn bytes_to_u_int16_with_bytes_int32( + bytes: Vec, + pos: i32, + ) -> Result { + Ok(read_or_zero::<2>(&bytes, pos)?.map_or(0, u16::from_le_bytes)) + } + pub fn bytes_to_u_int_with_bytes(bytes: Vec) -> Result { + Self::bytes_to_u_int_with_bytes_int32(bytes, 0) + } + pub fn bytes_to_u_int_with_bytes_int32(bytes: Vec, pos: i32) -> Result { + Ok(read_or_zero::<4>(&bytes, pos)?.map_or(0, u32::from_le_bytes)) + } + pub fn bytes_to_u_int64(bytes: Vec) -> Result { + Ok(read_or_zero::<8>(&bytes, 0)?.map_or(0, u64::from_le_bytes)) + } + pub fn bytes_to_float(bytes: Vec, pos: i32) -> Result { + Ok(f32::from_le_bytes(read_exact::<4>(&bytes, pos)?)) + } + pub fn bytes_to_double(bytes: Vec, pos: i32) -> Result { + Ok(f64::from_le_bytes(read_exact::<8>(&bytes, pos)?)) + } + + pub fn int16_to_bytes_with_int16(value: i16) -> Result, crate::Error> { + Ok(value.to_le_bytes().to_vec()) + } + pub fn int16_to_bytes_with_int16_bytes_int32( + value: i16, + dest: &mut [u8], + pos: i32, + ) -> Result<(), crate::Error> { + write_at(dest, pos, &value.to_le_bytes()) + } + pub fn u_int16_to_bytes_with_u_int16(value: u16) -> Result, crate::Error> { + Ok(value.to_le_bytes().to_vec()) + } + pub fn u_int16_to_bytes_with_u_int16_bytes_int32( + value: u16, + dest: &mut [u8], + pos: i32, + ) -> Result<(), crate::Error> { + write_at(dest, pos, &value.to_le_bytes()) + } + pub fn u_int16_to_bytes_big(value: u16, dest: &mut [u8], pos: i32) -> Result<(), crate::Error> { + write_at(dest, pos, &value.to_be_bytes()) + } + pub fn int_to_bytes_with_int32(value: i32) -> Result, crate::Error> { + Ok(value.to_le_bytes().to_vec()) + } + pub fn int_to_bytes_big(value: i32) -> Result, crate::Error> { + Ok(value.to_be_bytes().to_vec()) + } + pub fn int_to_bytes_with_int32_bytes_int32( + value: i32, + dest: &mut [u8], + pos: i32, + ) -> Result<(), crate::Error> { + write_at(dest, pos, &value.to_le_bytes()) + } + pub fn u_int_to_bytes_with_u_int32(value: u32) -> Result, crate::Error> { + Ok(value.to_le_bytes().to_vec()) + } + pub fn u_int_to_bytes_with_u_int32_bytes_int32( + value: u32, + dest: &mut [u8], + pos: i32, + ) -> Result<(), crate::Error> { + write_at(dest, pos, &value.to_le_bytes()) + } + pub fn u_int_to_bytes_big(value: u32, dest: &mut [u8], pos: i32) -> Result<(), crate::Error> { + write_at(dest, pos, &value.to_be_bytes()) + } + pub fn int64_to_bytes_with_int64(value: i64) -> Result, crate::Error> { + Ok(value.to_le_bytes().to_vec()) + } + pub fn int64_to_bytes_with_int64_bytes_int32( + value: i64, + dest: &mut [u8], + pos: i32, + ) -> Result<(), crate::Error> { + write_at(dest, pos, &value.to_le_bytes()) + } + pub fn u_int64_to_bytes_with_u_int64(value: u64) -> Result, crate::Error> { + Ok(value.to_le_bytes().to_vec()) + } + pub fn u_int64_to_bytes_big_with_u_int64(value: u64) -> Result, crate::Error> { + Ok(value.to_be_bytes().to_vec()) + } + pub fn u_int64_to_bytes_with_u_int64_bytes_int32( + value: u64, + dest: &mut [u8], + pos: i32, + ) -> Result<(), crate::Error> { + write_at(dest, pos, &value.to_le_bytes()) + } + pub fn u_int64_to_bytes_big_with_u_int64_bytes_int32( + value: u64, + dest: &mut [u8], + pos: i32, + ) -> Result<(), crate::Error> { + write_at(dest, pos, &value.to_be_bytes()) + } + pub fn float_to_bytes_with_single(value: f32) -> Result, crate::Error> { + Ok(value.to_le_bytes().to_vec()) + } + pub fn float_to_bytes_with_single_bytes_int32( + value: f32, + dest: &mut [u8], + pos: i32, + ) -> Result<(), crate::Error> { + write_at(dest, pos, &value.to_le_bytes()) + } + pub fn double_to_bytes_with_double(value: f64) -> Result, crate::Error> { + Ok(value.to_le_bytes().to_vec()) + } + pub fn double_to_bytes_big(value: f64) -> Result, crate::Error> { + Ok(value.to_be_bytes().to_vec()) + } + pub fn double_to_bytes_with_double_bytes_int32( + value: f64, + dest: &mut [u8], + pos: i32, + ) -> Result<(), crate::Error> { + write_at(dest, pos, &value.to_le_bytes()) + } + + pub fn u_int_to_hex_string(i: u32) -> Result { + Ok(format!("{i:08x}")) + } + pub fn bytes_to_string_with_bytes(mut bytes: Vec) -> Result { + if bytes.last() == Some(&0) { + bytes.pop(); + } + Ok(String::from_utf8_lossy(&bytes).into_owned()) + } + pub fn bytes_to_string_with_bytes_int32_int32( + bytes: Vec, + index: i32, + count: i32, + ) -> Result { + let index = usize::try_from(index).map_err(|_| crate::Error::IndexOutOfRange)?; + let count = usize::try_from(count).map_err(|_| crate::Error::Argument)?; + let end = index.checked_add(count).ok_or(crate::Error::Argument)?; + let mut count = count; + if count == 0 && bytes.len() > index { + return Err(crate::Error::IndexOutOfRange); + } + if bytes.len() > end && count > 0 && bytes[end - 1] == 0 { + count -= 1; + } + let slice = bytes + .get(index..index + count) + .ok_or(crate::Error::Argument)?; + Ok(String::from_utf8_lossy(slice).into_owned()) + } + pub fn bytes_to_hex_string_with_bytes_string( + bytes: Vec, + field_name: String, + ) -> Result { + Self::bytes_to_hex_string_with_bytes_int32_string( + bytes.clone(), + bytes.len() as i32, + Some(field_name), + ) + } + pub fn bytes_to_hex_string_with_bytes_int32_string( + bytes: Vec, + length: i32, + field_name: Option, + ) -> Result { + let length = usize::try_from(length).map_err(|_| crate::Error::Argument)?; + if length > bytes.len() { + return Err(crate::Error::Argument); + } + let mut output = String::new(); + for (line, chunk) in bytes[..length].chunks(16).enumerate() { + if line > 0 { + output.push('\n'); + } + if let Some(name) = field_name.as_deref().filter(|name| !name.is_empty()) { + output.push_str(name); + output.push_str(": "); + } + for (index, byte) in chunk.iter().enumerate() { + use std::fmt::Write as _; + if index > 0 { + output.push(' '); + } + write!(&mut output, "{byte:02X}").expect("writing to String cannot fail"); + } + } + Ok(output) + } + pub fn string_to_bytes(str: String) -> Result, crate::Error> { + if str.is_empty() { + return Ok(Vec::new()); + } + let mut bytes = str.into_bytes(); + if bytes.last() != Some(&0) { + bytes.push(0); + } + Ok(bytes) + } + pub fn hex_string_to_bytes( + hex_string: String, + handle_dirty: bool, + ) -> Result, crate::Error> { + let cleaned = if handle_dirty { + hex_string + .chars() + .filter(char::is_ascii_hexdigit) + .collect::() + } else { + hex_string + }; + let usable = cleaned.len() & !1; + (0..usable) + .step_by(2) + .map(|i| u8::from_str_radix(&cleaned[i..i + 2], 16).map_err(|_| crate::Error::Argument)) + .collect() + } + + pub fn float_to_byte(val: f32, lower: f32, upper: f32) -> Result { + let val = Self::clamp_with_single_single_single(val, lower, upper)?; + Ok(((val - lower) / (upper - lower) * 255.0).floor() as u8) + } + pub fn byte_to_float_with_bytes_int32_single_single( + bytes: Vec, + pos: i32, + lower: f32, + upper: f32, + ) -> Result { + let Ok(pos) = usize::try_from(pos) else { + return Err(crate::Error::IndexOutOfRange); + }; + match bytes.get(pos) { + Some(value) => Self::byte_to_float_with_byte_single_single(*value, lower, upper), + None => Ok(0.0), + } + } + pub fn byte_to_float_with_byte_single_single( + val: u8, + lower: f32, + upper: f32, + ) -> Result { + let delta = upper - lower; + let mut value = f32::from(val) * (1.0 / 255.0) * delta + lower; + if value.abs() < delta * (1.0 / 255.0) { + value = 0.0; + } + Ok(value) + } + pub fn u_int16_to_float_with_bytes_int32_single_single( + bytes: Vec, + pos: i32, + lower: f32, + upper: f32, + ) -> Result { + let value = Self::bytes_to_u_int16_with_bytes_int32(bytes, pos)?; + Self::u_int16_to_float_with_u_int16_single_single(value, lower, upper) + } + pub fn u_int16_to_float_with_u_int16_single_single( + val: u16, + lower: f32, + upper: f32, + ) -> Result { + let delta = upper - lower; + let mut value = f32::from(val) * (1.0 / 65_535.0) * delta + lower; + if value.abs() < delta * (1.0 / 65_535.0) { + value = 0.0; + } + Ok(value) + } + pub fn float_to_u_int16(value: f32, lower: f32, upper: f32) -> Result { + Ok(((value - lower) / (upper - lower) * 65_535.0) as u16) + } + + pub fn try_parse_single(s: String, result: &mut f32) -> bool { + if let Ok(value) = s.trim().parse() { + *result = value; + true + } else { + *result = 0.0; + false + } + } + pub fn try_parse_double(s: String, result: &mut f64) -> bool { + if let Ok(value) = s.trim().parse() { + *result = value; + true + } else { + *result = 0.0; + false + } + } + pub fn try_parse_hex(s: String, result: &mut u32) -> bool { + if let Ok(value) = u32::from_str_radix(s.trim(), 16) { + *result = value; + true + } else { + *result = 0; + false + } + } + pub fn enum_to_text(value: EnumValue) -> Result { + Ok(value.text.unwrap_or(value.name).to_owned()) + } + pub fn enum_try_parse( + str_type: String, + result: &mut Option, + ) -> Result { + *result = T::parse_name(&str_type); + Ok(result.is_some()) + } + + pub fn asset_type_to_string(type_: AssetType) -> Result { + indexed_name(&ASSET_TYPE_NAMES, type_ as i8 as i32) + } + pub fn string_to_asset_type(type_: String) -> Result { + Ok( + match ASSET_TYPE_NAMES.iter().position(|name| *name == type_) { + Some(0) => AssetType::Texture, + Some(1) => AssetType::Sound, + Some(2) => AssetType::CallingCard, + Some(3) => AssetType::Landmark, + Some(4) => AssetType::Script, + Some(5) => AssetType::Clothing, + Some(6) => AssetType::Object, + Some(7) => AssetType::Notecard, + Some(8) => AssetType::Folder, + Some(10) => AssetType::LSLText, + Some(11) => AssetType::LSLBytecode, + Some(12) => AssetType::TextureTGA, + Some(13) => AssetType::Bodypart, + Some(17) => AssetType::SoundWAV, + Some(18) => AssetType::ImageTGA, + Some(19) => AssetType::ImageJPEG, + Some(20) => AssetType::Animation, + Some(21) => AssetType::Gesture, + Some(22) => AssetType::Simstate, + Some(24) => AssetType::Link, + Some(25) => AssetType::LinkFolder, + Some(49) => AssetType::Mesh, + _ => AssetType::Unknown, + }, + ) + } + pub fn folder_type_to_string(type_: FolderType) -> Result { + indexed_name(&FOLDER_TYPE_NAMES, type_ as i8 as i32) + } + pub fn string_to_folder_type(type_: String) -> Result { + Ok( + FolderType::parse_name(folder_variant_for_wire(&type_).unwrap_or("None")) + .unwrap_or(FolderType::None), + ) + } + pub fn inventory_type_to_string(type_: InventoryType) -> Result { + indexed_name(&INVENTORY_TYPE_NAMES, i32::from(type_.raw())) + } + pub fn string_to_inventory_type(type_: String) -> Result { + Ok(INVENTORY_TYPE_NAMES + .iter() + .position(|name| *name == type_) + .map_or(InventoryType::UNKNOWN, |index| { + InventoryType::from_raw(index as i8) + })) + } + pub fn sale_type_to_string(type_: SaleType) -> Result { + indexed_name(&SALE_TYPE_NAMES, type_ as u8 as i32) + } + pub fn string_to_sale_type(value: String) -> Result { + Ok( + match SALE_TYPE_NAMES.iter().position(|name| *name == value) { + Some(1) => SaleType::Original, + Some(2) => SaleType::Copy, + Some(3) => SaleType::Contents, + _ => SaleType::Not, + }, + ) + } + pub fn string_to_attachment_point(value: String) -> Result { + let Some(index) = ATTACHMENT_POINT_NAMES + .iter() + .position(|name| *name == value) + else { + return Ok(AttachmentPoint::Default); + }; + AttachmentPoint::parse_name(attachment_variant(index)).ok_or(crate::Error::Argument) + } + + pub fn copy_bytes(bytes: Option>) -> Result>, crate::Error> { + Ok(bytes) + } + pub fn u_ints_to_long(a: u32, b: u32) -> Result { + Ok((u64::from(a) << 32) | u64::from(b)) + } + pub fn long_to_u_ints(a: u64, b: &mut u32, c: &mut u32) -> Result<(), crate::Error> { + *b = (a >> 32) as u32; + *c = a as u32; + Ok(()) + } + pub fn ip_to_u_int(address: IpAddr) -> Result { + let bytes = match address { + IpAddr::V4(ip) => ip.octets(), + IpAddr::V6(ip) => { + let octets = ip.octets(); + [octets[0], octets[1], octets[2], octets[3]] + } + }; + Ok(u32::from_le_bytes(bytes)) + } + pub fn get_unix_time() -> Result { + Ok(SystemTime::now() + .duration_since(UNIX_EPOCH) + .map_err(|_| crate::Error::InvalidOperation)? + .as_secs() as u32) + } + pub fn unix_time_to_date_time_with_u_int32(timestamp: u32) -> Result { + Ok(UNIX_EPOCH + Duration::from_secs(u64::from(timestamp))) + } + pub fn unix_time_to_date_time_with_int32(timestamp: i32) -> Result { + Self::unix_time_to_date_time_with_u_int32(timestamp as u32) + } + pub fn date_time_to_unix_time(time: SystemTime) -> Result { + Ok(match time.duration_since(UNIX_EPOCH) { + Ok(duration) => duration.as_secs() as u32, + Err(error) => (-(error.duration().as_secs() as i64)) as u32, + }) + } + pub fn swap(lhs: &mut Option, rhs: &mut Option) -> Result<(), crate::Error> { + std::mem::swap(lhs, rhs); + Ok(()) + } + pub fn swap_words(value: u8) -> Result { + Ok(value.rotate_left(4)) + } + pub fn hostname_to_i_pv4(hostname: String) -> Result, crate::Error> { + if let Ok(ip) = hostname.parse() { + return Ok(Some(ip)); + } + let addresses = (hostname.as_str(), 0) + .to_socket_addrs() + .map_err(|_| crate::Error::Socket)?; + Ok(addresses.map(|address| address.ip()).find(IpAddr::is_ipv4)) + } +} + +fn hermite_f64(value1: f64, tangent1: f64, value2: f64, tangent2: f64, amount: f64) -> f64 { + if amount == 0.0 { + return value1; + } + if amount == 1.0 { + return value2; + } + let cubed = amount * amount * amount; + let squared = amount * amount; + (2.0 * value1 - 2.0 * value2 + tangent2 + tangent1) * cubed + + (3.0 * value2 - 3.0 * value1 - 2.0 * tangent1 - tangent2) * squared + + tangent1 * amount + + value1 +} + +fn read_or_zero(bytes: &[u8], pos: i32) -> Result, crate::Error> { + let pos = usize::try_from(pos).map_err(|_| crate::Error::IndexOutOfRange)?; + let Some(end) = pos.checked_add(N) else { + return Ok(None); + }; + Ok(bytes.get(pos..end).and_then(|slice| slice.try_into().ok())) +} + +fn read_exact(bytes: &[u8], pos: i32) -> Result<[u8; N], crate::Error> { + read_or_zero(bytes, pos)?.ok_or(crate::Error::Argument) +} + +fn write_at(dest: &mut [u8], pos: i32, source: &[u8]) -> Result<(), crate::Error> { + let pos = usize::try_from(pos).map_err(|_| crate::Error::IndexOutOfRange)?; + for (offset, byte) in source.iter().copied().enumerate() { + *dest + .get_mut( + pos.checked_add(offset) + .ok_or(crate::Error::IndexOutOfRange)?, + ) + .ok_or(crate::Error::IndexOutOfRange)? = byte; + } + Ok(()) +} + +fn indexed_name(names: &[&str; N], index: i32) -> Result { + usize::try_from(index) + .ok() + .and_then(|index| names.get(index)) + .map(|name| (*name).to_owned()) + .ok_or(crate::Error::IndexOutOfRange) +} + +fn lower_hex(bytes: &[u8]) -> String { + use std::fmt::Write as _; + let mut output = String::with_capacity(bytes.len() * 2); + for byte in bytes { + write!(&mut output, "{byte:02x}").expect("writing to String cannot fail"); + } + output +} + +fn hmac_sha1(key: &[u8], data: &[u8]) -> [u8; 20] { + let mut block = [0_u8; 64]; + if key.len() > block.len() { + block[..20].copy_from_slice(&Sha1::digest(key)); + } else { + block[..key.len()].copy_from_slice(key); + } + let mut inner_pad = [0x36_u8; 64]; + let mut outer_pad = [0x5c_u8; 64]; + for index in 0..64 { + inner_pad[index] ^= block[index]; + outer_pad[index] ^= block[index]; + } + let mut inner = Sha1::new(); + inner.update(inner_pad); + inner.update(data); + let inner_hash = inner.finalize(); + let mut outer = Sha1::new(); + outer.update(outer_pad); + outer.update(inner_hash); + outer.finalize().into() +} + +fn pbkdf2_sha1(password: &[u8], salt: &[u8], iterations: usize) -> [u8; 20] { + let mut initial = Vec::with_capacity(salt.len() + 4); + initial.extend_from_slice(salt); + initial.extend_from_slice(&1_u32.to_be_bytes()); + let mut current = hmac_sha1(password, &initial); + let mut result = current; + for _ in 1..iterations { + current = hmac_sha1(password, ¤t); + for (result, byte) in result.iter_mut().zip(current) { + *result ^= byte; + } + } + result +} + +fn folder_variant_for_wire(value: &str) -> Option<&'static str> { + let index = FOLDER_TYPE_NAMES.iter().position(|name| *name == value)?; + Some(match index { + 0 => "Texture", + 1 => "Sound", + 2 => "CallingCard", + 3 => "Landmark", + 5 => "Clothing", + 6 => "Object", + 7 => "Notecard", + 8 => "Root", + 10 => "LSLText", + 13 => "BodyPart", + 14 => "Trash", + 15 => "Snapshot", + 16 => "LostAndFound", + 20 => "Animation", + 21 => "Gesture", + 23 => "Favorites", + 26..=45 => { + if index == 45 { + "EnsembleEnd" + } else { + "EnsembleStart" + } + } + 46 => "CurrentOutfit", + 47 => "Outfit", + 48 => "MyOutfits", + 49 => "Mesh", + 50 => "Inbox", + 51 => "Outbox", + 52 => "BasicRoot", + 53 => "MarketplaceListings", + 54 => "MarketplaceStock", + _ => return None, + }) +} + +fn attachment_variant(index: usize) -> &'static str { + const VARIANTS: [&str; 56] = [ + "Default", + "Chest", + "Skull", + "LeftShoulder", + "RightShoulder", + "LeftHand", + "RightHand", + "LeftFoot", + "RightFoot", + "Spine", + "Pelvis", + "Mouth", + "Chin", + "LeftEar", + "RightEar", + "LeftEyeball", + "RightEyeball", + "Nose", + "RightUpperArm", + "RightForearm", + "LeftUpperArm", + "LeftForearm", + "RightHip", + "RightUpperLeg", + "RightLowerLeg", + "LeftHip", + "LeftUpperLeg", + "LeftLowerLeg", + "Stomach", + "LeftPec", + "RightPec", + "HUDCenter2", + "HUDTopRight", + "HUDTop", + "HUDTopLeft", + "HUDCenter", + "HUDBottomLeft", + "HUDBottom", + "HUDBottomRight", + "Neck", + "Root", + "LeftHandRing", + "RightHandRing", + "TailBase", + "TailTip", + "LeftWing", + "RightWing", + "Jaw", + "AltLeftEar", + "AltRightEar", + "AltLeftEye", + "AltRightEye", + "Tongue", + "Groin", + "LeftHindFoot", + "RightHindFoot", + ]; + VARIANTS[index] +} + +#[cfg(test)] +mod tests { + use super::Utils; + use crate::{AssetType, AttachmentPoint, EnumInfoExtensions, PrimFlags}; + + #[test] + fn byte_and_string_conversions_match_protocol_sentinels() { + assert_eq!(Utils::bytes_to_int_with_bytes(vec![1, 2, 3]), Ok(0)); + assert_eq!( + Utils::bytes_to_int_with_bytes(vec![0x78, 0x56, 0x34, 0x12]), + Ok(0x1234_5678) + ); + assert_eq!( + Utils::string_to_bytes("hello".to_owned()), + Ok(b"hello\0".to_vec()) + ); + assert_eq!( + Utils::bytes_to_string_with_bytes(b"hello\0".to_vec()), + Ok("hello".to_owned()) + ); + assert_eq!( + Utils::hex_string_to_bytes("z01 2x3".to_owned(), true), + Ok(vec![0x01, 0x23]) + ); + assert_eq!( + Utils::bytes_to_int_with_bytes_int32(vec![0; 4], -1), + Err(crate::Error::IndexOutOfRange) + ); + assert_eq!( + Utils::bytes_to_string_with_bytes_int32_int32(vec![1], 0, 0), + Err(crate::Error::IndexOutOfRange) + ); + let dump = Utils::bytes_to_hex_string_with_bytes_int32_string( + (0..17).collect(), + 17, + Some("field".to_owned()), + ); + assert_eq!( + dump, + Ok("field: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\nfield: 10".to_owned()) + ); + } + + #[test] + fn hashes_and_numeric_packing_match_known_vectors() { + assert_eq!( + Utils::md5_string("abc".to_owned()), + Ok("900150983cd24fb0d6963f7d28e17f72".to_owned()) + ); + assert_eq!( + Utils::sha1_string("abc".to_owned()), + Ok("a9993e364706816aba3e25717850c26c9cd0d89d".to_owned()) + ); + assert_eq!( + Utils::sha256_string("abc".to_owned()), + Ok("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad".to_owned()) + ); + assert_eq!( + Utils::u_ints_to_long(0x1122_3344, 0x5566_7788), + Ok(0x1122_3344_5566_7788) + ); + assert_eq!( + super::pbkdf2_sha1(b"password", b"salt", 1), + [ + 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, + 0x12, 0x06, 0x2f, 0xe0, 0x37, 0xa6, + ] + ); + } + + #[test] + fn enum_conversion_and_metadata_match_golden_names() { + assert_eq!( + Utils::asset_type_to_string(AssetType::LSLText), + Ok("lsltext".to_owned()) + ); + assert_eq!( + Utils::string_to_asset_type("material".to_owned()), + Ok(AssetType::Unknown) + ); + assert_eq!( + Utils::string_to_attachment_point("ATTACH_HEAD".to_owned()), + Ok(AttachmentPoint::Skull) + ); + assert_eq!( + Utils::enum_to_text(AssetType::Texture.into()), + Ok("texture".to_owned()) + ); + assert_eq!( + EnumInfoExtensions::get_text(PrimFlags::PHYSICS.into()), + Ok(String::new()) + ); + } + + #[test] + fn destination_writes_are_real_mutations() { + let mut bytes = [0_u8; 6]; + assert_eq!( + Utils::u_int_to_bytes_with_u_int32_bytes_int32(0x1234_5678, &mut bytes, 1), + Ok(()) + ); + assert_eq!(bytes, [0, 0x78, 0x56, 0x34, 0x12, 0]); + } +} diff --git a/tests/api-compile/Cargo.lock b/tests/api-compile/Cargo.lock index ecfc3cf..3b77f42 100644 --- a/tests/api-compile/Cargo.lock +++ b/tests/api-compile/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "block-buffer" version = "0.10.4" @@ -11,6 +17,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" +dependencies = [ + "hybrid-array", +] + [[package]] name = "bumpalo" version = "3.20.3" @@ -23,6 +38,30 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + [[package]] name = "crypto-common" version = "0.1.7" @@ -33,14 +72,34 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "hybrid-array", +] + [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", - "crypto-common", + "block-buffer 0.10.4", + "crypto-common 0.1.7", +] + +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.1", + "const-oid", + "crypto-common 0.2.2", ] [[package]] @@ -88,6 +147,15 @@ dependencies = [ "r-efi", ] +[[package]] +name = "hybrid-array" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b" +dependencies = [ + "typenum", +] + [[package]] name = "js-sys" version = "0.3.104" @@ -182,8 +250,11 @@ dependencies = [ name = "libremetaverse-types" version = "0.0.1" dependencies = [ + "base64", "getrandom", "md-5", + "sha1", + "sha2", "uuid", ] @@ -221,7 +292,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ "cfg-if", - "digest", + "digest 0.10.7", ] [[package]] @@ -285,6 +356,28 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" +[[package]] +name = "sha1" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "digest 0.11.3", +] + [[package]] name = "slab" version = "0.4.12" diff --git a/tests/api-compile/src/lib.rs b/tests/api-compile/src/lib.rs index 8ada464..96869fc 100644 --- a/tests/api-compile/src/lib.rs +++ b/tests/api-compile/src/lib.rs @@ -176754,7 +176754,7 @@ fn member_29709() { } // C# member: `M:LibreMetaverse.Utils.EnumTryParse``1(System.String,``0@)`. -fn member_29710() { +fn member_29710() { let _ = libremetaverse_types::Utils::enum_try_parse::(argument(), argument()); } diff --git a/tests/red-suite-baseline.json b/tests/red-suite-baseline.json index 2756c09..07fee8f 100644 --- a/tests/red-suite-baseline.json +++ b/tests/red-suite-baseline.json @@ -17,7 +17,8 @@ "LibreMetaverse.Tests/TypeTests.cs::TypeTests.TestMatrix::test", "LibreMetaverse.Tests/TypeTests.cs::TypeTests.UUIDs::test", "LibreMetaverse.Tests/TypeTests.cs::TypeTests.Vector3ApproxEquals::test", - "LibreMetaverse.Tests/TypeTests.cs::TypeTests.VectorCasting::test" + "LibreMetaverse.Tests/TypeTests.cs::TypeTests.VectorCasting::test", + "LibreMetaverse.Tests/UtilsConversionsTests.cs::UtilsConversionsTests.StringToBytes::test" ], - "support_passes": 49 + "support_passes": 56 } diff --git a/tools/generate_api_shims.py b/tools/generate_api_shims.py index bcf86a3..44883f2 100644 --- a/tools/generate_api_shims.py +++ b/tools/generate_api_shims.py @@ -40,6 +40,8 @@ TARGETS = { NATIVE_TYPES = { "T:LibreMetaverse.Color4": "crate::color4::Color4", "T:LibreMetaverse.CRC32": "crate::crc32::CRC32", + "T:LibreMetaverse.EnumInfoAttribute": "crate::enum_compat::EnumInfoAttribute", + "T:LibreMetaverse.EnumInfoExtensions": "crate::enum_compat::EnumInfoExtensions", "T:LibreMetaverse.Matrix4": "crate::geometry::Matrix4", "T:LibreMetaverse.Quaternion": "crate::geometry::Quaternion", "T:LibreMetaverse.Ray": "crate::vectors::Ray", @@ -48,6 +50,7 @@ NATIVE_TYPES = { "T:LibreMetaverse.Vector3": "crate::vectors::Vector3", "T:LibreMetaverse.Vector3d": "crate::vectors::Vector3d", "T:LibreMetaverse.Vector4": "crate::vectors::Vector4", + "T:LibreMetaverse.Utils": "crate::utils::Utils", } NATIVE_MEMBER_BODIES = { @@ -453,6 +456,11 @@ def render_compile_fixture( row = member_rows[member["doc_id"]] method_names = generic_names(member) parameters = [*owner_names, *generic_declarations(member, mapper, owner_names)] + if member["doc_id"] == "M:LibreMetaverse.Utils.EnumTryParse``1(System.String,``0@)": + parameters = [ + *owner_names, + "T: libremetaverse_types::EnumValueMetadata", + ] if trait: parameters.append(f"__Probe: {owner_type}") declaration = generic_suffix(parameters) @@ -838,7 +846,10 @@ def coverage_report(catalog: dict, coverage: dict[str, tuple[int, int, bool]]) - if complete and (types, members) != (got_types, got_members): raise ValueError(f"incomplete generated slice for {name}") native_type_ids = { - item["doc_id"] for item in assembly["types"] if item["doc_id"] in NATIVE_TYPES + item["doc_id"] + for item in assembly["types"] + if item["doc_id"] in NATIVE_TYPES + or (name == "LibreMetaverse.Types" and item["kind"] == "enum") } native_member_ids = { member["doc_id"] diff --git a/tools/generate_rust_mapping.py b/tools/generate_rust_mapping.py index 3b9b9f3..9f62b9f 100644 --- a/tools/generate_rust_mapping.py +++ b/tools/generate_rust_mapping.py @@ -189,6 +189,30 @@ MEMBER_TYPE_OVERRIDES = { ), } MEMBER_SIGNATURE_OVERRIDES = { + "M:LibreMetaverse.Utils.DoubleToBytes(System.Double,System.Byte[],System.Int32)": ( + "pub fn double_to_bytes_with_double_bytes_int32(value: f64, dest: &mut [u8], pos: i32) -> Result<(), crate::Error>", + "owned,mutable_borrow,owned", + ), + "M:LibreMetaverse.Utils.EnumTryParse``1(System.String,``0@)": ( + "pub fn enum_try_parse(str_type: String, result: &mut Option) -> Result", + "owned,mutable_borrow", + ), + "M:LibreMetaverse.Utils.FloatToBytes(System.Single,System.Byte[],System.Int32)": ( + "pub fn float_to_bytes_with_single_bytes_int32(value: f32, dest: &mut [u8], pos: i32) -> Result<(), crate::Error>", + "owned,mutable_borrow,owned", + ), + "M:LibreMetaverse.Utils.Int16ToBytes(System.Int16,System.Byte[],System.Int32)": ( + "pub fn int16_to_bytes_with_int16_bytes_int32(value: i16, dest: &mut [u8], pos: i32) -> Result<(), crate::Error>", + "owned,mutable_borrow,owned", + ), + "M:LibreMetaverse.Utils.Int64ToBytes(System.Int64,System.Byte[],System.Int32)": ( + "pub fn int64_to_bytes_with_int64_bytes_int32(value: i64, dest: &mut [u8], pos: i32) -> Result<(), crate::Error>", + "owned,mutable_borrow,owned", + ), + "M:LibreMetaverse.Utils.IntToBytes(System.Int32,System.Byte[],System.Int32)": ( + "pub fn int_to_bytes_with_int32_bytes_int32(value: i32, dest: &mut [u8], pos: i32) -> Result<(), crate::Error>", + "owned,mutable_borrow,owned", + ), "M:LibreMetaverse.Utils.ReadSingleLittleEndian(System.Byte[],System.Int32)": ( "pub fn read_single_little_endian(src: &[u8], pos: i32) -> Result", "shared_borrow,owned", @@ -205,6 +229,30 @@ MEMBER_SIGNATURE_OVERRIDES = { "pub fn write_double_little_endian(dest: &mut [u8], pos: i32, value: f64) -> Result<(), crate::Error>", "mutable_borrow,owned,owned", ), + "M:LibreMetaverse.Utils.UInt16ToBytes(System.UInt16,System.Byte[],System.Int32)": ( + "pub fn u_int16_to_bytes_with_u_int16_bytes_int32(value: u16, dest: &mut [u8], pos: i32) -> Result<(), crate::Error>", + "owned,mutable_borrow,owned", + ), + "M:LibreMetaverse.Utils.UInt16ToBytesBig(System.UInt16,System.Byte[],System.Int32)": ( + "pub fn u_int16_to_bytes_big(value: u16, dest: &mut [u8], pos: i32) -> Result<(), crate::Error>", + "owned,mutable_borrow,owned", + ), + "M:LibreMetaverse.Utils.UInt64ToBytes(System.UInt64,System.Byte[],System.Int32)": ( + "pub fn u_int64_to_bytes_with_u_int64_bytes_int32(value: u64, dest: &mut [u8], pos: i32) -> Result<(), crate::Error>", + "owned,mutable_borrow,owned", + ), + "M:LibreMetaverse.Utils.UInt64ToBytesBig(System.UInt64,System.Byte[],System.Int32)": ( + "pub fn u_int64_to_bytes_big_with_u_int64_bytes_int32(value: u64, dest: &mut [u8], pos: i32) -> Result<(), crate::Error>", + "owned,mutable_borrow,owned", + ), + "M:LibreMetaverse.Utils.UIntToBytes(System.UInt32,System.Byte[],System.Int32)": ( + "pub fn u_int_to_bytes_with_u_int32_bytes_int32(value: u32, dest: &mut [u8], pos: i32) -> Result<(), crate::Error>", + "owned,mutable_borrow,owned", + ), + "M:LibreMetaverse.Utils.UIntToBytesBig(System.UInt32,System.Byte[],System.Int32)": ( + "pub fn u_int_to_bytes_big(value: u32, dest: &mut [u8], pos: i32) -> Result<(), crate::Error>", + "owned,mutable_borrow,owned", + ), "M:LibreMetaverse.UUID.ToBytes(System.Byte[],System.Int32)": ( "pub fn to_bytes(&self, dest: &mut [u8], pos: i32) -> Result<(), crate::Error>", "shared_self,mutable_borrow,owned",