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,
};

/// A read-only file buffer, the file is mmaped when available.
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 {
    /// Read the file with name filename, and put its content in a newly
    /// allocated read-only buffer (will map it with mmap() when available).
    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?");
    }
}