Skip to main content

Texel

Struct Texel 

Source
pub struct Texel<P: ?Sized>(/* private fields */);
Expand description

Marker struct to denote a texel type.

Can be constructed only for types that have expected alignment and no byte invariants. It always implements Copy and Clone, regardless of the underlying type and is zero-sized.

This is the central encapsulation of unsafety in this crate. It utilizes bytemuck for a safe interface but permits other types with an unsafe interface, and offers the cast operations without a bound on the Pod trait. Note that Pod is a pure marker trait; its properties must hold even if it is not explicitly mentioned. If all constructors (safely or unsafely) ensure that its properties hold we can use Texel as a witness type for the bound and subsequently write interfaces to take an instance instead of having a static type bound. This achieves two effects:

  • Firstly, it makes the interface independent of the chosen transmutation crate. Potentially we will have a method to construct the Texel via a core trait.
  • Secondly, it allows creating texel of third-party types for which the bound can not be implemented. Crucially, this includes SIMD representations that would be a burden to support directly. And conversely you can also deal with arbitrary existing texel without a bound in your own interfaces!

Implementations§

Source§

impl<P: Pod> Texel<P>

Source

pub const fn for_type() -> Option<Self>

Try to construct an instance of the marker.

If successful, you can freely use it to access the image buffers. This requires:

  • The type must have an alignment of at most MAX_ALIGN.
  • The type must not be a ZST.
  • The type must not have any Drop-glue (no drop, any contain not part that is Drop).
Source§

impl<P> Texel<P>

Source

pub const unsafe fn new_unchecked() -> Self

Create a witness certifying P as a texel without checks.

§Safety

The type P must not:

  • have any validity invariants, i.e. is mustn’t contain any padding.
  • have any safety invariants. This implies it can be copied.
  • have an alignment larger than MaxAligned.
  • be a zero-size type.

Furthermore, tentatively, the type must not have any drop glue. That is its members are all simple types without Drop implementations. This requirement exists mainly to avoid code accidentally leaking instances, and ensures that copies created from their byte representation—which is safe according to the other invairants— do not cause unexpected effects.

Note that the alignment requirement with regards to MaxAligned is architecture dependent as the exact bound varies across the target_arch feature. Where possible, add static assertions to each call site of this function.

Source

pub const fn align(self) -> usize

Proxy of core::mem::align_of.

Source

pub const fn size(self) -> usize

Proxy of core::mem::size_of.

Source

pub const fn size_nz(self) -> NonZeroUsize

Publicly visible function to use the guarantee of non-ZST.

Source

pub const fn array<const N: usize>(self) -> Texel<[P; N]>

Construct a texel as an array of no elements.

§Panics

This function panics when called with N equal to 0.

Source

pub const fn unaligned(self) -> Texel<Unaligned<P>>

Construct a texel for unaligned data of the contained type.

Source

pub const fn transparent_wrap<O>( self, _: IsTransparentWrapper<P, O>, ) -> Texel<O>

Construct a texel by wrapping into a transparent wrapper.

TODO: a constructor for Texel<O> based on proof of transmutation from &mut P to &mut O, based on the standard transmutation RFC. This is more flexible than bytemuck’s TransparentWrapper trait.

Source

pub const fn transparent_unwrap<O>( self, _: IsTransparentWrapper<O, P>, ) -> Texel<O>

Construct a texel by unwrapping a transparent wrapper.

Source

pub const fn num_wrapping(self) -> Texel<Wrapping<P>>

Construct a texel that contains a number in the standard Wrapping type.

Source§

impl<T, const N: usize> Texel<[T; N]>

Source

pub const fn array_element(self) -> Texel<T>

Construct a texel, from an array of elements.

Source§

impl<P> Texel<P>

Operations that can be performed based on the evidence of Texel.

Source

pub fn zeroed(self) -> P

Construct a value of P from thin air, with zeroed representation.

Source

pub fn copy_val(self, val: &P) -> P

Copy a texel.

Note that this does not require Copy because that requirement was part of the requirements of constructing this Texel witness.

Source

pub fn copy_cell(self, val: &Cell<P>) -> P

Source

pub fn cell_as_slice(self, val: &[Cell<P>]) -> &Cell<[P]>

Source

pub fn store_cell_slice(self, val: &[Cell<P>], from: &[P])

Efficiently store a slice of shared read values to cells.

