<commit_before>use std::collections::BTreeMap;
use std::fs::{File, OpenOptions};
use std::io::{Read, Seek, SeekFrom, Write};
use std::path::Path;
use std::sync::Arc;

use index::storage::{Result, Storage, StorageError};
// TODO: WRONG! FIX
use index::boolean_index::posting::Posting;
use utils::compression::{vbyte_encode, VByteDecoder};

pub struct FsPostingStorage {
    // Stores for every id the offset in the file and the length
    data: BTreeMap<u64, (u64, u32)>,
    dir: File,
    offset: u64,
}

impl FsPostingStorage {
    pub fn new(path: &Path) -> Self {
        FsPostingStorage {
            offset: 0,
            data: BTreeMap::new(),
            dir: OpenOptions::new()
                .read(true)
                .write(true)
                .create(true)
                .truncate(true)
                .open(path)
                .unwrap(),
        }
    }
}

impl Storage<Vec<Posting>> for FsPostingStorage {
    fn get(&self, id: u64) -> Result<Arc<Vec<Posting>>> {
        let posting_offset = self.data.get(&id).unwrap();
        let mut f = self.dir.try_clone().unwrap();
        f.seek(SeekFrom::Start(posting_offset.0)).unwrap();
        let mut bytes = vec![0; posting_offset.1 as usize];
        f.read_exact(&mut bytes).unwrap();
        let mut decoder = VByteDecoder::new(bytes.into_iter());
        let dec_id = decoder.next().unwrap() as u64;
        assert_eq!(id, dec_id);
        let postings = decode_listing(decoder);
        Ok(Arc::new(postings))
    }

    fn store(&mut self, id: u64, data: Vec<Posting>) -> Result<()> {
        //Encode the data
        let bytes = encode_listing(id, &data);
        //Append it to the file
        if let Err(e) = self.dir.write_all(&bytes) {
            return Err(StorageError::WriteError(Some(e)))
        }
        //And save the offset and the number of bytes written for later recovery
        self.data.insert(id, (self.offset, bytes.len() as u32));
        //Update offset
        self.offset += bytes.len() as u64;
        Ok(())
    }
}

// TODO: Remove theses methods from here. They do not belog here.
// Probably belong in index::boolean_index::posting or similar
fn decode_listing(mut decoder: VByteDecoder) -> Vec<Posting> {
    let postings_len = decoder.next().unwrap();
    let mut postings = Vec::with_capacity(postings_len);
    for _ in 0..postings_len {
        let doc_id = decoder.next().unwrap();
        let positions_len = decoder.next().unwrap();
        let mut positions = Vec::with_capacity(positions_len as usize);
        let mut last_position = 0;
        for _ in 0..positions_len {
            last_position += decoder.next().unwrap();
            positions.push(last_position as u32);
        }
        postings.push((doc_id as u64, positions));
    }
    postings
}

fn encode_listing(term_id: u64, listing: &[Posting]) -> Vec<u8> {
    let mut bytes: Vec<u8> = Vec::new();
    bytes.append(&mut vbyte_encode(term_id as usize));
    bytes.append(&mut vbyte_encode(listing.len()));
    for posting in listing {
        bytes.append(&mut vbyte_encode(posting.0 as usize));
        bytes.append(&mut vbyte_encode(posting.1.len() as usize));
        let mut last_position = 0;
        for position in &posting.1 {
            bytes.append(&mut vbyte_encode((*position - last_position) as usize));
            last_position = *position;
        }
    }
    bytes
}

#[test]
pub fn fs_provider() {
    let posting1 = vec![(10, vec![0, 1, 2, 3, 4]), (1, vec![15])];
    let posting2 = vec![(0, vec![0, 1, 4]), (1, vec![5, 15566, 3423565]), (5, vec![0, 24, 56])];
    let mut prov = FsPostingStorage::new(Path::new("/tmp/test_index.bin"));
    prov.store(0, posting1.clone());
    assert_eq!(prov.get(0).unwrap().as_ref(), &posting1);
    prov.store(1, posting2.clone());
    assert_eq!(prov.get(1).unwrap().as_ref(), &posting2);
    assert!(prov.get(0).unwrap().as_ref() != &posting2);
    assert_eq!(prov.get(0).unwrap().as_ref(), &posting1);
}
<commit_msg>Make fs_storage persistent<commit_after>use std::collections::BTreeMap;
use std::fs::{File, OpenOptions};
use std::io::{Read, Seek, SeekFrom, Write};
use std::path::Path;
use std::sync::Arc;

use index::storage::{Result, Storage, StorageError};
// TODO: WRONG! FIX
use index::boolean_index::posting::Posting;
use utils::compression::{vbyte_encode, VByteDecoder};

pub struct FsPostingStorage {
    // Stores for every id the offset in the file and the length
    entries: BTreeMap<u64, (u64 /* offset */, u32 /* length */)>,
    persistent_entries: File,
    data: File,
    current_offset: u64,
}

impl FsPostingStorage {
    /// Creates a new and empty instance of FsPostingStorage
    pub fn new(path: &Path) -> Self {
        assert!(path.is_dir(),
                "FsStorage::new expects a directory not a file!");
        FsPostingStorage {
            current_offset: 0,
            entries: BTreeMap::new(),
            persistent_entries: OpenOptions::new()
                .write(true)
                .create(true)
                .truncate(true)
                .open(path.join("entries.bin"))
                .unwrap(),
            data: OpenOptions::new()
                .read(true)
                .write(true)
                .create(true)
                .truncate(true)
                .open(path.join("data.bin"))
                .unwrap(),
        }
    }

    /// Reads a FsStorage from an previously populated folder.
    // TODO: Return result
    pub fn from_folder(path: &Path) -> Self {
        // Read from entry file to BTreeMap.
        let mut entries = BTreeMap::new();
        // 1. Open file
        let mut entries_file =
            OpenOptions::new().read(true).open(path.join("entries.bin")).unwrap();
        let mut bytes = Vec::with_capacity(entries_file.metadata().unwrap().len() as usize);
        // 2. Read file
        assert!(entries_file.read_to_end(&mut bytes).is_ok());
        let mut decoder = VByteDecoder::new(bytes.into_iter());
        // 3. Decode entries and write them to BTreeMap
        while let Some(entry) = decode_entry(&mut decoder) {
            entries.insert(entry.0, (entry.1, entry.2));
        }

        //Get data file length for offset
        let offset = File::open(path.join("data.bin"))
            .unwrap()
            .metadata()
            .unwrap()
            .len();

        FsPostingStorage {
            current_offset: offset,
            entries: entries,
            persistent_entries: OpenOptions::new()
                .append(true)
                .open(path.join("entries.bin"))
                .unwrap(),
            data: OpenOptions::new()
                .read(true)
                .append(true)
                .open(path.join("data.bin"))
                .unwrap(),
        }
    }
}

impl Storage<Vec<Posting>> for FsPostingStorage {
    fn get(&self, id: u64) -> Result<Arc<Vec<Posting>>> {
        let posting_offset = self.entries.get(&id).unwrap();
        let mut f = self.data.try_clone().unwrap();
        f.seek(SeekFrom::Start(posting_offset.0)).unwrap();
        let mut bytes = vec![0; posting_offset.1 as usize];
        f.read_exact(&mut bytes).unwrap();
        let mut decoder = VByteDecoder::new(bytes.into_iter());
        let dec_id = decoder.next().unwrap() as u64;
        assert_eq!(id, dec_id);
        let postings = decode_listing(decoder);
        Ok(Arc::new(postings))
    }

    fn store(&mut self, id: u64, data: Vec<Posting>) -> Result<()> {
        // Encode the data
        let bytes = encode_listing(id, &data);
        // Append it to the file
        if let Err(e) = self.data.write_all(&bytes) {
            return Err(StorageError::WriteError(Some(e)));
        }
        // And save the offset and the number of bytes written for later recovery
        self.entries.insert(id, (self.current_offset, bytes.len() as u32));
        // Also write the id, offset and number of bytes written to file for persistence
        let entry_bytes = encode_entry(id, self.current_offset, bytes.len() as u32);
        if let Err(e) = self.persistent_entries.write_all(&entry_bytes) {
            return Err(StorageError::WriteError(Some(e)));
        }

        // Update offset
        self.current_offset += bytes.len() as u64;
        Ok(())
    }
}

// TODO: Remove theses methods from here. They do not belog here.
// Probably belong in index::boolean_index::posting or similar
fn decode_listing(mut decoder: VByteDecoder) -> Vec<Posting> {
    let postings_len = decoder.next().unwrap();
    let mut postings = Vec::with_capacity(postings_len);
    for _ in 0..postings_len {
        let doc_id = decoder.next().unwrap();
        let positions_len = decoder.next().unwrap();
        let mut positions = Vec::with_capacity(positions_len as usize);
        let mut last_position = 0;
        for _ in 0..positions_len {
            last_position += decoder.next().unwrap();
            positions.push(last_position as u32);
        }
        postings.push((doc_id as u64, positions));
    }
    postings
}

