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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright 2018 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under The General Public License (GPL), version 3.
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. Please review the Licences for the specific language governing
// permissions and limitations relating to use of the SAFE Network Software.

use super::MAX_FILE_SIZE;
use memmap::MmapMut;
use std::{
    io::{Error as IoError, Write},
    ops::{Deref, DerefMut, Index, IndexMut},
};
use unwrap::unwrap;

pub const MAX_IN_MEMORY_SIZE: usize = 50 * 1024 * 1024;

enum Data {
    Vector(Vec<u8>),
    Mmap(MmapMut),
}

/// Optionally create a sequence of bytes via a vector or memory map.
pub struct Sequencer {
    data: Data,
}

#[allow(clippy::len_without_is_empty)]
impl Sequencer {
    /// Initialise as a vector.
    pub fn new_as_vector() -> Sequencer {
        Sequencer {
            data: Data::Vector(Vec::with_capacity(MAX_IN_MEMORY_SIZE)),
        }
    }

    /// Initialise as a memory map
    pub fn new_as_mmap() -> Result<Sequencer, IoError> {
        Ok(Sequencer {
            data: Data::Mmap(MmapMut::map_anon(MAX_FILE_SIZE)?),
        })
    }

    /// Return the current length of the sequencer.
    pub fn len(&self) -> usize {
        match self.data {
            Data::Vector(ref vector) => vector.len(),
            Data::Mmap(ref mmap) => mmap.len(),
        }
    }

    /// Initialise with the Sequencer with 'content'.
    pub fn init(&mut self, content: &[u8]) {
        match self.data {
            Data::Vector(ref mut vector) => vector.extend_from_slice(content),
            Data::Mmap(ref mut mmap) => {
                let _ = (&mut mmap[..]).write_all(&content[..]);
            }
        }
    }

    /// Truncate internal object to given size. Note that this affects the vector only since the
    /// memory map is a fixed size.
    pub fn truncate(&mut self, size: usize) {
        if let Data::Vector(ref mut vector) = self.data {
            vector.truncate(size);
        }
    }

    /// Create a memory map if we haven't already done so.
    pub fn create_mapping(&mut self) -> Result<(), IoError> {
        self.data = match self.data {
            Data::Mmap(_) => return Ok(()),
            Data::Vector(ref vector) => {
                let mut mmap = MmapMut::map_anon(MAX_FILE_SIZE)?;
                (&mut mmap[..]).write_all(&vector[..])?;
                Data::Mmap(mmap)
            }
        };
        Ok(())
    }
}

impl Index<usize> for Sequencer {
    type Output = u8;
    fn index(&self, index: usize) -> &u8 {
        match self.data {
            Data::Vector(ref vector) => &vector[index],
            Data::Mmap(ref mmap) => unwrap!(mmap.get(index)),
        }
    }
}

impl IndexMut<usize> for Sequencer {
    fn index_mut(&mut self, index: usize) -> &mut u8 {
        match self.data {
            Data::Vector(ref mut vector) => &mut vector[index],
            Data::Mmap(ref mut mmap) => unwrap!(mmap.get_mut(index)),
        }
    }
}

impl Deref for Sequencer {
    type Target = [u8];
    fn deref(&self) -> &[u8] {
        match self.data {
            Data::Vector(ref vector) => &*vector,
            Data::Mmap(ref mmap) => &*mmap,
        }
    }
}

impl DerefMut for Sequencer {
    fn deref_mut(&mut self) -> &mut [u8] {
        match self.data {
            Data::Vector(ref mut vector) => &mut *vector,
            Data::Mmap(ref mut mmap) => &mut *mmap,
        }
    }
}

impl Extend<u8> for Sequencer {
    fn extend<I>(&mut self, iterable: I)
    where
        I: IntoIterator<Item = u8>,
    {
        if let Data::Vector(ref mut vector) = self.data {
            vector.extend(iterable);
        }
    }
}