<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// The crate store - a central repo for information collected about external
// crates and libraries

use metadata::decoder;
use metadata::loader;

use std::cell::RefCell;
use std::hashmap::HashMap;
use syntax::ast;
use syntax::parse::token::ident_interner;

// A map from external crate numbers (as decoded from some crate file) to
// local crate numbers (as generated during this session). Each external
// crate may refer to types in other external crates, and each has their
// own crate numbers.
pub type cnum_map = @mut HashMap<ast::CrateNum, ast::CrateNum>;

pub enum MetadataBlob {
    MetadataVec(~[u8]),
    MetadataArchive(loader::ArchiveMetadata),
}

pub struct crate_metadata {
    name: @str,
    data: MetadataBlob,
    cnum_map: cnum_map,
    cnum: ast::CrateNum
}

#[deriving(Eq)]
pub enum LinkagePreference {
    RequireDynamic,
    RequireStatic,
}

#[deriving(Eq, FromPrimitive)]
pub enum NativeLibaryKind {
    NativeStatic,    // native static library (.a archive)
    NativeFramework, // OSX-specific
    NativeUnknown,   // default way to specify a dynamic library
}

// Where a crate came from on the local filesystem. One of these two options
// must be non-None.
#[deriving(Eq)]
pub struct CrateSource {
    dylib: Option<Path>,
    rlib: Option<Path>,
    cnum: ast::CrateNum,
}

pub struct CStore {
    priv metas: RefCell<HashMap<ast::CrateNum, @crate_metadata>>,
    priv extern_mod_crate_map: RefCell<extern_mod_crate_map>,
    priv used_crate_sources: ~[CrateSource],
    priv used_libraries: ~[(~str, NativeLibaryKind)],
    priv used_link_args: ~[~str],
    intr: @ident_interner
}

// Map from NodeId's of local extern mod statements to crate numbers
type extern_mod_crate_map = HashMap<ast::NodeId, ast::CrateNum>;

impl CStore {
    pub fn new(intr: @ident_interner) -> CStore {
        CStore {
            metas: RefCell::new(HashMap::new()),
            extern_mod_crate_map: RefCell::new(HashMap::new()),
            used_crate_sources: ~[],
            used_libraries: ~[],
            used_link_args: ~[],
            intr: intr
        }
    }

    pub fn get_crate_data(&self, cnum: ast::CrateNum) -> @crate_metadata {
        let metas = self.metas.borrow();
        *metas.get().get(&cnum)
    }

    pub fn get_crate_hash(&self, cnum: ast::CrateNum) -> @str {
        let cdata = self.get_crate_data(cnum);
        decoder::get_crate_hash(cdata.data())
    }

    pub fn get_crate_vers(&self, cnum: ast::CrateNum) -> @str {
        let cdata = self.get_crate_data(cnum);
        decoder::get_crate_vers(cdata.data())
    }

    pub fn set_crate_data(&mut self, cnum: ast::CrateNum, data: @crate_metadata) {
        let mut metas = self.metas.borrow_mut();
        metas.get().insert(cnum, data);
    }

    pub fn have_crate_data(&self, cnum: ast::CrateNum) -> bool {
        let metas = self.metas.borrow();
        metas.get().contains_key(&cnum)
    }

    pub fn iter_crate_data(&self, i: |ast::CrateNum, @crate_metadata|) {
        let metas = self.metas.borrow();
        for (&k, &v) in metas.get().iter() {
            i(k, v);
        }
    }

    pub fn add_used_crate_source(&mut self, src: CrateSource) {
        if !self.used_crate_sources.contains(&src) {
            self.used_crate_sources.push(src);
        }
    }

    pub fn get_used_crate_sources<'a>(&'a self) -> &'a [CrateSource] {
        self.used_crate_sources.as_slice()
    }

    pub fn get_used_crates(&self, prefer: LinkagePreference)
                           -> ~[(ast::CrateNum, Option<Path>)] {
        self.used_crate_sources.iter()
            .map(|src| (src.cnum, match prefer {
                RequireDynamic => src.dylib.clone(),
                RequireStatic => src.rlib.clone(),
            }))
            .collect()
    }

    pub fn add_used_library(&mut self, lib: ~str, kind: NativeLibaryKind) -> bool {
        assert!(!lib.is_empty());
        if self.used_libraries.iter().any(|&(ref x, _)| x == &lib) {
            return false;
        }
        self.used_libraries.push((lib, kind));
        true
    }

    pub fn get_used_libraries<'a>(&'a self) -> &'a [(~str, NativeLibaryKind)] {
        self.used_libraries.as_slice()
    }

    pub fn add_used_link_args(&mut self, args: &str) {
        for s in args.split(' ') {
            self.used_link_args.push(s.to_owned());
        }
    }

    pub fn get_used_link_args<'a>(&'a self) -> &'a [~str] {
        self.used_link_args.as_slice()
    }

    pub fn add_extern_mod_stmt_cnum(&mut self,
                                    emod_id: ast::NodeId,
                                    cnum: ast::CrateNum) {
        let mut extern_mod_crate_map = self.extern_mod_crate_map.borrow_mut();
        extern_mod_crate_map.get().insert(emod_id, cnum);
    }

    pub fn find_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId)
                                     -> Option<ast::CrateNum> {
        let extern_mod_crate_map = self.extern_mod_crate_map.borrow();
        extern_mod_crate_map.get().find(&emod_id).map(|x| *x)
    }

    // returns hashes of crates directly used by this crate. Hashes are sorted by
    // (crate name, crate version, crate hash) in lexicographic order (not semver)
    pub fn get_dep_hashes(&self) -> ~[@str] {
        let mut result = ~[];

        let extern_mod_crate_map = self.extern_mod_crate_map.borrow();
        for (_, &cnum) in extern_mod_crate_map.get().iter() {
            let cdata = self.get_crate_data(cnum);
            let hash = decoder::get_crate_hash(cdata.data());
            let vers = decoder::get_crate_vers(cdata.data());
            debug!("Add hash[{}]: {} {}", cdata.name, vers, hash);
            result.push(crate_hash {
                name: cdata.name,
                vers: vers,
                hash: hash
            });
        }

        result.sort();

        debug!("sorted:");
        for x in result.iter() {
            debug!("  hash[{}]: {}", x.name, x.hash);
        }

        result.map(|ch| ch.hash)
    }
}

#[deriving(Clone, TotalEq, TotalOrd)]
struct crate_hash {
    name: @str,
    vers: @str,
    hash: @str,
}

impl crate_metadata {
    pub fn data<'a>(&'a self) -> &'a [u8] { self.data.as_slice() }
}

impl MetadataBlob {
    pub fn as_slice<'a>(&'a self) -> &'a [u8] {
        match *self {
            MetadataVec(ref vec) => vec.as_slice(),
            MetadataArchive(ref ar) => ar.as_slice(),
        }
    }
}
<commit_msg>librustc: De-`@mut` `CStore::used_crate_sources`<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// The crate store - a central repo for information collected about external
// crates and libraries

use metadata::decoder;
use metadata::loader;

use std::cell::RefCell;
use std::hashmap::HashMap;
use syntax::ast;
use syntax::parse::token::ident_interner;

// A map from external crate numbers (as decoded from some crate file) to
// local crate numbers (as generated during this session). Each external
// crate may refer to types in other external crates, and each has their
// own crate numbers.
pub type cnum_map = @mut HashMap<ast::CrateNum, ast::CrateNum>;

pub enum MetadataBlob {
    MetadataVec(~[u8]),
    MetadataArchive(loader::ArchiveMetadata),
}

pub struct crate_metadata {
    name: @str,
    data: MetadataBlob,
    cnum_map: cnum_map,
    cnum: ast::CrateNum
}

#[deriving(Eq)]
pub enum LinkagePreference {
    RequireDynamic,
    RequireStatic,
}

#[deriving(Eq, FromPrimitive)]
pub enum NativeLibaryKind {
    NativeStatic,    // native static library (.a archive)
    NativeFramework, // OSX-specific
    NativeUnknown,   // default way to specify a dynamic library
}

// Where a crate came from on the local filesystem. One of these two options
// must be non-None.
#[deriving(Eq)]
pub struct CrateSource {
    dylib: Option<Path>,
    rlib: Option<Path>,
    cnum: ast::CrateNum,
}

pub struct CStore {
    priv metas: RefCell<HashMap<ast::CrateNum, @crate_metadata>>,
    priv extern_mod_crate_map: RefCell<extern_mod_crate_map>,
    priv used_crate_sources: RefCell<~[CrateSource]>,
    priv used_libraries: ~[(~str, NativeLibaryKind)],
    priv used_link_args: ~[~str],
    intr: @ident_interner
}

// Map from NodeId's of local extern mod statements to crate numbers
type extern_mod_crate_map = HashMap<ast::NodeId, ast::CrateNum>;

impl CStore {
    pub fn new(intr: @ident_interner) -> CStore {
        CStore {
            metas: RefCell::new(HashMap::new()),
            extern_mod_crate_map: RefCell::new(HashMap::new()),
            used_crate_sources: RefCell::new(~[]),
            used_libraries: ~[],
            used_link_args: ~[],
            intr: intr
        }
    }

    pub fn get_crate_data(&self, cnum: ast::CrateNum) -> @crate_metadata {
        let metas = self.metas.borrow();
        *metas.get().get(&cnum)
    }

    pub fn get_crate_hash(&self, cnum: ast::CrateNum) -> @str {
        let cdata = self.get_crate_data(cnum);
        decoder::get_crate_hash(cdata.data())
    }

    pub fn get_crate_vers(&self, cnum: ast::CrateNum) -> @str {
        let cdata = self.get_crate_data(cnum);
        decoder::get_crate_vers(cdata.data())
    }

    pub fn set_crate_data(&mut self, cnum: ast::CrateNum, data: @crate_metadata) {
        let mut metas = self.metas.borrow_mut();
        metas.get().insert(cnum, data);
    }

    pub fn have_crate_data(&self, cnum: ast::CrateNum) -> bool {
        let metas = self.metas.borrow();
        metas.get().contains_key(&cnum)
    }

    pub fn iter_crate_data(&self, i: |ast::CrateNum, @crate_metadata|) {
        let metas = self.metas.borrow();
        for (&k, &v) in metas.get().iter() {
            i(k, v);
        }
    }

    pub fn add_used_crate_source(&mut self, src: CrateSource) {
        let mut used_crate_sources = self.used_crate_sources.borrow_mut();
        if !used_crate_sources.get().contains(&src) {
            used_crate_sources.get().push(src);
        }
    }

    pub fn get_used_crates(&self, prefer: LinkagePreference)
                           -> ~[(ast::CrateNum, Option<Path>)] {
        let used_crate_sources = self.used_crate_sources.borrow();
        used_crate_sources.get()
            .iter()
            .map(|src| (src.cnum, match prefer {
                RequireDynamic => src.dylib.clone(),
                RequireStatic => src.rlib.clone(),
            }))
            .collect()
    }

    pub fn add_used_library(&mut self, lib: ~str, kind: NativeLibaryKind) -> bool {
        assert!(!lib.is_empty());
        if self.used_libraries.iter().any(|&(ref x, _)| x == &lib) {
            return false;
        }
        self.used_libraries.push((lib, kind));
        true
    }