fn encode_entry(id: u64, offset: u64, length: u32) -> Vec<u8> {
    let mut bytes: Vec<u8> = Vec::new();
    bytes.append(&mut vbyte_encode(id as usize));
    bytes.append(&mut vbyte_encode(offset as usize));
    bytes.append(&mut vbyte_encode(length as usize));
    bytes
}

fn decode_entry(decoder: &mut VByteDecoder) -> Option<(u64, u64, u32)> {
    let id = try_option!(decoder.next()) as u64;
    let offset = try_option!(decoder.next()) as u64;
    let length = try_option!(decoder.next()) as u32;
    Some((id, offset, length))
}

fn encode_listing(term_id: u64, listing: &[Posting]) -> Vec<u8> {
    let mut bytes: Vec<u8> = Vec::new();
    bytes.append(&mut vbyte_encode(term_id as usize));
    bytes.append(&mut vbyte_encode(listing.len()));
    for posting in listing {
        bytes.append(&mut vbyte_encode(posting.0 as usize));
        bytes.append(&mut vbyte_encode(posting.1.len() as usize));
        let mut last_position = 0;
        for position in &posting.1 {
            bytes.append(&mut vbyte_encode((*position - last_position) as usize));
            last_position = *position;
        }
    }
    bytes
}

#[cfg(test)]
mod tests {
    use std::fs::create_dir_all;
    use std::path::Path;

    use super::*;
    use index::storage::Storage;

    #[test]
    pub fn basic() {
        let posting1 = vec![(10, vec![0, 1, 2, 3, 4]), (1, vec![15])];
        let posting2 = vec![(0, vec![0, 1, 4]), (1, vec![5, 15566, 3423565]), (5, vec![0, 24, 56])];
        assert!(create_dir_all(Path::new("/tmp/test_index")).is_ok());
        let mut prov = FsPostingStorage::new(Path::new("/tmp/test_index"));
        assert!(prov.store(0, posting1.clone()).is_ok());
        assert_eq!(prov.get(0).unwrap().as_ref(), &posting1);
        assert!(prov.store(1, posting2.clone()).is_ok());
        assert_eq!(prov.get(1).unwrap().as_ref(), &posting2);
        assert!(prov.get(0).unwrap().as_ref() != &posting2);
        assert_eq!(prov.get(0).unwrap().as_ref(), &posting1);
    }

    #[test]
    pub fn persistence() {
        let posting1 = vec![(10, vec![0, 1, 2, 3, 4]), (1, vec![15])];
        let posting2 = vec![(0, vec![0, 1, 4]), (1, vec![5, 15566, 3423565]), (5, vec![0, 24, 56])];
        let posting3 =
            vec![(15, vec![24, 745, 6946]), (37, vec![234, 2356, 12345]), (98, vec![0, 1, 2, 3])];
        assert!(create_dir_all(Path::new("/tmp/test_index2")).is_ok());
        {
            let mut prov1 = FsPostingStorage::new(Path::new("/tmp/test_index2"));
            assert!(prov1.store(0, posting1.clone()).is_ok());
            assert!(prov1.store(1, posting2.clone()).is_ok());
        }

        {
            let mut prov2 = FsPostingStorage::from_folder(Path::new("/tmp/test_index2"));
            assert_eq!(prov2.get(0).unwrap().as_ref(), &posting1);
            assert_eq!(prov2.get(1).unwrap().as_ref(), &posting2);
            assert!(prov2.store(2, posting3.clone()).is_ok());
            assert_eq!(prov2.get(2).unwrap().as_ref(), &posting3);
        }

        {
            let prov3 = FsPostingStorage::from_folder(Path::new("/tmp/test_index2"));
            assert_eq!(prov3.get(0).unwrap().as_ref(), &posting1);
            assert_eq!(prov3.get(1).unwrap().as_ref(), &posting2);
            assert_eq!(prov3.get(2).unwrap().as_ref(), &posting3);
        }
    }
}
<|endoftext|>


<commit_before>use std::slice;

use binding::vm::init;
use class::object::Object;
use types::{Argc, Value};

use class::traits::RawObject;

pub struct VM;

impl VM {
    pub fn init() {
        init();
    }

    pub fn parse_arguments(argc: Argc, arguments: *const Object) -> Vec<Object> {
        unsafe {
            slice::from_raw_parts(arguments, argc as usize).to_vec()
        }
    }

    pub fn parse_itself(itself: Value) -> Object {
        Object::from(itself)
    }
}
<commit_msg>Remove unused RawObject import from class:VM<commit_after>use std::slice;

use binding::vm::init;
use class::object::Object;
use types::{Argc, Value};

pub struct VM;

impl VM {
    pub fn init() {
        init();
    }

    pub fn parse_arguments(argc: Argc, arguments: *const Object) -> Vec<Object> {
        unsafe {
            slice::from_raw_parts(arguments, argc as usize).to_vec()
        }
    }

    pub fn parse_itself(itself: Value) -> Object {
        Object::from(itself)
    }
}
<|endoftext|>


<commit_before>pub trait GerberCode {
    fn to_code(&self) -> String;
}

#[derive(Debug)]
pub enum Command {
    FunctionCode(FunctionCode),
    ExtendedCode(ExtendedCode),
}

#[derive(Debug)]
pub enum FunctionCode {
    DCode(DCode),
    GCode(GCode),
    MCode(MCode),
}

#[derive(Debug)]
pub enum ExtendedCode {
    FS,
    MO,
    AD,
    AM,
    SR,
    LP,
    TF,
    TA,
    TD,
}

#[derive(Debug)]
pub enum DCode {
    Operation,
    SelectAperture,
}

#[derive(Debug)]
pub enum InterpolationMode {
    Linear,
    ClockwiseCircular,
    CounterclockwiseCircular,
}

#[derive(Debug)]
pub enum QuadrantMode {
    Single,
    Multi,
}

#[derive(Debug)]
pub enum GCode {
    InterpolationMode(InterpolationMode),
    RegionMode(bool),
    QuadrantMode(QuadrantMode),
    Comment(String),
}

impl GerberCode for GCode {
    fn to_code(&self) -> String {
        match self {
            &GCode::InterpolationMode(ref mode) => {
                match *mode {
                    InterpolationMode::Linear => "G01*",
                    InterpolationMode::ClockwiseCircular => "G02*",
                    InterpolationMode::CounterclockwiseCircular => "G03*",
                }.to_string()
            },
            &GCode::RegionMode(enabled) => {
                match enabled {
                    true => "G36*",
                    false => "G37*",
                }.to_string()
            },
            &GCode::QuadrantMode(ref mode) => {
                match *mode {
                    QuadrantMode::Single => "G74*",
                    QuadrantMode::Multi => "G75*",
                }.to_string()
            },
            &GCode::Comment(ref comment) => format!("G04 {} *", comment),
        }
    }
}

#[derive(Debug)]
pub enum MCode {
    EndOfFile,
}

impl GerberCode for MCode {
    fn to_code(&self) -> String {
        match *self {
            MCode::EndOfFile => "M02*",
        }.to_string()
    }
}

/// Implement GerberCode for Vectors of types that implement GerberCode.
impl<T: GerberCode> GerberCode for Vec<T> {
    fn to_code(&self) -> String {
        self.iter()
            .map(|g| g.to_code())
            .collect::<Vec<String>>()
            .join("\n")
    }
}

#[cfg(test)]
mod test {
    use super::{Command, FunctionCode, DCode};
    use super::{GCode, InterpolationMode, QuadrantMode};
    use super::{MCode};
    use super::GerberCode;

    #[test]
    fn test_debug() {
        //! The debug representation should work properly.
        let c = Command::FunctionCode(FunctionCode::GCode(GCode::Comment("test".to_string())));
        let debug = format!("{:?}", c);
        assert_eq!(debug, "FunctionCode(GCode(Comment(\"test\")))");
    }

    #[test]
    fn test_to_code() {
        //! The to_code method of the GerberCode trait should generate strings.
        let comment = GCode::Comment("testcomment".to_string());
        assert_eq!(comment.to_code(), "G04 testcomment *".to_string());
    }

    #[test]
    fn test_vec_to_code() {
        //! A `Vec<T: GerberCode>` should also implement `GerberCode`.
        let mut v = Vec::new();
        v.push(GCode::Comment("comment 1".to_string()));
        v.push(GCode::Comment("another one".to_string()));
        assert_eq!(v.to_code(), "G04 comment 1 *\nG04 another one *".to_string());
    }

    #[test]
    fn test_interpolation_mode() {
        let mut commands = Vec::new();
        let c1 = GCode::InterpolationMode(InterpolationMode::Linear);
        let c2 = GCode::InterpolationMode(InterpolationMode::ClockwiseCircular);
        let c3 = GCode::InterpolationMode(InterpolationMode::CounterclockwiseCircular);
        commands.push(c1);
        commands.push(c2);
        commands.push(c3);
        assert_eq!(commands.to_code(), "G01*\nG02*\nG03*".to_string());
    }

