Complete first release candidate audit (#107)
Some checks failed
API and SemVer surface / api-surface (push) Failing after 1m34s
Native code generation / deterministic (push) Has been cancelled
Concurrency and resource soak audit / soak (push) Has been cancelled
Documentation / documentation (push) Has been cancelled
performance evidence / audit (push) Has been cancelled
First release candidate / non-fuzz-release-gate (push) Has been cancelled
Release platform and feature matrix / audit (push) Has been cancelled
Release platform and feature matrix / matrix (false, linux-stable-minimal, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (false, macos-stable-portable, x86_64-apple-darwin, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (false, windows-stable-portable, x86_64-pc-windows-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-msrv-portable, x86_64-unknown-linux-gnu, 1.96.0) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-default, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-features, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-release-surface, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Dependency and supply-chain audit / audit (push) Has been cancelled
Native release artifact audit / audit (push) Has been cancelled
Imaging and meshing gate / native (push) Failing after 53s
JPEG 2000 feature / linux (push) Successful in 2m49s
Native Rust workspace compile / compile (push) Failing after 59s
Skia feature / linux (push) Has been cancelled

This commit is contained in:
2026-08-12 14:44:28 +00:00
parent dceb394378
commit c9a1170a27
140 changed files with 82175 additions and 27179 deletions

View File

@@ -0,0 +1,167 @@
//! Deterministic, reflection-free packet and compatibility-object diagnostics.
use std::fmt::Write as _;
use libremetaverse_structured_data::OSD;
use libremetaverse_types::Error;
use libremetaverse_types::compat::Object;
use crate::packets::{Header, Packet};
#[must_use]
pub(crate) fn interpret_options(header: &Header) -> String {
format!(
"[{} {} {} {}]",
if header.appended_acks { "Ack" } else { " " },
if header.resent { "Res" } else { " " },
if header.reliable { "Rel" } else { " " },
if header.zerocoded { "Zer" } else { " " },
)
}
pub(crate) fn packet_to_string(packet: &Packet) -> Result<String, Error> {
let descriptor =
crate::packet_catalog::descriptor_by_type(packet.type_).ok_or(Error::InvalidOperation)?;
let mut result = String::new();
writeln!(
result,
"Packet Type: {0} http://lib.openmetaverse.co/wiki/{0} http://wiki.secondlife.com/wiki/{0}",
descriptor.name,
)
.map_err(|_| Error::InvalidOperation)?;
writeln!(result, "[Packet Header]").map_err(|_| Error::InvalidOperation)?;
writeln!(result, "Sequence: {}", packet.header.sequence)
.map_err(|_| Error::InvalidOperation)?;
writeln!(result, " Options: {}", interpret_options(&packet.header))
.map_err(|_| Error::InvalidOperation)?;
writeln!(result, "\n[Packet Payload]").map_err(|_| Error::InvalidOperation)?;
let body = packet.packet_to_osd()?;
format_osd_map(&body.snapshot(), 0, &mut result)?;
Ok(result)
}
pub(crate) fn message_to_string(message: &Object, recurse_level: i32) -> Result<String, Error> {
if recurse_level < 0 || recurse_level > 64 {
return Err(Error::Argument);
}
let mut result = String::new();
format_object(
message,
usize::try_from(recurse_level).map_err(|_| Error::Argument)?,
&mut result,
)?;
Ok(result)
}
fn format_object(value: &Object, depth: usize, output: &mut String) -> Result<(), Error> {
let indent = " ".repeat(depth);
match value {
Object::Undefined => output.push_str(&format!("{indent}undefined\n")),
Object::Boolean(value) => output.push_str(&format!("{indent}{value} [Boolean]\n")),
Object::Integer(value) => output.push_str(&format!("{indent}{value} [Int32]\n")),
Object::UInteger(value) => output.push_str(&format!("{indent}{value} [UInt32]\n")),
Object::Long(value) => output.push_str(&format!("{indent}{value} [Int64]\n")),
Object::ULong(value) => output.push_str(&format!("{indent}{value} [UInt64]\n")),
Object::Real(value) => output.push_str(&format!("{indent}{value} [Double]\n")),
Object::String(value) => output.push_str(&format!("{indent}{value} [String]\n")),
Object::Bytes(value) => {
output.push_str(&format!("{indent}[Byte[{0}]]\n", value.len()));
format_hex(value, depth + 1, output)?;
}
Object::Array(values) => {
output.push_str(&format!("{indent}[Array {0}]\n", values.len()));
for (index, value) in values.iter().enumerate() {
output.push_str(&format!("{indent} [{index}]\n"));
format_object(value, depth + 2, output)?;
}
}
Object::Map(values) => {
output.push_str(&format!("{indent}[Map {0}]\n", values.len()));
let mut entries = values.iter().collect::<Vec<_>>();
entries.sort_by(|left, right| left.0.cmp(right.0));
for (key, value) in entries {
output.push_str(&format!("{indent} {key}:\n"));
format_object(value, depth + 2, output)?;
}
}
other => output.push_str(&format!("{indent}{other:?}\n")),
}
Ok(())
}
fn format_osd_map(
values: &std::collections::HashMap<String, OSD>,
depth: usize,
output: &mut String,
) -> Result<(), Error> {
let mut entries = values.iter().collect::<Vec<_>>();
entries.sort_by(|left, right| left.0.cmp(right.0));
for (key, value) in entries {
writeln!(output, "{}{key}:", " ".repeat(depth)).map_err(|_| Error::InvalidOperation)?;
format_osd(value, depth + 1, output)?;
}
Ok(())
}
fn format_osd(value: &OSD, depth: usize, output: &mut String) -> Result<(), Error> {
let indent = " ".repeat(depth);
match value {
OSD::Map(values) => format_osd_map(values, depth, output),
OSD::Array(values) => {
for (index, value) in values.iter().enumerate() {
writeln!(output, "{indent}[{index}]").map_err(|_| Error::InvalidOperation)?;
format_osd(value, depth + 1, output)?;
}
Ok(())
}
OSD::Binary(bytes) => format_hex(bytes, depth, output),
other => writeln!(output, "{indent}{other:?}").map_err(|_| Error::InvalidOperation),
}
}
fn format_hex(bytes: &[u8], depth: usize, output: &mut String) -> Result<(), Error> {
let indent = " ".repeat(depth);
for chunk in bytes.chunks(16) {
write!(output, "{indent}").map_err(|_| Error::InvalidOperation)?;
for byte in chunk {
write!(output, "{byte:02X} ").map_err(|_| Error::InvalidOperation)?;
}
output.push('\n');
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn options_match_reference_layout() {
let mut header = crate::packet_catalog::new_header(crate::PacketFrequency::High, 1, false);
header.reliable = true;
header.resent = true;
assert_eq!(interpret_options(&header), "[ Res Rel ]");
}
#[test]
fn packet_dump_contains_header_and_sorted_payload() {
let packet =
crate::packet_catalog::build_packet(crate::packet_catalog::PacketType::CloseCircuit)
.unwrap();
let dump = packet_to_string(&packet).unwrap();
assert!(dump.contains("Packet Type: CloseCircuit"));
assert!(dump.contains("[Packet Header]"));
assert!(dump.contains("[Packet Payload]"));
}
#[test]
fn message_dump_formats_nested_values_and_bytes() {
let value = Object::Map(std::collections::HashMap::from([
("z".to_owned(), Object::Bytes(vec![0xab, 0xcd])),
("a".to_owned(), Object::Integer(7)),
]));
let text = message_to_string(&value, 0).unwrap();
assert!(text.find("a:").unwrap() < text.find("z:").unwrap());
assert!(text.contains("AB CD"));
}
}