    pub fn get_used_libraries<'a>(&'a self) -> &'a [(~str, NativeLibaryKind)] {
        self.used_libraries.as_slice()
    }

    pub fn add_used_link_args(&mut self, args: &str) {
        for s in args.split(' ') {
            self.used_link_args.push(s.to_owned());
        }
    }

    pub fn get_used_link_args<'a>(&'a self) -> &'a [~str] {
        self.used_link_args.as_slice()
    }

    pub fn add_extern_mod_stmt_cnum(&mut self,
                                    emod_id: ast::NodeId,
                                    cnum: ast::CrateNum) {
        let mut extern_mod_crate_map = self.extern_mod_crate_map.borrow_mut();
        extern_mod_crate_map.get().insert(emod_id, cnum);
    }

    pub fn find_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId)
                                     -> Option<ast::CrateNum> {
        let extern_mod_crate_map = self.extern_mod_crate_map.borrow();
        extern_mod_crate_map.get().find(&emod_id).map(|x| *x)
    }

    // returns hashes of crates directly used by this crate. Hashes are sorted by
    // (crate name, crate version, crate hash) in lexicographic order (not semver)
    pub fn get_dep_hashes(&self) -> ~[@str] {
        let mut result = ~[];

        let extern_mod_crate_map = self.extern_mod_crate_map.borrow();
        for (_, &cnum) in extern_mod_crate_map.get().iter() {
            let cdata = self.get_crate_data(cnum);
            let hash = decoder::get_crate_hash(cdata.data());
            let vers = decoder::get_crate_vers(cdata.data());
            debug!("Add hash[{}]: {} {}", cdata.name, vers, hash);
            result.push(crate_hash {
                name: cdata.name,
                vers: vers,
                hash: hash
            });
        }

        result.sort();

        debug!("sorted:");
        for x in result.iter() {
            debug!("  hash[{}]: {}", x.name, x.hash);
        }

        result.map(|ch| ch.hash)
    }
}

#[deriving(Clone, TotalEq, TotalOrd)]
struct crate_hash {
    name: @str,
    vers: @str,
    hash: @str,
}

impl crate_metadata {
    pub fn data<'a>(&'a self) -> &'a [u8] { self.data.as_slice() }
}

impl MetadataBlob {
    pub fn as_slice<'a>(&'a self) -> &'a [u8] {
        match *self {
            MetadataVec(ref vec) => vec.as_slice(),
            MetadataArchive(ref ar) => ar.as_slice(),
        }
    }
}
<|endoftext|>


<commit_before>pub trait PaginatableIterator {
    fn paginate(self, page: usize) -> Paginate<Self>;
}

impl<T, U : Iterator<Item = T>> PaginatableIterator for U {
    fn paginate(self, page: usize) -> Paginate<U> {
        Paginate {
            iter: self,
            page: page,
        }
    }
}

struct Paginate<I> {
    iter: I,
    page: usize,
}

impl<E, I : Iterator<Item = E>> Iterator for Paginate<I> {
    type Item = Vec<E>;

    fn next(&mut self) -> Option<Vec<E>> {
        let mut r = Vec::new();
        for _ in 0..self.page {
            match self.iter.next() {
                Some(next) => r.push(next),
                None if r.is_empty() => return None,
                None                 => return Some(r),
            }
        }
        Some(r)
    }
}

<commit_msg>The PaginateIterable trait needs Self to be sized.<commit_after>pub trait PaginatableIterator : Sized {
    fn paginate(self, page: usize) -> Paginate<Self>;
}

impl<T, U : Iterator<Item = T>> PaginatableIterator for U {
    fn paginate(self, page: usize) -> Paginate<U> {
        Paginate {
            iter: self,
            page: page,
        }
    }
}

struct Paginate<I> {
    iter: I,
    page: usize,
}

impl<E, I : Iterator<Item = E>> Iterator for Paginate<I> {
    type Item = Vec<E>;

    fn next(&mut self) -> Option<Vec<E>> {
        let mut r = Vec::new();
        for _ in 0..self.page {
            match self.iter.next() {
                Some(next) => r.push(next),
                None if r.is_empty() => return None,
                None                 => return Some(r),
            }
        }
        Some(r)
    }
}

<|endoftext|>


<commit_before>//! History API

use std::collections::VecDeque;
use std::fs::File;
use std::path::Path;

use super::Result;
use config::{Config, HistoryDuplicates};

pub struct History {
    entries: VecDeque<String>,
    max_len: usize,
    ignore_space: bool,
    ignore_dups: bool,
}

impl History {
    pub fn new(config: Config) -> History {
        History {
            entries: VecDeque::new(),
            max_len: config.max_history_size(),
            ignore_space: config.history_duplicates() == HistoryDuplicates::IgnoreConsecutive,
            ignore_dups: config.history_ignore_space(),
        }
    }

    /// Return the history entry at position `index`, starting from 0.
    pub fn get(&self, index: usize) -> Option<&String> {
        self.entries.get(index)
    }

    /// Add a new entry in the history.
    pub fn add(&mut self, line: &str) -> bool {
        if self.max_len == 0 {
            return false;
        }
        if line.is_empty() ||
           (self.ignore_space && line.chars().next().map_or(true, |c| c.is_whitespace())) {
            return false;
        }
        if self.ignore_dups {
            if let Some(s) = self.entries.back() {
                if s == line {
                    return false;
                }
            }
        }
        if self.entries.len() == self.max_len {
            self.entries.pop_front();
        }
        self.entries.push_back(String::from(line));
        true
    }

    /// Returns the number of entries in the history.
    pub fn len(&self) -> usize {
        self.entries.len()
    }
    /// Returns true if the history has no entry.
    pub fn is_empty(&self) -> bool {
        self.entries.is_empty()
    }

    /// Set the maximum length for the history. This function can be called even
    /// if there is already some history, the function will make sure to retain
    /// just the latest `len` elements if the new history length value is smaller
    /// than the amount of items already inside the history.
    pub fn set_max_len(&mut self, len: usize) {
        self.max_len = len;
        if len == 0 {
            self.entries.clear();
            return;
        }
        loop {
            if self.entries.len() <= len {
                break;
            }
            self.entries.pop_front();
        }
    }

    /// Save the history in the specified file.
    pub fn save<P: AsRef<Path> + ?Sized>(&self, path: &P) -> Result<()> {
        use std::io::{BufWriter, Write};

        if self.is_empty() {
            return Ok(());
        }
        let file = try!(File::create(path));
        let mut wtr = BufWriter::new(file);
        for entry in &self.entries {
            try!(wtr.write_all(&entry.as_bytes()));
            try!(wtr.write_all(b"\n"));
        }
        Ok(())
    }

    /// Load the history from the specified file.
    pub fn load<P: AsRef<Path> + ?Sized>(&mut self, path: &P) -> Result<()> {
        use std::io::{BufRead, BufReader};

        let file = try!(File::open(&path));
        let rdr = BufReader::new(file);
        for line in rdr.lines() {
            self.add(try!(line).as_ref()); // TODO truncate to MAX_LINE
        }
        Ok(())
    }

    /// Clear history
    pub fn clear(&mut self) {
        self.entries.clear()
    }