    #[test]
    fn test_region_mode() {
        let mut commands = Vec::new();
        commands.push(GCode::RegionMode(true));
        commands.push(GCode::RegionMode(false));
        assert_eq!(commands.to_code(), "G36*\nG37*".to_string());
    }

    #[test]
    fn test_quadrant_mode() {
        let mut commands = Vec::new();
        commands.push(GCode::QuadrantMode(QuadrantMode::Single));
        commands.push(GCode::QuadrantMode(QuadrantMode::Multi));
        assert_eq!(commands.to_code(), "G74*\nG75*".to_string());
    }

    #[test]
    fn test_end_of_file() {
        let c = MCode::EndOfFile;
        assert_eq!(c.to_code(), "M02*".to_string());
    }

}
<commit_msg>Move GerberCode impl to subtypes<commit_after>pub trait GerberCode {
    fn to_code(&self) -> String;
}

#[derive(Debug)]
pub enum Command {
    FunctionCode(FunctionCode),
    ExtendedCode(ExtendedCode),
}

#[derive(Debug)]
pub enum FunctionCode {
    DCode(DCode),
    GCode(GCode),
    MCode(MCode),
}

#[derive(Debug)]
pub enum ExtendedCode {
    FS,
    MO,
    AD,
    AM,
    SR,
    LP,
    TF,
    TA,
    TD,
}

#[derive(Debug)]
pub enum DCode {
    Operation,
    SelectAperture,
}

#[derive(Debug)]
pub enum InterpolationMode {
    Linear,
    ClockwiseCircular,
    CounterclockwiseCircular,
}

impl GerberCode for InterpolationMode {
    fn to_code(&self) -> String {
        match *self {
            InterpolationMode::Linear => "G01*",
            InterpolationMode::ClockwiseCircular => "G02*",
            InterpolationMode::CounterclockwiseCircular => "G03*",
        }.to_string()
    }
}

#[derive(Debug)]
pub enum QuadrantMode {
    Single,
    Multi,
}

impl GerberCode for QuadrantMode {
    fn to_code(&self) -> String {
        match *self {
            QuadrantMode::Single => "G74*",
            QuadrantMode::Multi => "G75*",
        }.to_string()
    }
}

#[derive(Debug)]
pub enum GCode {
    InterpolationMode(InterpolationMode),
    RegionMode(bool),
    QuadrantMode(QuadrantMode),
    Comment(String),
}

impl GerberCode for GCode {
    fn to_code(&self) -> String {
        match *self {
            GCode::InterpolationMode(ref mode) => mode.to_code(),
            GCode::RegionMode(enabled) => {
                match enabled {
                    true => "G36*",
                    false => "G37*",
                }.to_string()
            },
            GCode::QuadrantMode(ref mode) => mode.to_code(),
            GCode::Comment(ref comment) => format!("G04 {} *", comment),
        }
    }
}

#[derive(Debug)]
pub enum MCode {
    EndOfFile,
}

impl GerberCode for MCode {
    fn to_code(&self) -> String {
        match *self {
            MCode::EndOfFile => "M02*",
        }.to_string()
    }
}

/// Implement GerberCode for Vectors of types that implement GerberCode.
impl<T: GerberCode> GerberCode for Vec<T> {
    fn to_code(&self) -> String {
        self.iter()
            .map(|g| g.to_code())
            .collect::<Vec<String>>()
            .join("\n")
    }
}

#[cfg(test)]
mod test {
    use super::{Command, FunctionCode, DCode};
    use super::{GCode, InterpolationMode, QuadrantMode};
    use super::{MCode};
    use super::GerberCode;

    #[test]
    fn test_debug() {
        //! The debug representation should work properly.
        let c = Command::FunctionCode(FunctionCode::GCode(GCode::Comment("test".to_string())));
        let debug = format!("{:?}", c);
        assert_eq!(debug, "FunctionCode(GCode(Comment(\"test\")))");
    }

    #[test]
    fn test_to_code() {
        //! The to_code method of the GerberCode trait should generate strings.
        let comment = GCode::Comment("testcomment".to_string());
        assert_eq!(comment.to_code(), "G04 testcomment *".to_string());
    }

    #[test]
    fn test_vec_to_code() {
        //! A `Vec<T: GerberCode>` should also implement `GerberCode`.
        let mut v = Vec::new();
        v.push(GCode::Comment("comment 1".to_string()));
        v.push(GCode::Comment("another one".to_string()));
        assert_eq!(v.to_code(), "G04 comment 1 *\nG04 another one *".to_string());
    }

    #[test]
    fn test_interpolation_mode() {
        let mut commands = Vec::new();
        let c1 = GCode::InterpolationMode(InterpolationMode::Linear);
        let c2 = GCode::InterpolationMode(InterpolationMode::ClockwiseCircular);
        let c3 = GCode::InterpolationMode(InterpolationMode::CounterclockwiseCircular);
        commands.push(c1);
        commands.push(c2);
        commands.push(c3);
        assert_eq!(commands.to_code(), "G01*\nG02*\nG03*".to_string());
    }

    #[test]
    fn test_region_mode() {
        let mut commands = Vec::new();
        commands.push(GCode::RegionMode(true));
        commands.push(GCode::RegionMode(false));
        assert_eq!(commands.to_code(), "G36*\nG37*".to_string());
    }

    #[test]
    fn test_quadrant_mode() {
        let mut commands = Vec::new();
        commands.push(GCode::QuadrantMode(QuadrantMode::Single));
        commands.push(GCode::QuadrantMode(QuadrantMode::Multi));
        assert_eq!(commands.to_code(), "G74*\nG75*".to_string());
    }

    #[test]
    fn test_end_of_file() {
        let c = MCode::EndOfFile;
        assert_eq!(c.to_code(), "M02*".to_string());
    }

}
<|endoftext|>


<commit_before>use git2::Error as Git2Error;

use libimagstore::hook::error::HookError as HE;
use libimagstore::hook::error::HookErrorKind as HEK;
use libimagstore::hook::result::HookResult;

generate_error_module!(
    generate_error_types!(GitHookError, GitHookErrorKind,
        ConfigError => "Configuration Error",
        NoConfigError => "No Configuration",
        ConfigTypeError => "Configuration value type wrong",

        RepositoryError                   => "Error while interacting with git repository",
        RepositoryBackendError            => "Error in the git library",
        RepositoryBranchError             => "Error while interacting with git branch(es)",
        RepositoryBranchNameFetchingError => "Error while fetching branch name",
        RepositoryIndexFetchingError      => "Error while fetching Repository Index",
        RepositoryIndexWritingError       => "Error while writing Repository Index",
        RepositoryPathAddingError         => "Error while adding Path to Index",
        RepositoryCommittingError         => "Error while committing",
        RepositoryParentFetchingError     => "Error while fetching parent of commit",

        HeadFetchError                    => "Error while getting HEAD",
        NotOnBranch                       => "No Branch is checked out",
        MkRepo                            => "Repository creation error",
        MkSignature                       => "Error while building Signature object",

        RepositoryFileStatusError         => "Error while getting file status",

        GitConfigFetchError               => "Error fetching git config",
        GitConfigEditorFetchError         => "Error fetching 'editor' from git config",
        EditorError                       => "Error while calling editor"
    );
);

impl GitHookError {

    pub fn inside_of<T>(self, h: HEK) -> HookResult<T> {
        Err(HE::new(h, Some(Box::new(self))))
    }

}

impl From<GitHookError> for HE {

    fn from(he: GitHookError) -> HE {
        HE::new(HEK::HookExecutionError, Some(Box::new(he)))
    }

}

impl From<Git2Error> for GitHookError {

    fn from(ge: Git2Error) -> GitHookError {
        GitHookError::new(GitHookErrorKind::RepositoryBackendError, Some(Box::new(ge)))
    }

}

pub trait MapIntoHookError<T> {
    fn map_into_hook_error(self) -> Result<T, HE>;
}

impl<T> MapIntoHookError<T> for Result<T, GitHookError> {

    fn map_into_hook_error(self) -> Result<T, HE> {
        self.map_err(|e| HE::new(HEK::HookExecutionError, Some(Box::new(e))))
    }

}

pub use self::error::GitHookError;
pub use self::error::GitHookErrorKind;
pub use self::error::MapErrInto;

<commit_msg>Add error kind for repo initialization errors<commit_after>use git2::Error as Git2Error;

use libimagstore::hook::error::HookError as HE;
use libimagstore::hook::error::HookErrorKind as HEK;
use libimagstore::hook::result::HookResult;