We choose an outer slice for the parameter only since the standard library offers the transposition out of the type parameter, but not its inverse yet. Call Cell::as_slice_of_cells as needed.

Source

pub fn load_cell_slice(self, val: &[Cell<P>], into: &mut [P])

Efficiently copy a slice of values from cells to an owned buffer.

We choose an outer slice for the parameter only since the standard library offers the transposition out of the type parameter, but not its inverse yet. Call Cell::as_slice_of_cells as needed.

Source

pub fn load_atomic(self, val: AtomicRef<'_, P>) -> P

Load a value from an atomic slice.

The results is only correct if no concurrent modification occurs. The library promises basic soundness but no particular defined behaviour under parallel modifications to the memory bytes which describe the value to be loaded.

Each atomic unit is read at most once.

Source

pub fn load_atomic_slice(self, val: AtomicSliceRef<'_, P>, into: &mut [P])

Load values from an atomic slice.

The results is only correct if no concurrent modification occurs. The library promises basic soundness but no particular defined behaviour under parallel modifications to the memory bytes which describe the value to be loaded.

Each atomic unit is read at most once.

§Panics

This method panics if the slice and the target buffer do not have the same logical length.

Source

pub fn load_atomic_to_cells(self, val: AtomicSliceRef<'_, P>, into: &[Cell<P>])

Load values from an atomic slice to a slice of cells.

The results is only correct if no concurrent modification occurs. The library promises basic soundness but no particular defined behaviour under parallel modifications to the memory bytes which describe the value to be loaded.

Each atomic unit is read at most once.

§Panics

This method panics if the slice and the target buffer do not have the same length.

Source

pub fn store_atomic(self, val: AtomicRef<'_, P>, value: P)

Store a value to an atomic slice.

The results is only correct if no concurrent modification occurs. The library promises basic soundness but no particular defined behaviour under parallel modifications to the memory bytes which describe the value to be store.

Provides the same wait-freeness as the underlying platform for fetch_* instructions, that is this does not use compare_exchange_weak. This implies that concurrent modifications to bytes not covered by this particular representation will not inherently block progress.

Source

pub fn store_atomic_slice(self, val: AtomicSliceRef<'_, P>, source: &[P])

Store values to an atomic slice.

The results is only correct if no concurrent modification occurs. The library promises basic soundness but no particular defined behaviour under parallel modifications to the memory bytes which describe the value to be store.

Provides the same wait-freeness as the underlying platform for fetch_* instructions, that is this does not use compare_exchange_weak. This implies that concurrent modifications to bytes not covered by this particular representation will not inherently block progress.

§Panics

This method panics if the slice and the source buffer do not have the same logical length.

Source

pub fn store_atomic_from_cells( self, val: AtomicSliceRef<'_, P>, source: &[Cell<P>], )

Store values from cells to an atomic slice.

The results is only correct if no concurrent modification occurs. The library promises basic soundness but no particular defined behaviour under parallel modifications to the memory bytes which describe the value to be store.

Provides the same wait-freeness as the underlying platform for fetch_* instructions, that is this does not use compare_exchange_weak. This implies that concurrent modifications to bytes not covered by this particular representation will not inherently block progress.

§Panics

This method panics if the slice and the source buffer do not have the same logical length.

Source

pub fn to_slice<'buf>(self, buffer: &'buf [MaxAligned]) -> &'buf [P]

Reinterpret a slice of aligned bytes as a slice of the texel.

Note that the size (in bytes) of the slice will be shortened if the size of P is not a divisor of the input slice’s size.

Source

pub fn to_mut_slice<'buf>(self, buffer: &'buf mut [MaxAligned]) -> &'buf mut [P]

Reinterpret a slice of aligned bytes as a mutable slice of the texel.

Note that the size (in bytes) of the slice will be shortened if the size of P is not a divisor of the input slice’s size.

Source

pub fn try_to_slice<'buf>(self, bytes: &'buf [u8]) -> Option<&'buf [P]>

Try to reinterpret a slice of bytes as a slice of the texel.

This returns Some if the buffer is suitably aligned, and None otherwise.

Source

pub fn try_to_slice_mut<'buf>( self, bytes: &'buf mut [u8], ) -> Option<&'buf mut [P]>

Try to reinterpret a slice of bytes as a slice of the texel.

This returns Some if the buffer is suitably aligned, and None otherwise.

Source

pub fn to_unaligned_slice<'buf>(self, bytes: &'buf [u8]) -> &'buf [Unaligned<P>]

Interpret a byte slice as unaligned values of another type.

This is essentially a call to Texel::to_slice however the specific output type selection ensures that it always succeeds.

§Examples
use image_texel::texels::{U8, U64};

// This buffer is not guaranteed to be aligned!
let raw_buffer = [0u16, 1, 2, 3].map(u16::to_be_bytes);
let raw_bytes = U8.array().to_bytes(&raw_buffer);

let unaligned = U64.to_unaligned_slice(raw_bytes);
// Forces a copy. `texel.unaligned().copy` would work, too.
assert_eq!(u64::from_be(unaligned[0].0), 0x0000_0001_0002_0003);
Source

pub fn to_unaligned_slice_mut<'buf>( self, bytes: &'buf mut [u8], ) -> &'buf mut [Unaligned<P>]

