Skip to content

Commit

Permalink
Revert "fix ComponentBytes impls while still delegating to bytemuck"
Browse files Browse the repository at this point in the history
This reverts commit 339fa9a.
  • Loading branch information
kornelski authored Jul 8, 2024
1 parent 339fa9a commit 66e80b1
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 229 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ edition = "2021"
default = ["as-bytes", "argb", "grb"]
# safe as_bytes() casts require a marker trait for non-padded, non-pointery types.
as-bytes = ["bytemuck"]
# Preferred over as-bytes
bytemuck = ["dep:bytemuck"]
# Deprecated: all pixel types are enabled by default. No-op.
argb = []
# Deprecated: all pixel types are enabled by default. No-op.
Expand Down
107 changes: 13 additions & 94 deletions src/bytemuck.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,18 @@
use crate::alt::{Gray, GrayAlpha, BGR, BGRA, GRB};
use crate::alt::{ABGR, ARGB};
use crate::ComponentBytes;
use crate::{RGB, RGBA};
use crate::alt::{Gray, GrayAlpha, BGR, BGRA};
use crate::alt::{ARGB, ABGR};

#[cfg(feature = "as-bytes")]
unsafe impl<T> crate::Pod for RGB<T> where T: crate::Pod {}
#[cfg(feature = "as-bytes")]
unsafe impl<T> crate::Pod for BGR<T> where T: crate::Pod {}
#[cfg(feature = "as-bytes")]
unsafe impl<T> crate::Pod for GRB<T> where T: crate::Pod {}
#[cfg(feature = "as-bytes")]
unsafe impl<T> crate::Zeroable for RGB<T> where T: crate::Zeroable {}
#[cfg(feature = "as-bytes")]
unsafe impl<T> crate::Zeroable for BGR<T> where T: crate::Zeroable {}
#[cfg(feature = "as-bytes")]
unsafe impl<T> crate::Zeroable for GRB<T> where T: crate::Zeroable {}

