Skip to content

Commit 3c31dbb

Browse files
authored
RFC: Remove aligned-vec dependency (#51)
1 parent 1bc21a8 commit 3c31dbb

4 files changed

Lines changed: 298 additions & 33 deletions

File tree

Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ repository = "https://github.com/rust-av/v_frame"
99
include = ["Cargo.toml", "README.md", "LICENSE", "src"]
1010

1111
[dependencies]
12-
aligned-vec = "0.6.4"
1312
num-traits = "0.2.19"
1413
thiserror = "2.0.17"
1514

@@ -129,7 +128,6 @@ mod_module_files = "warn"
129128
needless_continue = "warn"
130129
needless_pass_by_ref_mut = "warn"
131130
option_as_ref_cloned = "warn"
132-
option_if_let_else = "warn"
133131
pathbuf_init_then_push = "warn"
134132
precedence_bits = "warn"
135133
range_minus_one = "warn"

src/pixel.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@
2424
2525
use num_traits::PrimInt;
2626

27+
mod private {
28+
pub trait Sealed {}
29+
30+
impl Sealed for u8 {}
31+
impl Sealed for u16 {}
32+
}
33+
2734
/// A trait for types that can be used as pixel data.
2835
///
2936
/// This trait abstracts over the pixel data types supported by the library,
@@ -41,10 +48,21 @@ use num_traits::PrimInt;
4148
///
4249
/// Attempting to create a frame with a mismatched type will result in
4350
/// [`Error::DataTypeMismatch`](crate::error::Error::DataTypeMismatch).
44-
pub trait Pixel: Copy + Clone + Default + Send + Sync + PrimInt + 'static {}
51+
///
52+
/// # Safety
53+
///
54+
/// All implementing types must be valid if represented by an all-zero byte-pattern,
55+
/// i.e. using [`std::mem::zeroed`] must __not__ cause undefined behavior for
56+
/// implementing types.
57+
pub unsafe trait Pixel:
58+
Copy + Clone + Default + Send + Sync + PrimInt + 'static + private::Sealed
59+
{
60+
}
4561

4662
/// Pixel implementation for 8-bit video data.
47-
impl Pixel for u8 {}
63+
// SAFETY: u8 is valid if represented by a zeroed byte.
64+
unsafe impl Pixel for u8 {}
4865

4966
/// Pixel implementation for high bit-depth (9-16 bit) video data.
50-
impl Pixel for u16 {}
67+
// SAFETY: u16 is valid if represented by zeroed bytes.
68+
unsafe impl Pixel for u16 {}

src/plane.rs

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,13 @@
3333
#[cfg(test)]
3434
mod tests;
3535

36-
use std::{
37-
iter,
38-
num::{NonZeroU8, NonZeroUsize},
39-
};
36+
use std::num::{NonZeroU8, NonZeroUsize};
4037

41-
use aligned_vec::{ABox, AVec, ConstAlign};
38+
mod aligned;
39+
use aligned::AlignedData;
4240

4341
use crate::{error::Error, pixel::Pixel};
4442

45-
/// Alignment for plane data on WASM platforms (8 bytes).
46-
#[cfg(target_arch = "wasm32")]
47-
const DATA_ALIGNMENT: usize = 1 << 3;
48-
49-
/// Alignment for plane data on non-WASM platforms (64 bytes for SIMD optimization).
50-
#[cfg(not(target_arch = "wasm32"))]
51-
const DATA_ALIGNMENT: usize = 1 << 6;
52-
5343
/// A two-dimensional plane of pixel data with optional padding.
5444
///
5545
/// `Plane<T>` represents a rectangular array of pixels of type `T`, where `T` implements
@@ -74,10 +64,10 @@ const DATA_ALIGNMENT: usize = 1 << 6;
7464
/// - [`rows()`](Plane::rows) / [`rows_mut()`](Plane::rows_mut): Iterate over all visible rows
7565
/// - [`pixel()`](Plane::pixel) / [`pixel_mut()`](Plane::pixel_mut): Access individual pixels
7666
/// - [`pixels()`](Plane::pixels) / [`pixels_mut()`](Plane::pixels_mut): Iterate over all visible pixels
77-
#[derive(Clone)]
67+
#[derive(Debug, Clone)]
7868
pub struct Plane<T: Pixel> {
7969
/// The underlying pixel data buffer, including padding.
80-
pub(crate) data: ABox<[T], ConstAlign<DATA_ALIGNMENT>>,
70+
pub(crate) data: AlignedData<T>,
8171
/// Geometry information describing dimensions and padding.
8272
pub(crate) geometry: PlaneGeometry,
8373
}
@@ -92,12 +82,11 @@ where
9282
.height
9383
.saturating_add(geometry.pad_top)
9484
.saturating_add(geometry.pad_bottom);
85+
86+
let pixels = rows.get() * geometry.stride.get();
87+
9588
Self {
96-
data: AVec::from_iter(
97-
DATA_ALIGNMENT,
98-
iter::repeat_n(T::zero(), geometry.stride.get() * rows.get()),
99-
)
100-
.into_boxed_slice(),
89+
data: AlignedData::new(pixels),
10190
geometry,
10291
}
10392
}
@@ -137,11 +126,9 @@ where
137126
#[inline]
138127
#[must_use]
139128
pub fn rows(&self) -> impl DoubleEndedIterator<Item = &[T]> + ExactSizeIterator {
140-
let origin = self.geometry.stride.get() * self.geometry.pad_top;
141-
// SAFETY: The plane creation interface ensures the data is large enough
142-
let visible_data = unsafe { self.data.get_unchecked(origin..) };
143-
visible_data
129+
self.data
144130
.chunks_exact(self.geometry.stride.get())
131+
.skip(self.geometry.pad_top)
145132
.take(self.geometry.height.get())
146133
.map(|row| {
147134
let start_idx = self.geometry.pad_left;
@@ -155,11 +142,9 @@ where
155142
/// in the plane, from top to bottom.
156143
#[inline]
157144
pub fn rows_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut [T]> + ExactSizeIterator {
158-
let origin = self.geometry.stride.get() * self.geometry.pad_top;
159-
// SAFETY: The plane creation interface ensures the data is large enough
160-
let visible_data = unsafe { self.data.get_unchecked_mut(origin..) };
161-
visible_data
145+
self.data
162146
.chunks_exact_mut(self.geometry.stride.get())
147+
.skip(self.geometry.pad_top)
163148
.take(self.geometry.height.get())
164149
.map(|row| {
165150
let start_idx = self.geometry.pad_left;

0 commit comments

Comments
 (0)