numcodecs_jpeg2000/ffi/
stream.rs1use std::ffi::c_void;
4
5pub struct DecodeStream<'a> {
6 stream: *mut openjpeg_sys::opj_stream_t,
7 _buf: &'a [u8],
8}
9
10impl Drop for DecodeStream<'_> {
11 fn drop(&mut self) {
12 unsafe {
13 openjpeg_sys::opj_stream_destroy(self.stream);
14 }
15 }
16}
17
18impl<'a> DecodeStream<'a> {
19 pub fn new(buf: &'a [u8]) -> Self {
20 let len = buf.len();
21 let data = Box::into_raw(Box::new(WrappedSlice::new(buf)));
22
23 let stream = unsafe {
24 let stream = openjpeg_sys::opj_stream_default_create(1);
25 openjpeg_sys::opj_stream_set_read_function(stream, Some(buf_read_stream_read_fn));
26 openjpeg_sys::opj_stream_set_skip_function(stream, Some(buf_read_stream_skip_fn));
27 openjpeg_sys::opj_stream_set_seek_function(stream, Some(buf_read_stream_seek_fn));
28 openjpeg_sys::opj_stream_set_user_data_length(stream, len as u64);
29 openjpeg_sys::opj_stream_set_user_data(
30 stream,
31 data.cast(),
32 Some(buf_read_stream_free_fn),
33 );
34 stream
35 };
36
37 Self { stream, _buf: buf }
38 }
39
40 #[allow(clippy::needless_pass_by_ref_mut)]
41 pub fn as_raw(&mut self) -> *mut openjpeg_sys::opj_stream_t {
42 self.stream
43 }
44}
45
46extern "C" fn buf_read_stream_free_fn(p_data: *mut c_void) {
47 let ptr: *mut WrappedSlice = p_data.cast();
48 drop(unsafe { Box::from_raw(ptr) });
49}
50
51extern "C" fn buf_read_stream_read_fn(
52 p_buffer: *mut c_void,
53 nb_bytes: usize,
54 p_data: *mut c_void,
55) -> usize {
56 if p_buffer.is_null() || nb_bytes == 0 {
57 return usize::MAX;
58 }
59
60 let slice: &mut WrappedSlice = unsafe { &mut *p_data.cast() };
61 slice
62 .read_into(p_buffer.cast(), nb_bytes)
63 .unwrap_or(usize::MAX)
64}
65
66extern "C" fn buf_read_stream_skip_fn(nb_bytes: i64, p_data: *mut c_void) -> i64 {
67 let slice: &mut WrappedSlice = unsafe { &mut *p_data.cast() };
68 #[allow(
69 clippy::cast_sign_loss,
70 clippy::cast_possible_truncation,
71 clippy::cast_possible_wrap
72 )]
73 {
74 slice.consume(nb_bytes as usize) as i64
75 }
76}
77
78extern "C" fn buf_read_stream_seek_fn(nb_bytes: i64, p_data: *mut c_void) -> i32 {
79 let slice: &mut WrappedSlice = unsafe { &mut *p_data.cast() };
80 #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
81 let seek_offset = nb_bytes as usize;
82 let new_offset = slice.seek(seek_offset);
83
84 i32::from(seek_offset == new_offset)
86}
87
88struct WrappedSlice<'a> {
89 offset: usize,
90 buf: &'a [u8],
91}
92
93impl<'a> WrappedSlice<'a> {
94 const fn new(buf: &'a [u8]) -> Self {
95 Self { offset: 0, buf }
96 }
97
98 const fn remaining(&self) -> usize {
99 self.buf.len() - self.offset
100 }
101
102 fn seek(&mut self, new_offset: usize) -> usize {
103 self.offset = std::cmp::min(self.buf.len(), new_offset);
105 self.offset
106 }
107
108 fn consume(&mut self, n_bytes: usize) -> usize {
109 let offset = self.offset.saturating_add(n_bytes);
110 self.offset = self.buf.len().min(offset);
112 self.offset
113 }
114
115 fn read_into(&mut self, out: *mut u8, len: usize) -> Option<usize> {
116 let remaining = self.remaining();
118 if remaining == 0 {
119 return None;
121 }
122
123 let n_read = std::cmp::min(remaining, len);
125 let offset = self.offset;
126 self.consume(n_read);
127
128 unsafe {
129 std::ptr::copy_nonoverlapping(self.buf.as_ptr().add(offset), out, n_read);
130 }
131
132 Some(n_read)
133 }
134}
135
136pub struct EncodeStream<'a> {
137 stream: *mut openjpeg_sys::opj_stream_t,
138 _buf: &'a mut Vec<u8>,
139}
140
141impl<'a> EncodeStream<'a> {
142 pub fn new(buf: &'a mut Vec<u8>) -> Self {
143 let stream = unsafe {
144 let stream = openjpeg_sys::opj_stream_default_create(0);
145 openjpeg_sys::opj_stream_set_write_function(stream, Some(vec_write_stream_write_fn));
146 openjpeg_sys::opj_stream_set_user_data(stream, std::ptr::from_mut(buf).cast(), None);
147 stream
148 };
149
150 Self { stream, _buf: buf }
151 }
152
153 #[allow(clippy::needless_pass_by_ref_mut)]
154 pub fn as_raw(&mut self) -> *mut openjpeg_sys::opj_stream_t {
155 self.stream
156 }
157}
158
159extern "C" fn vec_write_stream_write_fn(
160 p_buffer: *mut c_void,
161 nb_bytes: usize,
162 p_data: *mut c_void,
163) -> usize {
164 if p_buffer.is_null() {
165 return usize::MAX;
166 }
167
168 let vec: &mut Vec<u8> = unsafe { &mut *p_data.cast() };
169
170 let data = unsafe { std::slice::from_raw_parts(p_buffer.cast(), nb_bytes) };
171
172 vec.extend_from_slice(data);
173
174 nb_bytes
175}