    /// Search history (start position inclusive [0, len-1])
    /// Return the absolute index of the nearest history entry that matches `term`.
    /// Return None if no entry contains `term` between [start, len -1] for forward search
    /// or between [0, start] for reverse search.
    pub fn search(&self, term: &str, start: usize, reverse: bool) -> Option<usize> {
        if term.is_empty() || start >= self.len() {
            return None;
        }
        if reverse {
            let index = self.entries
                .iter()
                .rev()
                .skip(self.entries.len() - 1 - start)
                .position(|entry| entry.contains(term));
            index.and_then(|index| Some(start - index))
        } else {
            let index = self.entries.iter().skip(start).position(|entry| entry.contains(term));
            index.and_then(|index| Some(index + start))
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate tempdir;
    use std::path::Path;
    use config::Config;

    fn init() -> super::History {
        let mut history = super::History::new(Config::default());
        assert!(history.add("line1"));
        assert!(history.add("line2"));
        assert!(history.add("line3"));
        history
    }

    #[test]
    fn new() {
        let config = Config::default();
        let history = super::History::new(config);
        assert_eq!(config.max_history_size(), history.max_len);
        assert_eq!(0, history.entries.len());
    }

    #[test]
    fn add() {
        let config = Config::builder()
            .history_ignore_space(true)
            .build();
        let mut history = super::History::new(config);
        assert!(history.add("line1"));
        assert!(history.add("line2"));
        assert!(!history.add("line2"));
        assert!(!history.add(""));
        assert!(!history.add(" line3"));
    }

    #[test]
    fn set_max_len() {
        let mut history = init();
        history.set_max_len(1);
        assert_eq!(1, history.entries.len());
        assert_eq!(Some(&"line3".to_string()), history.entries.back());
    }

    #[test]
    fn save() {
        let mut history = init();
        let td = tempdir::TempDir::new_in(&Path::new("."), "histo").unwrap();
        let history_path = td.path().join(".history");

        history.save(&history_path).unwrap();
        history.load(&history_path).unwrap();
        td.close().unwrap();
    }

    #[test]
    fn search() {
        let history = init();
        assert_eq!(None, history.search("", 0, false));
        assert_eq!(None, history.search("none", 0, false));
        assert_eq!(None, history.search("line", 3, false));

        assert_eq!(Some(0), history.search("line", 0, false));
        assert_eq!(Some(1), history.search("line", 1, false));
        assert_eq!(Some(2), history.search("line3", 1, false));
    }

    #[test]
    fn reverse_search() {
        let history = init();
        assert_eq!(None, history.search("", 2, true));
        assert_eq!(None, history.search("none", 2, true));
        assert_eq!(None, history.search("line", 3, true));

        assert_eq!(Some(2), history.search("line", 2, true));
        assert_eq!(Some(1), history.search("line", 1, true));
        assert_eq!(Some(0), history.search("line1", 1, true));
    }
}
<commit_msg>Fix #80<commit_after>//! History API

use std::collections::VecDeque;
use std::fs::File;
use std::path::Path;

use super::Result;
use config::{Config, HistoryDuplicates};

pub struct History {
    entries: VecDeque<String>,
    max_len: usize,
    ignore_space: bool,
    ignore_dups: bool,
}

impl History {
    pub fn new(config: Config) -> History {
        History {
            entries: VecDeque::new(),
            max_len: config.max_history_size(),
            ignore_space: config.history_duplicates() == HistoryDuplicates::IgnoreConsecutive,
            ignore_dups: config.history_ignore_space(),
        }
    }

    /// Return the history entry at position `index`, starting from 0.
    pub fn get(&self, index: usize) -> Option<&String> {
        self.entries.get(index)
    }

    /// Add a new entry in the history.
    pub fn add(&mut self, line: &str) -> bool {
        if self.max_len == 0 {
            return false;
        }
        if line.is_empty() ||
           (self.ignore_space && line.chars().next().map_or(true, |c| c.is_whitespace())) {
            return false;
        }
        if self.ignore_dups {
            if let Some(s) = self.entries.back() {
                if s == line {
                    return false;
                }
            }
        }
        if self.entries.len() == self.max_len {
            self.entries.pop_front();
        }
        self.entries.push_back(String::from(line));
        true
    }

    /// Returns the number of entries in the history.
    pub fn len(&self) -> usize {
        self.entries.len()
    }
    /// Returns true if the history has no entry.
    pub fn is_empty(&self) -> bool {
        self.entries.is_empty()
    }

    /// Set the maximum length for the history. This function can be called even
    /// if there is already some history, the function will make sure to retain
    /// just the latest `len` elements if the new history length value is smaller
    /// than the amount of items already inside the history.
    pub fn set_max_len(&mut self, len: usize) {
        self.max_len = len;
        if len == 0 {
            self.entries.clear();
            return;
        }
        loop {
            if self.entries.len() <= len {
                break;
            }
            self.entries.pop_front();
        }
    }

    /// Save the history in the specified file.
    pub fn save<P: AsRef<Path> + ?Sized>(&self, path: &P) -> Result<()> {
        use std::io::{BufWriter, Write};

        if self.is_empty() {
            return Ok(());
        }
        let file = try!(File::create(path));
        let mut wtr = BufWriter::new(file);
        for entry in &self.entries {
            try!(wtr.write_all(&entry.as_bytes()));
            try!(wtr.write_all(b"\n"));
        }
        Ok(())
    }

    /// Load the history from the specified file.
    ///
    /// # Failure
    /// Will return `Err` if path does not already exist.
    pub fn load<P: AsRef<Path> + ?Sized>(&mut self, path: &P) -> Result<()> {
        use std::io::{BufRead, BufReader};

        let file = try!(File::open(&path));
        let rdr = BufReader::new(file);
        for line in rdr.lines() {
            self.add(try!(line).as_ref()); // TODO truncate to MAX_LINE
        }
        Ok(())
    }

    /// Clear history
    pub fn clear(&mut self) {
        self.entries.clear()
    }

    /// Search history (start position inclusive [0, len-1])
    /// Return the absolute index of the nearest history entry that matches `term`.
    /// Return None if no entry contains `term` between [start, len -1] for forward search
    /// or between [0, start] for reverse search.
    pub fn search(&self, term: &str, start: usize, reverse: bool) -> Option<usize> {
        if term.is_empty() || start >= self.len() {
            return None;
        }
        if reverse {
            let index = self.entries
                .iter()
                .rev()
                .skip(self.entries.len() - 1 - start)
                .position(|entry| entry.contains(term));
            index.and_then(|index| Some(start - index))
        } else {
            let index = self.entries.iter().skip(start).position(|entry| entry.contains(term));
            index.and_then(|index| Some(index + start))
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate tempdir;
    use std::path::Path;
    use config::Config;

    fn init() -> super::History {
        let mut history = super::History::new(Config::default());
        assert!(history.add("line1"));
        assert!(history.add("line2"));
        assert!(history.add("line3"));
        history
    }

    #[test]
    fn new() {
        let config = Config::default();
        let history = super::History::new(config);
        assert_eq!(config.max_history_size(), history.max_len);
        assert_eq!(0, history.entries.len());
    }

    #[test]
    fn add() {
        let config = Config::builder()
            .history_ignore_space(true)
            .build();
        let mut history = super::History::new(config);
        assert!(history.add("line1"));
        assert!(history.add("line2"));
        assert!(!history.add("line2"));
        assert!(!history.add(""));
        assert!(!history.add(" line3"));
    }

    #[test]
    fn set_max_len() {
        let mut history = init();
        history.set_max_len(1);
        assert_eq!(1, history.entries.len());
        assert_eq!(Some(&"line3".to_string()), history.entries.back());
    }

    #[test]
    fn save() {
        let mut history = init();
        let td = tempdir::TempDir::new_in(&Path::new("."), "histo").unwrap();
        let history_path = td.path().join(".history");

        history.save(&history_path).unwrap();
        history.load(&history_path).unwrap();
        td.close().unwrap();
    }

    #[test]
    fn search() {
        let history = init();
        assert_eq!(None, history.search("", 0, false));
        assert_eq!(None, history.search("none", 0, false));
        assert_eq!(None, history.search("line", 3, false));

        assert_eq!(Some(0), history.search("line", 0, false));
        assert_eq!(Some(1), history.search("line", 1, false));
        assert_eq!(Some(2), history.search("line3", 1, false));
    }

    #[test]
    fn reverse_search() {
        let history = init();
        assert_eq!(None, history.search("", 2, true));
        assert_eq!(None, history.search("none", 2, true));
        assert_eq!(None, history.search("line", 3, true));

        assert_eq!(Some(2), history.search("line", 2, true));
        assert_eq!(Some(1), history.search("line", 1, true));
        assert_eq!(Some(0), history.search("line1", 1, true));
    }
}
<|endoftext|>


<commit_before>iface iterable<A> {
    fn iter(blk: fn(A));
}

impl<A> of iterable<A> for fn@(fn(A)) {
    fn iter(blk: fn(A)) {
        self(blk);
    }
}

// accomodate the fact that int/uint are passed by value by default:
impl of iterable<int> for fn@(fn(int)) {
    fn iter(blk: fn(&&int)) {
        self {|i| blk(i)}
    }
}

impl of iterable<uint> for fn@(fn(uint)) {
    fn iter(blk: fn(&&uint)) {
        self {|i| blk(i)}
    }
}

impl<A> of iterable<A> for [A] {
    fn iter(blk: fn(A)) {
        vec::iter(self, blk)
    }
}

impl<A> of iterable<A> for option<A> {
    fn iter(blk: fn(A)) {
        option::may(self, blk)
    }
}

impl of iterable<char> for str {
    fn iter(blk: fn(&&char)) {
        str::chars_iter(self) { |ch| blk(ch) }
    }
}

fn enumerate<A,IA:iterable<A>>(self: IA, blk: fn(uint, A)) {
    let mut i = 0u;
    self.iter {|a|
        blk(i, a);
        i += 1u;
    }
}

// Here: we have to use fn@ for predicates and map functions, because
// we will be binding them up into a closure.  Disappointing.  A true
// region type system might be able to do better than this.

fn filter<A,IA:iterable<A>>(self: IA, prd: fn@(A) -> bool, blk: fn(A)) {
    self.iter {|a|
        if prd(a) { blk(a) }
    }
}

fn filter_map<A,B,IA:iterable<A>>(self: IA, cnv: fn@(A) -> option<B>,
                                  blk: fn(B)) {
    self.iter {|a|
        alt cnv(a) {
          some(b) { blk(b) }
          none { }
        }
    }
}

fn map<A,B,IA:iterable<A>>(self: IA, cnv: fn@(A) -> B, blk: fn(B)) {
    self.iter {|a|
        let b = cnv(a);
        blk(b);
    }
}

fn flat_map<A,B,IA:iterable<A>,IB:iterable<B>>(
    self: IA, cnv: fn@(A) -> IB, blk: fn(B)) {
    self.iter {|a|
        cnv(a).iter(blk)
    }
}

fn foldl<A,B,IA:iterable<A>>(self: IA, +b0: B, blk: fn(-B, A) -> B) -> B {
    let mut b <- b0;
    self.iter {|a|
        b = blk(b, a);
    }
    ret b;
}

fn foldr<A:copy,B,IA:iterable<A>>(
    self: IA, +b0: B, blk: fn(A, -B) -> B) -> B {

    let mut b <- b0;
    reversed(self) {|a|
        b = blk(a, b);
    }
    ret b;
}

fn to_list<A:copy,IA:iterable<A>>(self: IA) -> [A] {
    foldl::<A,[A],IA>(self, [], {|r, a| r + [a]})
}

// FIXME: This could be made more efficient with an riterable interface
fn reversed<A:copy,IA:iterable<A>>(self: IA, blk: fn(A)) {
    vec::riter(to_list(self), blk)
}

fn count<A,IA:iterable<A>>(self: IA, x: A) -> uint {
    foldl(self, 0u) {|count, value|
        if value == x {
            count + 1u
        } else {
            count
        }
    }
}

fn repeat(times: uint, blk: fn()) {
    let mut i = 0u;
    while i < times {
        blk();
        i += 1u;
    }
}

fn min<A:copy,IA:iterable<A>>(self: IA) -> A {
    alt foldl::<A,option<A>,IA>(self, none) {|a, b|
        alt a {
          some(a_) if a_ < b {
            // FIXME: Not sure if this is successfully optimized to a move
            a
          }
          _ { some(b) }
        }
    } {
        some(val) { val }
        none { fail "min called on empty iterator" }
    }
}

fn max<A:copy,IA:iterable<A>>(self: IA) -> A {
    alt foldl::<A,option<A>,IA>(self, none) {|a, b|
        alt a {
          some(a_) if a_ > b {
            // FIXME: Not sure if this is successfully optimized to a move
            a
          }
          _ { some(b) }
        }
    } {
        some(val) { val }
        none { fail "max called on empty iterator" }
    }
}

#[test]
fn test_enumerate() {
    enumerate(["0", "1", "2"]) {|i,j|
        assert #fmt["%u",i] == j;
    }
}

#[test]
fn test_map_and_to_list() {
    let a = bind vec::iter([0, 1, 2], _);
    let b = bind map(a, {|i| i*2}, _);
    let c = to_list(b);
    assert c == [0, 2, 4];
}

#[test]
fn test_map_directly_on_vec() {
    let b = bind map([0, 1, 2], {|i| i*2}, _);
    let c = to_list(b);
    assert c == [0, 2, 4];
}

#[test]
fn test_filter_on_int_range() {
    fn is_even(&&i: int) -> bool {
        ret (i % 2) == 0;
    }

    let l = to_list(bind filter(bind int::range(0, 10, _), is_even, _));
    assert l == [0, 2, 4, 6, 8];
}

#[test]
fn test_filter_on_uint_range() {
    fn is_even(&&i: uint) -> bool {
        ret (i % 2u) == 0u;
    }

    let l = to_list(bind filter(bind uint::range(0u, 10u, _), is_even, _));
    assert l == [0u, 2u, 4u, 6u, 8u];
}

#[test]
fn test_filter_map() {
    fn negativate_the_evens(&&i: int) -> option<int> {
        if i % 2 == 0 {
            some(-i)
        } else {
            none
        }
    }

    let l = to_list(bind filter_map(
        bind int::range(0, 5, _), negativate_the_evens, _));
    assert l == [0, -2, -4];
}

#[test]
fn test_flat_map_with_option() {
    fn if_even(&&i: int) -> option<int> {
        if (i % 2) == 0 { some(i) }
        else { none }
    }

    let a = bind vec::iter([0, 1, 2], _);
    let b = bind flat_map(a, if_even, _);
    let c = to_list(b);
    assert c == [0, 2];
}

#[test]
fn test_flat_map_with_list() {
    fn repeat(&&i: int) -> [int] {
        let r = [];
        int::range(0, i) {|_j| r += [i]; }
        r
    }

    let a = bind vec::iter([0, 1, 2, 3], _);
    let b = bind flat_map(a, repeat, _);
    let c = to_list(b);
    #debug["c = %?", c];
    assert c == [1, 2, 2, 3, 3, 3];
}

#[test]
fn test_repeat() {
    let c = [],
        i = 0u;
    repeat(5u) {||
        c += [(i * i)];
        i += 1u;
    };
    #debug["c = %?", c];
    assert c == [0u, 1u, 4u, 9u, 16u];
}

#[test]
fn test_min() {
    assert min([5, 4, 1, 2, 3]) == 1;
}

#[test]
#[should_fail]
#[ignore(cfg(target_os = "win32"))]
fn test_min_empty() {
    min::<int, [int]>([]);
}

#[test]
fn test_max() {
    assert max([1, 2, 4, 2, 3]) == 4;
}

#[test]
#[should_fail]
#[ignore(cfg(target_os = "win32"))]
fn test_max_empty() {
    max::<int, [int]>([]);
}

#[test]
fn test_reversed() {
    assert to_list(bind reversed([1, 2, 3], _)) == [3, 2, 1];
}

#[test]
fn test_count() {
    assert count([1, 2, 1, 2, 1], 1) == 3u;
}

#[test]
fn test_foldr() {
    fn sub(&&a: int, -b: int) -> int {
        a - b
    }
    let sum = foldr([1, 2, 3, 4], 0, sub);
    assert sum == -2;
}<commit_msg>Comments only: associate core::iter FIXMEs with issue numbers<commit_after>iface iterable<A> {
    fn iter(blk: fn(A));
}

impl<A> of iterable<A> for fn@(fn(A)) {
    fn iter(blk: fn(A)) {
        self(blk);
    }
}

// accomodate the fact that int/uint are passed by value by default:
impl of iterable<int> for fn@(fn(int)) {
    fn iter(blk: fn(&&int)) {
        self {|i| blk(i)}
    }
}

impl of iterable<uint> for fn@(fn(uint)) {
    fn iter(blk: fn(&&uint)) {
        self {|i| blk(i)}
    }
}

impl<A> of iterable<A> for [A] {
    fn iter(blk: fn(A)) {
        vec::iter(self, blk)
    }
}

impl<A> of iterable<A> for option<A> {
    fn iter(blk: fn(A)) {
        option::may(self, blk)
    }
}

impl of iterable<char> for str {
    fn iter(blk: fn(&&char)) {
        str::chars_iter(self) { |ch| blk(ch) }
    }
}

fn enumerate<A,IA:iterable<A>>(self: IA, blk: fn(uint, A)) {
    let mut i = 0u;
    self.iter {|a|
        blk(i, a);
        i += 1u;
    }
}

// Here: we have to use fn@ for predicates and map functions, because
// we will be binding them up into a closure.  Disappointing.  A true
// region type system might be able to do better than this.

fn filter<A,IA:iterable<A>>(self: IA, prd: fn@(A) -> bool, blk: fn(A)) {
    self.iter {|a|
        if prd(a) { blk(a) }
    }
}

fn filter_map<A,B,IA:iterable<A>>(self: IA, cnv: fn@(A) -> option<B>,
                                  blk: fn(B)) {
    self.iter {|a|
        alt cnv(a) {
          some(b) { blk(b) }
          none { }
        }
    }
}

fn map<A,B,IA:iterable<A>>(self: IA, cnv: fn@(A) -> B, blk: fn(B)) {
    self.iter {|a|
        let b = cnv(a);
        blk(b);
    }
}

fn flat_map<A,B,IA:iterable<A>,IB:iterable<B>>(
    self: IA, cnv: fn@(A) -> IB, blk: fn(B)) {
    self.iter {|a|
        cnv(a).iter(blk)
    }
}

fn foldl<A,B,IA:iterable<A>>(self: IA, +b0: B, blk: fn(-B, A) -> B) -> B {
    let mut b <- b0;
    self.iter {|a|
        b = blk(b, a);
    }
    ret b;
}

fn foldr<A:copy,B,IA:iterable<A>>(
    self: IA, +b0: B, blk: fn(A, -B) -> B) -> B {

    let mut b <- b0;
    reversed(self) {|a|
        b = blk(a, b);
    }
    ret b;
}

fn to_list<A:copy,IA:iterable<A>>(self: IA) -> [A] {
    foldl::<A,[A],IA>(self, [], {|r, a| r + [a]})
}

// FIXME: This could be made more efficient with an riterable interface
// #2005
fn reversed<A:copy,IA:iterable<A>>(self: IA, blk: fn(A)) {
    vec::riter(to_list(self), blk)
}

fn count<A,IA:iterable<A>>(self: IA, x: A) -> uint {
    foldl(self, 0u) {|count, value|
        if value == x {
            count + 1u
        } else {
            count
        }
    }
}

fn repeat(times: uint, blk: fn()) {
    let mut i = 0u;
    while i < times {
        blk();
        i += 1u;
    }
}

fn min<A:copy,IA:iterable<A>>(self: IA) -> A {
    alt foldl::<A,option<A>,IA>(self, none) {|a, b|
        alt a {
          some(a_) if a_ < b {
            // FIXME: Not sure if this is successfully optimized to a move
            // #2005
            a
          }
          _ { some(b) }
        }
    } {
        some(val) { val }
        none { fail "min called on empty iterator" }
    }
}

fn max<A:copy,IA:iterable<A>>(self: IA) -> A {
    alt foldl::<A,option<A>,IA>(self, none) {|a, b|
        alt a {
          some(a_) if a_ > b {
            // FIXME: Not sure if this is successfully optimized to a move
            // #2005
            a
          }
          _ { some(b) }
        }
    } {
        some(val) { val }
        none { fail "max called on empty iterator" }
    }
}

#[test]
fn test_enumerate() {
    enumerate(["0", "1", "2"]) {|i,j|
        assert #fmt["%u",i] == j;
    }
}

#[test]
fn test_map_and_to_list() {
    let a = bind vec::iter([0, 1, 2], _);
    let b = bind map(a, {|i| i*2}, _);
    let c = to_list(b);
    assert c == [0, 2, 4];
}

#[test]
fn test_map_directly_on_vec() {
    let b = bind map([0, 1, 2], {|i| i*2}, _);
    let c = to_list(b);
    assert c == [0, 2, 4];
}

#[test]
fn test_filter_on_int_range() {
    fn is_even(&&i: int) -> bool {
        ret (i % 2) == 0;
    }

    let l = to_list(bind filter(bind int::range(0, 10, _), is_even, _));
    assert l == [0, 2, 4, 6, 8];
}

#[test]
fn test_filter_on_uint_range() {
    fn is_even(&&i: uint) -> bool {
        ret (i % 2u) == 0u;
    }

    let l = to_list(bind filter(bind uint::range(0u, 10u, _), is_even, _));
    assert l == [0u, 2u, 4u, 6u, 8u];
}

#[test]
fn test_filter_map() {
    fn negativate_the_evens(&&i: int) -> option<int> {
        if i % 2 == 0 {
            some(-i)
        } else {
            none
        }
    }

    let l = to_list(bind filter_map(
        bind int::range(0, 5, _), negativate_the_evens, _));
    assert l == [0, -2, -4];
}

#[test]
fn test_flat_map_with_option() {
    fn if_even(&&i: int) -> option<int> {
        if (i % 2) == 0 { some(i) }
        else { none }
    }

    let a = bind vec::iter([0, 1, 2], _);
    let b = bind flat_map(a, if_even, _);
    let c = to_list(b);
    assert c == [0, 2];
}

#[test]
fn test_flat_map_with_list() {
    fn repeat(&&i: int) -> [int] {
        let r = [];
        int::range(0, i) {|_j| r += [i]; }
        r
    }

    let a = bind vec::iter([0, 1, 2, 3], _);
    let b = bind flat_map(a, repeat, _);
    let c = to_list(b);
    #debug["c = %?", c];
    assert c == [1, 2, 2, 3, 3, 3];
}

#[test]
fn test_repeat() {
    let c = [],
        i = 0u;
    repeat(5u) {||
        c += [(i * i)];
        i += 1u;
    };
    #debug["c = %?", c];
    assert c == [0u, 1u, 4u, 9u, 16u];
}

#[test]
fn test_min() {
    assert min([5, 4, 1, 2, 3]) == 1;
}

#[test]
#[should_fail]
#[ignore(cfg(target_os = "win32"))]
fn test_min_empty() {
    min::<int, [int]>([]);
}

#[test]
fn test_max() {
    assert max([1, 2, 4, 2, 3]) == 4;
}

#[test]
#[should_fail]
#[ignore(cfg(target_os = "win32"))]
fn test_max_empty() {
    max::<int, [int]>([]);
}

#[test]
fn test_reversed() {
    assert to_list(bind reversed([1, 2, 3], _)) == [3, 2, 1];
}

#[test]
fn test_count() {
    assert count([1, 2, 1, 2, 1], 1) == 3u;
}

#[test]
fn test_foldr() {
    fn sub(&&a: int, -b: int) -> int {
        a - b
    }
    let sum = foldr([1, 2, 3, 4], 0, sub);
    assert sum == -2;
}<|endoftext|>


<commit_before>#![allow(dead_code)]
#![allow(unused_variables)]

// Dependencies
mod vjoyinterface;
extern crate std;
extern crate libc;

// Number of digital inputs on a standard N64 controller
const NUM_N64_BUTTONS: u8 = 14;

// Control constants - what magic numbers do we need to play with each virtual device input?
// USB HID joystick constants. We assume our emulator is configured to map virtual joystick to N64 joystick
const HID_JOYSTICK_X: libc::c_uint = 0x30;
const HID_JOYSTICK_Y: libc::c_uint = 0x31;

#[derive(Debug)]
pub enum VirtualN64ControllerButton {
    A,
    B,
    Z,
    L,
    R,
    Start,
    Cup,
    Cdown,
    Cleft,
    Cright,
    Dup,
    Ddown,
    Dleft,
    Dright
}

// Default emulator button bindings. vJoy button indices are one-based
impl VirtualN64ControllerButton {
    fn get_vjoy_button_index(&self) -> libc::c_uchar {
        match *self {
            VirtualN64ControllerButton::A => 0x01,
            VirtualN64ControllerButton::B => 0x02,
            VirtualN64ControllerButton::Z => 0x03,
            VirtualN64ControllerButton::L => 0x04,
            VirtualN64ControllerButton::R => 0x05,
            VirtualN64ControllerButton::Start => 0x06,
            VirtualN64ControllerButton::Cup => 0x07,
            VirtualN64ControllerButton::Cdown => 0x08,
            VirtualN64ControllerButton::Cleft => 0x09,
            VirtualN64ControllerButton::Cright => 0x10,
            VirtualN64ControllerButton::Dup => 0x11,
            VirtualN64ControllerButton::Ddown => 0x12,
            VirtualN64ControllerButton::Dleft => 0x13,
            VirtualN64ControllerButton::Dright => 0x14
        }
    }
}

// Info about our virtual joystick
// Post-initialization, this should all be read-only
struct VirtualN64ControllerProps {
    vjoy_device_number: libc::c_uint,

    x_min: libc::c_long,
    x_max: libc::c_long,
    y_min: libc::c_long,
    y_max: libc::c_long,
}

// Last-set values
struct VirtualN64ControllerState {
    x: libc::c_long,
    y: libc::c_long,
    a: libc::c_int,
    b: libc::c_int,
    z: libc::c_int,
    l: libc::c_int,
    r: libc::c_int,
    cup: libc::c_int,
    cdown: libc::c_int,
    cleft: libc::c_int,
    cright: libc::c_int,
    dup: libc::c_int,
    ddown: libc::c_int,
    dleft: libc::c_int,
    dright: libc::c_int,
}

pub struct VirtualN64Controller {
    props: VirtualN64ControllerProps,
    state: VirtualN64ControllerState,
}

impl Default for VirtualN64Controller {
    fn default() -> VirtualN64Controller {
        VirtualN64Controller {
            props: VirtualN64ControllerProps {
                vjoy_device_number: 0,
                x_min: 0,
                x_max: 0,
                y_min: 0,
                y_max: 0
            },
            state: VirtualN64ControllerState {
                x: 0,
                y: 0,
                a: 0,
                b: 0,
                z: 0,
                l: 0,
                r: 0,
                cup: 0,
                cdown: 0,
                cleft: 0,
                cright: 0,
                dup: 0,
                ddown: 0,
                dleft: 0,
                dright: 0
            }
        }
    }
}

// vJoy device utility functions
fn is_vjoy_enabled() -> bool {
    unsafe {
        let vjoy_enabled = vjoyinterface::vJoyEnabled();
        if vjoy_enabled == 0 {
            println!("vJoy isn't enabled");
            return false;
        }
    }

    true
}

fn does_vjoystick_axis_exist(index: libc::c_uint, axis: libc::c_uint) -> bool {
    unsafe {
        let axis_exists = vjoyinterface::GetVJDAxisExist(index, axis);
        if axis_exists == 0 {
            println!("vJoy device {} doesn't have axis {}", index, axis);
            return false;
        }
    }

    true
}

fn get_vjoystick_axis_min(index: libc::c_uint, axis: libc::c_uint) -> Result<libc::c_long, &'static str> {
    unsafe {
        let mut min: libc::c_long = 0;
        let min_raw_pointer = &mut min as *mut libc::c_long;
        let min_result = vjoyinterface::GetVJDAxisMin(index, axis, min_raw_pointer);
        if min_result == 0 {
            return Err("Unable to get axis minimum");
        }

        Ok(min)
    }
}

fn get_vjoystick_axis_max(index: libc::c_uint, axis: libc::c_uint) -> Result<libc::c_long, &'static str> {
    unsafe {
        let mut max: libc::c_long = 0;
        let max_raw_pointer = &mut max as *mut libc::c_long;
        let max_result = vjoyinterface::GetVJDAxisMax(index, axis, max_raw_pointer);
        if max_result == 0 {
            return Err("Unable to get axis maximum");
        }

        Ok(max)
    }
}

fn get_vjoystick_button_count(index: libc::c_uint) -> u8 {
    unsafe {
        let num_buttons = vjoyinterface::GetVJDButtonNumber(index);
        println!("vJoy device {} has {} buttons", index, num_buttons);
        num_buttons as u8
    }
}

fn get_vjoystick_status(index: libc::c_uint) -> vjoyinterface::Enum_VjdStat {
    unsafe {
        let joystick_status = vjoyinterface::GetVJDStatus(index);
        println!("vJoy device {} has status {}", index, joystick_status);
        return joystick_status;
    }
}

fn claim_vjoystick(index: libc::c_uint) -> Result<(), &'static str> {
    unsafe {
        let joystick_status = get_vjoystick_status(index);
        if joystick_status == vjoyinterface::VJD_STAT_FREE {
            // Try to claim it
            let acquire_vjd_result = vjoyinterface::AcquireVJD(index);
            if acquire_vjd_result == 0 {
                return Err("Virtual joystick is available, but unable to acquire it");
            } else {
                return Ok(());
            }
        } else if joystick_status == vjoyinterface::VJD_STAT_OWN {
            // We've already claimed it
            return Ok(());
        }
    }

    return Err("Virtual joystick is owned by someone else, missing, or in unknown state");
}

fn reset_vjoystick(index: libc::c_uint) -> Result<(), &'static str> {
    unsafe {
        let reset_result = vjoyinterface::ResetVJD(index);
        if reset_result == 0 {
            return Err("vJoy reset function returned failure");
        }
    }

