Skip to main content

image_texel/layout/
relocated.rs

1use crate::layout::{AlignedOffset, Decay, Layout, PlaneOf, Relocate, SliceLayout};
2use crate::texels::TexelRange;
3
4/// Moves a base layout to an aligned offset location.
5///
6/// This effectively allows turning one layout into a plane of another.
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8pub struct Relocated<T> {
9    pub offset: AlignedOffset,
10    pub inner: T,
11}
12
13impl<T: Layout> Relocated<T> {
14    pub fn new(inner: T) -> Self {
15        Relocated {
16            offset: AlignedOffset::default(),
17            inner,
18        }
19    }
20
21    /// Get the next aligned offset that comes after this relocated layout.
22    pub fn next_aligned_offset(&self) -> Option<AlignedOffset> {
23        self.offset.next_up(self.inner.byte_len())
24    }
25
26    /// Get an index addressing all samples covered by the range of this relocated layout.
27    pub fn texel_range(&self) -> TexelRange<T::Sample>
28    where
29        T: SliceLayout,
30    {
31        TexelRange::from_byte_range(self.inner.sample(), self.offset.get()..self.byte_len())
32            .unwrap()
33    }
34}
35
36impl<T: Layout> Layout for Relocated<T> {
37    fn byte_len(&self) -> usize {
38        self.inner.byte_len() + self.offset.0
39    }
40}
41
42impl<T: Layout> Relocate for Relocated<T> {
43    fn byte_offset(&self) -> usize {
44        self.offset.0
45    }
46
47    fn relocate(&mut self, offset: AlignedOffset) {
48        self.offset = offset;
49    }
50}
51
52impl<T: Layout> Decay<T> for Relocated<T> {
53    fn decay(inner: T) -> Relocated<T> {
54        Relocated::new(inner)
55    }
56}
57
58impl<T: Layout> Decay<Relocated<Relocated<T>>> for Relocated<T> {
59    fn decay(inner: Relocated<Relocated<T>>) -> Relocated<T> {
60        Relocated {
61            offset: AlignedOffset::new(inner.offset.get() + inner.inner.offset.get()).unwrap(),
62            inner: inner.inner.inner,
63        }
64    }
65}
66
67impl<Idx, L> PlaneOf<Relocated<L>> for Idx
68where
69    Idx::Plane: Relocate,
70    Idx: PlaneOf<L>,
71{
72    type Plane = Idx::Plane;
73
74    fn get_plane(self, layout: &Relocated<L>) -> Option<Self::Plane> {
75        let mut inner = self.get_plane(&layout.inner)?;
76        let mut inner_offset = inner.byte_offset();
77        // This addition preserves the alignment up to MAX_ALIGN.
78        inner_offset += layout.offset.get();
79        // As an approximation this should succeed based on alignment requirements. Otherwise this
80        // is a best attempt.
81        if inner.relocate_to_byte(inner_offset) {
82            Some(inner)
83        } else {
84            None
85        }
86    }
87}