Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

273
vendor/ktx2/src/enums.rs vendored Normal file
View File

@@ -0,0 +1,273 @@
use core::{fmt, num::NonZeroU32};
macro_rules! pseudo_enum {
($(#[$attr:meta])* $name:ident { $($case:ident = $value:literal,)* }) => {
$(#[$attr])*
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct $name(pub NonZeroU32);
#[allow(non_upper_case_globals)]
impl $name {
pub fn new(x: u32) -> Option<Self> {
Some(Self(NonZeroU32::new(x)?))
}
$(
pub const $case: Self = Self(unsafe { NonZeroU32::new_unchecked($value) });
)*
}
impl fmt::Debug for $name {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let name = match self.0.get() {
$($value => Some(stringify!($case)),)*
_ => None,
};
match name {
Some(name) => f.pad(name),
None => write!(f, concat!(stringify!($name), "({})"), self.0.get()),
}
}
}
};
}
pseudo_enum! {
/// Known texture formats
Format {
R4G4_UNORM_PACK8 = 1,
R4G4B4A4_UNORM_PACK16 = 2,
B4G4R4A4_UNORM_PACK16 = 3,
R5G6B5_UNORM_PACK16 = 4,
B5G6R5_UNORM_PACK16 = 5,
R5G5B5A1_UNORM_PACK16 = 6,
B5G5R5A1_UNORM_PACK16 = 7,
A1R5G5B5_UNORM_PACK16 = 8,
R8_UNORM = 9,
R8_SNORM = 10,
R8_UINT = 13,
R8_SINT = 14,
R8_SRGB = 15,
R8G8_UNORM = 16,
R8G8_SNORM = 17,
R8G8_UINT = 20,
R8G8_SINT = 21,
R8G8_SRGB = 22,
R8G8B8_UNORM = 23,
R8G8B8_SNORM = 24,
R8G8B8_UINT = 27,
R8G8B8_SINT = 28,
R8G8B8_SRGB = 29,
B8G8R8_UNORM = 30,
B8G8R8_SNORM = 31,
B8G8R8_UINT = 34,
B8G8R8_SINT = 35,
B8G8R8_SRGB = 36,
R8G8B8A8_UNORM = 37,
R8G8B8A8_SNORM = 38,
R8G8B8A8_UINT = 41,
R8G8B8A8_SINT = 42,
R8G8B8A8_SRGB = 43,
B8G8R8A8_UNORM = 44,
B8G8R8A8_SNORM = 45,
B8G8R8A8_UINT = 48,
B8G8R8A8_SINT = 49,
B8G8R8A8_SRGB = 50,
A2R10G10B10_UNORM_PACK32 = 58,
A2R10G10B10_SNORM_PACK32 = 59,
A2R10G10B10_UINT_PACK32 = 62,
A2R10G10B10_SINT_PACK32 = 63,
A2B10G10R10_UNORM_PACK32 = 64,
A2B10G10R10_SNORM_PACK32 = 65,
A2B10G10R10_UINT_PACK32 = 68,
A2B10G10R10_SINT_PACK32 = 69,
R16_UNORM = 70,
R16_SNORM = 71,
R16_UINT = 74,
R16_SINT = 75,
R16_SFLOAT = 76,
R16G16_UNORM = 77,
R16G16_SNORM = 78,
R16G16_UINT = 81,
R16G16_SINT = 82,
R16G16_SFLOAT = 83,
R16G16B16_UNORM = 84,
R16G16B16_SNORM = 85,
R16G16B16_UINT = 88,
R16G16B16_SINT = 89,
R16G16B16_SFLOAT = 90,
R16G16B16A16_UNORM = 91,
R16G16B16A16_SNORM = 92,
R16G16B16A16_UINT = 95,
R16G16B16A16_SINT = 96,
R16G16B16A16_SFLOAT = 97,
R32_UINT = 98,
R32_SINT = 99,
R32_SFLOAT = 100,
R32G32_UINT = 101,
R32G32_SINT = 102,
R32G32_SFLOAT = 103,
R32G32B32_UINT = 104,
R32G32B32_SINT = 105,
R32G32B32_SFLOAT = 106,
R32G32B32A32_UINT = 107,
R32G32B32A32_SINT = 108,
R32G32B32A32_SFLOAT = 109,
R64_UINT = 110,
R64_SINT = 111,
R64_SFLOAT = 112,
R64G64_UINT = 113,
R64G64_SINT = 114,
R64G64_SFLOAT = 115,
R64G64B64_UINT = 116,
R64G64B64_SINT = 117,
R64G64B64_SFLOAT = 118,
R64G64B64A64_UINT = 119,
R64G64B64A64_SINT = 120,
R64G64B64A64_SFLOAT = 121,
B10G11R11_UFLOAT_PACK32 = 122,
E5B9G9R9_UFLOAT_PACK32 = 123,
D16_UNORM = 124,
X8_D24_UNORM_PACK32 = 125,
D32_SFLOAT = 126,
S8_UINT = 127,
D16_UNORM_S8_UINT = 128,
D24_UNORM_S8_UINT = 129,
D32_SFLOAT_S8_UINT = 130,
BC1_RGB_UNORM_BLOCK = 131,
BC1_RGB_SRGB_BLOCK = 132,
BC1_RGBA_UNORM_BLOCK = 133,
BC1_RGBA_SRGB_BLOCK = 134,
BC2_UNORM_BLOCK = 135,
BC2_SRGB_BLOCK = 136,
BC3_UNORM_BLOCK = 137,
BC3_SRGB_BLOCK = 138,
BC4_UNORM_BLOCK = 139,
BC4_SNORM_BLOCK = 140,
BC5_UNORM_BLOCK = 141,
BC5_SNORM_BLOCK = 142,
BC6H_UFLOAT_BLOCK = 143,
BC6H_SFLOAT_BLOCK = 144,
BC7_UNORM_BLOCK = 145,
BC7_SRGB_BLOCK = 146,
ETC2_R8G8B8_UNORM_BLOCK = 147,
ETC2_R8G8B8_SRGB_BLOCK = 148,
ETC2_R8G8B8A1_UNORM_BLOCK = 149,
ETC2_R8G8B8A1_SRGB_BLOCK = 150,
ETC2_R8G8B8A8_UNORM_BLOCK = 151,
ETC2_R8G8B8A8_SRGB_BLOCK = 152,
EAC_R11_UNORM_BLOCK = 153,
EAC_R11_SNORM_BLOCK = 154,
EAC_R11G11_UNORM_BLOCK = 155,
EAC_R11G11_SNORM_BLOCK = 156,
ASTC_4x4_UNORM_BLOCK = 157,
ASTC_4x4_SRGB_BLOCK = 158,
ASTC_5x4_UNORM_BLOCK = 159,
ASTC_5x4_SRGB_BLOCK = 160,
ASTC_5x5_UNORM_BLOCK = 161,
ASTC_5x5_SRGB_BLOCK = 162,
ASTC_6x5_UNORM_BLOCK = 163,
ASTC_6x5_SRGB_BLOCK = 164,
ASTC_6x6_UNORM_BLOCK = 165,
ASTC_6x6_SRGB_BLOCK = 166,
ASTC_8x5_UNORM_BLOCK = 167,
ASTC_8x5_SRGB_BLOCK = 168,
ASTC_8x6_UNORM_BLOCK = 169,
ASTC_8x6_SRGB_BLOCK = 170,
ASTC_8x8_UNORM_BLOCK = 171,
ASTC_8x8_SRGB_BLOCK = 172,
ASTC_10x5_UNORM_BLOCK = 173,
ASTC_10x5_SRGB_BLOCK = 174,
ASTC_10x6_UNORM_BLOCK = 175,
ASTC_10x6_SRGB_BLOCK = 176,
ASTC_10x8_UNORM_BLOCK = 177,
ASTC_10x8_SRGB_BLOCK = 178,
ASTC_10x10_UNORM_BLOCK = 179,
ASTC_10x10_SRGB_BLOCK = 180,
ASTC_12x10_UNORM_BLOCK = 181,
ASTC_12x10_SRGB_BLOCK = 182,
ASTC_12x12_UNORM_BLOCK = 183,
ASTC_12x12_SRGB_BLOCK = 184,
}
}
pseudo_enum! {
/// Known supercompression schemes
SupercompressionScheme {
BasisLZ = 1,
Zstandard = 2,
ZLIB = 3,
}
}
pseudo_enum! {
ColorModel {
RGBSDA = 1,
YUVSDA = 2,
YIQSDA = 3,
LabSDA = 4,
CMYKA = 5,
XYZW = 6,
HSVAAng = 7,
HSLAAng = 8,
HSVAHex = 9,
HSLAHex = 10,
YCgCoA = 11,
YcCbcCrc = 12,
ICtCp = 13,
CIEXYZ = 14,
CIEXYY = 15,
BC1A = 128,
BC2 = 129,
BC3 = 130,
BC4 = 131,
BC5 = 132,
BC6H = 133,
BC7 = 134,
ETC1 = 160,
ETC2 = 161,
ASTC = 162,
ETC1S = 163,
PVRTC = 164,
PVRTC2 = 165,
UASTC = 166,
}
}
pseudo_enum! {
ColorPrimaries {
BT709 = 1,
BT601EBU = 2,
BT601SMPTE = 3,
BT2020 = 4,
CIEXYZ = 5,
ACES = 6,
ACESCC = 7,
NTSC1953 = 8,
PAL525 = 9,
DISPLAYP3 = 10,
AdobeRGB = 11,
}
}
pseudo_enum! {
TransferFunction {
Linear = 1,
SRGB = 2,
ITU = 3,
NTSC = 4,
SLOG = 5,
SLOG2 = 6,
BT1886 = 7,
HLGOETF = 8,
HLGEOTF = 9,
PQEOTF = 10,
PQOETF = 11,
DCIP3 = 12,
PALOETF = 13,
PAL625EOTF = 14,
ST240 = 15,
ACESCC = 16,
ACESCCT = 17,
AdobeRGB = 18,
}
}

31
vendor/ktx2/src/error.rs vendored Normal file
View File

@@ -0,0 +1,31 @@
use core::fmt;
#[cfg(feature = "std")]
use std::error::Error;
/// Error, that happend when data doesn't satisfy expected parameters.
#[derive(Debug)]
#[non_exhaustive]
pub enum ParseError {
/// Unexpected magic numbers
BadMagic,
/// Zero pixel width
ZeroWidth,
/// Zero face count
ZeroFaceCount,
/// Unexpected end of buffer
UnexpectedEnd,
}
#[cfg(feature = "std")]
impl Error for ParseError {}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self {
ParseError::BadMagic => f.pad("unexpected magic numbers"),
ParseError::ZeroWidth => f.pad("zero pixel width"),
ParseError::ZeroFaceCount => f.pad("zero face count"),
ParseError::UnexpectedEnd => f.pad("unexpected end of buffer"),
}
}
}