Interpret a mutable byte slice as unaligned values of another type.

§Examples
use image_texel::texels::{U16, U64};

// This buffer is not guaranteed to be aligned!
let mut raw_buffer = [0u16; 4];
let raw_bytes = U16.to_mut_bytes(&mut raw_buffer);

let unaligned = U64.to_unaligned_slice_mut(raw_bytes);
unaligned[0].0 = u64::from_be(0x0000_0001_0002_0003);
assert_eq!(raw_buffer.map(u16::from_be), [0, 1, 2, 3]);
Source

pub fn to_cell<'buf>(self, buffer: &'buf [MaxCell]) -> &'buf Cell<[P]>

Reinterpret a shared slice as a some particular type.

Note that the size (in bytes) of the slice will be shortened if the size of P is not a divisor of the input slice’s size.

Source

pub fn try_to_cell<'buf>( self, bytes: &'buf [Cell<u8>], ) -> Option<&'buf Cell<[P]>>

Reinterpret a slice of texel as memory.

Note that you can convert a reference to a single value by core::slice::from_ref.

Source

pub fn to_unaligned_cell<'buf>( self, bytes: &'buf [Cell<u8>], ) -> &'buf Cell<[Unaligned<P>]>

Interpret a slice of cells as unaligned cells of another type.

§Examples
use core::cell::Cell;
use image_texel::texels::{U16, U64};

// This buffer is not guaranteed to be aligned to u64!
let mut raw_buffer = [0u16; 4].map(Cell::new);
let raw_bytes = U16.cell_bytes(&raw_buffer).as_slice_of_cells();

// Write a u64 value anyways.
let unaligned = U64.to_unaligned_cell(raw_bytes).as_slice_of_cells();
unaligned[0].set(u64::from_be(0x0000_0001_0002_0003).into());

let raw_buffer = raw_buffer.map(Cell::into_inner);
assert_eq!(raw_buffer.map(u16::from_be), [0, 1, 2, 3]);
Source

pub fn try_to_atomic<'buf>( self, bytes: AtomicSliceRef<'buf, u8>, ) -> Option<AtomicSliceRef<'buf, P>>

Reinterpret a slice of atomically access memory with a type annotation.

Source

pub fn to_unaligned_atomic<'buf>( self, bytes: AtomicSliceRef<'buf, u8>, ) -> AtomicSliceRef<'buf, Unaligned<P>>

Interpret a slice of cells as unaligned atomic values of another type.

§Examples
use image_texel::texels::atomic_buf;
use image_texel::texels::{MaxAtomic, U16, U64};

let underlying = [MaxAtomic::zero(); 1];
let raw_buffer = atomic_buf::new(&underlying[..]);

// Get a partial slice of it, that is is not aligned to u64.
let u16_slice = raw_buffer.index(U16.to_range(1..5).unwrap());
let raw_bytes = U16.atomic_bytes(u16_slice);

// Re-Interpret that as an unaligned slice of u64 values.
let unaligned = U64.to_unaligned_atomic(raw_bytes);

std::thread::scope(|scope| {
    scope.spawn(|| {
        // Write a u64 value.
        U64.unaligned().store_atomic(
            unaligned.index_one(0),
            u64::from_be(0x0000_0001_0002_0003).into()
        )
   });
});

// Load from the buffer we've written to atomically.
let mut values = [0; 4];
U16.load_atomic_slice(u16_slice, &mut values[..]);
assert_eq!(values.map(u16::from_be), [0u16, 1, 2, 3]);
Source

pub fn to_bytes<'buf>(self, texel: &'buf [P]) -> &'buf [u8]