#[cfg(feature = "as-bytes")]
unsafe impl<T, A> crate::Zeroable for ABGR<T, A>
where
T: crate::Zeroable,
A: crate::Zeroable,
{
unsafe impl<T, A> crate::Zeroable for ABGR<T, A> where T: crate::Zeroable, A: crate::Zeroable {
#[track_caller]
#[inline(always)]
fn zeroed() -> Self {
Expand All @@ -40,27 +31,13 @@ const fn assert_no_padding<T, A, S>() {
}

#[cfg(feature = "as-bytes")]
unsafe impl<T, A> crate::Pod for RGBA<T, A>
where
T: crate::Pod,
A: crate::Pod,
{
}
unsafe impl<T, A> crate::Pod for RGBA<T, A> where T: crate::Pod, A: crate::Pod {}

#[cfg(feature = "as-bytes")]
unsafe impl<T, A> crate::Pod for BGRA<T, A>
where
T: crate::Pod,
A: crate::Pod,
{
}
unsafe impl<T, A> crate::Pod for BGRA<T, A> where T: crate::Pod, A: crate::Pod {}

#[cfg(feature = "as-bytes")]
unsafe impl<T, A> crate::Zeroable for RGBA<T, A>
where
T: crate::Zeroable,
A: crate::Zeroable,
{
unsafe impl<T, A> crate::Zeroable for RGBA<T, A> where T: crate::Zeroable, A: crate::Zeroable {
#[track_caller]
#[inline(always)]
fn zeroed() -> Self {
Expand All @@ -72,27 +49,13 @@ where
}

#[cfg(feature = "as-bytes")]
unsafe impl<T, A> crate::Pod for ARGB<T, A>
where
T: crate::Pod,
A: crate::Pod,
{
}
unsafe impl<T, A> crate::Pod for ARGB<T, A> where T: crate::Pod, A: crate::Pod {}

#[cfg(feature = "as-bytes")]
unsafe impl<T, A> crate::Pod for ABGR<T, A>
where
T: crate::Pod,
A: crate::Pod,
{
}
unsafe impl<T, A> crate::Pod for ABGR<T, A> where T: crate::Pod, A: crate::Pod {}

#[cfg(feature = "as-bytes")]
unsafe impl<T, A> crate::Zeroable for ARGB<T, A>
where
T: crate::Zeroable,
A: crate::Zeroable,
{
unsafe impl<T, A> crate::Zeroable for ARGB<T, A> where T: crate::Zeroable, A: crate::Zeroable {
#[track_caller]
#[inline(always)]
fn zeroed() -> Self {
Expand All @@ -104,11 +67,7 @@ where
}

#[cfg(feature = "as-bytes")]
unsafe impl<T, A> crate::Zeroable for BGRA<T, A>
where
T: crate::Zeroable,
A: crate::Zeroable,
{
unsafe impl<T, A> crate::Zeroable for BGRA<T, A> where T: crate::Zeroable, A: crate::Zeroable {
#[track_caller]
#[inline(always)]
fn zeroed() -> Self {
Expand All @@ -122,59 +81,19 @@ where
#[cfg(feature = "as-bytes")]
unsafe impl<T> crate::Pod for Gray<T> where T: crate::Pod {}
#[cfg(feature = "as-bytes")]
unsafe impl<T, A> crate::Pod for GrayAlpha<T, A>
where
T: crate::Pod,
A: crate::Pod,
{
}
unsafe impl<T, A> crate::Pod for GrayAlpha<T, A> where T: crate::Pod, A: crate::Pod {}
#[cfg(feature = "as-bytes")]
unsafe impl<T> crate::Zeroable for Gray<T> where T: crate::Zeroable {}
#[cfg(feature = "as-bytes")]
unsafe impl<T, A> crate::Zeroable for GrayAlpha<T, A>
where
T: crate::Zeroable,
A: crate::Zeroable,
{
unsafe impl<T, A> crate::Zeroable for GrayAlpha<T, A> where T: crate::Zeroable, A: crate::Zeroable {
#[track_caller]
#[inline(always)]
fn zeroed() -> Self {
unsafe {
if core::mem::size_of::<A>() + core::mem::size_of::<T>() != core::mem::size_of::<Self>()
{
if core::mem::size_of::<A>() + core::mem::size_of::<T>() != core::mem::size_of::<Self>() {
panic!("type has padding");
}
core::mem::zeroed()
}
}
}

#[cfg(feature = "as-bytes")]
impl<T: crate::Pod> ComponentBytes<T> for [Gray<T>] {
#[inline]
fn as_bytes(&self) -> &[u8] {
assert_ne!(0, core::mem::size_of::<T>());
::bytemuck::cast_slice(self)
}

#[inline]
fn as_bytes_mut(&mut self) -> &mut [u8] {
assert_ne!(0, core::mem::size_of::<T>());
::bytemuck::cast_slice_mut(self)
}
}

#[cfg(feature = "as-bytes")]
impl<T: crate::Pod> ComponentBytes<T> for [GrayAlpha<T>] {
#[inline]
fn as_bytes(&self) -> &[u8] {
assert_ne!(0, core::mem::size_of::<T>());
::bytemuck::cast_slice(self)
}

#[inline]
fn as_bytes_mut(&mut self) -> &mut [u8] {
assert_ne!(0, core::mem::size_of::<T>());
::bytemuck::cast_slice_mut(self)
}
}
23 changes: 18 additions & 5 deletions src/legacy/internal/pixel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,29 @@ pub trait ComponentSlice<T> {
///
/// Plain types are not allowed to contain struct padding, booleans, chars, enums, references or pointers.
#[cfg(feature = "as-bytes")]
pub trait ComponentBytes<T: crate::Pod> {
pub trait ComponentBytes<T: ::bytemuck::Pod> {
/// The components interpreted as raw bytes, in machine's native endian. In `RGB` bytes of the red component are first.
fn as_bytes(&self) -> &[u8];

/// The components interpreted as raw bytes, in machine's native endian. In `RGB` bytes of the red component are first.
fn as_bytes_mut(&mut self) -> &mut [u8];
}

#[cfg(feature = "as-bytes")]
impl<T: ::bytemuck::Pod> ComponentBytes<T> for [T] {
#[inline]
fn as_bytes(&self) -> &[u8] {
assert_ne!(0, core::mem::size_of::<T>());
::bytemuck::cast_slice(self)
}

#[inline]
fn as_bytes_mut(&mut self) -> &mut [u8] {
assert_ne!(0, core::mem::size_of::<T>());
::bytemuck::cast_slice_mut(self)
}
}

/// Applying operation to every component
///
/// ```rust
Expand All @@ -59,8 +74,7 @@ pub trait ComponentMap<DestPixel, SrcComponent, DestComponent> {
///
/// Note that it returns the pixel directly, not an Interator.
fn map<Callback>(&self, f: Callback) -> DestPixel
where
Callback: FnMut(SrcComponent) -> DestComponent;
where Callback: FnMut(SrcComponent) -> DestComponent;
}

/// Same as `ComponentMap`, but doesn't change the alpha channel (if there's any alpha).
Expand All @@ -69,6 +83,5 @@ pub trait ColorComponentMap<DestPixel, SrcComponent, DestComponent> {
///
/// Note that it returns the pixel directly, not an Interator.
fn map_c<Callback>(&self, f: Callback) -> DestPixel
where
Callback: FnMut(SrcComponent) -> DestComponent;
where Callback: FnMut(SrcComponent) -> DestComponent;
}
79 changes: 31 additions & 48 deletions src/legacy/internal/rgb.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
use super::pixel::*;
use crate::alt::GRB;
use crate::alt::{BGR, BGRA};
use crate::ComponentSlice;
use crate::{RGB, RGBA};
use core::fmt;

impl<T> BGR<T> {
/// Convenience function for creating a new pixel
/// Warning: The order of arguments is R,G,B
#[deprecated(
note = "This function has a misleading order of arguments. Use BGR{} literal instead"
)]
#[deprecated(note = "This function has a misleading order of arguments. Use BGR{} literal instead")]
#[inline(always)]
pub const fn new(r: T, g: T, b: T) -> Self {
Self { b, g, r }
Expand All @@ -30,47 +27,49 @@ macro_rules! impl_rgb {
impl<T: Copy, B> ComponentMap<$RGB<B>, T, B> for $RGB<T> {
#[inline(always)]
fn map<F>(&self, mut f: F) -> $RGB<B>
where
F: FnMut(T) -> B,
{
where F: FnMut(T) -> B {
$RGB {
r: f(self.r),
g: f(self.g),
b: f(self.b),
r:f(self.r),
g:f(self.g),
b:f(self.b),
}
}
}

impl<T: Copy, B> ColorComponentMap<$RGB<B>, T, B> for $RGB<T> {
#[inline(always)]
fn map_c<F>(&self, mut f: F) -> $RGB<B>
where
F: FnMut(T) -> B,
{
where F: FnMut(T) -> B {
$RGB {
r: f(self.r),
g: f(self.g),
b: f(self.b),
r:f(self.r),
g:f(self.g),
b:f(self.b),
}
}
}

impl<T> ComponentSlice<T> for $RGB<T> {
#[inline(always)]
fn as_slice(&self) -> &[T] {
unsafe { core::slice::from_raw_parts(self as *const Self as *const T, 3) }
unsafe {
core::slice::from_raw_parts(self as *const Self as *const T, 3)
}
}

#[inline(always)]
fn as_mut_slice(&mut self) -> &mut [T] {
unsafe { core::slice::from_raw_parts_mut(self as *mut Self as *mut T, 3) }
unsafe {
core::slice::from_raw_parts_mut(self as *mut Self as *mut T, 3)
}
}
}

impl<T> ComponentSlice<T> for [$RGB<T>] {
#[inline]
fn as_slice(&self) -> &[T] {
unsafe { core::slice::from_raw_parts(self.as_ptr() as *const _, self.len() * 3) }
unsafe {
core::slice::from_raw_parts(self.as_ptr() as *const _, self.len() * 3)
}
}

#[inline]
Expand All @@ -81,20 +80,6 @@ macro_rules! impl_rgb {
}
}

#[cfg(feature = "as-bytes")]
impl<T: crate::Pod> ComponentBytes<T> for [$RGB<T>] {
#[inline]
fn as_bytes(&self) -> &[u8] {
assert_ne!(0, core::mem::size_of::<T>());
::bytemuck::cast_slice(self)
}

#[inline]
fn as_bytes_mut(&mut self) -> &mut [u8] {
assert_ne!(0, core::mem::size_of::<T>());
::bytemuck::cast_slice_mut(self)
}
}
};
}

Expand Down Expand Up @@ -196,42 +181,40 @@ mod rgb_test {

#[test]
fn grb_test() {
let grb = GRB { g: 1, r: 2, b: 3 }.map(|c| c * 2) + 1;
let grb = GRB {g:1,r:2,b:3}.map(|c| c * 2) + 1;
let rgb: crate::RGB8 = grb.into();
assert_eq!(rgb, RGB::new(5, 3, 7));
assert_eq!(rgb, RGB::new(5,3,7));
}

#[test]
fn sanity_check() {
let neg = RGB::new(1, 2, 3i32).map(|x| -x);
let neg = RGB::new(1,2,3i32).map(|x| -x);
assert_eq!(neg.r, -1);
assert_eq!(neg.g, -2);
assert_eq!(neg.b, -3);

let mut px = RGB::new(3, 4, 5);
let mut px = RGB::new(3,4,5);
px.as_mut_slice()[1] = 111;
assert_eq!(111, px.g);

assert_eq!(
RGBA::new(250, 251, 252, 253),
RGB::new(250, 251, 252).with_alpha(253)
);
assert_eq!(RGBA::new(250,251,252,253), RGB::new(250,251,252).with_alpha(253));

assert_eq!(RGB { r: 1u8, g: 2, b: 3 }, RGB::new(1u8, 2, 3));
assert!(RGB { r: 1u8, g: 1, b: 2 } < RGB::new(2, 1, 1));
assert_eq!(RGB{r:1u8,g:2,b:3}, RGB::new(1u8,2,3));
assert!(RGB{r:1u8,g:1,b:2} < RGB::new(2,1,1));

let mut h = std::collections::HashSet::new();
h.insert(px);
assert!(h.contains(&RGB::new(3, 111, 5)));
assert!(!h.contains(&RGB::new(111, 5, 3)));
assert!(h.contains(&RGB::new(3,111,5)));
assert!(!h.contains(&RGB::new(111,5,3)));


#[cfg(feature = "as-bytes")]
{
let v = vec![RGB::new(1u8, 2, 3), RGB::new(4, 5, 6)];
assert_eq!(&[1, 2, 3, 4, 5, 6], v.as_bytes());
let v = vec![RGB::new(1u8,2,3), RGB::new(4,5,6)];
assert_eq!(&[1,2,3,4,5,6], v.as_bytes());
}

assert_eq!(RGB::new(0u8, 0, 0), Default::default());
assert_eq!(RGB::new(0u8,0,0), Default::default());
}

#[test]
Expand Down
Loading

0 comments on commit 66e80b1

Please sign in to comment.