Establish release CI matrix (#99)
Some checks failed
Native code generation / deterministic (push) Failing after 2m4s
Imaging and meshing gate / native (push) Successful in 6m35s
JPEG 2000 feature / linux (push) Successful in 2m45s
Release platform and feature matrix / audit (push) Successful in 34s
Native Rust workspace compile / compile (push) Failing after 56s
Skia feature / linux (push) Successful in 30m55s
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-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
Release platform and feature matrix / matrix (false, linux-msrv-portable, x86_64-unknown-linux-gnu, 1.96.0) (push) Has been cancelled

This commit is contained in:
2026-08-11 22:12:31 +00:00
parent a9e2711447
commit 9779e50ce9
15 changed files with 1194 additions and 23 deletions

View File

@@ -8,9 +8,10 @@ repository.workspace = true
description = "Rust rewrite shell for the LibreMetaverse client library"
[features]
default = ["dds-bc67", "jpeg2000"]
default = ["dds-bc67"]
dds-bc67 = ["dep:bcdec_rs"]
jpeg2000 = ["libremetaverse-imaging/jpeg2000"]
vorbis = ["dep:vorbis_rs"]
[dependencies]
base64 = "0.22.1"
@@ -28,7 +29,7 @@ roxmltree = "0.21.1"
serde_json = "1.0.143"
tar = "0.4.46"
tokio = { version = "1.47.1", features = ["macros", "net", "rt", "sync", "time"] }
vorbis_rs = "0.5.5"
vorbis_rs = { version = "0.5.6", optional = true }
[dev-dependencies]
tokio = { version = "1.47.1", features = ["macros", "net", "rt-multi-thread", "sync", "test-util", "time"] }

View File

@@ -155,20 +155,14 @@ raw_asset!(AssetScriptBinary, AssetType::LSLBytecode);
raw_asset!(AssetSound, AssetType::Sound);
impl AssetSound {
#[cfg(feature = "vorbis")]
pub fn pcm_to_ogg(
pcm_data: Vec<u8>,
sample_rate: i32,
channels: i32,
bits_per_sample: Option<i32>,
) -> Result<Vec<u8>, Error> {
validate_bytes(&pcm_data)?;
if pcm_data.is_empty()
|| sample_rate <= 0
|| !matches!(channels, 1 | 2)
|| !matches!(bits_per_sample.unwrap_or(16), 8 | 16)
{
return Err(Error::Argument);
}
validate_pcm(&pcm_data, sample_rate, channels, bits_per_sample)?;
let bits = bits_per_sample.unwrap_or(16);
let bytes_per_sample = usize::try_from(bits / 8).map_err(|_| Error::Argument)?;
let channels = usize::try_from(channels).map_err(|_| Error::Argument)?;
@@ -215,6 +209,43 @@ impl AssetSound {
validate_bytes(&ogg_data)?;
Ok(ogg_data)
}
#[cfg(not(feature = "vorbis"))]
pub fn pcm_to_ogg(
pcm_data: Vec<u8>,
sample_rate: i32,
channels: i32,
bits_per_sample: Option<i32>,
) -> Result<Vec<u8>, Error> {
validate_pcm(&pcm_data, sample_rate, channels, bits_per_sample)?;
Err(Error::InvalidOperation)
}
}
fn validate_pcm(
pcm_data: &[u8],
sample_rate: i32,
channels: i32,
bits_per_sample: Option<i32>,
) -> Result<(), Error> {
validate_bytes(pcm_data)?;
if pcm_data.is_empty()
|| sample_rate <= 0
|| !matches!(channels, 1 | 2)
|| !matches!(bits_per_sample.unwrap_or(16), 8 | 16)
{
return Err(Error::Argument);
}
let bytes_per_sample =
usize::try_from(bits_per_sample.unwrap_or(16) / 8).map_err(|_| Error::Argument)?;
let channels = usize::try_from(channels).map_err(|_| Error::Argument)?;
let frame_size = bytes_per_sample
.checked_mul(channels)
.ok_or(Error::Argument)?;
if !pcm_data.len().is_multiple_of(frame_size) {
return Err(Error::Argument);
}
Ok(())
}
#[derive(Clone, Debug)]

View File

@@ -1,7 +1,10 @@
use crate::assets::{AssetMesh, AssetMutable, AssetSound, AssetTexture};
#[cfg(feature = "jpeg2000")]
use crate::assets::AssetTexture;
use crate::assets::{AssetMesh, AssetMutable, AssetSound};
use crate::{
AssetCache, AssetCacheComputeAssetCacheFilenameDelegate, Error, GridClient, ImageCodec,
};
#[cfg(feature = "jpeg2000")]
use libremetaverse_imaging::{ManagedImage, ManagedImageImageChannels};
use libremetaverse_types::{AssetType, UUID};
use std::fs;
@@ -33,10 +36,28 @@ fn asset_models_retain_type_and_reject_malformed_meshes() {
}
#[test]
fn sound_and_texture_codecs_produce_real_valid_payloads() {
#[cfg(feature = "vorbis")]
fn sound_codec_produces_real_valid_payload() {
let ogg = AssetSound::pcm_to_ogg(vec![0_u8; 256 * 2], 44_100, 1, Some(16)).unwrap();
assert!(ogg.starts_with(b"OggS"));
}
#[test]
#[cfg(not(feature = "vorbis"))]
fn sound_codec_is_explicitly_feature_gated() {
assert_eq!(
AssetSound::pcm_to_ogg(vec![0_u8; 256 * 2], 44_100, 1, Some(16)),
Err(Error::InvalidOperation)
);
assert_eq!(
AssetSound::pcm_to_ogg(Vec::new(), 44_100, 1, Some(16)),
Err(Error::Argument)
);
}
#[test]
#[cfg(feature = "jpeg2000")]
fn texture_codec_produces_real_valid_payload() {
let mut image = ManagedImage::new(2, 2, ManagedImageImageChannels::COLOR).unwrap();
image.red.fill(255);
let texture = AssetTexture::new_with_managed_image(image).unwrap();

View File

@@ -2913,12 +2913,10 @@ mod tests {
block.name = b"Native object".to_vec();
block.description = b"decoded".to_vec();
packet.object_data = vec![block];
let wire = transport_wire(&packet.to_bytes_with_method().expect("wire packet"));
manager
.inner
.handle_object_properties(
&packet.to_bytes_with_method().expect("wire packet"),
simulator.clone(),
)
.handle_object_properties(&wire, simulator.clone())
.expect("properties reply");
assert!(observed.load(Ordering::Acquire));
assert_eq!(

View File

@@ -104,9 +104,9 @@ fn generated_constructors_initialize_blocks_headers_and_sizing_metadata() {
let ack = PacketAckPacket::new_with_constructor().unwrap();
assert!(ack.packets.is_empty());
// The source generator includes one variable-block metadata byte in the
// base and one in the block contribution; preserve that exact Length API.
assert_eq!(ack.length(), 12);
// The low-frequency header contributes ten bytes and the empty variable
// block contributes its single count byte.
assert_eq!(ack.length(), 11);
assert!(!ack.uses_buffer_pooling());
let circuit = UseCircuitCodePacket::new_with_constructor().unwrap();