generate_error_module!(
    generate_error_types!(GitHookError, GitHookErrorKind,
        ConfigError => "Configuration Error",
        NoConfigError => "No Configuration",
        ConfigTypeError => "Configuration value type wrong",

        RepositoryError                   => "Error while interacting with git repository",
        RepositoryInitError               => "Error while loading the git repository",
        RepositoryBackendError            => "Error in the git library",
        RepositoryBranchError             => "Error while interacting with git branch(es)",
        RepositoryBranchNameFetchingError => "Error while fetching branch name",
        RepositoryIndexFetchingError      => "Error while fetching Repository Index",
        RepositoryIndexWritingError       => "Error while writing Repository Index",
        RepositoryPathAddingError         => "Error while adding Path to Index",
        RepositoryCommittingError         => "Error while committing",
        RepositoryParentFetchingError     => "Error while fetching parent of commit",

        HeadFetchError                    => "Error while getting HEAD",
        NotOnBranch                       => "No Branch is checked out",
        MkRepo                            => "Repository creation error",
        MkSignature                       => "Error while building Signature object",

        RepositoryFileStatusError         => "Error while getting file status",

        GitConfigFetchError               => "Error fetching git config",
        GitConfigEditorFetchError         => "Error fetching 'editor' from git config",
        EditorError                       => "Error while calling editor"
    );
);

impl GitHookError {

    pub fn inside_of<T>(self, h: HEK) -> HookResult<T> {
        Err(HE::new(h, Some(Box::new(self))))
    }

}

impl From<GitHookError> for HE {

    fn from(he: GitHookError) -> HE {
        HE::new(HEK::HookExecutionError, Some(Box::new(he)))
    }

}

impl From<Git2Error> for GitHookError {

    fn from(ge: Git2Error) -> GitHookError {
        GitHookError::new(GitHookErrorKind::RepositoryBackendError, Some(Box::new(ge)))
    }

}

pub trait MapIntoHookError<T> {
    fn map_into_hook_error(self) -> Result<T, HE>;
}

impl<T> MapIntoHookError<T> for Result<T, GitHookError> {

    fn map_into_hook_error(self) -> Result<T, HE> {
        self.map_err(|e| HE::new(HEK::HookExecutionError, Some(Box::new(e))))
    }

}

pub use self::error::GitHookError;
pub use self::error::GitHookErrorKind;
pub use self::error::MapErrInto;

<|endoftext|>


<commit_before>//!
//! Hold the `Game` struct and the `play()` function
//!

// Tcod
extern crate tcod;
use self::tcod::{console, Console};
use core::tcod::input;

// core::world
pub mod world;
use core::world::World;

// core::object
pub mod object;
// Game state depends on what actions the player can do
use core::object::actions::Actions;

// core::renderer
pub mod renderer;
use self::renderer::Renderer;
use self::renderer::RGB;

// core::log
pub mod log;
use self::log::GlobalLog;

// Use init here privately
// After all, what game function requires that something in the initalizer be ran?
mod init;

///
/// Enum representing the state of the game
///
pub enum State {
  // Game just created
  New,
  // Player acted
  Act(Actions),
  // Debug
  Debug
}

///
/// Engine struct. Holds a world, state, and renderer
///
pub struct Engine {
  world: World,
  state: State,
  ren: Renderer,
  root: console::Root,
}

impl Engine {

  ///
  /// Capture keyboard input from tcod and update player state
  ///
  fn process_keypress(&mut self, keypress: input::Key) {

    match keypress.code {

      // If the keycode isn't escape we continue checking for important keys
      input::KeyCode::Escape => panic!("Bye"),
      _ => {

        if keypress.printable != ' ' {

          let oldpos = self.world.player.actor.pos.clone();

          // Wipe the state
          self.state = State::New;

          match keypress.printable {

            // Movement keys are bound to vim-like controls (hjklyubn)
            'h' => {
              self.world.player.actor.move_cart(-1, 0);
              self.world.player.state = Actions::Move;
            },
            'j' => {
              self.world.player.actor.move_cart(0, 1);
              self.world.player.state = Actions::Move;
            },
            'k' => {
              self.world.player.actor.move_cart(0, -1);
              self.world.player.state = Actions::Move;
            },
            'l' => {
              self.world.player.actor.move_cart(1, 0);
              self.world.player.state = Actions::Move;
            },
            'y' => {
              self.world.player.actor.move_cart(-1, -1);
              self.world.player.state = Actions::Move;
            },
            'u' => {
              self.world.player.actor.move_cart(1, -1);
              self.world.player.state = Actions::Move;
            },
            'b' => {
              self.world.player.actor.move_cart(-1, 1);
              self.world.player.state = Actions::Move;
            },
            'n' => {
              self.world.player.actor.move_cart(1, 1);
              self.world.player.state = Actions::Move;
            },
            // "Regenerate" current level
            'w' => {
              self.world.test_traverse();
              self.state = State::Act(Actions::Unknown);
            },
            // Create an empty level for testing
            'q' => {
              self.world.test_empty();
              self.state = State::Act(Actions::Unknown);
            },
            // Wait
            '.' => {
              self.world.player.state = Actions::Wait;
            },
            // Go downstars (if possible)
            '>' => { self.world.player.state = Actions::DownStair },
            // Go upstairs (if possible)
            '<' => { self.world.player.state = Actions::UpStair },
            // Unbound key, so we just say we don't know what the player did

            // Debug keypresses

            // Toggle scent
            'r' => {
              self.ren.show_scent = !self.ren.show_scent;
              self.ren.draw_all(&mut self.root, &mut self.world);
              self.state = State::Debug;
            },

            // Toggle sound
            't' => {
              self.ren.show_sound = !self.ren.show_sound;
              self.ren.draw_all(&mut self.root, &mut self.world);
              self.state = State::Debug;
            },

            // Toggle FoV
            'f' => {
              self.ren.fov = !self.ren.fov;
              self.ren.draw_all(&mut self.root, &mut self.world);
              self.state = State::Debug;
            },

            _ => { self.world.player.state = Actions::Unknown }

          }

          // Make sure player doesn't do anything dumb
          if !self.world.is_valid(self.world.player.actor.pos.x, self.world.player.actor.pos.y) {
            self.world.player.actor.pos = oldpos;
            self.world.player.state = Actions::Unknown;
          }

          // If state is Debug, don't override
          match self.state {
            State::Debug => (),
            _ => {
              match self.world.player.state {
                _ => { self.state = State::Act(self.world.player.state.clone()) }
              }
            }
          }

        }

        /*
        // Prints keycode to console in case if you're trying to find a key that isn't intutive
        else {
          println!("{:?}", keypress.code);
        }
        */

      }

    }

  }

  ///
  /// Return a new `Game`
  ///
  /// This function assumes you will just be passing in tcod::console::Root.width() and height(),
  /// so inputs are i32s instead of usizes (they get converted)
  ///
  pub fn new() -> Engine {

    // Get map height
    let map_dim = init::map_dimensions();

    // Get root console
    let root = init::root();

    Engine {
      world: World::new(map_dim),
      state: State::New,
      ren: Renderer::new(
        map_dim,
        (root.width() as isize, root.height() as isize),
        init::console_height(),
        init::panel_width()
      ),
      root: root,
    }

  }

  ///
  /// Update the game state, then update depending on the new state
  ///
  fn update(&mut self) {

    match &self.state {
      // Moving or waiting prompts a world update
      &State::Act(Actions::Move) | &State::Act(Actions::Wait) => self.world.update(),

      // Trying to go up and downstairs prompts the respective response from world
      &State::Act(Actions::DownStair) => {
        if self.world.can_go_down() {
          self.world.go_down();
        }
      },
      &State::Act(Actions::UpStair) => {
        if self.world.can_go_up() {
          self.world.go_up();
        }
      }

      // All other variants are dropped
      _ => ()
    }

  }

  ///
  /// Play the game.
  ///
  pub fn play(&mut self) {

    // Some starting messages, will be removed in later versions
    let mut log = GlobalLog.lock().unwrap();
    log.push(("Welcome to Edgequest", RGB(255, 0, 255)));
    log.push(("Move with vim keys", RGB(255, 255, 255)));
    log.push(("esc to quit, w to regenerate", RGB(255, 255, 255)));
    log.push(("r to toggle scent, t to toggle sound", RGB(255, 255, 255)));
    log.push(("f to toggle FoV", RGB(255, 255, 255)));
    drop(log);

    // Initial update
    self.update();

    // Draw all and capture keypresses
    while !self.root.window_closed() {

      // Draw what the camera sees
      self.ren.draw_all(&mut self.root, &mut self.world);

      // Capture game keys (Keys that change the state of the player)
      // This is what gives it the turn based nature, i.e. waits for player input before
      // doing anything
      let keypress = self.root.wait_for_keypress(true);
      self.process_keypress(keypress);

      // Update game
      self.update();

    }

  }

}<commit_msg>Add noclip<commit_after>//!
//! Hold the `Game` struct and the `play()` function
//!

// Tcod
extern crate tcod;
use self::tcod::{console, Console};
use core::tcod::input;

// core::world
pub mod world;
use core::world::World;

// core::object
pub mod object;
// Game state depends on what actions the player can do
use core::object::actions::Actions;

// core::renderer
pub mod renderer;
use self::renderer::Renderer;
use self::renderer::RGB;

// core::log
pub mod log;
use self::log::GlobalLog;

// Use init here privately
// After all, what game function requires that something in the initalizer be ran?
mod init;

