1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use std::{
ffi::CStr,
ops::Deref,
ptr::{null_mut, NonNull},
slice,
};
use crate::{
error::{Result, RsmpegError},
ffi,
shared::RetUpgrade,
};
pub struct AVMmap {
bufptr: NonNull<u8>,
size: ffi::size_t,
}
unsafe impl Send for AVMmap {}
impl Deref for AVMmap {
type Target = [u8];
fn deref(&self) -> &Self::Target {
unsafe { slice::from_raw_parts(self.bufptr.as_ptr(), self.size as _) }
}
}
impl AVMmap {
pub fn new(filename: &CStr) -> Result<Self> {
let mut bufptr = null_mut();
let mut size = 0;
unsafe { ffi::av_file_map(filename.as_ptr(), &mut bufptr, &mut size, 0, null_mut()) }
.upgrade()
.map(RsmpegError::AVError)?;
Ok(Self {
bufptr: NonNull::new(bufptr).unwrap(),
size,
})
}
}
impl Drop for AVMmap {
fn drop(&mut self) {
unsafe {
ffi::av_file_unmap(self.bufptr.as_ptr(), self.size);
}
}
}
#[cfg(test)]
mod test {
use std::{ffi::CString, fs::File, io::Write};
use super::*;
use tempdir::TempDir;
#[test]
fn test_file_mapping() {
let tempdir = TempDir::new("tmp").unwrap();
let file_path = tempdir.path().join("emm.txt");
{
let mut x = File::create(&file_path).unwrap();
x.write_all(b"hello? you here?").unwrap();
}
let file_path = &CString::new(file_path.into_os_string().into_string().unwrap()).unwrap();
let mmap = AVMmap::new(file_path).unwrap();
let x: &[u8] = &mmap;
assert_eq!(x, b"hello? you here?");
}
}