image_texel/rec.rs
1// Distributed under The MIT License (MIT)
2//
3// Copyright (c) 2019 The `image-rs` developers
4use core::cmp;
5use core::fmt;
6use core::ops::{Deref, DerefMut};
7
8use crate::buf::{buf, Buffer};
9use crate::{AsTexel, Texel};
10
11/// A reinterpretable vector for an array of texels.
12///
13/// It allows efficient conversion to other texel representations, that is effective
14/// reinterpretation casts.
15pub struct TexelBuffer<P = u8> {
16 inner: Buffer,
17 length: usize,
18 texel: Texel<P>,
19}
20
21/// Error representation for a failed buffer reuse.
22///
23/// Indicates that the capacity of the underlying buffer is not large enough to perform the
24/// operation without a reallocation. This may be either since the allocation is simply not large
25/// enough or due to the requested length not having any representation in memory for the chosen
26/// texel type.
27///
28/// ```
29/// # use image_texel::TexelBuffer;
30/// let mut buffer = TexelBuffer::<u16>::new(16);
31///
32/// let err = match buffer.reuse(buffer.capacity() + 1) {
33/// Ok(_) => unreachable!("Increasing capacity would require reallocation"),
34/// Err(err) => err,
35/// };
36///
37/// let err = match buffer.reuse(usize::max_value()) {
38/// Ok(_) => unreachable!("A slice of u16 can never have usize::MAX elements"),
39/// Err(err) => err,
40/// };
41/// ```
42pub struct BufferReuseError {
43 pub(crate) requested: Option<usize>,
44 pub(crate) capacity: usize,
45}
46
47impl<P> TexelBuffer<P> {
48 /// Allocate a texel buffer by the texel count.
49 ///
50 /// # Panics
51 ///
52 /// This function will panic when the byte-length of the slice with the provided count would
53 /// exceed the possible `usize` values. To avoid this, use `bytes_for_texel` with manual
54 /// calculation of the byte length instead.
55 ///
56 /// This function will also panic if the allocation fails.
57 pub fn new(count: usize) -> Self
58 where
59 P: AsTexel,
60 {
61 Self::new_for_texel(P::texel(), count)
62 }
63
64 /// Allocate a texel buffer by the texel count.
65 ///
66 /// Provides the opportunity to construct the texel argument via other means than the trait,
67 /// for example a dynamically checked expression.
68 ///
69 /// # Panics
70 ///
71 /// This function will panic when the byte-length of the slice with the provided count would
72 /// exceed the possible `usize` values. To avoid this, use `bytes_for_texel` with manual
73 /// calculation of the byte length instead.
74 ///
75 /// This function will also panic if the allocation fails.
76 pub fn new_for_texel(texel: Texel<P>, count: usize) -> Self {
77 Self::bytes_for_texel(texel, mem_size(texel, count))
78 }
79
80 /// Allocate a texel buffer by providing the byte count you wish to allocate.
81 ///
82 /// # Panics
83 ///
84 /// This function will panic if the allocation fails.
85 pub fn bytes_for_texel(texel: Texel<P>, mem_size: usize) -> Self {
86 TexelBuffer {
87 inner: Buffer::new(mem_size),
88 length: mem_size,
89 texel,
90 }
91 }
92
93 /// Allocate a buffer with initial contents.
94 ///
95 /// The `TexelBuffer` will have a byte capacity that holds exactly as many elements as the slice
96 /// contains. Note that the elements are copied bytewise.
97 ///
98 /// # Panics
99 ///
100 /// This function will panic if the allocation fails.
101 pub fn with_elements(elements: &[P]) -> Self
102 where
103 P: AsTexel,
104 {
105 Self::with_elements_for_texel(P::texel(), elements)
106 }
107
108 /// Allocate a buffer with initial contents.
109 ///
110 /// The `TexelBuffer` will have a byte capacity that holds exactly as many elements as the slice
111 /// contains. Note that the elements are copied bytewise.
112 ///
113 /// # Panics
114 ///
115 /// This function will panic if the allocation fails.
116 pub fn with_elements_for_texel(texel: Texel<P>, elements: &[P]) -> Self {
117 let src = texel.to_bytes(elements);
118 let mut buffer = TexelBuffer::from_buffer(Buffer::from(src), texel);
119 // Will be treated as empty, so adjust to be filled up to count.
120 buffer.length = src.len();
121 buffer
122 }
123
124 pub(crate) fn from_buffer(inner: Buffer, texel: Texel<P>) -> Self {
125 TexelBuffer {
126 inner,
127 texel,
128 length: 0,
129 }
130 }
131
132 /// Change the number of texel.
133 ///
134 /// This will always reallocate the buffer if the size exceeds the current capacity.
135 ///
136 /// # Panics
137 ///
138 /// This function will panic when the byte-length of the slice with the provided count would
139 /// exceed the possible `usize` values. To avoid this, use `resize_bytes` with manual
140 /// calculation of the byte length instead.
141 ///
142 /// This function will also panic if an allocation is necessary but fails.
143 pub fn resize(&mut self, count: usize) {
144 self.resize_bytes(mem_size(self.texel, count))
145 }
146
147 /// Change the size in bytes.
148 ///
149 /// The length is afterwards equal to `bytes / mem::size_of::<P>()`, i.e. the quotient rounded
150 /// down.
151 ///
152 /// This will always reallocate the buffer if the size exceeds the current capacity.
153 ///
154 /// # Panics
155 ///
156 /// This function will panic if an allocation is necessary but fails.
157 pub fn resize_bytes(&mut self, bytes: usize) {
158 self.inner.grow_to(bytes);
159 self.length = bytes;
160 }
161
162 /// Change the allocated bytes, interpreted for another texel.
163 ///
164 /// This will always reallocate the buffer if the size exceeds the current capacity.
165 ///
166 /// # Panics
167 ///
168 /// This function will panic when the byte-length of the slice with the provided count would
169 /// exceed the possible `usize` values. To avoid this, use `resize_bytes` with manual
170 /// calculation of the byte length instead.
171 ///
172 /// This function will also panic if an allocation is necessary but fails.
173 pub fn resize_for_texel<O>(&mut self, count: usize, texel: Texel<O>) {
174 self.resize_bytes(mem_size(texel, count))
175 }
176
177 /// Change the number of texel without reallocation.
178 ///
179 /// Returns `Ok` when the resizing was successfully completed to the requested size and returns
180 /// `Err` if this could not have been performed without a reallocation. This function will also
181 /// never deallocate memory.
182 ///
183 /// ```
184 /// # use image_texel::TexelBuffer;
185 /// // Initial allocation may panic due to allocation error for now.
186 /// let mut buffer: TexelBuffer<u16> = TexelBuffer::new(100);
187 /// buffer.reuse(0)
188 /// .expect("Requested size smaller than allocation");
189 /// buffer.reuse(100)
190 /// .expect("The buffer didn't shrink from previous reuse");
191 ///
192 /// // Capacity may be larger than requested size at initialization.
193 /// let capacity = buffer.capacity();
194 /// buffer.reuse(capacity)
195 /// .expect("Set to full underlying allocation size.");
196 /// ```
197 pub fn reuse(&mut self, count: usize) -> Result<(), BufferReuseError> {
198 let bytes = count
199 .checked_mul(self.texel.size())
200 .ok_or_else(|| BufferReuseError {
201 requested: None,
202 capacity: self.byte_capacity(),
203 })?;
204 self.reuse_bytes(bytes)
205 }
206
207 /// Change the number of bytes without reallocation.
208 ///
209 /// Returns `Ok` when the resizing was successfully completed to the requested size and returns
210 /// `Err` with the new byte size otherwise.
211 pub fn reuse_bytes(&mut self, bytes: usize) -> Result<(), BufferReuseError> {
212 if bytes > self.byte_capacity() {
213 return Err(BufferReuseError {
214 requested: Some(bytes),
215 capacity: self.capacity(),
216 });
217 }
218
219 // Resize within capacity will not reallocate, thus not panic.
220 Ok(self.resize_bytes(bytes))
221 }
222
223 /// Reallocate the slice to contain exactly as many bytes as necessary.
224 ///
225 /// The number of contained elements is not changed. However, the number of elements
226 /// interpreted as a different type may change.
227 ///
228 /// ```
229 /// # use image_texel::TexelBuffer;
230 /// let buf_u8 = TexelBuffer::<u8>::new(7);
231 /// assert_eq!(buf_u8.len(), 7);
232 ///
233 /// let mut buf_u32 = buf_u8.reinterpret::<u32>();
234 /// assert_eq!(buf_u32.len(), 1);
235 /// buf_u32.shrink_to_fit();
236 ///
237 /// let buf_u8 = buf_u32.reinterpret::<u8>();
238 /// assert_eq!(buf_u8.len(), 4);
239 /// ```
240 ///
241 /// # Panics
242 ///
243 /// This function will panic if the allocation fails.
244 pub fn shrink_to_fit(&mut self) {
245 let exact_size = mem_size(self.texel, self.len());
246 self.inner.resize_to(exact_size);
247 self.length = exact_size;
248 }
249
250 /// View the valid portion of the buffer as a slice of the texel type.
251 pub fn as_slice(&self) -> &[P] {
252 self.buf().as_texels(self.texel)
253 }
254
255 /// View the valid portion of the buffer as a mutable slice of the texel type.
256 pub fn as_mut_slice(&mut self) -> &mut [P] {
257 let texel = self.texel;
258 self.buf_mut().as_mut_texels(texel)
259 }
260
261 /// The number of accessible elements for the current type.
262 pub fn len(&self) -> usize {
263 self.as_slice().len()
264 }
265
266 /// The number of elements that can fit without reallocation.
267 pub fn capacity(&self) -> usize {
268 self.inner.capacity() / self.texel.size_nz().get()
269 }
270
271 /// View the raw bytes representing the buffer, in the native memory layout.
272 pub fn as_bytes(&self) -> &[u8] {
273 self.buf().as_bytes()
274 }
275
276 /// View the mutable raw bytes representing the buffer, in the native memory layout.
277 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
278 self.buf_mut().as_bytes_mut()
279 }
280
281 /// View the raw bytes wrapped in the aligned buffer type.
282 pub fn as_buf(&self) -> &buf {
283 self.buf()
284 }
285
286 /// View the mutable raw bytes wrapped in the aligned buffer type.
287 pub fn as_buf_mut(&mut self) -> &mut buf {
288 self.buf_mut()
289 }
290
291 /// View the buffer as a different texel type.
292 pub fn as_texels<O>(&self, pixel: Texel<O>) -> &[O] {
293 self.buf().as_texels(pixel)
294 }
295
296 /// Mutate the buffer as a different texel type.
297 pub fn as_mut_texels<O>(&mut self, pixel: Texel<O>) -> &mut [O] {
298 self.buf_mut().as_mut_texels(pixel)
299 }
300
301 /// The total number of managed bytes.
302 ///
303 /// This will not change even through a reinterpretation casts. This corresponds to the
304 /// capacity of the storage.
305 pub fn byte_len(&self) -> usize {
306 self.as_bytes().len()
307 }
308
309 /// The total number of managable bytes.
310 pub fn byte_capacity(&self) -> usize {
311 self.inner.capacity()
312 }
313
314 /// Reinterpret the buffer for a different type of texel.
315 ///
316 /// See `reinterpret_to` for details.
317 pub fn reinterpret<Q>(self) -> TexelBuffer<Q>
318 where
319 Q: AsTexel,
320 {
321 self.reinterpret_to(Q::texel())
322 }
323
324 /// Reinterpret the buffer for a different type of texel.
325 ///
326 /// Note that this may leave some of the underlying texels unaccessible if the new type is
327 /// larger than the old one and the allocation was not a multiple of the new size. Conversely,
328 /// some new bytes may become accessible if the memory length was not a multiple of the
329 /// previous texel type's length.
330 pub fn reinterpret_to<Q>(self, texel: Texel<Q>) -> TexelBuffer<Q> {
331 TexelBuffer {
332 inner: self.inner,
333 length: self.length,
334 texel,
335 }
336 }
337
338 /// Map all elements to another value.
339 ///
340 /// See [`TexelBuffer::map_to`] for details.
341 pub fn map<Q>(self, f: impl Fn(P) -> Q) -> TexelBuffer<Q>
342 where
343 Q: AsTexel,
344 {
345 self.map_to(f, Q::texel())
346 }
347
348 /// Map elements to another value.
349 ///
350 /// This will keep the logical length of the `TexelBuffer` so that the number of texels stays constant.
351 /// If necessary, it will grow the internal buffer to achieve this.
352 ///
353 /// # Panics
354 ///
355 /// This function will panic if the allocation fails or the necessary allocation exceeds the
356 /// value range of `usize`.
357 pub fn map_to<Q>(mut self, f: impl Fn(P) -> Q, texel: Texel<Q>) -> TexelBuffer<Q> {
358 // Ensure we have enough memory for both representations.
359 let length = self.as_slice().len();
360 let new_bytes = mem_size(texel, length);
361 self.inner.grow_to(new_bytes);
362 self.inner.map_within(..length, 0, f, self.texel, texel);
363 TexelBuffer {
364 inner: self.inner,
365 length: new_bytes,
366 texel,
367 }
368 }
369
370 fn buf(&self) -> &buf {
371 &self.inner[..self.length]
372 }
373
374 fn buf_mut(&mut self) -> &mut buf {
375 &mut self.inner[..self.length]
376 }
377
378 pub(crate) fn into_inner(self) -> Buffer {
379 self.inner
380 }
381}
382
383fn mem_size<P>(texel: Texel<P>, count: usize) -> usize {
384 texel
385 .size()
386 .checked_mul(count)
387 .unwrap_or_else(|| panic!("Requested count overflows memory size"))
388}
389
390impl<P> Deref for TexelBuffer<P> {
391 type Target = [P];
392
393 fn deref(&self) -> &[P] {
394 self.as_slice()
395 }
396}
397
398impl<P> DerefMut for TexelBuffer<P> {
399 fn deref_mut(&mut self) -> &mut [P] {
400 self.as_mut_slice()
401 }
402}
403
404impl<P> Clone for TexelBuffer<P> {
405 fn clone(&self) -> Self {
406 TexelBuffer {
407 inner: self.inner.clone(),
408 ..*self
409 }
410 }
411}
412
413impl<P: AsTexel> Default for TexelBuffer<P> {
414 fn default() -> Self {
415 TexelBuffer {
416 inner: Buffer::default(),
417 length: 0,
418 texel: P::texel(),
419 }
420 }
421}
422
423impl<P: AsTexel + Clone> From<&'_ [P]> for TexelBuffer<P> {
424 fn from(elements: &'_ [P]) -> Self {
425 TexelBuffer::with_elements(elements)
426 }
427}
428
429impl<P: cmp::PartialEq> cmp::PartialEq for TexelBuffer<P> {
430 fn eq(&self, other: &Self) -> bool {
431 self.as_slice().eq(other.as_slice())
432 }
433}
434
435impl<P: cmp::Eq> cmp::Eq for TexelBuffer<P> {}
436
437impl<P: cmp::PartialOrd> cmp::PartialOrd for TexelBuffer<P> {
438 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
439 self.as_slice().partial_cmp(other.as_slice())
440 }
441}
442
443impl<P: cmp::Ord> cmp::Ord for TexelBuffer<P> {
444 fn cmp(&self, other: &Self) -> cmp::Ordering {
445 self.as_slice().cmp(other.as_slice())
446 }
447}
448
449impl<P: fmt::Debug> fmt::Debug for TexelBuffer<P> {
450 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
451 f.debug_list().entries(self.as_slice().iter()).finish()
452 }
453}
454
455impl fmt::Debug for BufferReuseError {
456 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
457 match self.requested {
458 None => write!(f, "Buffer reuse failed: Bytes count can not be expressed"),
459 Some(requested) => write!(
460 f,
461 "Buffer reuse failed: {} bytes requested, only {} available",
462 requested, self.capacity
463 ),
464 }
465 }
466}
467
468#[cfg(test)]
469mod tests {
470 use super::*;
471
472 #[test]
473 fn resize() {
474 let mut buffer: TexelBuffer<u8> = TexelBuffer::new(0);
475 assert_eq!(buffer.capacity(), 0);
476 assert_eq!(buffer.len(), 0);
477 buffer.resize(4);
478 assert!(buffer.capacity() >= 4);
479 assert_eq!(buffer.len(), 4);
480 buffer.resize(2);
481 assert!(buffer.capacity() >= 2);
482 assert_eq!(buffer.len(), 2);
483 buffer.resize(0);
484 buffer.shrink_to_fit();
485 assert_eq!(buffer.capacity(), 0);
486 assert_eq!(buffer.len(), 0);
487 }
488
489 #[test]
490 fn map() {
491 let mut buffer: TexelBuffer<u8> = TexelBuffer::new(8);
492 assert_eq!(buffer.len(), 8);
493 buffer.copy_from_slice(&[0, 1, 2, 3, 4, 5, 6, 7]);
494
495 let buffer = buffer.map(u32::from);
496 assert_eq!(buffer.len(), 8);
497 assert_eq!(buffer.as_slice(), &[0, 1, 2, 3, 4, 5, 6, 7]);
498
499 let buffer = buffer.map(|p| p as u8);
500 assert_eq!(buffer.len(), 8);
501 assert_eq!(buffer.as_slice(), &[0, 1, 2, 3, 4, 5, 6, 7]);
502 }
503
504 #[test]
505 fn with_elements() {
506 const HELLO_WORLD: &[u8] = b"Hello, World!";
507 let buffer = TexelBuffer::with_elements(HELLO_WORLD);
508 assert_eq!(buffer.as_slice(), HELLO_WORLD);
509 assert_eq!(buffer.byte_len(), HELLO_WORLD.len());
510
511 let from_buffer = TexelBuffer::from(HELLO_WORLD);
512 assert_eq!(buffer, from_buffer);
513 }
514}