///
/// Enum representing the state of the game
///
pub enum State {
  // Game just created
  New,
  // Player acted
  Act(Actions),
  // Debug
  Debug
}

///
/// Engine struct. Holds a world, state, and renderer
///
pub struct Engine {
  world: World,
  state: State,
  ren: Renderer,
  root: console::Root,

  // Debug
  noclip: bool

}

impl Engine {

  ///
  /// Capture keyboard input from tcod and update player state
  ///
  fn process_keypress(&mut self, keypress: input::Key) {

    match keypress.code {

      // If the keycode isn't escape we continue checking for important keys
      input::KeyCode::Escape => panic!("Bye"),
      _ => {

        if keypress.printable != ' ' {

          let oldpos = self.world.player.actor.pos.clone();

          // Wipe the state
          self.state = State::New;

          match keypress.printable {

            // Movement keys are bound to vim-like controls (hjklyubn)
            'h' => {
              self.world.player.actor.move_cart(-1, 0);
              self.world.player.state = Actions::Move;
            },
            'j' => {
              self.world.player.actor.move_cart(0, 1);
              self.world.player.state = Actions::Move;
            },
            'k' => {
              self.world.player.actor.move_cart(0, -1);
              self.world.player.state = Actions::Move;
            },
            'l' => {
              self.world.player.actor.move_cart(1, 0);
              self.world.player.state = Actions::Move;
            },
            'y' => {
              self.world.player.actor.move_cart(-1, -1);
              self.world.player.state = Actions::Move;
            },
            'u' => {
              self.world.player.actor.move_cart(1, -1);
              self.world.player.state = Actions::Move;
            },
            'b' => {
              self.world.player.actor.move_cart(-1, 1);
              self.world.player.state = Actions::Move;
            },
            'n' => {
              self.world.player.actor.move_cart(1, 1);
              self.world.player.state = Actions::Move;
            },
            // "Regenerate" current level
            'w' => {
              self.world.test_traverse();
              self.state = State::Act(Actions::Unknown);
            },
            // Create an empty level for testing
            'q' => {
              self.world.test_empty();
              self.state = State::Act(Actions::Unknown);
            },
            // Wait
            '.' => {
              self.world.player.state = Actions::Wait;
            },
            // Go downstars (if possible)
            '>' => { self.world.player.state = Actions::DownStair },
            // Go upstairs (if possible)
            '<' => { self.world.player.state = Actions::UpStair },
            // Unbound key, so we just say we don't know what the player did

            // Debug keypresses

            // Toggle scent
            'r' => {
              self.ren.show_scent = !self.ren.show_scent;
              self.ren.draw_all(&mut self.root, &mut self.world);
              self.state = State::Debug;
            },

            // Toggle sound
            't' => {
              self.ren.show_sound = !self.ren.show_sound;
              self.ren.draw_all(&mut self.root, &mut self.world);
              self.state = State::Debug;
            },

            // Toggle FoV
            'f' => {
              self.ren.fov = !self.ren.fov;
              self.ren.draw_all(&mut self.root, &mut self.world);
              self.state = State::Debug;
            },

            // Toggle noclip
            'z' => {
              self.noclip = !self.noclip;
              self.state = State::Debug;
            },

            _ => { self.world.player.state = Actions::Unknown }

          }

          // If state is Debug, don't override
          match self.state {
            State::Debug => (),
            _ => {
              // Set game state to player state
              self.state = State::Act(self.world.player.state.clone());

              match self.world.player.state {
                Actions::Move => {
                  // Make sure player doesn't do anything dumb
                  if !self.world.is_valid(self.world.player.actor.pos.x, self.world.player.actor.pos.y) && !self.noclip {
                    self.world.player.actor.pos = oldpos;
                    self.world.player.state = Actions::Unknown;
                  }
                }
                _ => ()
              }

            }
          }

        }

        /*
        // Prints keycode to console in case if you're trying to find a key that isn't intutive
        else {
          println!("{:?}", keypress.code);
        }
        */

      }

    }

  }

  ///
  /// Return a new `Game`
  ///
  /// This function assumes you will just be passing in tcod::console::Root.width() and height(),
  /// so inputs are i32s instead of usizes (they get converted)
  ///
  pub fn new() -> Engine {

    // Get map height
    let map_dim = init::map_dimensions();

    // Get root console
    let root = init::root();

    Engine {
      world: World::new(map_dim),
      state: State::New,
      ren: Renderer::new(
        map_dim,
        (root.width() as isize, root.height() as isize),
        init::console_height(),
        init::panel_width()
      ),
      root: root,

      // Debug
      noclip: false
    }

  }

  ///
  /// Update the game state, then update depending on the new state
  ///
  fn update(&mut self) {

    match &self.state {
      // Moving or waiting prompts a world update
      &State::Act(Actions::Move) | &State::Act(Actions::Wait) => self.world.update(),

      // Trying to go up and downstairs prompts the respective response from world
      &State::Act(Actions::DownStair) => {
        if self.world.can_go_down() {
          self.world.go_down();
        }
      },
      &State::Act(Actions::UpStair) => {
        if self.world.can_go_up() {
          self.world.go_up();
        }
      }

      // All other variants are dropped
      _ => ()
    }

  }

  ///
  /// Play the game.
  ///
  pub fn play(&mut self) {

    // Some starting messages, will be removed in later versions
    let mut log = GlobalLog.lock().unwrap();
    log.push(("Welcome to Edgequest", RGB(255, 0, 255)));
    log.push(("Move with vim keys", RGB(255, 255, 255)));
    log.push(("esc to quit, w to regenerate", RGB(255, 255, 255)));
    log.push(("r to toggle scent, t to toggle sound", RGB(255, 255, 255)));
    log.push(("f to toggle FoV, z to toggle noclip", RGB(255, 255, 255)));
    drop(log);

    // Initial update
    self.update();

    // Draw all and capture keypresses
    while !self.root.window_closed() {

      // Draw what the camera sees
      self.ren.draw_all(&mut self.root, &mut self.world);

      // Capture game keys (Keys that change the state of the player)
      // This is what gives it the turn based nature, i.e. waits for player input before
      // doing anything
      let keypress = self.root.wait_for_keypress(true);
      self.process_keypress(keypress);

      // Update game
      self.update();

    }

  }

}<|endoftext|>


<commit_before>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

extern crate libc;

use libc::{gid_t, pid_t, uid_t};
use std::os::raw::{c_char, c_int, c_ulong};

/// Struct minijail is an opaque type inside libminijail.
/// See the minijail man page for a description of funcitons.
#[derive(Debug, Copy, Clone)]
pub enum minijail {}