    return Ok(());
}

fn set_vjoystick_axis(index: libc::c_uint, axis: libc::c_uint, value: libc::c_long) -> bool {
    unsafe {
        let set_x_result = vjoyinterface::SetAxis(value, index, axis);
        if set_x_result == 0 {
            return false;
        }
    }

    return true;
}

fn set_vjoystick_button(index: libc::c_uint, button: libc::c_uchar, value: libc::c_int) -> bool {
    unsafe {
        let set_result = vjoyinterface::SetBtn(value, index, button);
        if set_result == 0 {
            return false;
        }
    }

    return true;
}

// Test if a vJoy device has the controls we need to treat it like an N64 controller
// If this fails, the vJoy device should be configured manually using vJoy's supplied configuration tool
fn is_vjoystick_n64(index: libc::c_uint) -> bool {
    if !does_vjoystick_axis_exist(index, HID_JOYSTICK_X) { return false; }
    if !does_vjoystick_axis_exist(index, HID_JOYSTICK_Y) { return false; }
    if !(get_vjoystick_button_count(index) >= NUM_N64_BUTTONS) { return false; }

    return true;
}

// Make a virtual N64 controller given a vJoy device number
fn make_vn64c(vjoy_device_number: libc::c_uint) -> Result<(VirtualN64Controller), &'static str> {
    let mut controller = VirtualN64Controller { ..Default::default() };

    controller.props.vjoy_device_number = vjoy_device_number;

    // Get and capture vjoystick min and max
    match get_vjoystick_axis_min(vjoy_device_number, HID_JOYSTICK_X) {
        Ok(min) => controller.props.x_min = min,
        Err(msg) => return Err(msg)
    };
    match get_vjoystick_axis_max(vjoy_device_number, HID_JOYSTICK_X) {
        Ok(max) => controller.props.x_max = max,
        Err(msg) => return Err(msg)
    };
    match get_vjoystick_axis_min(vjoy_device_number, HID_JOYSTICK_Y) {
        Ok(min) => controller.props.y_min = min,
        Err(msg) => return Err(msg)
    };
    match get_vjoystick_axis_min(vjoy_device_number, HID_JOYSTICK_Y) {
        Ok(max) => controller.props.y_max = max,
        Err(msg) => return Err(msg)
    };

    // Set joystick values to neutral
    controller.state.x = (controller.props.x_max - controller.props.x_min) / 2;
    controller.state.y = (controller.props.y_max - controller.props.y_min) / 2;

    Ok(controller)
}

