1use std::io::{Read, Seek};
2use std::os::raw::{c_char, c_longlong, c_uint, c_ulonglong};
3use std::path::Path;
4
5use crate::internal_prelude::*;
6use crate::*;
7
8#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
9pub struct Buffer(pub(crate) Handle);
10
11impl Buffer {
12 pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Buffer> {
13 let path = path.as_ref();
14 let u_str = path
15 .to_str()
16 .ok_or_else(|| Error::rust_error("Path is not valid utf8"))?;
17 let c_str = std::ffi::CString::new(u_str)
18 .map_err(|_| Error::rust_error("Path contains a NULL byte"))?;
19
20 wrap_constructor(|ud, cb| {
21 let mut h = Default::default();
22 check_error(unsafe {
23 syz_createBufferFromFile(&mut h as *mut syz_Handle, c_str.as_ptr(), ud, Some(cb))
24 })?;
25 Ok(Buffer(Handle::new(h)))
26 })
27 }
28
29 pub fn from_encoded_data(data: &[u8]) -> Result<Buffer> {
30 let mut h = Default::default();
31 check_error(unsafe {
32 syz_createBufferFromEncodedData(
33 &mut h as *mut syz_Handle,
34 data.len() as c_ulonglong,
35 &data[0] as *const u8 as *const i8,
36 std::ptr::null_mut(),
37 None,
38 )
39 })?;
40 Ok(Buffer(Handle::new(h)))
41 }
42
43 pub fn from_float_array(sr: c_uint, channels: c_uint, data: &[f32]) -> Result<Buffer> {
44 if data.is_empty() {
45 return Err(Error::rust_error(
46 "Cannot create a buffer from an empty array",
47 ));
48 }
49 if channels == 0 {
50 return Err(Error::rust_error("channels may not be 0"));
51 }
52 if data.len() % channels as usize != 0 {
53 return Err(Error::rust_error(
54 "Length of data must be a multiple of the channel count",
55 ));
56 }
57
58 let mut h = Default::default();
59 check_error(unsafe {
60 syz_createBufferFromFloatArray(
61 &mut h as *mut syz_Handle,
62 sr,
63 channels,
64 data.len() as c_ulonglong / channels as c_ulonglong,
65 &data[0] as *const f32,
66 std::ptr::null_mut(),
67 None,
68 )
69 })?;
70 Ok(Buffer(Handle::new(h)))
71 }
72
73 pub fn from_stream_handle(&self, handle: StreamHandle) -> Result<Buffer> {
74 let mut h = Default::default();
75 check_error(unsafe {
76 syz_createBufferFromStreamHandle(
77 &mut h as *mut syz_Handle,
78 handle.get_handle(),
79 std::ptr::null_mut(),
80 None,
81 )
82 })?;
83 Ok(Buffer(Handle::new(h)))
85 }
86
87 pub fn from_stream_params(protocol: &str, path: &str, param: usize) -> Result<Buffer> {
88 let mut h = Default::default();
91 let protocol_c = std::ffi::CString::new(protocol)
92 .map_err(|_| Error::rust_error("Unable to convert protocol to a C string"))?;
93 let path_c = std::ffi::CString::new(path)
94 .map_err(|_| Error::rust_error("Unable to convert path to a C string"))?;
95 let protocol_ptr = protocol_c.as_ptr();
96 let path_ptr = path_c.as_ptr();
97 check_error(unsafe {
98 syz_createBufferFromStreamParams(
99 &mut h as *mut syz_Handle,
100 protocol_ptr as *const c_char,
101 path_ptr as *const c_char,
102 std::mem::transmute(param),
103 std::ptr::null_mut(),
104 None,
105 )
106 })?;
107 Ok(Buffer(Handle::new(h)))
108 }
109
110 pub fn from_read_seek<R: Read + Seek>(mut reader: R) -> Result<Buffer> {
118 let size = reader
119 .seek(std::io::SeekFrom::End(0))
120 .and_then(|_| reader.stream_position())
121 .and_then(|_| reader.seek(std::io::SeekFrom::Start(0)))
122 .map_err(|x| Error::rust_error(&format!("{}", x)))?;
123
124 let cdata = CustomStreamData {
125 err_msg: Default::default(),
126 stream: reader,
127 };
128
129 let mut boxed = Box::new(cdata);
130
131 let mut sdef = syz_CustomStreamDef {
132 read_cb: Some(stream_read_cb::<R>),
133 seek_cb: Some(stream_seek_cb::<R>),
134 length: size as c_longlong,
135 userdata: &mut *boxed as *mut CustomStreamData<R> as *mut std::ffi::c_void,
136 ..Default::default()
137 };
138
139 let mut sh = 0;
140 check_error(unsafe {
141 syz_createStreamHandleFromCustomStream(
142 &mut sh as *mut syz_Handle,
143 &mut sdef as *mut syz_CustomStreamDef,
144 null_mut(),
145 None,
146 )
147 })?;
148 let sh = Handle::new(sh);
152
153 wrap_constructor(|ud, cb| {
154 let mut h = Default::default();
155 check_error(unsafe {
156 syz_createBufferFromStreamHandle(
157 &mut h as *mut syz_Handle,
158 sh.to_syz_handle(),
159 ud,
160 Some(cb),
161 )
162 })?;
163 Ok(Buffer(Handle::new(h)))
164 })
165 }
166
167 pub fn get_length_in_samples(&self) -> Result<u32> {
168 let mut out = Default::default();
169 check_error(unsafe {
170 syz_bufferGetLengthInSamples(&mut out as *mut u32, self.to_syz_handle())
171 })?;
172 Ok(out)
173 }
174
175 pub fn get_length_in_seconds(&self) -> Result<f64> {
176 let mut out = Default::default();
177 check_error(unsafe {
178 syz_bufferGetLengthInSeconds(&mut out as *mut f64, self.to_syz_handle())
179 })?;
180 Ok(out)
181 }
182
183 pub fn get_channels(&self) -> Result<u32> {
184 let mut out = Default::default();
185 check_error(unsafe { syz_bufferGetChannels(&mut out as *mut u32, self.to_syz_handle()) })?;
186 Ok(out)
187 }
188
189 pub fn get_size_in_bytes(&self) -> Result<u64> {
190 let mut out = 0;
191 check_error(unsafe {
192 syz_bufferGetSizeInBytes(&mut out as *mut u64, self.to_syz_handle())
193 })?;
194 Ok(out)
195 }
196 object_common!();
197}
198
199handle_traits!(Buffer);