#[link(name = "minijail")]
extern "C" {
    pub fn minijail_new() -> *mut minijail;
    pub fn minijail_change_uid(j: *mut minijail, uid: uid_t);
    pub fn minijail_change_gid(j: *mut minijail, gid: gid_t);
    pub fn minijail_set_supplementary_gids(j: *mut minijail,
                                           size: usize,
                                           list: *const gid_t);
    pub fn minijail_keep_supplementary_gids(j: *mut minijail);
    pub fn minijail_change_user(j: *mut minijail,
                                user: *const c_char)
                                -> c_int;
    pub fn minijail_change_group(j: *mut minijail,
                                 group: *const c_char)
                                 -> c_int;
    pub fn minijail_use_seccomp(j: *mut minijail);
    pub fn minijail_no_new_privs(j: *mut minijail);
    pub fn minijail_use_seccomp_filter(j: *mut minijail);
    pub fn minijail_set_seccomp_filter_tsync(j: *mut minijail);
    pub fn minijail_parse_seccomp_filters(j: *mut minijail, path: *const c_char);
    pub fn minijail_parse_seccomp_filters_from_fd(j: *mut minijail, fd: c_int);
    pub fn minijail_log_seccomp_filter_failures(j: *mut minijail);
    pub fn minijail_use_caps(j: *mut minijail, capmask: u64);
    pub fn minijail_capbset_drop(j: *mut minijail, capmask: u64);
    pub fn minijail_set_ambient_caps(j: *mut minijail);
    pub fn minijail_reset_signal_mask(j: *mut minijail);
    pub fn minijail_namespace_vfs(j: *mut minijail);
    pub fn minijail_namespace_enter_vfs(j: *mut minijail, ns_path: *const c_char);
    pub fn minijail_new_session_keyring(j: *mut minijail);
    pub fn minijail_skip_remount_private(j: *mut minijail);
    pub fn minijail_namespace_ipc(j: *mut minijail);
    pub fn minijail_namespace_net(j: *mut minijail);
    pub fn minijail_namespace_enter_net(j: *mut minijail, ns_path: *const c_char);
    pub fn minijail_namespace_cgroups(j: *mut minijail);
    pub fn minijail_close_open_fds(j: *mut minijail);
    pub fn minijail_namespace_pids(j: *mut minijail);
    pub fn minijail_namespace_user(j: *mut minijail);
    pub fn minijail_namespace_user_disable_setgroups(j: *mut minijail);
    pub fn minijail_uidmap(j: *mut minijail,
                           uidmap: *const c_char)
                           -> c_int;
    pub fn minijail_gidmap(j: *mut minijail,
                           gidmap: *const c_char)
                           -> c_int;
    pub fn minijail_remount_proc_readonly(j: *mut minijail);
    pub fn minijail_run_as_init(j: *mut minijail);
    pub fn minijail_write_pid_file(j: *mut minijail,
                                   path: *const c_char)
                                   -> c_int;
    pub fn minijail_inherit_usergroups(j: *mut minijail);
    pub fn minijail_use_alt_syscall(j: *mut minijail,
                                    table: *const c_char)
                                    -> c_int;
    pub fn minijail_add_to_cgroup(j: *mut minijail,
                                  path: *const c_char)
                                  -> c_int;
    pub fn minijail_enter_chroot(j: *mut minijail,
                                 dir: *const c_char)
                                 -> c_int;
    pub fn minijail_enter_pivot_root(j: *mut minijail,
                                     dir: *const c_char)
                                     -> c_int;
    pub fn minijail_fork(j: *mut minijail) -> pid_t;
    pub fn minijail_get_original_path(j: *mut minijail,
                                      chroot_path: *const c_char)
                                      -> *mut c_char;
    pub fn minijail_mount_tmp(j: *mut minijail);
    pub fn minijail_mount_tmp_size(j: *mut minijail, size: usize);
    pub fn minijail_mount_with_data(j: *mut minijail,
                                    src: *const c_char,
                                    dest: *const c_char,
                                    type_: *const c_char,
                                    flags: c_ulong,
                                    data: *const c_char)
                                    -> c_int;
    pub fn minijail_mount(j: *mut minijail,
                          src: *const c_char,
                          dest: *const c_char,
                          type_: *const c_char,
                          flags: c_ulong)
                          -> c_int;
    pub fn minijail_bind(j: *mut minijail,
                         src: *const c_char,
                         dest: *const c_char,
                         writeable: c_int)
                         -> c_int;
    pub fn minijail_preserve_fd(j: *mut minijail,
                                parent_fd: c_int,
                                child_fd: c_int)
                                -> c_int;
    pub fn minijail_enter(j: *const minijail);
    pub fn minijail_run(j: *mut minijail,
                        filename: *const c_char,
                        argv: *const *const c_char)
                        -> c_int;
    pub fn minijail_run_no_preload(j: *mut minijail,
                                   filename: *const c_char,
                                   argv: *const *const c_char)
                                   -> c_int;
    pub fn minijail_run_pid(j: *mut minijail,
                            filename: *const c_char,
                            argv: *const *const c_char,
                            pchild_pid: *mut pid_t)
                            -> c_int;
    pub fn minijail_run_pipe(j: *mut minijail,
                             filename: *const c_char,
                             argv: *const *const c_char,
                             pstdin_fd: *mut c_int)
                             -> c_int;
    pub fn minijail_run_pid_pipes(j: *mut minijail,
                                  filename: *const c_char,
                                  argv: *const *const c_char,
                                  pchild_pid: *mut pid_t,
                                  pstdin_fd: *mut c_int,
                                  pstdout_fd: *mut c_int,
                                  pstderr_fd: *mut c_int)
                                  -> c_int;
    pub fn minijail_run_pid_pipes_no_preload(j: *mut minijail,
                                             filename: *const c_char,
                                             argv: *const *const c_char,
                                             pchild_pid: *mut pid_t,
                                             pstdin_fd: *mut c_int,
                                             pstdout_fd: *mut c_int,
                                             pstderr_fd: *mut c_int)
                                             -> c_int;
    pub fn minijail_kill(j: *mut minijail) -> c_int;
    pub fn minijail_wait(j: *mut minijail) -> c_int;
    pub fn minijail_destroy(j: *mut minijail);
} // extern "C"
<commit_msg>Fix typo in libminijail.rs.<commit_after>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

extern crate libc;

use libc::{gid_t, pid_t, uid_t};
use std::os::raw::{c_char, c_int, c_ulong};

/// Struct minijail is an opaque type inside libminijail.
/// See the minijail man page for a description of functions.
#[derive(Debug, Copy, Clone)]
pub enum minijail {}

#[link(name = "minijail")]
extern "C" {
    pub fn minijail_new() -> *mut minijail;
    pub fn minijail_change_uid(j: *mut minijail, uid: uid_t);
    pub fn minijail_change_gid(j: *mut minijail, gid: gid_t);
    pub fn minijail_set_supplementary_gids(j: *mut minijail,
                                           size: usize,
                                           list: *const gid_t);
    pub fn minijail_keep_supplementary_gids(j: *mut minijail);
    pub fn minijail_change_user(j: *mut minijail,
                                user: *const c_char)
                                -> c_int;
    pub fn minijail_change_group(j: *mut minijail,
                                 group: *const c_char)
                                 -> c_int;
    pub fn minijail_use_seccomp(j: *mut minijail);
    pub fn minijail_no_new_privs(j: *mut minijail);
    pub fn minijail_use_seccomp_filter(j: *mut minijail);
    pub fn minijail_set_seccomp_filter_tsync(j: *mut minijail);
    pub fn minijail_parse_seccomp_filters(j: *mut minijail, path: *const c_char);
    pub fn minijail_parse_seccomp_filters_from_fd(j: *mut minijail, fd: c_int);
    pub fn minijail_log_seccomp_filter_failures(j: *mut minijail);
    pub fn minijail_use_caps(j: *mut minijail, capmask: u64);
    pub fn minijail_capbset_drop(j: *mut minijail, capmask: u64);
    pub fn minijail_set_ambient_caps(j: *mut minijail);
    pub fn minijail_reset_signal_mask(j: *mut minijail);
    pub fn minijail_namespace_vfs(j: *mut minijail);
    pub fn minijail_namespace_enter_vfs(j: *mut minijail, ns_path: *const c_char);
    pub fn minijail_new_session_keyring(j: *mut minijail);
    pub fn minijail_skip_remount_private(j: *mut minijail);
    pub fn minijail_namespace_ipc(j: *mut minijail);
    pub fn minijail_namespace_net(j: *mut minijail);
    pub fn minijail_namespace_enter_net(j: *mut minijail, ns_path: *const c_char);
    pub fn minijail_namespace_cgroups(j: *mut minijail);
    pub fn minijail_close_open_fds(j: *mut minijail);
    pub fn minijail_namespace_pids(j: *mut minijail);
    pub fn minijail_namespace_user(j: *mut minijail);
    pub fn minijail_namespace_user_disable_setgroups(j: *mut minijail);
    pub fn minijail_uidmap(j: *mut minijail,
                           uidmap: *const c_char)
                           -> c_int;
    pub fn minijail_gidmap(j: *mut minijail,
                           gidmap: *const c_char)
                           -> c_int;
    pub fn minijail_remount_proc_readonly(j: *mut minijail);
    pub fn minijail_run_as_init(j: *mut minijail);
    pub fn minijail_write_pid_file(j: *mut minijail,
                                   path: *const c_char)
                                   -> c_int;
    pub fn minijail_inherit_usergroups(j: *mut minijail);
    pub fn minijail_use_alt_syscall(j: *mut minijail,
                                    table: *const c_char)
                                    -> c_int;
    pub fn minijail_add_to_cgroup(j: *mut minijail,
                                  path: *const c_char)
                                  -> c_int;
    pub fn minijail_enter_chroot(j: *mut minijail,
                                 dir: *const c_char)
                                 -> c_int;
    pub fn minijail_enter_pivot_root(j: *mut minijail,
                                     dir: *const c_char)
                                     -> c_int;
    pub fn minijail_fork(j: *mut minijail) -> pid_t;
    pub fn minijail_get_original_path(j: *mut minijail,
                                      chroot_path: *const c_char)
                                      -> *mut c_char;
    pub fn minijail_mount_tmp(j: *mut minijail);
    pub fn minijail_mount_tmp_size(j: *mut minijail, size: usize);
    pub fn minijail_mount_with_data(j: *mut minijail,
                                    src: *const c_char,
                                    dest: *const c_char,
                                    type_: *const c_char,
                                    flags: c_ulong,
                                    data: *const c_char)
                                    -> c_int;
    pub fn minijail_mount(j: *mut minijail,
                          src: *const c_char,
                          dest: *const c_char,
                          type_: *const c_char,
                          flags: c_ulong)
                          -> c_int;
    pub fn minijail_bind(j: *mut minijail,
                         src: *const c_char,
                         dest: *const c_char,
                         writeable: c_int)
                         -> c_int;
    pub fn minijail_preserve_fd(j: *mut minijail,
                                parent_fd: c_int,
                                child_fd: c_int)
                                -> c_int;
    pub fn minijail_enter(j: *const minijail);
    pub fn minijail_run(j: *mut minijail,
                        filename: *const c_char,
                        argv: *const *const c_char)
                        -> c_int;
    pub fn minijail_run_no_preload(j: *mut minijail,
                                   filename: *const c_char,
                                   argv: *const *const c_char)
                                   -> c_int;
    pub fn minijail_run_pid(j: *mut minijail,
                            filename: *const c_char,
                            argv: *const *const c_char,
                            pchild_pid: *mut pid_t)
                            -> c_int;
    pub fn minijail_run_pipe(j: *mut minijail,
                             filename: *const c_char,
                             argv: *const *const c_char,
                             pstdin_fd: *mut c_int)
                             -> c_int;
    pub fn minijail_run_pid_pipes(j: *mut minijail,
                                  filename: *const c_char,
                                  argv: *const *const c_char,
                                  pchild_pid: *mut pid_t,
                                  pstdin_fd: *mut c_int,
                                  pstdout_fd: *mut c_int,
                                  pstderr_fd: *mut c_int)
                                  -> c_int;
    pub fn minijail_run_pid_pipes_no_preload(j: *mut minijail,
                                             filename: *const c_char,
                                             argv: *const *const c_char,
                                             pchild_pid: *mut pid_t,
                                             pstdin_fd: *mut c_int,
                                             pstdout_fd: *mut c_int,
                                             pstderr_fd: *mut c_int)
                                             -> c_int;
    pub fn minijail_kill(j: *mut minijail) -> c_int;
    pub fn minijail_wait(j: *mut minijail) -> c_int;
    pub fn minijail_destroy(j: *mut minijail);
} // extern "C"
<|endoftext|>