Reinterpret a slice of texel as memory.

Note that you can convert a reference to a single value by core::slice::from_ref.

Source

pub fn to_mut_bytes<'buf>(self, texel: &'buf mut [P]) -> &'buf mut [u8]

Reinterpret a mutable slice of texel as memory.

Note that you can convert a reference to a single value by core::slice::from_mut.

Source

pub fn cell_bytes<'buf>(self, texel: &'buf [Cell<P>]) -> &'buf Cell<[u8]>

Reinterpret a slice of texel as memory.

Note that you can convert a reference to a single value by core::slice::from_ref.

Source

pub fn atomic_bytes<'buf>( self, texel: AtomicSliceRef<'buf, P>, ) -> AtomicSliceRef<'buf, u8>

Reinterpret a slice of atomically modified texels as atomic bytes.

Source

pub fn to_range(self, range: Range<usize>) -> Option<TexelRange<P>>

Construct a range indexing to a slice of this texel.

See TexelRange::new as this is just a proxy.

use image_texel::{texels::{U16, buf}, TexelBuffer};

let buffer = TexelBuffer::with_elements(&[1u32, 2, 3, 4]);
let range = U16.to_range(4..8).unwrap();
let u16_view = &buffer.as_buf()[range];

assert_eq!(u16_view.len(), 4);
// This view extends over the `3u32` and `4u32` elements.
// Results depend on native endianess of the `u32` type.
assert!(u16_view[0] == 3 || u16_view[1] == 3);
assert!(u16_view[2] == 4 || u16_view[3] == 4);
Source

pub fn to_byte_range(self, range: Range<usize>) -> Option<TexelRange<P>>

Construct a range indexing to a slice of this texel by bytes.

See TexelRange::from_byte_range as this is just a proxy.

Trait Implementations§

Source§

impl<P> Clone for Texel<P>

This is a pure marker type.

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<P> Copy for Texel<P>

This is a pure marker type.

Source§

impl<P> Debug for Texel<P>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<P> Eq for Texel<P>

Source§

impl<T> From<Texel<T>> for TexelLayout

Convert a pixel to an element, discarding the exact type information.

Source§

fn from(texel: Texel<T>) -> Self

Converts to this type from the input type.
Source§

impl<P> Hash for Texel<P>

Source§

fn hash<H: Hasher>(&self, _: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl<P> Ord for Texel<P>

Source§

fn cmp(&self, _: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 (const: unstable) · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 (const: unstable) · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 (const: unstable) · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl<P> PartialEq for Texel<P>

Source§

fn eq(&self, _: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<P> PartialOrd for Texel<P>

Source§

fn partial_cmp(&self, _: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 (const: unstable) · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 (const: unstable) · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 (const: unstable) · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 (const: unstable) · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl<P> TryMend<MatrixBytes> for Texel<P>

Try to use the matrix with a specific pixel type.

Source§

impl<T, const N: usize> TryMend<PlaneBytes<N>> for Texel<T>

Upgrade to a collection of planes of the same texel.

Source§

impl<P> TryMend<StridedBytes> for Texel<P>

Try to use the matrix with a specific pixel type.

Auto Trait Implementations§

§

impl<P> Freeze for Texel<P>
where P: ?Sized,

§

impl<P> RefUnwindSafe for Texel<P>
where P: RefUnwindSafe + ?Sized,

§

impl<P> Send for Texel<P>
where P: Send + ?Sized,

§

impl<P> Sync for Texel<P>
where P: Sync + ?Sized,

§

impl<P> Unpin for Texel<P>
where P: Unpin + ?Sized,

§

impl<P> UnsafeUnpin for Texel<P>
where P: ?Sized,

§

impl<P> UnwindSafe for Texel<P>
where P: UnwindSafe + ?Sized,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, L> PlaneOf<&L> for P
where P: PlaneOf<L>,

Source§

type Plane = <P as PlaneOf<L>>::Plane

Source§

fn get_plane(self, layout: &&L) -> Option<<P as PlaneOf<&L>>::Plane>

Get the layout describing the plane.
Source§

impl<P, L> PlaneOf<&mut L> for P
where P: PlaneOf<L>,

Source§

type Plane = <P as PlaneOf<L>>::Plane

Source§

fn get_plane(self, layout: &&mut L) -> Option<<P as PlaneOf<&mut L>>::Plane>

Get the layout describing the plane.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.