Skip to content

Commit 9100e3c

Browse files
lilithkornelski
authored andcommitted
fix: add sound Pod/Zeroable impls for GrayA and Gray_v09 in as-bytes
Use single-type-parameter bounds (T: Pod) instead of the unsound two-parameter pattern (T: Pod, A: Pod) used by legacy types. bytemuck_impl.rs is gated on not(feature = "as-bytes"), so these impls are needed in as_bytes.rs for the default feature set. Users can use bytemuck::cast_slice() directly rather than ComponentBytes.
1 parent f453ade commit 9100e3c

2 files changed

Lines changed: 37 additions & 0 deletions

File tree

src/as_bytes.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use crate::{RGB, RGBA};
22
use crate::alt::{Gray, GrayAlpha, BGR, BGRA};
33
use crate::alt::{ARGB, ABGR};
4+
use crate::formats::gray_a::GrayA;
5+
#[cfg(feature = "unstable-experimental")]
6+
use crate::formats::gray::Gray_v09;
47
use crate::ComponentBytes;
58

69
#[cfg(feature = "as-bytes")]
@@ -115,3 +118,15 @@ impl<T: crate::Pod> ComponentBytes<T> for [Gray<T>] {}
115118
#[cfg(feature = "as-bytes")]
116119
impl<T: crate::Pod> ComponentBytes<T> for [GrayAlpha<T>] {}
117120

121+
// GrayA and Gray_v09 use the sound single-type-parameter impls (T: Pod),
122+
// not the unsound two-parameter pattern used by the legacy types above.
123+
#[cfg(feature = "as-bytes")]
124+
unsafe impl<T: crate::Pod> crate::Pod for GrayA<T> {}
125+
#[cfg(feature = "as-bytes")]
126+
unsafe impl<T: crate::Zeroable> crate::Zeroable for GrayA<T> {}
127+
128+
#[cfg(all(feature = "as-bytes", feature = "unstable-experimental"))]
129+
unsafe impl<T: crate::Pod> crate::Pod for Gray_v09<T> {}
130+
#[cfg(all(feature = "as-bytes", feature = "unstable-experimental"))]
131+
unsafe impl<T: crate::Zeroable> crate::Zeroable for Gray_v09<T> {}
132+

tests/v08.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,3 +605,25 @@ fn converts2() {
605605
assert_eq!(Bgra {r:1u8,g:2,b:3,a:4}, (3,2,1,4).into());
606606
assert_eq!(Bgr {r:1u8,g:2,b:3}, (3,2,1).into());
607607
}
608+
609+
#[test]
610+
#[cfg(feature = "as-bytes")]
611+
fn graya_bytemuck_with_as_bytes() {
612+
use rgb::GrayA;
613+
let pixels: [GrayA<u8>; 2] = [GrayA { v: 1, a: 128 }, GrayA { v: 2, a: 255 }];
614+
let bytes: &[u8] = rgb::bytemuck::cast_slice(&pixels);
615+
assert_eq!(bytes, &[1, 128, 2, 255]);
616+
let back: &[GrayA<u8>] = rgb::bytemuck::cast_slice(bytes);
617+
assert_eq!(back, &pixels);
618+
}
619+
620+
#[test]
621+
#[cfg(all(feature = "as-bytes", feature = "unstable-experimental"))]
622+
fn gray_v09_bytemuck_with_as_bytes() {
623+
type Gray09<T> = rgb::Gray<T>;
624+
let pixels = [Gray09 { v: 10u8 }, Gray09 { v: 20 }, Gray09 { v: 30 }];
625+
let bytes: &[u8] = rgb::bytemuck::cast_slice(&pixels);
626+
assert_eq!(bytes, &[10, 20, 30]);
627+
let back: &[Gray09<u8>] = rgb::bytemuck::cast_slice(bytes);
628+
assert_eq!(back, &pixels);
629+
}

0 commit comments

Comments
 (0)