<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Ben Gamari <bgamari@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::rc::Rc;
use std::iter::FromIterator;
use syntax::ast;
use syntax::ptr::P;
use syntax::ast_util::empty_generics;
use syntax::codemap::{DUMMY_SP, dummy_spanned, respan, Spanned};
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::parse::token;

use node;
use super::Builder;
use super::utils;

enum RegOrPadding<'a> {
  /// A register
  Reg(&'a node::Reg),
  /// A given number of bytes of padding
  Pad(u64)
}

/// An iterator which takes a potentially unsorted list of registers,
/// sorts them, and adds padding to make offsets correct
struct PaddedRegsIterator<'a> {
  sorted_regs: &'a Vec<node::Reg>,
  index: usize,
  last_offset: u64,
}

impl<'a> PaddedRegsIterator<'a> {
  fn new(regs: &'a mut Vec<node::Reg>) -> PaddedRegsIterator<'a> {
    regs.sort_by(|r1,r2| r1.offset.cmp(&r2.offset));
    PaddedRegsIterator {
      sorted_regs: regs,
      index: 0,
      last_offset: 0,
    }
  }
}

impl<'a> Iterator for PaddedRegsIterator<'a> {
  type Item = RegOrPadding<'a>;
  fn next(&mut self) -> Option<RegOrPadding<'a>> {
    if self.index >= self.sorted_regs.len() {
      None
    } else {
      let ref reg = self.sorted_regs[self.index];
      if reg.offset > self.last_offset {
        let pad_length = reg.offset - self.last_offset;
        self.last_offset = reg.offset;
        Some(RegOrPadding::Pad(pad_length))
      } else {
        self.index += 1;
        self.last_offset += reg.size();
        Some(RegOrPadding::Reg(reg))
      }
    }
  }
}

/// Build types for `RegUnions`
pub struct BuildUnionTypes<'a> {
  builder: &'a mut Builder,
  cx: &'a ExtCtxt<'a>
}

impl<'a> BuildUnionTypes<'a> {
  pub fn new(builder: &'a mut Builder, cx: &'a ExtCtxt<'a>)
      -> BuildUnionTypes<'a> {
    BuildUnionTypes { builder: builder, cx: cx }
  }
}

fn expr_usize(cx: &ExtCtxt, n: Spanned<u64>) -> P<ast::Expr> {
  cx.expr_lit(n.span, ast::LitInt(n.node as u64, ast::UnsignedIntLit(ast::TyUs)))
}

/// Returns the type of the field representing the given register
/// within a `RegGroup` struct
fn reg_struct_type(cx: &ExtCtxt, path: &Vec<String>, reg: &node::Reg)
                   -> P<ast::Ty> {
  let base_ty_path = cx.path_ident(reg.name.span, utils::path_ident(cx, path));
  let base_ty: P<ast::Ty> = cx.ty_path(base_ty_path);
  match reg.count.node {
    1 => base_ty,
    n =>
      cx.ty(reg.count.span,
            ast::TyFixedLengthVec(base_ty, expr_usize(cx, respan(reg.count.span, n as u64)))),
  }
}

impl<'a> node::RegVisitor for BuildUnionTypes<'a> {
  fn visit_union_reg<'b>(&'b mut self, path: &Vec<String>, reg: &'b node::Reg,
                         subregs: Rc<Vec<node::Reg>>) {
    let items = self.build_union_type(path, reg, &*subregs);
    for item in items.into_iter() {
      self.builder.push_item(item);
    }
  }
}

impl<'a> BuildUnionTypes<'a> {
  /// Produce a field for the given register in a `RegUnion` struct
  fn build_reg_union_field(&self, path: &Vec<String>, reg: &node::Reg)
                           -> ast::StructField {
    let attrs = match reg.docstring {
      Some(doc) => vec!(utils::doc_attribute(self.cx, token::get_ident(doc.node))),
      None => Vec::new(),
    };
    let mut field_path = path.clone();
    field_path.push(reg.name.node.clone());
    dummy_spanned(
      ast::StructField_ {
        kind: ast::NamedField(
          self.cx.ident_of(reg.name.node.as_str()),
          ast::Public),
        id: ast::DUMMY_NODE_ID,
        ty: reg_struct_type(self.cx, &field_path, reg),
        attrs: attrs,
      }
    )
  }

  /// Build field for padding or a register
  // Dummy spans allowed here because u8 doesn't come from anywhere
  #[allow(dummy_span)]
  fn build_pad_or_reg(&self, path: &Vec<String>, reg_or_pad: RegOrPadding,
                      index: usize) -> ast::StructField {
    match reg_or_pad {
      RegOrPadding::Reg(reg) => self.build_reg_union_field(path, reg),
      RegOrPadding::Pad(length) => {
        let u8_path = self.cx.path_ident(
          DUMMY_SP,
          self.cx.ident_of("u8"));
        let u8_ty: P<ast::Ty> = self.cx.ty_path(u8_path);
        let ty: P<ast::Ty> =
          self.cx.ty(
            DUMMY_SP,
            ast::TyFixedLengthVec(u8_ty, expr_usize(self.cx, respan(DUMMY_SP, length))));
        dummy_spanned(
          ast::StructField_ {
            kind: ast::NamedField(
              self.cx.ident_of(format!("_pad{}", index).as_str()),
              ast::Inherited),
            id: ast::DUMMY_NODE_ID,
            ty: ty,
            attrs: Vec::new(),
          },
        )
      },
    }
  }

  /// Build the type associated with a register group
  fn build_union_type(&self, path: &Vec<String>, reg: &node::Reg,
                      regs: &Vec<node::Reg>) -> Vec<P<ast::Item>> {
    let name = utils::path_ident(self.cx, path);
    // Registers are already sorted by parser
    let mut regs = regs.clone();
    let mut regs2 = regs.clone();
    let padded_regs = PaddedRegsIterator::new(&mut regs);
    let fields =
      padded_regs.enumerate().map(|(n,r)| self.build_pad_or_reg(path, r, n));
    let struct_def = ast::StructDef {
      fields: FromIterator::from_iter(fields),
      ctor_id: None,
    };
    let mut attrs: Vec<ast::Attribute> = vec!(
      utils::list_attribute(self.cx, "allow",
                            vec!("non_camel_case_types",
                                 "dead_code",
                                 "missing_docs"),
                            reg.name.span),
    );
    match reg.docstring {
      Some(docstring) =>
        attrs.push(
          utils::doc_attribute(self.cx, token::get_ident(docstring.node))),
      None => (),
    }
    let struct_item = P(ast::Item {
      ident: name,
      attrs: attrs,
      id: ast::DUMMY_NODE_ID,
      node: ast::ItemStruct(P(struct_def), empty_generics()),
      vis: ast::Public,
      span: reg.name.span,
    });
    let mut full_size: u64 = 0;
    //FIXME(mcoffin) - We're making this iterator twice
    let padded_regs2 = PaddedRegsIterator::new(&mut regs2);
    padded_regs2.enumerate().map(|(_, rp)| {
      full_size += match rp {
        RegOrPadding::Reg(reg) => reg.ty.size(),
        RegOrPadding::Pad(s) => s,
      };
    }).count();
    let clone_impl = quote_item!(self.cx,
      impl ::core::clone::Clone for $name {
        fn clone(&self) -> Self {
          let mut next: $name = unsafe {
            ::core::mem::uninitialized()
          };
          unsafe {
            let next_ptr: *mut $name = &mut next;
            ::core::intrinsics::copy(
              ::core::mem::transmute(self),
              next_ptr,
              $full_size as usize);
            return next;
          }
        }
      }
    ).unwrap();

    let copy_impl = quote_item!(self.cx, impl ::core::marker::Copy for $name {}).unwrap();

    let item_address = reg.address;
    let item_getter = quote_item!(self.cx,
      #[allow(non_snake_case, dead_code)]
      pub fn $name() -> &'static $name {
          unsafe { ::core::intrinsics::transmute($item_address as usize) }
      }
    ).unwrap();
    if item_address == 0 {
      vec!(struct_item, clone_impl, copy_impl)
    } else {
      vec!(struct_item, clone_impl, copy_impl, item_getter)
    }
  }
}
<commit_msg>Added docattr for ioreg placement getter<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Ben Gamari <bgamari@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::rc::Rc;
use std::iter::FromIterator;
use syntax::ast;
use syntax::ptr::P;
use syntax::ast_util::empty_generics;
use syntax::codemap::{DUMMY_SP, dummy_spanned, respan, Spanned};
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::parse::token;

