use core::num::NonZeroU32;
use ::buffa::{
DecodeError, DefaultInstance, Message, SizeCache,
bytes::{Buf, BufMut},
encoding::{Tag, WireType, encode_varint, skip_field_depth, varint_len},
types::{decode_uint32, encode_uint32, uint32_encoded_len},
};
use crate::{
color::{
ChromaCoord, ChromaLocation, ColorInfo, ColorMatrix, ColorPrimaries, ColorRange, ColorTransfer,
ContentLightLevel, DcpTargetGamut, HdrStaticMetadata, MasteringDisplay,
},
frame::{Dimensions, Rect, Rotation, SampleAspectRatio},
pixel_format::PixelFormat,
};
const VARINT: u8 = WireType::Varint as u8;
const LEN: u8 = WireType::LengthDelimited as u8;
macro_rules! impl_enum_message {
($ty:ty, $to:expr, $from:expr) => {
impl DefaultInstance for $ty {
fn default_instance() -> &'static Self {
static VALUE: buffa::__private::OnceBox<$ty> = buffa::__private::OnceBox::new();
VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(<$ty>::default()))
}
}
impl Message for $ty {
fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
if *self != <$ty>::default() {
let v: u32 = $to(self);
1 + uint32_encoded_len(v) as u32
} else {
0
}
}
fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl BufMut) {
if *self != <$ty>::default() {
let v: u32 = $to(self);
Tag::new(1, WireType::Varint).encode(buf);
encode_uint32(v, buf);
}
}
fn merge_field(
&mut self,
tag: Tag,
buf: &mut impl Buf,
depth: u32,
) -> Result<(), DecodeError> {
match tag.field_number() {
1 => {
if tag.wire_type() != WireType::Varint {
return Err(DecodeError::WireTypeMismatch {
field_number: 1,
expected: VARINT,
actual: tag.wire_type() as u8,
});
}
let v = decode_uint32(buf)?;
*self = $from(v);
}
_ => skip_field_depth(tag, buf, depth)?,
}
Ok(())
}
fn clear(&mut self) {
*self = <$ty>::default();
}
}
};
}
impl_enum_message!(
ColorMatrix,
|s: &ColorMatrix| s.to_u32(),
ColorMatrix::from_u32
);
impl_enum_message!(
ColorPrimaries,
|s: &ColorPrimaries| s.to_u32(),
ColorPrimaries::from_u32
);
impl_enum_message!(
ColorTransfer,
|s: &ColorTransfer| s.to_u32(),
ColorTransfer::from_u32
);
impl_enum_message!(
ColorRange,
|s: &ColorRange| s.to_u32(),
ColorRange::from_u32
);
impl_enum_message!(
ChromaLocation,
|s: &ChromaLocation| s.to_u32(),
ChromaLocation::from_u32
);
impl_enum_message!(
DcpTargetGamut,
|s: &DcpTargetGamut| s.to_u32(),
DcpTargetGamut::from_u32
);
impl_enum_message!(Rotation, |s: &Rotation| s.to_u32(), Rotation::from_u32);
impl_enum_message!(
PixelFormat,
|s: &PixelFormat| s.to_u32(),
PixelFormat::from_u32
);
impl DefaultInstance for Dimensions {
fn default_instance() -> &'static Self {
static VALUE: buffa::__private::OnceBox<Dimensions> = buffa::__private::OnceBox::new();
VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(Dimensions::default()))
}
}
impl Message for Dimensions {
fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
let mut size = 0u32;
if self.width() != 0 {
size += 1 + uint32_encoded_len(self.width()) as u32;
}
if self.height() != 0 {
size += 1 + uint32_encoded_len(self.height()) as u32;
}
size
}
fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl BufMut) {
if self.width() != 0 {
Tag::new(1, WireType::Varint).encode(buf);
encode_uint32(self.width(), buf);
}
if self.height() != 0 {
Tag::new(2, WireType::Varint).encode(buf);
encode_uint32(self.height(), buf);
}
}
fn merge_field(&mut self, tag: Tag, buf: &mut impl Buf, depth: u32) -> Result<(), DecodeError> {
match tag.field_number() {
1 => {
if tag.wire_type() != WireType::Varint {
return Err(DecodeError::WireTypeMismatch {
field_number: 1,
expected: VARINT,
actual: tag.wire_type() as u8,
});
}
let w = decode_uint32(buf)?;
self.set_width(w);
}
2 => {
if tag.wire_type() != WireType::Varint {
return Err(DecodeError::WireTypeMismatch {
field_number: 2,
expected: VARINT,
actual: tag.wire_type() as u8,
});
}
let h = decode_uint32(buf)?;
self.set_height(h);
}
_ => skip_field_depth(tag, buf, depth)?,
}
Ok(())
}
fn clear(&mut self) {
*self = Dimensions::default();
}
}
impl DefaultInstance for Rect {
fn default_instance() -> &'static Self {
static VALUE: buffa::__private::OnceBox<Rect> = buffa::__private::OnceBox::new();
VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(Rect::default()))
}
}
impl Message for Rect {
fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
let mut size = 0u32;
if self.x() != 0 {
size += 1 + uint32_encoded_len(self.x()) as u32;
}
if self.y() != 0 {
size += 1 + uint32_encoded_len(self.y()) as u32;
}
if self.width() != 0 {
size += 1 + uint32_encoded_len(self.width()) as u32;
}
if self.height() != 0 {
size += 1 + uint32_encoded_len(self.height()) as u32;
}
size
}
fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl BufMut) {
if self.x() != 0 {
Tag::new(1, WireType::Varint).encode(buf);
encode_uint32(self.x(), buf);
}
if self.y() != 0 {
Tag::new(2, WireType::Varint).encode(buf);
encode_uint32(self.y(), buf);
}
if self.width() != 0 {
Tag::new(3, WireType::Varint).encode(buf);
encode_uint32(self.width(), buf);
}
if self.height() != 0 {
Tag::new(4, WireType::Varint).encode(buf);
encode_uint32(self.height(), buf);
}
}
fn merge_field(&mut self, tag: Tag, buf: &mut impl Buf, depth: u32) -> Result<(), DecodeError> {
match tag.field_number() {
1 => {
if tag.wire_type() != WireType::Varint {
return Err(DecodeError::WireTypeMismatch {
field_number: 1,
expected: VARINT,
actual: tag.wire_type() as u8,
});
}
let v = decode_uint32(buf)?;
self.set_x(v);
}
2 => {
if tag.wire_type() != WireType::Varint {
return Err(DecodeError::WireTypeMismatch {
field_number: 2,
expected: VARINT,
actual: tag.wire_type() as u8,
});
}
let v = decode_uint32(buf)?;
self.set_y(v);
}
3 => {
if tag.wire_type() != WireType::Varint {
return Err(DecodeError::WireTypeMismatch {
field_number: 3,
expected: VARINT,
actual: tag.wire_type() as u8,
});
}
let v = decode_uint32(buf)?;
self.set_width(v);
}
4 => {
if tag.wire_type() != WireType::Varint {
return Err(DecodeError::WireTypeMismatch {
field_number: 4,
expected: VARINT,
actual: tag.wire_type() as u8,
});
}
let v = decode_uint32(buf)?;
self.set_height(v);
}
_ => skip_field_depth(tag, buf, depth)?,
}
Ok(())
}
fn clear(&mut self) {
*self = Rect::default();
}
}
impl DefaultInstance for SampleAspectRatio {
fn default_instance() -> &'static Self {
static VALUE: buffa::__private::OnceBox<SampleAspectRatio> = buffa::__private::OnceBox::new();
VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(SampleAspectRatio::default()))
}
}
impl Message for SampleAspectRatio {
fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
2 + uint32_encoded_len(self.num()) as u32 + uint32_encoded_len(self.den().get()) as u32
}
fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl BufMut) {
Tag::new(1, WireType::Varint).encode(buf);
encode_uint32(self.num(), buf);
Tag::new(2, WireType::Varint).encode(buf);
encode_uint32(self.den().get(), buf);
}
fn merge_field(&mut self, tag: Tag, buf: &mut impl Buf, depth: u32) -> Result<(), DecodeError> {
match tag.field_number() {
1 => {
if tag.wire_type() != WireType::Varint {
return Err(DecodeError::WireTypeMismatch {
field_number: 1,
expected: VARINT,
actual: tag.wire_type() as u8,
});
}
let num = decode_uint32(buf)?;
self.set_num(num);
}
2 => {
if tag.wire_type() != WireType::Varint {
return Err(DecodeError::WireTypeMismatch {
field_number: 2,
expected: VARINT,
actual: tag.wire_type() as u8,
});
}
let den = NonZeroU32::new(decode_uint32(buf)?).unwrap_or(NonZeroU32::MIN);
self.set_den(den);
}
_ => skip_field_depth(tag, buf, depth)?,
}
Ok(())
}
fn clear(&mut self) {
*self = SampleAspectRatio::default();
}
}
impl DefaultInstance for ColorInfo {
fn default_instance() -> &'static Self {
static VALUE: buffa::__private::OnceBox<ColorInfo> = buffa::__private::OnceBox::new();
VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(ColorInfo::UNSPECIFIED))
}
}
impl Message for ColorInfo {
fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
5 + uint32_encoded_len(self.primaries().to_u32()) as u32
+ uint32_encoded_len(self.transfer().to_u32()) as u32
+ uint32_encoded_len(self.matrix().to_u32()) as u32
+ uint32_encoded_len(self.range().to_u32()) as u32
+ uint32_encoded_len(self.chroma_location().to_u32()) as u32
}
fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl BufMut) {
Tag::new(1, WireType::Varint).encode(buf);
encode_uint32(self.primaries().to_u32(), buf);
Tag::new(2, WireType::Varint).encode(buf);
encode_uint32(self.transfer().to_u32(), buf);
Tag::new(3, WireType::Varint).encode(buf);
encode_uint32(self.matrix().to_u32(), buf);
Tag::new(4, WireType::Varint).encode(buf);
encode_uint32(self.range().to_u32(), buf);
Tag::new(5, WireType::Varint).encode(buf);
encode_uint32(self.chroma_location().to_u32(), buf);
}
fn merge_field(&mut self, tag: Tag, buf: &mut impl Buf, depth: u32) -> Result<(), DecodeError> {
match tag.field_number() {
1 => {
if tag.wire_type() != WireType::Varint {
return Err(DecodeError::WireTypeMismatch {
field_number: 1,
expected: VARINT,
actual: tag.wire_type() as u8,
});
}
let v = decode_uint32(buf)?;
self.set_primaries(ColorPrimaries::from_u32(v));
}
2 => {
if tag.wire_type() != WireType::Varint {
return Err(DecodeError::WireTypeMismatch {
field_number: 2,
expected: VARINT,
actual: tag.wire_type() as u8,
});
}
let v = decode_uint32(buf)?;
self.set_transfer(ColorTransfer::from_u32(v));
}
3 => {
if tag.wire_type() != WireType::Varint {
return Err(DecodeError::WireTypeMismatch {
field_number: 3,
expected: VARINT,
actual: tag.wire_type() as u8,
});
}
let v = decode_uint32(buf)?;
self.set_matrix(ColorMatrix::from_u32(v));
}
4 => {
if tag.wire_type() != WireType::Varint {
return Err(DecodeError::WireTypeMismatch {
field_number: 4,
expected: VARINT,
actual: tag.wire_type() as u8,
});
}
let v = decode_uint32(buf)?;
self.set_range(ColorRange::from_u32(v));
}
5 => {
if tag.wire_type() != WireType::Varint {
return Err(DecodeError::WireTypeMismatch {
field_number: 5,
expected: VARINT,
actual: tag.wire_type() as u8,
});
}
let v = decode_uint32(buf)?;
self.set_chroma_location(ChromaLocation::from_u32(v));
}
_ => skip_field_depth(tag, buf, depth)?,
}
Ok(())
}
fn clear(&mut self) {
*self = ColorInfo::UNSPECIFIED;
}
}
impl DefaultInstance for ContentLightLevel {
fn default_instance() -> &'static Self {
static VALUE: buffa::__private::OnceBox<ContentLightLevel> = buffa::__private::OnceBox::new();
VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(ContentLightLevel::default()))
}
}
impl Message for ContentLightLevel {
fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
let mut size = 0u32;
if self.max_cll() != 0 {
size += 1 + uint32_encoded_len(self.max_cll()) as u32;
}
if self.max_fall() != 0 {
size += 1 + uint32_encoded_len(self.max_fall()) as u32;
}
size
}
fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl BufMut) {
if self.max_cll() != 0 {
Tag::new(1, WireType::Varint).encode(buf);
encode_uint32(self.max_cll(), buf);
}
if self.max_fall() != 0 {
Tag::new(2, WireType::Varint).encode(buf);
encode_uint32(self.max_fall(), buf);
}
}
fn merge_field(&mut self, tag: Tag, buf: &mut impl Buf, depth: u32) -> Result<(), DecodeError> {
match tag.field_number() {
1 => {
if tag.wire_type() != WireType::Varint {
return Err(DecodeError::WireTypeMismatch {
field_number: 1,
expected: VARINT,
actual: tag.wire_type() as u8,
});
}
let v = decode_uint32(buf)?;
self.set_max_cll(v);
}
2 => {
if tag.wire_type() != WireType::Varint {
return Err(DecodeError::WireTypeMismatch {
field_number: 2,
expected: VARINT,
actual: tag.wire_type() as u8,
});
}
let v = decode_uint32(buf)?;
self.set_max_fall(v);
}
_ => skip_field_depth(tag, buf, depth)?,
}
Ok(())
}
fn clear(&mut self) {
*self = ContentLightLevel::default();
}
}
impl DefaultInstance for ChromaCoord {
fn default_instance() -> &'static Self {
static VALUE: buffa::__private::OnceBox<ChromaCoord> = buffa::__private::OnceBox::new();
VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(ChromaCoord::default()))
}
}
impl Message for ChromaCoord {
fn compute_size(&self, _cache: &mut SizeCache) -> u32 {
let mut size = 0u32;
if self.x() != 0 {
size += 1 + uint32_encoded_len(self.x()) as u32;
}
if self.y() != 0 {
size += 1 + uint32_encoded_len(self.y()) as u32;
}
size
}
fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl BufMut) {
if self.x() != 0 {
Tag::new(1, WireType::Varint).encode(buf);
encode_uint32(self.x(), buf);
}
if self.y() != 0 {
Tag::new(2, WireType::Varint).encode(buf);
encode_uint32(self.y(), buf);
}
}
fn merge_field(&mut self, tag: Tag, buf: &mut impl Buf, depth: u32) -> Result<(), DecodeError> {
match tag.field_number() {
1 => {
if tag.wire_type() != WireType::Varint {
return Err(DecodeError::WireTypeMismatch {
field_number: 1,
expected: VARINT,
actual: tag.wire_type() as u8,
});
}
self.set_x(decode_uint32(buf)?);
}
2 => {
if tag.wire_type() != WireType::Varint {
return Err(DecodeError::WireTypeMismatch {
field_number: 2,
expected: VARINT,
actual: tag.wire_type() as u8,
});
}
self.set_y(decode_uint32(buf)?);
}
_ => skip_field_depth(tag, buf, depth)?,
}
Ok(())
}
fn clear(&mut self) {
*self = ChromaCoord::default();
}
}
impl DefaultInstance for MasteringDisplay {
fn default_instance() -> &'static Self {
static VALUE: buffa::__private::OnceBox<MasteringDisplay> = buffa::__private::OnceBox::new();
VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(MasteringDisplay::default()))
}
}
impl Message for MasteringDisplay {
fn compute_size(&self, cache: &mut SizeCache) -> u32 {
let mut size = 0u32;
let primaries = self.display_primaries();
for cc in &primaries {
let slot = cache.reserve();
let inner = cc.compute_size(cache);
cache.set(slot, inner);
size += 1 + varint_len(inner as u64) as u32 + inner;
}
{
let slot = cache.reserve();
let inner = self.white_point().compute_size(cache);
cache.set(slot, inner);
size += 1 + varint_len(inner as u64) as u32 + inner;
}
if self.max_luminance() != 0 {
size += 1 + uint32_encoded_len(self.max_luminance()) as u32;
}
if self.min_luminance() != 0 {
size += 1 + uint32_encoded_len(self.min_luminance()) as u32;
}
size
}
fn write_to(&self, cache: &mut SizeCache, buf: &mut impl BufMut) {
let primaries = self.display_primaries();
for (i, cc) in primaries.iter().enumerate() {
Tag::new(1 + i as u32, WireType::LengthDelimited).encode(buf);
encode_varint(cache.consume_next() as u64, buf);
cc.write_to(cache, buf);
}
Tag::new(4, WireType::LengthDelimited).encode(buf);
encode_varint(cache.consume_next() as u64, buf);
self.white_point().write_to(cache, buf);
if self.max_luminance() != 0 {
Tag::new(5, WireType::Varint).encode(buf);
encode_uint32(self.max_luminance(), buf);
}
if self.min_luminance() != 0 {
Tag::new(6, WireType::Varint).encode(buf);
encode_uint32(self.min_luminance(), buf);
}
}
fn merge_field(&mut self, tag: Tag, buf: &mut impl Buf, depth: u32) -> Result<(), DecodeError> {
match tag.field_number() {
n @ 1..=3 => {
if tag.wire_type() != WireType::LengthDelimited {
return Err(DecodeError::WireTypeMismatch {
field_number: n,
expected: LEN,
actual: tag.wire_type() as u8,
});
}
let mut primaries = self.display_primaries();
let mut cc = primaries[(n - 1) as usize];
buffa::Message::merge_length_delimited(&mut cc, buf, depth)?;
primaries[(n - 1) as usize] = cc;
self.set_display_primaries(primaries);
}
4 => {
if tag.wire_type() != WireType::LengthDelimited {
return Err(DecodeError::WireTypeMismatch {
field_number: 4,
expected: LEN,
actual: tag.wire_type() as u8,
});
}
let mut wp = self.white_point();
buffa::Message::merge_length_delimited(&mut wp, buf, depth)?;
self.set_white_point(wp);
}
5 => {
if tag.wire_type() != WireType::Varint {
return Err(DecodeError::WireTypeMismatch {
field_number: 5,
expected: VARINT,
actual: tag.wire_type() as u8,
});
}
let v = decode_uint32(buf)?;
self.set_max_luminance(v);
}
6 => {
if tag.wire_type() != WireType::Varint {
return Err(DecodeError::WireTypeMismatch {
field_number: 6,
expected: VARINT,
actual: tag.wire_type() as u8,
});
}
let v = decode_uint32(buf)?;
self.set_min_luminance(v);
}
_ => skip_field_depth(tag, buf, depth)?,
}
Ok(())
}
fn clear(&mut self) {
*self = MasteringDisplay::default();
}
}
impl DefaultInstance for HdrStaticMetadata {
fn default_instance() -> &'static Self {
static VALUE: buffa::__private::OnceBox<HdrStaticMetadata> = buffa::__private::OnceBox::new();
VALUE.get_or_init(|| buffa::alloc::boxed::Box::new(HdrStaticMetadata::default()))
}
}
impl Message for HdrStaticMetadata {
fn compute_size(&self, cache: &mut SizeCache) -> u32 {
let mut size = 0u32;
if let Some(md) = self.mastering() {
let slot = cache.reserve();
let inner = md.compute_size(cache);
cache.set(slot, inner);
size += 1 + varint_len(inner as u64) as u32 + inner;
}
if let Some(cll) = self.content_light() {
let slot = cache.reserve();
let inner = cll.compute_size(cache);
cache.set(slot, inner);
size += 1 + varint_len(inner as u64) as u32 + inner;
}
size
}
fn write_to(&self, cache: &mut SizeCache, buf: &mut impl BufMut) {
if let Some(md) = self.mastering() {
Tag::new(1, WireType::LengthDelimited).encode(buf);
encode_varint(cache.consume_next() as u64, buf);
md.write_to(cache, buf);
}
if let Some(cll) = self.content_light() {
Tag::new(2, WireType::LengthDelimited).encode(buf);
encode_varint(cache.consume_next() as u64, buf);
cll.write_to(cache, buf);
}
}
fn merge_field(&mut self, tag: Tag, buf: &mut impl Buf, depth: u32) -> Result<(), DecodeError> {
match tag.field_number() {
1 => {
if tag.wire_type() != WireType::LengthDelimited {
return Err(DecodeError::WireTypeMismatch {
field_number: 1,
expected: LEN,
actual: tag.wire_type() as u8,
});
}
let mut md = self.mastering().unwrap_or_default();
buffa::Message::merge_length_delimited(&mut md, buf, depth)?;
self.set_mastering(Some(md));
}
2 => {
if tag.wire_type() != WireType::LengthDelimited {
return Err(DecodeError::WireTypeMismatch {
field_number: 2,
expected: LEN,
actual: tag.wire_type() as u8,
});
}
let mut cll = self.content_light().unwrap_or_default();
buffa::Message::merge_length_delimited(&mut cll, buf, depth)?;
self.set_content_light(Some(cll));
}
_ => skip_field_depth(tag, buf, depth)?,
}
Ok(())
}
fn clear(&mut self) {
*self = HdrStaticMetadata::default();
}
}
#[cfg(test)]
mod tests {
use super::*;
use ::buffa::alloc::vec::Vec;
fn nz(n: u32) -> NonZeroU32 {
NonZeroU32::new(n).unwrap()
}
fn cc(x: u32, y: u32) -> ChromaCoord {
ChromaCoord::new(x, y)
}
#[test]
fn enum_default_elides_to_zero_bytes() {
assert!(ColorMatrix::default().encode_to_vec().is_empty());
assert!(ColorPrimaries::default().encode_to_vec().is_empty());
assert!(ColorTransfer::default().encode_to_vec().is_empty());
assert!(ColorRange::default().encode_to_vec().is_empty());
assert!(ChromaLocation::default().encode_to_vec().is_empty());
assert!(DcpTargetGamut::default().encode_to_vec().is_empty());
assert_eq!(
ColorMatrix::decode_from_slice(&[]).unwrap(),
ColorMatrix::default()
);
assert_eq!(
ColorPrimaries::decode_from_slice(&[]).unwrap(),
ColorPrimaries::default()
);
assert_eq!(
ColorTransfer::decode_from_slice(&[]).unwrap(),
ColorTransfer::default()
);
assert_eq!(
ColorRange::decode_from_slice(&[]).unwrap(),
ColorRange::default()
);
assert_eq!(
ChromaLocation::decode_from_slice(&[]).unwrap(),
ChromaLocation::default()
);
assert_eq!(
DcpTargetGamut::decode_from_slice(&[]).unwrap(),
DcpTargetGamut::default()
);
}
#[test]
fn enum_non_default_code_zero_is_encoded_not_conflated() {
let b = ColorMatrix::Rgb.encode_to_vec();
assert!(!b.is_empty(), "non-default code-0 Rgb must be encoded");
let back = ColorMatrix::decode_from_slice(&b).unwrap();
assert_eq!(back, ColorMatrix::Rgb);
assert!(back.is_rgb());
assert_ne!(back, ColorMatrix::default());
}
#[test]
fn enum_unknown_round_trips_losslessly() {
macro_rules! rt_unknown {
($ty:ty) => {{
let v = <$ty>::Unknown(12_345);
let b = v.encode_to_vec();
assert_eq!(<$ty>::decode_from_slice(&b).unwrap(), v);
}};
}
rt_unknown!(ColorMatrix);
rt_unknown!(ColorPrimaries);
rt_unknown!(ColorTransfer);
rt_unknown!(ColorRange);
rt_unknown!(ChromaLocation);
rt_unknown!(DcpTargetGamut);
rt_unknown!(PixelFormat);
}
#[test]
fn enum_non_default_round_trips() {
let cm = ColorMatrix::Bt2020Ncl.encode_to_vec();
assert_eq!(
ColorMatrix::decode_from_slice(&cm).unwrap(),
ColorMatrix::Bt2020Ncl
);
let cp = ColorPrimaries::Bt2020.encode_to_vec();
assert_eq!(
ColorPrimaries::decode_from_slice(&cp).unwrap(),
ColorPrimaries::Bt2020
);
let ct = ColorTransfer::AribStdB67Hlg.encode_to_vec();
assert_eq!(
ColorTransfer::decode_from_slice(&ct).unwrap(),
ColorTransfer::AribStdB67Hlg
);
let dg = DcpTargetGamut::Rec2020.encode_to_vec();
assert_eq!(
DcpTargetGamut::decode_from_slice(&dg).unwrap(),
DcpTargetGamut::Rec2020
);
}
#[test]
fn dcp_target_gamut_unknown_canonicalization() {
for (misuse, named) in [
(DcpTargetGamut::Unknown(0), DcpTargetGamut::DciP3),
(DcpTargetGamut::Unknown(1), DcpTargetGamut::Rec709),
(DcpTargetGamut::Unknown(2), DcpTargetGamut::Rec2020),
] {
let b = misuse.encode_to_vec();
assert_eq!(DcpTargetGamut::decode_from_slice(&b).unwrap(), named);
}
for v in [3u32, 4242, u32::MAX] {
let u = DcpTargetGamut::Unknown(v);
let b = u.encode_to_vec();
assert_eq!(DcpTargetGamut::decode_from_slice(&b).unwrap(), u);
assert_eq!(DcpTargetGamut::from_u32(v), DcpTargetGamut::Unknown(v));
}
}
#[test]
fn color_matrix_bt601_domain_variant_round_trips() {
let b = ColorMatrix::Bt601.encode_to_vec();
assert!(!b.is_empty(), "non-default domain Bt601 must be encoded");
let back = ColorMatrix::decode_from_slice(&b).unwrap();
assert_eq!(back, ColorMatrix::Bt601);
assert!(back.is_bt_601());
assert_ne!(back, ColorMatrix::default());
assert!(ColorMatrix::default().encode_to_vec().is_empty());
assert_eq!(
ColorMatrix::decode_from_slice(&[]).unwrap(),
ColorMatrix::default()
);
}
#[test]
fn color_matrix_default_instance_and_clear() {
assert_eq!(
*<ColorMatrix as DefaultInstance>::default_instance(),
ColorMatrix::default()
);
let mut m = ColorMatrix::YCgCo;
Message::clear(&mut m);
assert_eq!(m, ColorMatrix::default());
}
#[test]
fn color_range_round_trip() {
for r in [
ColorRange::Unspecified,
ColorRange::Limited,
ColorRange::Full,
] {
let b = r.encode_to_vec();
assert_eq!(ColorRange::decode_from_slice(&b).unwrap(), r);
}
}
#[test]
fn rotation_round_trip() {
for r in [
Rotation::D0,
Rotation::D90,
Rotation::D180,
Rotation::D270,
Rotation::Unknown(7),
Rotation::Unknown(4242),
] {
let b = r.encode_to_vec();
assert_eq!(Rotation::decode_from_slice(&b).unwrap(), r);
}
}
#[test]
fn enum_wrong_wire_type_errors() {
let mut buf: Vec<u8> = Vec::new();
Tag::new(1, WireType::LengthDelimited).encode(&mut buf);
encode_varint(0, &mut buf);
let err = <ColorMatrix as Message>::decode_from_slice(&buf).unwrap_err();
assert!(
matches!(err, DecodeError::WireTypeMismatch { field_number: 1, expected, actual }
if expected == VARINT && actual == LEN),
"got {err:?}"
);
}
#[test]
fn enum_unknown_field_is_skipped() {
let mut buf = ColorRange::Full.encode_to_vec();
Tag::new(7, WireType::Varint).encode(&mut buf); encode_varint(123, &mut buf);
assert_eq!(
<ColorRange as Message>::decode_from_slice(&buf).unwrap(),
ColorRange::Full
);
}
#[test]
fn enum_unknown_id_decodes_losslessly() {
let mut buf: Vec<u8> = Vec::new();
Tag::new(1, WireType::Varint).encode(&mut buf);
encode_uint32(9_999, &mut buf);
assert_eq!(
<ColorTransfer as Message>::decode_from_slice(&buf).unwrap(),
ColorTransfer::Unknown(9_999)
);
}
#[test]
fn pixel_format_round_trip_including_unknown() {
for p in [
PixelFormat::Yuv420p,
PixelFormat::default(), PixelFormat::Unknown(77),
] {
let b = p.encode_to_vec();
assert_eq!(PixelFormat::decode_from_slice(&b).unwrap(), p);
}
}
#[test]
fn dimensions_round_trip_and_default() {
for d in [
Dimensions::default(),
Dimensions::new(1920, 1080),
Dimensions::new(0, 720),
] {
let b = d.encode_to_vec();
assert_eq!(Dimensions::decode_from_slice(&b).unwrap(), d);
}
}
#[test]
fn dimensions_wrong_wire_type_and_unknown_skip() {
let mut buf: Vec<u8> = Vec::new();
Tag::new(2, WireType::LengthDelimited).encode(&mut buf);
encode_varint(0, &mut buf);
assert!(matches!(
<Dimensions as Message>::decode_from_slice(&buf).unwrap_err(),
DecodeError::WireTypeMismatch { field_number: 2, expected, actual }
if expected == VARINT && actual == LEN
));
let mut ok = Dimensions::new(64, 48).encode_to_vec();
Tag::new(9, WireType::Varint).encode(&mut ok);
encode_varint(5, &mut ok);
assert_eq!(
<Dimensions as Message>::decode_from_slice(&ok).unwrap(),
Dimensions::new(64, 48)
);
}
#[test]
fn rect_round_trip_and_default() {
for r in [
Rect::default(),
Rect::new(10, 20, 1280, 720),
Rect::new(0, 0, 0, 480),
] {
let b = r.encode_to_vec();
assert_eq!(Rect::decode_from_slice(&b).unwrap(), r);
}
}
#[test]
fn rect_wrong_wire_type_and_unknown_skip() {
let mut buf: Vec<u8> = Vec::new();
Tag::new(3, WireType::LengthDelimited).encode(&mut buf);
encode_varint(0, &mut buf);
assert!(matches!(
<Rect as Message>::decode_from_slice(&buf).unwrap_err(),
DecodeError::WireTypeMismatch { field_number: 3, expected, actual }
if expected == VARINT && actual == LEN
));
let mut ok = Rect::new(1, 2, 3, 4).encode_to_vec();
Tag::new(8, WireType::Varint).encode(&mut ok);
encode_varint(1, &mut ok);
assert_eq!(
<Rect as Message>::decode_from_slice(&ok).unwrap(),
Rect::new(1, 2, 3, 4)
);
}
#[test]
fn sar_round_trip_default_and_nondefault() {
for s in [
SampleAspectRatio::default(), SampleAspectRatio::new(40, nz(33)), SampleAspectRatio::new(0, nz(1)), ] {
let b = s.encode_to_vec();
assert_eq!(SampleAspectRatio::decode_from_slice(&b).unwrap(), s);
}
}
#[test]
fn sar_field2_wrong_wire_type_errors() {
let mut buf: Vec<u8> = Vec::new();
Tag::new(1, WireType::Varint).encode(&mut buf);
encode_uint32(4, &mut buf);
Tag::new(2, WireType::LengthDelimited).encode(&mut buf);
encode_varint(0, &mut buf);
assert!(matches!(
<SampleAspectRatio as Message>::decode_from_slice(&buf).unwrap_err(),
DecodeError::WireTypeMismatch { field_number: 2, expected, actual }
if expected == VARINT && actual == LEN
));
}
#[test]
fn sar_den_zero_clamped_and_unknown_skip() {
let mut buf: Vec<u8> = Vec::new();
Tag::new(1, WireType::Varint).encode(&mut buf);
encode_uint32(16, &mut buf);
Tag::new(2, WireType::Varint).encode(&mut buf);
encode_uint32(0, &mut buf); Tag::new(6, WireType::Varint).encode(&mut buf); encode_varint(42, &mut buf);
let s = <SampleAspectRatio as Message>::decode_from_slice(&buf).unwrap();
assert_eq!(s.num(), 16);
assert_eq!(s.den().get(), 1);
}
#[test]
fn color_info_round_trip_default_and_nondefault() {
let default = ColorInfo::UNSPECIFIED;
let b = default.encode_to_vec();
assert_eq!(ColorInfo::decode_from_slice(&b).unwrap(), default);
let ci = ColorInfo::UNSPECIFIED
.with_primaries(ColorPrimaries::Bt2020)
.with_transfer(ColorTransfer::SmpteSt2084Pq)
.with_matrix(ColorMatrix::Bt2020Ncl)
.with_range(ColorRange::Limited)
.with_chroma_location(ChromaLocation::Left);
let b2 = ci.encode_to_vec();
assert_eq!(ColorInfo::decode_from_slice(&b2).unwrap(), ci);
}
#[test]
fn color_info_matrix_always_encoded_round_trips_code_zero_matrix() {
let ci = ColorInfo::new(
ColorPrimaries::Unspecified,
ColorTransfer::Unspecified,
ColorMatrix::Rgb,
ColorRange::Unspecified,
ChromaLocation::Unspecified,
);
let b = ci.encode_to_vec();
let back = ColorInfo::decode_from_slice(&b).unwrap();
assert_eq!(back, ci);
assert!(back.matrix().is_rgb());
}
#[test]
fn color_info_wrong_wire_type_and_unknown_skip() {
let mut buf: Vec<u8> = Vec::new();
Tag::new(3, WireType::LengthDelimited).encode(&mut buf);
encode_varint(0, &mut buf);
assert!(matches!(
<ColorInfo as Message>::decode_from_slice(&buf).unwrap_err(),
DecodeError::WireTypeMismatch { field_number: 3, expected, actual }
if expected == VARINT && actual == LEN
));
let mut ok = ColorInfo::UNSPECIFIED
.with_range(ColorRange::Full)
.encode_to_vec();
Tag::new(9, WireType::Varint).encode(&mut ok);
encode_varint(1, &mut ok);
assert_eq!(
<ColorInfo as Message>::decode_from_slice(&ok).unwrap(),
ColorInfo::UNSPECIFIED.with_range(ColorRange::Full)
);
}
#[test]
fn content_light_round_trip_and_default() {
for c in [
ContentLightLevel::default(),
ContentLightLevel::new(1000, 400),
ContentLightLevel::new(0, 250),
] {
let b = c.encode_to_vec();
assert_eq!(ContentLightLevel::decode_from_slice(&b).unwrap(), c);
}
}
#[test]
fn content_light_wrong_wire_type_and_unknown_skip() {
let mut buf: Vec<u8> = Vec::new();
Tag::new(1, WireType::LengthDelimited).encode(&mut buf);
encode_varint(0, &mut buf);
assert!(matches!(
<ContentLightLevel as Message>::decode_from_slice(&buf).unwrap_err(),
DecodeError::WireTypeMismatch { field_number: 1, expected, actual }
if expected == VARINT && actual == LEN
));
let mut ok = ContentLightLevel::new(4000, 1000).encode_to_vec();
Tag::new(5, WireType::Varint).encode(&mut ok);
encode_varint(9, &mut ok);
assert_eq!(
<ContentLightLevel as Message>::decode_from_slice(&ok).unwrap(),
ContentLightLevel::new(4000, 1000)
);
}
#[test]
fn chroma_coord_round_trip_and_default() {
for c in [
ChromaCoord::default(),
cc(34000, 16000),
cc(0, 3000),
cc(u16::MAX as u32, u16::MAX as u32),
cc(70_000, 100_000),
cc(u32::MAX, u32::MAX - 1),
] {
let b = c.encode_to_vec();
assert_eq!(ChromaCoord::decode_from_slice(&b).unwrap(), c);
}
}
#[test]
fn mastering_display_round_trip_default_and_nondefault() {
let default = MasteringDisplay::default();
let b = default.encode_to_vec();
assert_eq!(MasteringDisplay::decode_from_slice(&b).unwrap(), default);
let md = MasteringDisplay::new(
[cc(34000, 16000), cc(13250, 34500), cc(7500, 3000)],
cc(15635, 16450),
10_000_000,
50,
);
let b2 = md.encode_to_vec();
let back = MasteringDisplay::decode_from_slice(&b2).unwrap();
assert_eq!(back, md);
assert_eq!(back.display_primaries()[1], cc(13250, 34500));
let md2 = MasteringDisplay::new([cc(1, 2), cc(3, 4), cc(5, 6)], cc(7, 8), 0, 0);
let b3 = md2.encode_to_vec();
assert_eq!(MasteringDisplay::decode_from_slice(&b3).unwrap(), md2);
}
#[test]
fn mastering_display_wrong_wire_type_and_unknown_skip() {
let mut buf: Vec<u8> = Vec::new();
Tag::new(2, WireType::Varint).encode(&mut buf);
encode_varint(0, &mut buf);
assert!(matches!(
<MasteringDisplay as Message>::decode_from_slice(&buf).unwrap_err(),
DecodeError::WireTypeMismatch { field_number: 2, expected, actual }
if expected == LEN && actual == VARINT
));
let mut buf5: Vec<u8> = Vec::new();
Tag::new(5, WireType::LengthDelimited).encode(&mut buf5);
encode_varint(0, &mut buf5);
assert!(matches!(
<MasteringDisplay as Message>::decode_from_slice(&buf5).unwrap_err(),
DecodeError::WireTypeMismatch { field_number: 5, expected, actual }
if expected == VARINT && actual == LEN
));
let original = MasteringDisplay::new([cc(9, 9), cc(8, 8), cc(7, 7)], cc(6, 6), 123, 4);
let mut ok = original.encode_to_vec();
Tag::new(12, WireType::Varint).encode(&mut ok);
encode_varint(99, &mut ok);
assert_eq!(
<MasteringDisplay as Message>::decode_from_slice(&ok).unwrap(),
original
);
}
#[test]
fn hdr_static_metadata_round_trip_all_presence_combos() {
let cll = ContentLightLevel::new(1000, 400);
let md = MasteringDisplay::new(
[cc(34000, 16000), cc(13250, 34500), cc(7500, 3000)],
cc(15635, 16450),
10_000_000,
50,
);
for h in [
HdrStaticMetadata::default(), HdrStaticMetadata::new(Some(md), None), HdrStaticMetadata::new(None, Some(cll)), HdrStaticMetadata::new(Some(md), Some(cll)), ] {
let b = h.encode_to_vec();
assert_eq!(HdrStaticMetadata::decode_from_slice(&b).unwrap(), h);
}
}
#[test]
fn hdr_static_metadata_wrong_wire_type_and_unknown_skip() {
let mut buf: Vec<u8> = Vec::new();
Tag::new(1, WireType::Varint).encode(&mut buf);
encode_varint(0, &mut buf);
assert!(matches!(
<HdrStaticMetadata as Message>::decode_from_slice(&buf).unwrap_err(),
DecodeError::WireTypeMismatch { field_number: 1, expected, actual }
if expected == LEN && actual == VARINT
));
let original = HdrStaticMetadata::new(None, Some(ContentLightLevel::new(2000, 500)));
let mut ok = original.encode_to_vec();
Tag::new(7, WireType::Varint).encode(&mut ok);
encode_varint(3, &mut ok);
assert_eq!(
<HdrStaticMetadata as Message>::decode_from_slice(&ok).unwrap(),
original
);
}
}