// Exposed functions
// Initialize a virtual N64 controller
// After calling this successfully, controller is a valid handle for other functions
pub fn init(vjoy_device_number: u8) -> Result<VirtualN64Controller, &'static str> {
    let vjoy_device_number_native = vjoy_device_number as libc::c_uint;

    if !is_vjoy_enabled() { return Err("vJoy isn't enabled"); }
    if !is_vjoystick_n64(vjoy_device_number_native) { return Err("Virtual joystick is not capable of emulating an N64 controller"); }
    match claim_vjoystick(vjoy_device_number_native) {
        Err(msg) => return Err(msg),
        _ => ()
    };
    match reset_vjoystick(vjoy_device_number_native) {
        Err(msg) => return Err(msg),
        _ => ()
    };
    match make_vn64c(vjoy_device_number_native) {
        Err(msg) => Err(msg),
        Ok(controller) => Ok(controller)
    }
}

// Set the virtual joystick, assuming that direction is in degrees and strength is a number 0-1 inclusive
//@todo don't trust controller argument
//@todo validate arguments (direction: 0-359, strength: 0-1)
pub fn set_joystick(controller: &mut VirtualN64Controller, direction: u16, strength: f32) -> Result<(), &'static str> {
    // Convert direction from degrees to radians
    let direction_rad: f32 = (direction as f32) * std::f32::consts::PI / 180.0;

    let x_strength = direction_rad.cos() * strength;
    let y_strength = direction_rad.sin() * strength;

    let x_mid: libc::c_long = ((controller.props.x_max - controller.props.x_min)/2) as libc::c_long;
    let y_mid: libc::c_long = ((controller.props.y_max - controller.props.y_min)/2) as libc::c_long;

    let x = x_mid + (x_strength * (x_mid as f32)) as libc::c_long;
    let y = y_mid + (y_strength * (y_mid as f32)) as libc::c_long;

    controller.state.x = x;
    controller.state.y = y;

    if !set_vjoystick_axis(controller.props.vjoy_device_number, HID_JOYSTICK_X, controller.state.x) {
        return Err("Unable to set X axis");
    }
    if !set_vjoystick_axis(controller.props.vjoy_device_number, HID_JOYSTICK_Y, controller.state.y) {
        return Err("Unable to set Y axis");
    }

    println!("Set joystick: x = {} y = {}", x_strength, y_strength);
    println!("Scaled for power, that's x = {} y = {}", x, y);

    Ok(())
}

pub fn set_button(controller: &VirtualN64Controller, button: VirtualN64ControllerButton, value: bool) -> bool {
    if !(set_vjoystick_button(controller.props.vjoy_device_number, button.get_vjoy_button_index(), value as libc::c_int)) {
        println!("Setting button failed!");
        return false;
    }

    println!("Set button {:?} to {}", button, value as libc::c_int);

    return true;
}<commit_msg>Clean up more of libvn64c<commit_after>#![allow(dead_code)]
#![allow(unused_variables)]

// Dependencies
mod vjoyinterface;
extern crate std;
extern crate libc;

// Control constants - what magic numbers do we need to play with each virtual device input?
// USB HID joystick constants. We assume our emulator is configured to map virtual joystick to N64 joystick
const HID_JOYSTICK_X: libc::c_uint = 0x30;
const HID_JOYSTICK_Y: libc::c_uint = 0x31;

// Number of digital inputs on a standard N64 controller
const NUM_N64_BUTTONS: u8 = 14;

#[derive(Debug)]
pub enum VirtualN64ControllerButton {
    A,
    B,
    Z,
    L,
    R,
    Start,
    Cup,
    Cdown,
    Cleft,
    Cright,
    Dup,
    Ddown,
    Dleft,
    Dright
}

// Default emulator button bindings. vJoy button indices are one-based
impl VirtualN64ControllerButton {
    fn get_vjoy_button_index(&self) -> libc::c_uchar {
        match *self {
            VirtualN64ControllerButton::A => 0x01,
            VirtualN64ControllerButton::B => 0x02,
            VirtualN64ControllerButton::Z => 0x03,
            VirtualN64ControllerButton::L => 0x04,
            VirtualN64ControllerButton::R => 0x05,
            VirtualN64ControllerButton::Start => 0x06,
            VirtualN64ControllerButton::Cup => 0x07,
            VirtualN64ControllerButton::Cdown => 0x08,
            VirtualN64ControllerButton::Cleft => 0x09,
            VirtualN64ControllerButton::Cright => 0x10,
            VirtualN64ControllerButton::Dup => 0x11,
            VirtualN64ControllerButton::Ddown => 0x12,
            VirtualN64ControllerButton::Dleft => 0x13,
            VirtualN64ControllerButton::Dright => 0x14
        }
    }
}

// Info about our virtual joystick
// Post-initialization, this should all be read-only
struct VirtualN64ControllerProps {
    vjoy_device_number: libc::c_uint,

    x_min: libc::c_long,
    x_max: libc::c_long,
    y_min: libc::c_long,
    y_max: libc::c_long,
}

// Last-set values
struct VirtualN64ControllerState {
    x: libc::c_long,
    y: libc::c_long,
    a: libc::c_int,
    b: libc::c_int,
    z: libc::c_int,
    l: libc::c_int,
    r: libc::c_int,
    cup: libc::c_int,
    cdown: libc::c_int,
    cleft: libc::c_int,
    cright: libc::c_int,
    dup: libc::c_int,
    ddown: libc::c_int,
    dleft: libc::c_int,
    dright: libc::c_int,
}

pub struct VirtualN64Controller {
    props: VirtualN64ControllerProps,
    state: VirtualN64ControllerState,
}

impl Default for VirtualN64Controller {
    fn default() -> VirtualN64Controller {
        VirtualN64Controller {
            props: VirtualN64ControllerProps {
                vjoy_device_number: 0,
                x_min: 0,
                x_max: 0,
                y_min: 0,
                y_max: 0
            },
            state: VirtualN64ControllerState {
                x: 0,
                y: 0,
                a: 0,
                b: 0,
                z: 0,
                l: 0,
                r: 0,
                cup: 0,
                cdown: 0,
                cleft: 0,
                cright: 0,
                dup: 0,
                ddown: 0,
                dleft: 0,
                dright: 0
            }
        }
    }
}

// vJoy device utility functions
fn is_vjoy_enabled() -> bool {
    unsafe {
        let vjoy_enabled = vjoyinterface::vJoyEnabled();
        if vjoy_enabled == 0 {
            return false;
        }
    }

    true
}

fn does_vjoystick_axis_exist(index: libc::c_uint, axis: libc::c_uint) -> bool {
    unsafe {
        let axis_exists = vjoyinterface::GetVJDAxisExist(index, axis);
        if axis_exists == 0 {
            return false;
        }
    }

    true
}