use node;
use super::Builder;
use super::utils;

enum RegOrPadding<'a> {
  /// A register
  Reg(&'a node::Reg),
  /// A given number of bytes of padding
  Pad(u64)
}

/// An iterator which takes a potentially unsorted list of registers,
/// sorts them, and adds padding to make offsets correct
struct PaddedRegsIterator<'a> {
  sorted_regs: &'a Vec<node::Reg>,
  index: usize,
  last_offset: u64,
}

impl<'a> PaddedRegsIterator<'a> {
  fn new(regs: &'a mut Vec<node::Reg>) -> PaddedRegsIterator<'a> {
    regs.sort_by(|r1,r2| r1.offset.cmp(&r2.offset));
    PaddedRegsIterator {
      sorted_regs: regs,
      index: 0,
      last_offset: 0,
    }
  }
}

impl<'a> Iterator for PaddedRegsIterator<'a> {
  type Item = RegOrPadding<'a>;
  fn next(&mut self) -> Option<RegOrPadding<'a>> {
    if self.index >= self.sorted_regs.len() {
      None
    } else {
      let ref reg = self.sorted_regs[self.index];
      if reg.offset > self.last_offset {
        let pad_length = reg.offset - self.last_offset;
        self.last_offset = reg.offset;
        Some(RegOrPadding::Pad(pad_length))
      } else {
        self.index += 1;
        self.last_offset += reg.size();
        Some(RegOrPadding::Reg(reg))
      }
    }
  }
}

/// Build types for `RegUnions`
pub struct BuildUnionTypes<'a> {
  builder: &'a mut Builder,
  cx: &'a ExtCtxt<'a>
}

impl<'a> BuildUnionTypes<'a> {
  pub fn new(builder: &'a mut Builder, cx: &'a ExtCtxt<'a>)
      -> BuildUnionTypes<'a> {
    BuildUnionTypes { builder: builder, cx: cx }
  }
}

fn expr_usize(cx: &ExtCtxt, n: Spanned<u64>) -> P<ast::Expr> {
  cx.expr_lit(n.span, ast::LitInt(n.node as u64, ast::UnsignedIntLit(ast::TyUs)))
}

/// Returns the type of the field representing the given register
/// within a `RegGroup` struct
fn reg_struct_type(cx: &ExtCtxt, path: &Vec<String>, reg: &node::Reg)
                   -> P<ast::Ty> {
  let base_ty_path = cx.path_ident(reg.name.span, utils::path_ident(cx, path));
  let base_ty: P<ast::Ty> = cx.ty_path(base_ty_path);
  match reg.count.node {
    1 => base_ty,
    n =>
      cx.ty(reg.count.span,
            ast::TyFixedLengthVec(base_ty, expr_usize(cx, respan(reg.count.span, n as u64)))),
  }
}

impl<'a> node::RegVisitor for BuildUnionTypes<'a> {
  fn visit_union_reg<'b>(&'b mut self, path: &Vec<String>, reg: &'b node::Reg,
                         subregs: Rc<Vec<node::Reg>>) {
    let items = self.build_union_type(path, reg, &*subregs);
    for item in items.into_iter() {
      self.builder.push_item(item);
    }
  }
}

impl<'a> BuildUnionTypes<'a> {
  /// Produce a field for the given register in a `RegUnion` struct
  fn build_reg_union_field(&self, path: &Vec<String>, reg: &node::Reg)
                           -> ast::StructField {
    let attrs = match reg.docstring {
      Some(doc) => vec!(utils::doc_attribute(self.cx, token::get_ident(doc.node))),
      None => Vec::new(),
    };
    let mut field_path = path.clone();
    field_path.push(reg.name.node.clone());
    dummy_spanned(
      ast::StructField_ {
        kind: ast::NamedField(
          self.cx.ident_of(reg.name.node.as_str()),
          ast::Public),
        id: ast::DUMMY_NODE_ID,
        ty: reg_struct_type(self.cx, &field_path, reg),
        attrs: attrs,
      }
    )
  }

  /// Build field for padding or a register
  // Dummy spans allowed here because u8 doesn't come from anywhere
  #[allow(dummy_span)]
  fn build_pad_or_reg(&self, path: &Vec<String>, reg_or_pad: RegOrPadding,
                      index: usize) -> ast::StructField {
    match reg_or_pad {
      RegOrPadding::Reg(reg) => self.build_reg_union_field(path, reg),
      RegOrPadding::Pad(length) => {
        let u8_path = self.cx.path_ident(
          DUMMY_SP,
          self.cx.ident_of("u8"));
        let u8_ty: P<ast::Ty> = self.cx.ty_path(u8_path);
        let ty: P<ast::Ty> =
          self.cx.ty(
            DUMMY_SP,
            ast::TyFixedLengthVec(u8_ty, expr_usize(self.cx, respan(DUMMY_SP, length))));
        dummy_spanned(
          ast::StructField_ {
            kind: ast::NamedField(
              self.cx.ident_of(format!("_pad{}", index).as_str()),
              ast::Inherited),
            id: ast::DUMMY_NODE_ID,
            ty: ty,
            attrs: Vec::new(),
          },
        )
      },
    }
  }

  /// Build the type associated with a register group
  fn build_union_type(&self, path: &Vec<String>, reg: &node::Reg,
                      regs: &Vec<node::Reg>) -> Vec<P<ast::Item>> {
    let name = utils::path_ident(self.cx, path);
    // Registers are already sorted by parser
    let mut regs = regs.clone();
    let mut regs2 = regs.clone();
    let padded_regs = PaddedRegsIterator::new(&mut regs);
    let fields =
      padded_regs.enumerate().map(|(n,r)| self.build_pad_or_reg(path, r, n));
    let struct_def = ast::StructDef {
      fields: FromIterator::from_iter(fields),
      ctor_id: None,
    };
    let mut attrs: Vec<ast::Attribute> = vec!(
      utils::list_attribute(self.cx, "allow",
                            vec!("non_camel_case_types",
                                 "dead_code",
                                 "missing_docs"),
                            reg.name.span),
    );
    match reg.docstring {
      Some(docstring) =>
        attrs.push(
          utils::doc_attribute(self.cx, token::get_ident(docstring.node))),
      None => (),
    }
    let struct_item = P(ast::Item {
      ident: name,
      attrs: attrs,
      id: ast::DUMMY_NODE_ID,
      node: ast::ItemStruct(P(struct_def), empty_generics()),
      vis: ast::Public,
      span: reg.name.span,
    });
    let mut full_size: u64 = 0;
    //FIXME(mcoffin) - We're making this iterator twice
    let padded_regs2 = PaddedRegsIterator::new(&mut regs2);
    padded_regs2.enumerate().map(|(_, rp)| {
      full_size += match rp {
        RegOrPadding::Reg(reg) => reg.ty.size(),
        RegOrPadding::Pad(s) => s,
      };
    }).count();
    let clone_impl = quote_item!(self.cx,
      impl ::core::clone::Clone for $name {
        fn clone(&self) -> Self {
          let mut next: $name = unsafe {
            ::core::mem::uninitialized()
          };
          unsafe {
            let next_ptr: *mut $name = &mut next;
            ::core::intrinsics::copy(
              ::core::mem::transmute(self),
              next_ptr,
              $full_size as usize);
            return next;
          }
        }
      }
    ).unwrap();

    let copy_impl = quote_item!(
        self.cx, impl ::core::marker::Copy for $name {}).unwrap();

    let item_address = reg.address;
    let docstring = format!("Placement getter for register {} at address 0x{:x}",
                            reg.name.node,
                            item_address);
    let doc_attr = utils::doc_attribute(self.cx, utils::intern_string(
        self.cx, docstring));
    let item_getter = quote_item!(self.cx,
      #[allow(non_snake_case, dead_code)]
      $doc_attr
      pub fn $name() -> &'static $name {
          unsafe { ::core::intrinsics::transmute($item_address as usize) }
      }
    ).unwrap();
    if item_address == 0 {
      vec!(struct_item, clone_impl, copy_impl)
    } else {
      vec!(struct_item, clone_impl, copy_impl, item_getter)
    }
  }
}
<|endoftext|>