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
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
use memmap::MmapMut;
use std::{
    io,
    ops::{Bound::*, RangeBounds},
    slice,
    sync::Arc,
};

/// A structure that implements a view into memory mapping.
#[derive(Debug, Clone)]
pub struct SharedMmap {
    mmap: Arc<MmapMut>,
    len: usize,
    slice: *mut u8,
}

impl SharedMmap {
    pub(crate) fn new(mut mmap: MmapMut) -> SharedMmap {
        let len = mmap.len();
        let slice = mmap.as_mut_ptr();
        SharedMmap {
            mmap: Arc::new(mmap),
            len,
            slice,
        }
    }

    pub fn len(&self) -> usize {
        self.len
    }

    pub fn is_empty(&self) -> bool {
        self.len == 0
    }

    pub(crate) fn flush(&self) -> Result<(), io::Error> {
        self.mmap.flush()
    }

    /// Get a sub-view. It will point to the same memory mapping as the parent
    /// mapping.
    pub fn slice(&self, bounds: impl RangeBounds<usize>) -> SharedMmap {
        if self.len == 0 {
            return SharedMmap {
                len: 0,
                ..self.clone()
            };
        }
        let start = match bounds.start_bound() {
            Included(start) => *start,
            Excluded(start) => start + 1,
            Unbounded => 0,
        };

        if start >= self.len {
            return SharedMmap {
                len: 0,
                ..self.clone()
            };
        }

        let end = match bounds.end_bound() {
            Included(end) => *end,
            Excluded(end) if *end == 0 => {
                return SharedMmap {
                    len: 0,
                    ..self.clone()
                };
            }
            Excluded(end) => end - 1,
            Unbounded => self.len - 1,
        };
        let end = std::cmp::min(end, self.len - 1);

        let len = if start <= end { end - start + 1 } else { 0 };

        let slice = unsafe { self.slice.add(start) };

        SharedMmap {
            mmap: self.mmap.clone(),
            len,
            slice,
        }
    }

    fn get_ref(&self) -> &[u8] {
        unsafe { slice::from_raw_parts(self.slice, self.len) }
    }

    fn get_mut(&mut self) -> &mut [u8] {
        unsafe { slice::from_raw_parts_mut(self.slice, self.len) }
    }
}

unsafe impl Send for SharedMmap {}

impl AsRef<[u8]> for SharedMmap {
    fn as_ref(&self) -> &[u8] {
        self.get_ref()
    }
}

impl AsMut<[u8]> for SharedMmap {
    fn as_mut(&mut self) -> &mut [u8] {
        self.get_mut()
    }
}