basisu_c_sys/extra/
mod.rs1#[cfg(feature = "encoder")]
2#[cfg_attr(docsrs, doc(cfg(feature = "encoder")))]
3mod encoder;
4mod transcoder;
5
6use bytemuck::NoUninit;
7#[cfg(feature = "encoder")]
8#[cfg_attr(docsrs, doc(cfg(feature = "encoder")))]
9pub use encoder::*;
10pub use transcoder::*;
11
12use crate::transcoder as trans_sys;
13use alloc::vec::Vec;
14use core::num::NonZero;
15use core::ops::{Bound, Range, RangeBounds};
16
17#[derive(Debug, thiserror::Error)]
18pub(crate) enum BuHeapAccessError {
19 #[error("Invalid {range:?}, end < start")]
20 InvalidRange { range: Range<u64> },
21 #[error("Read/Write out of bounds, the capacity is {capacity} but the end is {end}")]
22 OutOfBounds { end: u64, capacity: u64 },
23}
24
25pub(crate) struct BuHeap {
29 ptr: NonZero<u64>,
30 capacity: NonZero<u64>,
31}
32
33impl BuHeap {
34 pub fn new_uninit(capacity: NonZero<u64>) -> Self {
35 unsafe {
36 let ptr = trans_sys::bt_alloc(capacity.into());
37 Self {
38 ptr: NonZero::new(ptr).expect("basisu alloc failed"),
39 capacity,
40 }
41 }
42 }
43 pub fn new<T: NoUninit>(data: &[T]) -> Option<Self> {
44 let data = bytemuck::must_cast_slice(data);
45 let capacity = NonZero::new(data.len() as u64)?;
46 let mut bt = Self::new_uninit(capacity);
47 bt.try_write(0, data).unwrap();
48 Some(bt)
49 }
50 #[inline]
51 pub fn ptr(&self) -> NonZero<u64> {
52 self.ptr
53 }
54 #[inline]
55 pub fn capacity(&self) -> NonZero<u64> {
56 self.capacity
57 }
58 pub fn try_read<S: RangeBounds<u64>>(&self, range: S) -> Result<Vec<u8>, BuHeapAccessError> {
59 let capacity = u64::from(self.capacity());
60 let mut r = 0..capacity;
61 match range.start_bound() {
62 Bound::Included(&start_idx) => {
63 r.start = start_idx;
64 }
65 Bound::Excluded(&start) => {
66 r.start = start + 1;
67 }
68 Bound::Unbounded => {}
69 }
70 match range.end_bound() {
71 Bound::Included(&end_idx) => {
72 r.end = end_idx + 1;
73 }
74 Bound::Excluded(&end) => {
75 r.end = end;
76 }
77 Bound::Unbounded => {}
78 }
79 if r.end < r.start {
80 return Err(BuHeapAccessError::InvalidRange { range: r });
81 }
82 if r.end > capacity {
83 return Err(BuHeapAccessError::OutOfBounds {
84 end: r.end,
85 capacity,
86 });
87 }
88
89 if r.end == r.start {
90 return Ok(Vec::new());
91 }
92
93 Ok(unsafe {
94 crate::copy_basisu_memory_to_host(u64::from(self.ptr()) + r.start, r.end - r.start)
95 })
96 }
97 pub fn try_write(&mut self, offset: u64, data: &[u8]) -> Result<(), BuHeapAccessError> {
98 let capacity = u64::from(self.capacity());
99 let end = offset + data.len() as u64;
100 if end > capacity {
101 return Err(BuHeapAccessError::OutOfBounds { end, capacity });
102 }
103
104 unsafe { crate::copy_host_memory_to_basisu(data, u64::from(self.ptr()) + offset) };
105 Ok(())
106 }
107}
108impl Drop for BuHeap {
109 fn drop(&mut self) {
110 unsafe {
111 trans_sys::bt_free(u64::from(self.ptr()));
112 }
113 }
114}