fn get_vjoystick_axis_min(index: libc::c_uint, axis: libc::c_uint) -> Result<libc::c_long, &'static str> {
    unsafe {
        let mut min: libc::c_long = 0;
        let min_raw_pointer = &mut min as *mut libc::c_long;
        let min_result = vjoyinterface::GetVJDAxisMin(index, axis, min_raw_pointer);
        if min_result == 0 {
            return Err("Unable to get axis minimum");
        }

        Ok(min)
    }
}

fn get_vjoystick_axis_max(index: libc::c_uint, axis: libc::c_uint) -> Result<libc::c_long, &'static str> {
    unsafe {
        let mut max: libc::c_long = 0;
        let max_raw_pointer = &mut max as *mut libc::c_long;
        let max_result = vjoyinterface::GetVJDAxisMax(index, axis, max_raw_pointer);
        if max_result == 0 {
            return Err("Unable to get axis maximum");
        }

        Ok(max)
    }
}

fn get_vjoystick_button_count(index: libc::c_uint) -> u8 {
    unsafe {
        let num_buttons = vjoyinterface::GetVJDButtonNumber(index);

        num_buttons as u8
    }
}

fn get_vjoystick_status(index: libc::c_uint) -> vjoyinterface::Enum_VjdStat {
    unsafe {
        let joystick_status = vjoyinterface::GetVJDStatus(index);

        joystick_status
    }
}

fn claim_vjoystick(index: libc::c_uint) -> Result<(), &'static str> {
    unsafe {
        let joystick_status = get_vjoystick_status(index);
        if joystick_status == vjoyinterface::VJD_STAT_FREE {
            // Try to claim it
            let acquire_vjd_result = vjoyinterface::AcquireVJD(index);
            if acquire_vjd_result == 0 {
                return Err("Virtual joystick is available, but unable to acquire it");
            } else {
                return Ok(());
            }
        } else if joystick_status == vjoyinterface::VJD_STAT_OWN {
            // We've already claimed it
            return Ok(());
        }
    }

    return Err("Virtual joystick is owned by someone else, missing, or in unknown state");
}

fn reset_vjoystick(index: libc::c_uint) -> Result<(), &'static str> {
    unsafe {
        let reset_result = vjoyinterface::ResetVJD(index);
        if reset_result == 0 {
            return Err("vJoy reset function returned failure");
        }
    }

    return Ok(());
}

fn set_vjoystick_axis(index: libc::c_uint, axis: libc::c_uint, value: libc::c_long) -> Result<(), ()> {
    unsafe {
        let set_x_result = vjoyinterface::SetAxis(value, index, axis);
        if set_x_result == 0 {
            return Err(());
        }
    }

    Ok(())
}

fn set_vjoystick_button(index: libc::c_uint, button: libc::c_uchar, value: libc::c_int) -> Result<(), ()> {
    unsafe {
        let set_result = vjoyinterface::SetBtn(value, index, button);
        if set_result == 0 {
            return Err(());
        }
    }

    Ok(())
}

// Test if a vJoy device has the controls we need to treat it like an N64 controller
// If this fails, the vJoy device should be configured manually using vJoy's supplied configuration tool
fn is_vjoystick_n64(index: libc::c_uint) -> bool {
    if !does_vjoystick_axis_exist(index, HID_JOYSTICK_X) { return false; }
    if !does_vjoystick_axis_exist(index, HID_JOYSTICK_Y) { return false; }
    if !(get_vjoystick_button_count(index) >= NUM_N64_BUTTONS) { return false; }

    true
}

// Make a virtual N64 controller given a vJoy device number
fn make_vn64c(vjoy_device_number: libc::c_uint) -> Result<(VirtualN64Controller), &'static str> {
    let mut controller = VirtualN64Controller { ..Default::default() };

    controller.props.vjoy_device_number = vjoy_device_number;

    // Get and capture vjoystick min and max
    match get_vjoystick_axis_min(vjoy_device_number, HID_JOYSTICK_X) {
        Ok(min) => controller.props.x_min = min,
        Err(msg) => return Err(msg)
    };
    match get_vjoystick_axis_max(vjoy_device_number, HID_JOYSTICK_X) {
        Ok(max) => controller.props.x_max = max,
        Err(msg) => return Err(msg)
    };
    match get_vjoystick_axis_min(vjoy_device_number, HID_JOYSTICK_Y) {
        Ok(min) => controller.props.y_min = min,
        Err(msg) => return Err(msg)
    };
    match get_vjoystick_axis_min(vjoy_device_number, HID_JOYSTICK_Y) {
        Ok(max) => controller.props.y_max = max,
        Err(msg) => return Err(msg)
    };

    // Set joystick values to neutral
    controller.state.x = (controller.props.x_max - controller.props.x_min) / 2;
    controller.state.y = (controller.props.y_max - controller.props.y_min) / 2;

    Ok(controller)
}

// Exposed functions
// Initialize a virtual N64 controller
// After calling this successfully, controller is a valid handle for other functions
pub fn init(vjoy_device_number: u8) -> Result<VirtualN64Controller, &'static str> {
    let vjoy_device_number_native = vjoy_device_number as libc::c_uint;

    if !is_vjoy_enabled() { return Err("vJoy isn't enabled"); }
    if !is_vjoystick_n64(vjoy_device_number_native) { return Err("Virtual joystick is not capable of emulating an N64 controller"); }
    match claim_vjoystick(vjoy_device_number_native) {
        Err(msg) => return Err(msg),
        _ => ()
    };
    match reset_vjoystick(vjoy_device_number_native) {
        Err(msg) => return Err(msg),
        _ => ()
    };
    match make_vn64c(vjoy_device_number_native) {
        Err(msg) => Err(msg),
        Ok(controller) => Ok(controller)
    }
}

// Set the virtual joystick, assuming that direction is in degrees and strength is a number 0-1 inclusive
//@todo don't trust controller argument
//@todo validate arguments (direction: 0-359, strength: 0-1)
pub fn set_joystick(controller: &mut VirtualN64Controller, direction: u16, strength: f32) -> Result<(), &'static str> {
    // Convert direction from degrees to radians
    let direction_rad: f32 = (direction as f32) * std::f32::consts::PI / 180.0;

    let x_strength = direction_rad.cos() * strength;
    let y_strength = direction_rad.sin() * strength;

    let x_mid: libc::c_long = ((controller.props.x_max - controller.props.x_min)/2) as libc::c_long;
    let y_mid: libc::c_long = ((controller.props.y_max - controller.props.y_min)/2) as libc::c_long;

    let x = x_mid + (x_strength * (x_mid as f32)) as libc::c_long;
    let y = y_mid + (y_strength * (y_mid as f32)) as libc::c_long;

    match set_vjoystick_axis(controller.props.vjoy_device_number, HID_JOYSTICK_X, x) {
        Ok(_) => (),
        Err(_) => return Err("Unable to set X axis")
    };
    controller.state.x = x;

    match set_vjoystick_axis(controller.props.vjoy_device_number, HID_JOYSTICK_Y, y) {
        Ok(_) => (),
        Err(_) => return Err("Unable to set Y axis")
    };
    controller.state.y = y;

    Ok(())
}

pub fn set_button(controller: &VirtualN64Controller, button: VirtualN64ControllerButton, value: bool) -> Result<(), &'static str> {
    match set_vjoystick_button(controller.props.vjoy_device_number, button.get_vjoy_button_index(), value as libc::c_int) {
        Ok(_) => (),
        Err(_) => return Err("Unable to set virtual joystick button")
    };
    //@todo update controller state... how can we cleanly map VirtualN64ControllerButton to the state struct?

    Ok(())
}<|endoftext|>


<commit_before>extern crate llvm_sys as llvm;

use syntax::ast::expr::*;
use std::collections::HashMap;
use std::ffi::CString;
use std::boxed;

// Struct to keep track of data needed to build IR
pub struct Context {
    context: *mut llvm::LLVMContext,
    module: *mut llvm::LLVMModule,
    builder: *mut llvm::LLVMBuilder,
    named_values: HashMap<String, *mut llvm::LLVMValue>
}

impl Context {
    pub fn new(module_name: &str) -> Context {
        unsafe {
            let context = llvm::core::LLVMContextCreate();
            let module = llvm::core::LLVMModuleCreateWithNameInContext(c_str_ptr(module_name), context);
            let builder = llvm::core::LLVMCreateBuilderInContext(context);
            let named_values = HashMap::new();

            Context {
                context: context,
                module: module,
                builder: builder,
                named_values: named_values
            }
        }
    }

    // Dump the IR to stdout
    pub fn dump(&self) {
        unsafe {
            llvm::core::LLVMDumpModule(self.module);
        }
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            llvm::core::LLVMDisposeBuilder(self.builder);
            llvm::core::LLVMDisposeModule(self.module);
            llvm::core::LLVMContextDispose(self.context);
        }
    }
}

pub trait CodeGen {
    fn gen_code(&self, context: &mut Context) -> Option<*mut llvm::LLVMValue>;
}

impl CodeGen for ExprWrapper {
    fn gen_code(&self, context: &mut Context) -> Option<*mut llvm::LLVMValue> {
        self.get_expr().gen_code(context)
    }
}

impl CodeGen for Expr {
    fn gen_code(&self, context: &mut Context) -> Option<*mut llvm::LLVMValue> {
        match *self {
            Expr::Block(ref vec) => {
                for expr in vec {
                    expr.gen_code(context);
                }

                None
            },
            Expr::Ident(ref name) => {
                match context.named_values.get(name) {
                    Some(val) => Some(*val),
                    None => {
                        // Add a standard error writing system?
                        println!("Could not find func {}", name);

                        None
                    }
                }
            },
            Expr::FnCall(ref name, ref args) => {
                // This expr should always contain a string
                unsafe {
                    let function = llvm::core::LLVMGetNamedFunction(context.module, c_str_ptr(name));

                    if function.is_null() {
                        // ToDo: Add standardized error message writing?
                        println!("Error: Function {} not found.", name);
                        return None;
                    }

                    if llvm::core::LLVMCountParams(function) as usize != args.len() {
                        println!("Incorrect number of arguments");
                        return None;
                    }

                    let mut arg_values = Vec::new();

                    for arg in args {
                        if let Some(value) = arg.gen_code(context) {
                            arg_values.push(value);
                        }

                        return None;
                    }

                    let args_ptr = boxed::into_raw(Box::new(*arg_values.as_ptr()));

                    Some(llvm::core::LLVMBuildCall(context.builder, function, args_ptr, arg_values.len() as u32, c_str_ptr("calltmp")))
                }
            },
            Expr::NoOp => None,
            _ => None
        }
    }
}

// Helper functions
fn c_str_ptr(rust_str: &str) -> *const i8 {
    match CString::new(rust_str.as_bytes()) {
        Ok(string) => string,
        Err(err) => panic!(err)
    }.as_ptr()
}
<commit_msg>Removed unnecessary llvm crate paths that add no extra info.<commit_after>extern crate llvm_sys;

use syntax::ast::expr::*;
use std::collections::HashMap;
use std::ffi::CString;
use std::boxed;
use self::llvm_sys::core::*;
use self::llvm_sys::*;

// Struct to keep track of data needed to build IR
pub struct Context {
    context: *mut LLVMContext,
    module: *mut LLVMModule,
    builder: *mut LLVMBuilder,
    named_values: HashMap<String, *mut LLVMValue>
}

impl Context {
    pub fn new(module_name: &str) -> Context {
        unsafe {
            let context = LLVMContextCreate();
            let module = LLVMModuleCreateWithNameInContext(c_str_ptr(module_name), context);
            let builder = LLVMCreateBuilderInContext(context);
            let named_values = HashMap::new();

            Context {
                context: context,
                module: module,
                builder: builder,
                named_values: named_values
            }
        }
    }