426
vendor/ktx2/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,426 @@
//! Parser for the [ktx2](https://github.khronos.org/KTX-Specification/) texture container format.
//!
//! ## Features
//! - [x] Async reading
//! - [x] Parsing
//! - [x] Validating
//! - [x] [Data format description](https://github.khronos.org/KTX-Specification/#_data_format_descriptor)
//! - [ ] [Key/value data](https://github.khronos.org/KTX-Specification/#_keyvalue_data)
//
//! ## Example
//! ```rust
//! // Crate instance of reader. This validates the header
//! # let file = include_bytes!("../data/test_tex.ktx2");
//! let mut reader = ktx2::Reader::new(file).expect("Can't create reader"); // Crate instance of reader.
//!
//! // Get general texture information.
//! let header = reader.header();
//!
//! // Read iterator over slices of each mipmap level.
//! let levels = reader.levels().collect::<Vec<_>>();
//! # let _ = (header, levels);
//! ```
#![no_std]
#[cfg(feature = "std")]
extern crate std;
mod enums;
mod error;
pub use crate::{
enums::{ColorModel, ColorPrimaries, Format, SupercompressionScheme, TransferFunction},
error::ParseError,
};
use core::convert::TryInto;
/// Decodes KTX2 texture data
pub struct Reader<Data: AsRef<[u8]>> {
input: Data,
}
impl<Data: AsRef<[u8]>> Reader<Data> {
/// Decode KTX2 data from `input`
pub fn new(input: Data) -> Result<Self, ParseError> {
if input.as_ref().len() < Header::LENGTH {
return Err(ParseError::UnexpectedEnd);
}
if !input.as_ref().starts_with(&KTX2_MAGIC) {
return Err(ParseError::BadMagic);
}
let header_data = input.as_ref()[0..Header::LENGTH].try_into().unwrap();
let header = Header::from_bytes(header_data);
header.validate()?;
if (header.dfd_byte_offset + header.dfd_byte_length) as usize >= input.as_ref().len() {
return Err(ParseError::UnexpectedEnd);
}
let result = Self { input };
result.level_index()?; // Check index integrity
// Check level data integrity
let trailing = result.level_index().unwrap().max_by_key(|l| l.offset).unwrap();
if trailing.offset + trailing.length_bytes > result.input.as_ref().len() as u64 {
return Err(ParseError::UnexpectedEnd);
}
Ok(result)
}
fn level_index(&self) -> ParseResult<impl ExactSizeIterator<Item = LevelIndex> + '_> {
let level_count = self.header().level_count.max(1) as usize;
let level_index_end_byte = Header::LENGTH + level_count * LevelIndex::LENGTH;
let level_index_bytes = self
.input
.as_ref()
.get(Header::LENGTH..level_index_end_byte)
.ok_or(ParseError::UnexpectedEnd)?;
Ok(level_index_bytes
.chunks_exact(LevelIndex::LENGTH)
.map(LevelIndex::from_bytes))
}
/// Access underlying raw bytes
pub fn data(&self) -> &[u8] {
self.input.as_ref()
}
/// Container-level metadata
pub fn header(&self) -> Header {
let bytes = self.input.as_ref()[0..Header::LENGTH].try_into().unwrap();
Header::from_bytes(bytes)
}
/// Iterator over the texture's mip levels
pub fn levels(&self) -> impl ExactSizeIterator<Item = &[u8]> + '_ {
self.level_index()
.unwrap()
.map(move |level| &self.input.as_ref()[level.offset as usize..(level.offset + level.length_bytes) as usize])
}
pub fn supercompression_global_data(&self) -> &[u8] {
let header = self.header();
let start = header.sgd_byte_offset as usize;
let end = (header.sgd_byte_offset + header.sgd_byte_length) as usize;
&self.input.as_ref()[start..end]
}
pub fn data_format_descriptors(&self) -> impl Iterator<Item = DataFormatDescriptor> {
let header = self.header();
let start = header.dfd_byte_offset as usize;
let end = (header.dfd_byte_offset + header.dfd_byte_length) as usize;
DataFormatDescriptorIterator {
// start + 4 to skip the data format descriptors total length
data: &self.input.as_ref()[start + 4..end],
}
}
}
struct DataFormatDescriptorIterator<'data> {
data: &'data [u8],
}
impl<'data> Iterator for DataFormatDescriptorIterator<'data> {
type Item = DataFormatDescriptor<'data>;
fn next(&mut self) -> Option<Self::Item> {
if self.data.len() < DataFormatDescriptorHeader::LENGTH {
return None;
}
DataFormatDescriptorHeader::parse(&self.data[..DataFormatDescriptorHeader::LENGTH]).map_or(
None,
|(header, descriptor_block_size)| {
if descriptor_block_size == 0 || self.data.len() < descriptor_block_size {
return None;
}
let data = &self.data[DataFormatDescriptorHeader::LENGTH..descriptor_block_size];
self.data = &self.data[descriptor_block_size..];
Some(DataFormatDescriptor { header, data })
},
)
}
}
/// Identifier, expected in start of input texture data.
const KTX2_MAGIC: [u8; 12] = [0xAB, 0x4B, 0x54, 0x58, 0x20, 0x32, 0x30, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A];
/// Result of parsing data operation.
type ParseResult<T> = Result<T, ParseError>;
/// Container-level metadata
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct Header {
pub format: Option<Format>,
pub type_size: u32,
pub pixel_width: u32,
pub pixel_height: u32,
pub pixel_depth: u32,
pub layer_count: u32,
pub face_count: u32,
pub level_count: u32,
pub supercompression_scheme: Option<SupercompressionScheme>,
dfd_byte_offset: u32,
dfd_byte_length: u32,
kvd_byte_offset: u32,
kvd_byte_length: u32,
sgd_byte_offset: u64,
sgd_byte_length: u64,
}
impl Header {
const LENGTH: usize = 80;
fn from_bytes(data: &[u8; Self::LENGTH]) -> Self {
Self {
format: Format::new(u32::from_le_bytes(data[12..16].try_into().unwrap())),
type_size: u32::from_le_bytes(data[16..20].try_into().unwrap()),
pixel_width: u32::from_le_bytes(data[20..24].try_into().unwrap()),
pixel_height: u32::from_le_bytes(data[24..28].try_into().unwrap()),
pixel_depth: u32::from_le_bytes(data[28..32].try_into().unwrap()),
layer_count: u32::from_le_bytes(data[32..36].try_into().unwrap()),
face_count: u32::from_le_bytes(data[36..40].try_into().unwrap()),
level_count: u32::from_le_bytes(data[40..44].try_into().unwrap()),
supercompression_scheme: SupercompressionScheme::new(u32::from_le_bytes(data[44..48].try_into().unwrap())),
dfd_byte_offset: u32::from_le_bytes(data[48..52].try_into().unwrap()),
dfd_byte_length: u32::from_le_bytes(data[52..56].try_into().unwrap()),
kvd_byte_offset: u32::from_le_bytes(data[56..60].try_into().unwrap()),
kvd_byte_length: u32::from_le_bytes(data[60..64].try_into().unwrap()),
sgd_byte_offset: u64::from_le_bytes(data[64..72].try_into().unwrap()),
sgd_byte_length: u64::from_le_bytes(data[72..80].try_into().unwrap()),
}
}
fn validate(&self) -> ParseResult<()> {
if self.pixel_width == 0 {
return Err(ParseError::ZeroWidth);
}
if self.face_count == 0 {
return Err(ParseError::ZeroFaceCount);
}
Ok(())
}
}
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
struct LevelIndex {
offset: u64,
length_bytes: u64,
uncompressed_length_bytes: u64,
}
impl LevelIndex {
const LENGTH: usize = 24;
pub fn from_bytes(data: &[u8]) -> Self {
Self {
offset: u64::from_le_bytes(data[0..8].try_into().unwrap()),
length_bytes: u64::from_le_bytes(data[8..16].try_into().unwrap()),
uncompressed_length_bytes: u64::from_le_bytes(data[16..24].try_into().unwrap()),
}
}
}
bitflags::bitflags! {
#[repr(transparent)]
pub struct ChannelTypeQualifiers: u32 {
const LINEAR = (1 << 0);
const EXPONENT = (1 << 1);
const SIGNED = (1 << 2);
const FLOAT = (1 << 3);
}
}
bitflags::bitflags! {
#[derive(Default)]
#[repr(transparent)]
pub struct DataFormatFlags: u32 {
const STRAIGHT_ALPHA = 0;
const ALPHA_PREMULTIPLIED = (1 << 0);
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct DataFormatDescriptorHeader {
pub vendor_id: u32, //: 17;
pub descriptor_type: u32, //: 15;
pub version_number: u32, //: 16;
}
impl DataFormatDescriptorHeader {
const LENGTH: usize = 8;
pub const BASIC: Self = Self {
vendor_id: 0,
descriptor_type: 0,
version_number: 2,
};
fn parse(bytes: &[u8]) -> Result<(Self, usize), ParseError> {
let mut offset = 0;
let v = bytes_to_u32(bytes, &mut offset)?;
let vendor_id = shift_and_mask_lower(0, 17, v);
let descriptor_type = shift_and_mask_lower(17, 15, v);
let v = bytes_to_u32(bytes, &mut offset)?;
let version_number = shift_and_mask_lower(0, 16, v);
let descriptor_block_size = shift_and_mask_lower(16, 16, v);
Ok((
Self {
vendor_id,
descriptor_type,
version_number,
},
descriptor_block_size as usize,
))
}
}
pub struct DataFormatDescriptor<'data> {
pub header: DataFormatDescriptorHeader,
pub data: &'data [u8],
}
pub struct BasicDataFormatDescriptor<'data> {
/// None means Unspecified or is an otherwise unknown value
pub color_model: Option<ColorModel>, //: 8;
/// None means Unspecified or is an otherwise unknown value
pub color_primaries: Option<ColorPrimaries>, //: 8;
/// None means Unspecified or is an otherwise unknown value
pub transfer_function: Option<TransferFunction>, //: 8;
pub flags: DataFormatFlags, //: 8;
pub texel_block_dimensions: [u32; 4], //: 8 x 4;
pub bytes_planes: [u32; 8], //: 8 x 8;
sample_data: &'data [u8],
}
impl<'data> BasicDataFormatDescriptor<'data> {
pub fn parse(bytes: &'data [u8]) -> Result<Self, ParseError> {
let mut offset = 0;
let v = bytes_to_u32(bytes, &mut offset)?;
let model = shift_and_mask_lower(0, 8, v);
let primaries = shift_and_mask_lower(8, 8, v);
let transfer = shift_and_mask_lower(16, 8, v);
let flags = shift_and_mask_lower(24, 8, v);
let v = bytes_to_u32(bytes, &mut offset)?;
let texel_block_dimensions = [
shift_and_mask_lower(0, 8, v) + 1,
shift_and_mask_lower(8, 8, v) + 1,
shift_and_mask_lower(16, 8, v) + 1,
shift_and_mask_lower(24, 8, v) + 1,
];
let v = bytes_to_u32(bytes, &mut offset)?;
let mut bytes_planes = [0u32; 8];
bytes_planes[0] = shift_and_mask_lower(0, 8, v);
bytes_planes[1] = shift_and_mask_lower(8, 8, v);
bytes_planes[2] = shift_and_mask_lower(16, 8, v);
bytes_planes[3] = shift_and_mask_lower(24, 8, v);
let v = bytes_to_u32(bytes, &mut offset)?;
bytes_planes[4] = shift_and_mask_lower(0, 8, v);
bytes_planes[5] = shift_and_mask_lower(8, 8, v);
bytes_planes[6] = shift_and_mask_lower(16, 8, v);
bytes_planes[7] = shift_and_mask_lower(24, 8, v);
Ok(Self {
color_model: ColorModel::new(model),
color_primaries: ColorPrimaries::new(primaries),
transfer_function: TransferFunction::new(transfer),
flags: DataFormatFlags::from_bits_truncate(flags),
texel_block_dimensions,
bytes_planes,
sample_data: &bytes[offset..],
})
}
pub fn sample_information(&self) -> impl Iterator<Item = SampleInformation> + 'data {
SampleInformationIterator { data: self.sample_data }
}
}
struct SampleInformationIterator<'data> {
data: &'data [u8],
}
impl<'data> Iterator for SampleInformationIterator<'data> {
type Item = SampleInformation;
fn next(&mut self) -> Option<Self::Item> {
if self.data.len() < SampleInformation::LENGTH {
return None;
}
SampleInformation::parse(&self.data[..SampleInformation::LENGTH]).map_or(None, |sample_information| {
self.data = &self.data[SampleInformation::LENGTH..];
Some(sample_information)
})
}
}
#[derive(Debug)]
pub struct SampleInformation {
pub bit_offset: u32, //: 16;
pub bit_length: u32, //: 8;
pub channel_type: u32, //: 4;
pub channel_type_qualifiers: ChannelTypeQualifiers, //: 4;
pub sample_positions: [u32; 4], //: 8 x 4;
pub lower: u32, //;
pub upper: u32, //;
}
impl SampleInformation {
const LENGTH: usize = 16;
fn parse(bytes: &[u8]) -> Result<Self, ParseError> {
let mut offset = 0;
let v = bytes_to_u32(bytes, &mut offset)?;
let bit_offset = shift_and_mask_lower(0, 16, v);
let bit_length = shift_and_mask_lower(16, 8, v) + 1;
let channel_type = shift_and_mask_lower(24, 4, v);
let channel_type_qualifiers = ChannelTypeQualifiers::from_bits_truncate(shift_and_mask_lower(28, 4, v));
let v = bytes_to_u32(bytes, &mut offset)?;
let sample_positions = [
shift_and_mask_lower(0, 8, v),
shift_and_mask_lower(8, 8, v),
shift_and_mask_lower(16, 8, v),
shift_and_mask_lower(24, 8, v),
];
let lower = bytes_to_u32(bytes, &mut offset)?;
let upper = bytes_to_u32(bytes, &mut offset)?;
Ok(Self {
bit_offset,
bit_length,
channel_type,
channel_type_qualifiers,
sample_positions,
lower,
upper,
})
}
}
fn bytes_to_u32(bytes: &[u8], offset: &mut usize) -> Result<u32, ParseError> {
let v = u32::from_le_bytes(
bytes
.get(*offset..*offset + 4)
.ok_or(ParseError::UnexpectedEnd)?
.try_into()
.unwrap(),
);
*offset += 4;
Ok(v)
}
fn shift_and_mask_lower(shift: u32, mask: u32, value: u32) -> u32 {
(value >> shift) & ((1 << mask) - 1)
}