1use crate::math::*;
4use std::io::{Cursor};
5use crate::error::{Result, UnitResult};
6use smallvec::SmallVec;
7use std::ops::Range;
8use crate::block::{BlockIndex};
9use crate::meta::attribute::ChannelList;
10
11
12#[derive(Clone, Copy, Eq, PartialEq, Debug)]
15pub struct LineSlice<T> {
16
17 pub location: LineIndex,
21
22 pub value: T,
26}
27
28
29pub type LineRef<'s> = LineSlice<&'s [u8]>;
34
35pub type LineRefMut<'s> = LineSlice<&'s mut [u8]>;
40
41
42#[derive(Clone, Copy, Eq, PartialEq, Debug, Hash)]
46pub struct LineIndex {
47
48 pub layer: usize,
50
51 pub channel: usize,
53
54 pub level: Vec2<usize>,
56
57 pub position: Vec2<usize>,
59
60 pub sample_count: usize,
63}
64
65
66impl LineIndex {
67
68 #[inline]
75 #[must_use]
76 pub fn lines_in_block(block: BlockIndex, channels: &ChannelList) -> impl Iterator<Item=(Range<usize>, LineIndex)> {
77 struct LineIter {
78 layer: usize, level: Vec2<usize>, width: usize,
79 end_y: usize, x: usize, channel_sizes: SmallVec<[usize; 8]>,
80 byte: usize, channel: usize, y: usize,
81 }
82
83 impl Iterator for LineIter {
86 type Item = (Range<usize>, LineIndex);
87 fn next(&mut self) -> Option<Self::Item> {
90 if self.y < self.end_y {
91
92 let byte_len = self.channel_sizes[self.channel];
94 let return_value = (
95 (self.byte .. self.byte + byte_len),
96 LineIndex {
97 channel: self.channel,
98 layer: self.layer,
99 level: self.level,
100 position: Vec2(self.x, self.y),
101 sample_count: self.width,
102 }
103 );
104
105 { self.byte += byte_len;
107 self.channel += 1;
108
109 if self.channel == self.channel_sizes.len() {
110 self.channel = 0;
111 self.y += 1;
112 }
113 }
114
115 Some(return_value)
116 }
117
118 else {
119 None
120 }
121 }
122 }
123
124 let channel_line_sizes: SmallVec<[usize; 8]> = channels.list.iter()
125 .map(move |channel| block.pixel_size.0 * channel.sample_type.bytes_per_sample()) .collect();
127
128 LineIter {
129 layer: block.layer,
130 level: block.level,
131 width: block.pixel_size.0,
132 x: block.pixel_position.0,
133 end_y: block.pixel_position.y() + block.pixel_size.height(),
134 channel_sizes: channel_line_sizes,
135
136 byte: 0,
137 channel: 0,
138 y: block.pixel_position.y()
139 }
140 }
141}
142
143
144
145impl<'s> LineRefMut<'s> {
146
147 #[inline]
150 #[must_use]
151 pub fn write_samples_from_slice<T: crate::io::Data>(self, slice: &[T]) -> UnitResult {
152 debug_assert_eq!(slice.len(), self.location.sample_count, "slice size does not match the line width");
153 debug_assert_eq!(self.value.len(), self.location.sample_count * T::BYTE_SIZE, "sample type size does not match line byte size");
154
155 T::write_slice(&mut Cursor::new(self.value), slice)
156 }
157
158 #[inline]
164 #[must_use]
165 pub fn write_samples<T: crate::io::Data>(self, mut get_sample: impl FnMut(usize) -> T) -> UnitResult {
166 debug_assert_eq!(self.value.len(), self.location.sample_count * T::BYTE_SIZE, "sample type size does not match line byte size");
167
168 let mut write = Cursor::new(self.value);
169
170 for index in 0..self.location.sample_count {
171 T::write(get_sample(index), &mut write)?;
172 }
173
174 Ok(())
175 }
176}
177
178impl LineRef<'_> {
179
180 pub fn read_samples_into_slice<T: crate::io::Data>(self, slice: &mut [T]) -> UnitResult {
183 debug_assert_eq!(slice.len(), self.location.sample_count, "slice size does not match the line width");
184 debug_assert_eq!(self.value.len(), self.location.sample_count * T::BYTE_SIZE, "sample type size does not match line byte size");
185
186 T::read_slice(&mut Cursor::new(self.value), slice)
187 }
188
189 pub fn read_samples<T: crate::io::Data>(&self) -> impl Iterator<Item = Result<T>> + '_ {
192 debug_assert_eq!(self.value.len(), self.location.sample_count * T::BYTE_SIZE, "sample type size does not match line byte size");
193
194 let mut read = self.value; (0..self.location.sample_count).map(move |_| T::read(&mut read))
196 }
197}