    // Dump the IR to stdout
    pub fn dump(&self) {
        unsafe {
            LLVMDumpModule(self.module);
        }
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            LLVMDisposeBuilder(self.builder);
            LLVMDisposeModule(self.module);
            LLVMContextDispose(self.context);
        }
    }
}

pub trait CodeGen {
    fn gen_code(&self, context: &mut Context) -> Option<*mut LLVMValue>;
}

impl CodeGen for ExprWrapper {
    fn gen_code(&self, context: &mut Context) -> Option<*mut LLVMValue> {
        self.get_expr().gen_code(context)
    }
}

impl CodeGen for Expr {
    fn gen_code(&self, context: &mut Context) -> Option<*mut LLVMValue> {
        match *self {
            Expr::Block(ref vec) => {
                for expr in vec {
                    expr.gen_code(context);
                }

                None
            },
            Expr::Ident(ref name) => {
                match context.named_values.get(name) {
                    Some(val) => Some(*val),
                    None => {
                        // Add a standard error writing system?
                        println!("Could not find func {}", name);

                        None
                    }
                }
            },
            Expr::FnCall(ref name, ref args) => {
                // This expr should always contain a string
                unsafe {
                    let function = LLVMGetNamedFunction(context.module, c_str_ptr(name));

                    if function.is_null() {
                        // ToDo: Add standardized error message writing?
                        println!("Error: Function {} not found.", name);
                        return None;
                    }

                    if LLVMCountParams(function) as usize != args.len() {
                        println!("Incorrect number of arguments");
                        return None;
                    }

                    let mut arg_values = Vec::new();

                    for arg in args {
                        if let Some(value) = arg.gen_code(context) {
                            arg_values.push(value);
                        }

                        return None;
                    }

                    // as_ptr gets *const not *mut so boxing -> raw gets *mut ptr
                    let args_ptr = boxed::into_raw(Box::new(*arg_values.as_ptr()));

                    Some(LLVMBuildCall(context.builder, function, args_ptr, arg_values.len() as u32, c_str_ptr("calltmp")))
                }
            },
            Expr::NoOp => None,
            _ => None
        }
    }
}

// Helper functions
fn c_str_ptr(rust_str: &str) -> *const i8 {
    match CString::new(rust_str.as_bytes()) {
        Ok(string) => string,
        Err(err) => panic!(err)
    }.as_ptr()
}
<|endoftext|>


<commit_before>// Copyright 2018 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.

pub mod fdt;

extern crate byteorder;
extern crate devices;
extern crate io_jail;
extern crate kernel_cmdline;
extern crate kvm;
extern crate libc;
extern crate resources;
extern crate sync;
extern crate sys_util;

use std::collections::BTreeMap;
use std::error::Error as StdError;
use std::fmt::{self, Display};
use std::fs::File;
use std::io::{self, Read, Seek, SeekFrom};
use std::os::unix::io::AsRawFd;
use std::sync::Arc;

use devices::virtio::VirtioDevice;
use devices::{
    Bus, BusDevice, BusError, PciDevice, PciDeviceError, PciInterruptPin, PciRoot, ProxyDevice,
    Serial,
};
use io_jail::Minijail;
use kvm::{IoeventAddress, Kvm, Vcpu, Vm};
use resources::SystemAllocator;
use sync::Mutex;
use sys_util::{syslog, EventFd, GuestAddress, GuestMemory, GuestMemoryError};

/// Holds the pieces needed to build a VM. Passed to `build_vm` in the `LinuxArch` trait below to
/// create a `RunnableLinuxVm`.
pub struct VmComponents {
    pub memory_mb: u64,
    pub vcpu_count: u32,
    pub kernel_image: File,
    pub android_fstab: Option<File>,
    pub initrd_image: Option<File>,
    pub extra_kernel_params: Vec<String>,
    pub wayland_dmabuf: bool,
}

/// Holds the elements needed to run a Linux VM. Created by `build_vm`.
pub struct RunnableLinuxVm {
    pub vm: Vm,
    pub kvm: Kvm,
    pub resources: SystemAllocator,
    pub stdio_serial: Arc<Mutex<Serial>>,
    pub exit_evt: EventFd,
    pub vcpus: Vec<Vcpu>,
    pub irq_chip: Option<File>,
    pub io_bus: Bus,
    pub mmio_bus: Bus,
    pub pid_debug_label_map: BTreeMap<u32, String>,
}

/// The device and optional jail.
pub struct VirtioDeviceStub {
    pub dev: Box<VirtioDevice>,
    pub jail: Option<Minijail>,
}

/// Trait which is implemented for each Linux Architecture in order to
/// set up the memory, cpus, and system devices and to boot the kernel.
pub trait LinuxArch {
    type Error: StdError;

    /// Takes `VmComponents` and generates a `RunnableLinuxVm`.
    ///
    /// # Arguments
    ///
    /// * `components` - Parts to use to build the VM.
    /// * `split_irqchip` - whether to use a split IRQ chip (i.e. userspace PIT/PIC/IOAPIC)
    /// * `create_devices` - Function to generate a list of devices.
    fn build_vm<F, E>(
        components: VmComponents,
        split_irqchip: bool,
        create_devices: F,
    ) -> Result<RunnableLinuxVm, Self::Error>
    where
        F: FnOnce(&GuestMemory, &EventFd) -> Result<Vec<(Box<PciDevice>, Option<Minijail>)>, E>,
        E: StdError + 'static;
}

/// Errors for device manager.
#[derive(Debug)]
pub enum DeviceRegistrationError {
    /// Could not allocate IO space for the device.
    AllocateIoAddrs(PciDeviceError),
    /// Could not allocate device address space for the device.
    AllocateDeviceAddrs(PciDeviceError),
    /// Could not allocate an IRQ number.
    AllocateIrq,
    /// Could not create the mmio device to wrap a VirtioDevice.
    CreateMmioDevice(sys_util::Error),
    /// Could not create an event fd.
    EventFdCreate(sys_util::Error),
    /// Could not add a device to the mmio bus.
    MmioInsert(BusError),
    /// Failed to register ioevent with VM.
    RegisterIoevent(sys_util::Error),
    /// Failed to register irq eventfd with VM.
    RegisterIrqfd(sys_util::Error),
    /// Failed to initialize proxy device for jailed device.
    ProxyDeviceCreation(devices::ProxyError),
    /// Appending to kernel command line failed.
    Cmdline(kernel_cmdline::Error),
    /// No more IRQs are available.
    IrqsExhausted,
    /// No more MMIO space available.
    AddrsExhausted,
}

impl Display for DeviceRegistrationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::DeviceRegistrationError::*;

        match self {
            AllocateIoAddrs(e) => write!(f, "Allocating IO addresses: {}", e),
            AllocateDeviceAddrs(e) => write!(f, "Allocating device addresses: {}", e),
            AllocateIrq => write!(f, "Allocating IRQ number"),
            CreateMmioDevice(e) => write!(f, "failed to create mmio device: {}", e),
            Cmdline(e) => write!(f, "unable to add device to kernel command line: {}", e),
            EventFdCreate(e) => write!(f, "failed to create eventfd: {}", e),
            MmioInsert(e) => write!(f, "failed to add to mmio bus: {}", e),
            RegisterIoevent(e) => write!(f, "failed to register ioevent to VM: {}", e),
            RegisterIrqfd(e) => write!(f, "failed to register irq eventfd to VM: {}", e),
            ProxyDeviceCreation(e) => write!(f, "failed to create proxy device: {}", e),
            IrqsExhausted => write!(f, "no more IRQs are available"),
            AddrsExhausted => write!(f, "no more addresses are available"),
        }
    }
}

/// Creates a root PCI device for use by this Vm.
pub fn generate_pci_root(
    devices: Vec<(Box<PciDevice>, Option<Minijail>)>,
    mmio_bus: &mut Bus,
    resources: &mut SystemAllocator,
    vm: &mut Vm,
) -> Result<(PciRoot, Vec<(u32, PciInterruptPin)>, BTreeMap<u32, String>), DeviceRegistrationError>
{
    let mut root = PciRoot::new();
    let mut pci_irqs = Vec::new();
    let mut pid_labels = BTreeMap::new();
    for (dev_idx, (mut device, jail)) in devices.into_iter().enumerate() {
        let mut keep_fds = device.keep_fds();
        syslog::push_fds(&mut keep_fds);

        let irqfd = EventFd::new().map_err(DeviceRegistrationError::EventFdCreate)?;
        let irq_resample_fd = EventFd::new().map_err(DeviceRegistrationError::EventFdCreate)?;
        let irq_num = resources
            .allocate_irq()
            .ok_or(DeviceRegistrationError::AllocateIrq)? as u32;
        let pci_irq_pin = match dev_idx % 4 {
            0 => PciInterruptPin::IntA,
            1 => PciInterruptPin::IntB,
            2 => PciInterruptPin::IntC,
            3 => PciInterruptPin::IntD,
            _ => panic!(""), // Obviously not possible, but the compiler is not smart enough.
        };
        vm.register_irqfd_resample(&irqfd, &irq_resample_fd, irq_num)
            .map_err(DeviceRegistrationError::RegisterIrqfd)?;
        keep_fds.push(irqfd.as_raw_fd());
        keep_fds.push(irq_resample_fd.as_raw_fd());
        device.assign_irq(irqfd, irq_resample_fd, irq_num, pci_irq_pin);
        pci_irqs.push((dev_idx as u32, pci_irq_pin));

        let ranges = device
            .allocate_io_bars(resources)
            .map_err(DeviceRegistrationError::AllocateIoAddrs)?;
        let device_ranges = device
            .allocate_device_bars(resources)
            .map_err(DeviceRegistrationError::AllocateDeviceAddrs)?;
        device.register_device_capabilities();
        for (event, addr, datamatch) in device.ioeventfds() {
            let io_addr = IoeventAddress::Mmio(addr);
            vm.register_ioevent(&event, io_addr, datamatch)
                .map_err(DeviceRegistrationError::RegisterIoevent)?;
            keep_fds.push(event.as_raw_fd());
        }
        let arced_dev: Arc<Mutex<BusDevice>> = if let Some(jail) = jail {
            let proxy = ProxyDevice::new(device, &jail, keep_fds)
                .map_err(DeviceRegistrationError::ProxyDeviceCreation)?;
            pid_labels.insert(proxy.pid() as u32, proxy.debug_label());
            Arc::new(Mutex::new(proxy))
        } else {
            device.on_sandboxed();
            Arc::new(Mutex::new(device))
        };
        root.add_device(arced_dev.clone());
        for range in &ranges {
            mmio_bus
                .insert(arced_dev.clone(), range.0, range.1, true)
                .map_err(DeviceRegistrationError::MmioInsert)?;
        }

        for range in &device_ranges {
            mmio_bus
                .insert(arced_dev.clone(), range.0, range.1, true)
                .map_err(DeviceRegistrationError::MmioInsert)?;
        }
    }
    Ok((root, pci_irqs, pid_labels))
}

/// Errors for image loading.
#[derive(Debug)]
pub enum LoadImageError {
    Seek(io::Error),
    ImageSizeTooLarge(u64),
    ReadToMemory(GuestMemoryError),
}

impl Display for LoadImageError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::LoadImageError::*;

        match self {
            Seek(e) => write!(f, "Seek failed: {}", e),
            ImageSizeTooLarge(size) => write!(f, "Image size too large: {}", size),
            ReadToMemory(e) => write!(f, "Reading image into memory failed: {}", e),
        }
    }
}

