// Copyright (c) the JPEG XL Project Authors. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file.
pubstruct OwnedRawImage { // Safety invariant: all the accessible bytes of `self.data` are initialized, and // belongs to a single allocation that lives until `self` is dropped. // The data referenced by self.data was allocated by RawImageBuffer::try_allocate. // `data.is_aligned(CACHE_LINE_BYTE_SIZE)` is true. pub(super) data: RawImageBuffer,
offset: (usize, usize),
padding: (usize, usize),
}
pubfn new_zeroed_with_padding(
byte_size: (usize, usize),
offset: (usize, usize), mut padding: (usize, usize),
) -> Result<Self> { // Since RawImageBuffer::try_allocate will round up the length of a row to a cache line, // might as well declare that as available padding space. if !(padding.0 + byte_size.0).is_multiple_of(CACHE_LINE_BYTE_SIZE) {
padding.0 += CACHE_LINE_BYTE_SIZE - (padding.0 + byte_size.0) % CACHE_LINE_BYTE_SIZE;
}
Ok(Self { // Safety note: the returned memory is initialized and part of a single allocation of // the correct length.
data: RawImageBuffer::try_allocate(
(byte_size.0 + padding.0, byte_size.1 + padding.1), false,
)?,
offset,
padding,
})
}
pubfn get_rect_including_padding_mut(&mutself, rect: Rect) -> RawImageRectMut<'_> {
RawImageRectMut { // Safety note: we are lending exclusive ownership to RawImageRectMut.
data: self.data.rect(rect),
_ph: PhantomData,
}
}
pubfn get_rect_including_padding(&'_ self, rect: Rect) -> RawImageRect<'_> {
RawImageRect { // Safety note: correctness ensured by the return value borrowing from `self`.
data: self.data.rect(rect),
_ph: PhantomData,
}
}
fn shift_rect(&self, rect: Rect) -> Rect { if cfg!(debug_assertions) { // Check the original rect is within the content size (without padding)
rect.check_within(self.byte_size());
}
Rect {
origin: (rect.origin.0 + self.offset.0, rect.origin.1 + self.offset.1),
size: rect.size,
}
}
#[inline(always)] pubfn row_mut(&mutself, row: usize) -> &mut [u8] { let offset = self.offset; let end = offset.0 + self.byte_size().0; // SAFETY: we don't write uninit data to `row`, and we have ownership of the accessible // bytes of `self.data`. let row = &mutunsafe { self.data.row_mut(row + offset.1) }[offset.0..end]; // SAFETY: MaybeUninit<u8> and u8 have the same size and layout, and our safety invariant // guarantees the data is initialized. unsafe { std::slice::from_raw_parts_mut(row.as_mut_ptr().cast::<u8>(), row.len()) }
}
#[inline(always)] pubfn row(&self, row: usize) -> &[u8] { let offset = self.offset; let end = offset.0 + self.byte_size().0; // SAFETY: we have shared access to the accessible bytes of `self.data`. let row = &unsafe { self.data.row(row + offset.1) }[offset.0..end]; // SAFETY: MaybeUninit<u8> and u8 have the same size and layout, and our safety invariant // guarantees the data is initialized. unsafe { std::slice::from_raw_parts(row.as_ptr().cast::<u8>(), row.len()) }
}
pubfn try_clone(&self) -> Result<OwnedRawImage> {
Ok(Self { // SAFETY: we own the data that self.data references, so it is all accessible. // Moreover, it is initialized and try_clone creates a copy, so the resulting data is // owned and initialized.
data: unsafe { self.data.try_clone()? },
offset: self.offset,
padding: self.padding,
})
}
}
impl Drop for OwnedRawImage { fn drop(&mutself) { // SAFETY: we own the data referenced by self.data, and it was allocated by // RawImageBuffer::try_allocate. unsafe { self.data.deallocate();
}
}
}
#[derive(Clone, Copy)] pubstruct RawImageRect<'a> { // Safety invariant: all the accessible bytes of `self.data` are initialized. pub(super) data: RawImageBuffer,
_ph: PhantomData<&'a u8>,
}
impl<'a> RawImageRect<'a> { #[inline(always)] pubfn row(&self, row: usize) -> &[u8] { // SAFETY: we have shared access to the accessible bytes of `self.data`. let row = unsafe { self.data.row(row) }; // SAFETY: MaybeUninit<u8> and u8 have the same size and layout, and our safety invariant // guarantees the data is initialized. unsafe { std::slice::from_raw_parts(row.as_ptr().cast::<u8>(), row.len()) }
}
pubfn rect(&self, rect: Rect) -> RawImageRect<'a> { Self { // Safety note: correctness ensured by the fact that the return value still borrows // from the original data source.
data: self.data.rect(rect),
_ph: PhantomData,
}
}
pubstruct RawImageRectMut<'a> { // Safety invariant: all the accessible bytes of `self.data` are initialized and we have // exclusive access to them. pub(super) data: RawImageBuffer,
_ph: PhantomData<&'a mut u8>,
}
impl<'a> RawImageRectMut<'a> { #[inline(always)] pubfn row(&mutself, row: usize) -> &mut [u8] { // SAFETY: we don't write uninit data to `row`, and we have exclusive access to the accessible // bytes of `self.data`. let row = unsafe { self.data.row_mut(row) }; // SAFETY: MaybeUninit<u8> and u8 have the same size and layout, and our safety invariant // guarantees the data is initialized. unsafe { std::slice::from_raw_parts_mut(row.as_mut_ptr().cast::<u8>(), row.len()) }
}
pubfn rect_mut(&'_ mut self, rect: Rect) -> RawImageRectMut<'_> { Self { // Safety note: we are lending ownership to the returned RawImageRectMut, and Rust's // type system ensures correctness.
data: self.data.rect(rect),
_ph: PhantomData,
}
}
pubfn as_rect(&'_ self) -> RawImageRect<'_> {
RawImageRect { // Safety note: correctness ensured by the return value borrowing from self.
data: self.data,
_ph: PhantomData,
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.