/// Load an image from a file into guest memory.
///
/// # Arguments
///
/// * `guest_mem` - The memory to be used by the guest.
/// * `guest_addr` - The starting address to load the image in the guest memory.
/// * `max_size` - The amount of space in bytes available in the guest memory for the image.
/// * `image` - The file containing the image to be loaded.
///
/// The size in bytes of the loaded image is returned.
pub fn load_image<F>(
    guest_mem: &GuestMemory,
    image: &mut F,
    guest_addr: GuestAddress,
    max_size: u64,
) -> Result<usize, LoadImageError>
where
    F: Read + Seek,
{
    let size = image.seek(SeekFrom::End(0)).map_err(LoadImageError::Seek)?;

    if size > usize::max_value() as u64 || size > max_size {
        return Err(LoadImageError::ImageSizeTooLarge(size));
    }

    // This is safe due to the bounds check above.
    let size = size as usize;

    image
        .seek(SeekFrom::Start(0))
        .map_err(LoadImageError::Seek)?;

    guest_mem
        .read_to_memory(guest_addr, image, size)
        .map_err(LoadImageError::ReadToMemory)?;

    Ok(size)
}
<commit_msg>arch: handle register_device_capabilities errors<commit_after>// Copyright 2018 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.

pub mod fdt;

extern crate byteorder;
extern crate devices;
extern crate io_jail;
extern crate kernel_cmdline;
extern crate kvm;
extern crate libc;
extern crate resources;
extern crate sync;
extern crate sys_util;

use std::collections::BTreeMap;
use std::error::Error as StdError;
use std::fmt::{self, Display};
use std::fs::File;
use std::io::{self, Read, Seek, SeekFrom};
use std::os::unix::io::AsRawFd;
use std::sync::Arc;

use devices::virtio::VirtioDevice;
use devices::{
    Bus, BusDevice, BusError, PciDevice, PciDeviceError, PciInterruptPin, PciRoot, ProxyDevice,
    Serial,
};
use io_jail::Minijail;
use kvm::{IoeventAddress, Kvm, Vcpu, Vm};
use resources::SystemAllocator;
use sync::Mutex;
use sys_util::{syslog, EventFd, GuestAddress, GuestMemory, GuestMemoryError};

/// Holds the pieces needed to build a VM. Passed to `build_vm` in the `LinuxArch` trait below to
/// create a `RunnableLinuxVm`.
pub struct VmComponents {
    pub memory_mb: u64,
    pub vcpu_count: u32,
    pub kernel_image: File,
    pub android_fstab: Option<File>,
    pub initrd_image: Option<File>,
    pub extra_kernel_params: Vec<String>,
    pub wayland_dmabuf: bool,
}

/// Holds the elements needed to run a Linux VM. Created by `build_vm`.
pub struct RunnableLinuxVm {
    pub vm: Vm,
    pub kvm: Kvm,
    pub resources: SystemAllocator,
    pub stdio_serial: Arc<Mutex<Serial>>,
    pub exit_evt: EventFd,
    pub vcpus: Vec<Vcpu>,
    pub irq_chip: Option<File>,
    pub io_bus: Bus,
    pub mmio_bus: Bus,
    pub pid_debug_label_map: BTreeMap<u32, String>,
}

/// The device and optional jail.
pub struct VirtioDeviceStub {
    pub dev: Box<VirtioDevice>,
    pub jail: Option<Minijail>,
}

/// Trait which is implemented for each Linux Architecture in order to
/// set up the memory, cpus, and system devices and to boot the kernel.
pub trait LinuxArch {
    type Error: StdError;

    /// Takes `VmComponents` and generates a `RunnableLinuxVm`.
    ///
    /// # Arguments
    ///
    /// * `components` - Parts to use to build the VM.
    /// * `split_irqchip` - whether to use a split IRQ chip (i.e. userspace PIT/PIC/IOAPIC)
    /// * `create_devices` - Function to generate a list of devices.
    fn build_vm<F, E>(
        components: VmComponents,
        split_irqchip: bool,
        create_devices: F,
    ) -> Result<RunnableLinuxVm, Self::Error>
    where
        F: FnOnce(&GuestMemory, &EventFd) -> Result<Vec<(Box<PciDevice>, Option<Minijail>)>, E>,
        E: StdError + 'static;
}

/// Errors for device manager.
#[derive(Debug)]
pub enum DeviceRegistrationError {
    /// Could not allocate IO space for the device.
    AllocateIoAddrs(PciDeviceError),
    /// Could not allocate device address space for the device.
    AllocateDeviceAddrs(PciDeviceError),
    /// Could not allocate an IRQ number.
    AllocateIrq,
    /// Could not create the mmio device to wrap a VirtioDevice.
    CreateMmioDevice(sys_util::Error),
    /// Could not create an event fd.
    EventFdCreate(sys_util::Error),
    /// Could not add a device to the mmio bus.
    MmioInsert(BusError),
    /// Failed to register ioevent with VM.
    RegisterIoevent(sys_util::Error),
    /// Failed to register irq eventfd with VM.
    RegisterIrqfd(sys_util::Error),
    /// Failed to initialize proxy device for jailed device.
    ProxyDeviceCreation(devices::ProxyError),
    /// Appending to kernel command line failed.
    Cmdline(kernel_cmdline::Error),
    /// No more IRQs are available.
    IrqsExhausted,
    /// No more MMIO space available.
    AddrsExhausted,
    /// Could not register PCI device capabilities.
    RegisterDeviceCapabilities(PciDeviceError),
}

impl Display for DeviceRegistrationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::DeviceRegistrationError::*;

        match self {
            AllocateIoAddrs(e) => write!(f, "Allocating IO addresses: {}", e),
            AllocateDeviceAddrs(e) => write!(f, "Allocating device addresses: {}", e),
            AllocateIrq => write!(f, "Allocating IRQ number"),
            CreateMmioDevice(e) => write!(f, "failed to create mmio device: {}", e),
            Cmdline(e) => write!(f, "unable to add device to kernel command line: {}", e),
            EventFdCreate(e) => write!(f, "failed to create eventfd: {}", e),
            MmioInsert(e) => write!(f, "failed to add to mmio bus: {}", e),
            RegisterIoevent(e) => write!(f, "failed to register ioevent to VM: {}", e),
            RegisterIrqfd(e) => write!(f, "failed to register irq eventfd to VM: {}", e),
            ProxyDeviceCreation(e) => write!(f, "failed to create proxy device: {}", e),
            IrqsExhausted => write!(f, "no more IRQs are available"),
            AddrsExhausted => write!(f, "no more addresses are available"),
            RegisterDeviceCapabilities(e) => {
                write!(f, "could not register PCI device capabilities: {}", e)
            }
        }
    }
}

/// Creates a root PCI device for use by this Vm.
pub fn generate_pci_root(
    devices: Vec<(Box<PciDevice>, Option<Minijail>)>,
    mmio_bus: &mut Bus,
    resources: &mut SystemAllocator,
    vm: &mut Vm,
) -> Result<(PciRoot, Vec<(u32, PciInterruptPin)>, BTreeMap<u32, String>), DeviceRegistrationError>
{
    let mut root = PciRoot::new();
    let mut pci_irqs = Vec::new();
    let mut pid_labels = BTreeMap::new();
    for (dev_idx, (mut device, jail)) in devices.into_iter().enumerate() {
        let mut keep_fds = device.keep_fds();
        syslog::push_fds(&mut keep_fds);

        let irqfd = EventFd::new().map_err(DeviceRegistrationError::EventFdCreate)?;
        let irq_resample_fd = EventFd::new().map_err(DeviceRegistrationError::EventFdCreate)?;
        let irq_num = resources
            .allocate_irq()
            .ok_or(DeviceRegistrationError::AllocateIrq)? as u32;
        let pci_irq_pin = match dev_idx % 4 {
            0 => PciInterruptPin::IntA,
            1 => PciInterruptPin::IntB,
            2 => PciInterruptPin::IntC,
            3 => PciInterruptPin::IntD,
            _ => panic!(""), // Obviously not possible, but the compiler is not smart enough.
        };
        vm.register_irqfd_resample(&irqfd, &irq_resample_fd, irq_num)
            .map_err(DeviceRegistrationError::RegisterIrqfd)?;
        keep_fds.push(irqfd.as_raw_fd());
        keep_fds.push(irq_resample_fd.as_raw_fd());
        device.assign_irq(irqfd, irq_resample_fd, irq_num, pci_irq_pin);
        pci_irqs.push((dev_idx as u32, pci_irq_pin));

        let ranges = device
            .allocate_io_bars(resources)
            .map_err(DeviceRegistrationError::AllocateIoAddrs)?;
        let device_ranges = device
            .allocate_device_bars(resources)
            .map_err(DeviceRegistrationError::AllocateDeviceAddrs)?;
        device
            .register_device_capabilities()
            .map_err(DeviceRegistrationError::RegisterDeviceCapabilities)?;
        for (event, addr, datamatch) in device.ioeventfds() {
            let io_addr = IoeventAddress::Mmio(addr);
            vm.register_ioevent(&event, io_addr, datamatch)
                .map_err(DeviceRegistrationError::RegisterIoevent)?;
            keep_fds.push(event.as_raw_fd());
        }
        let arced_dev: Arc<Mutex<BusDevice>> = if let Some(jail) = jail {
            let proxy = ProxyDevice::new(device, &jail, keep_fds)
                .map_err(DeviceRegistrationError::ProxyDeviceCreation)?;
            pid_labels.insert(proxy.pid() as u32, proxy.debug_label());
            Arc::new(Mutex::new(proxy))
        } else {
            device.on_sandboxed();
            Arc::new(Mutex::new(device))
        };
        root.add_device(arced_dev.clone());
        for range in &ranges {
            mmio_bus
                .insert(arced_dev.clone(), range.0, range.1, true)
                .map_err(DeviceRegistrationError::MmioInsert)?;
        }

        for range in &device_ranges {
            mmio_bus
                .insert(arced_dev.clone(), range.0, range.1, true)
                .map_err(DeviceRegistrationError::MmioInsert)?;
        }
    }
    Ok((root, pci_irqs, pid_labels))
}

/// Errors for image loading.
#[derive(Debug)]
pub enum LoadImageError {
    Seek(io::Error),
    ImageSizeTooLarge(u64),
    ReadToMemory(GuestMemoryError),
}

impl Display for LoadImageError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::LoadImageError::*;

        match self {
            Seek(e) => write!(f, "Seek failed: {}", e),
            ImageSizeTooLarge(size) => write!(f, "Image size too large: {}", size),
            ReadToMemory(e) => write!(f, "Reading image into memory failed: {}", e),
        }
    }
}

/// Load an image from a file into guest memory.
///
/// # Arguments
///
/// * `guest_mem` - The memory to be used by the guest.
/// * `guest_addr` - The starting address to load the image in the guest memory.
/// * `max_size` - The amount of space in bytes available in the guest memory for the image.
/// * `image` - The file containing the image to be loaded.
///
/// The size in bytes of the loaded image is returned.
pub fn load_image<F>(
    guest_mem: &GuestMemory,
    image: &mut F,
    guest_addr: GuestAddress,
    max_size: u64,
) -> Result<usize, LoadImageError>
where
    F: Read + Seek,
{
    let size = image.seek(SeekFrom::End(0)).map_err(LoadImageError::Seek)?;

    if size > usize::max_value() as u64 || size > max_size {
        return Err(LoadImageError::ImageSizeTooLarge(size));
    }

    // This is safe due to the bounds check above.
    let size = size as usize;

    image
        .seek(SeekFrom::Start(0))
        .map_err(LoadImageError::Seek)?;

    guest_mem
        .read_to_memory(guest_addr, image, size)
        .map_err(LoadImageError::ReadToMemory)?;

    Ok(size)
}
<|endoftext|>