<commit_before>use std::result;
use std::fmt;
use std::fmt::{Show,Formatter};
use semver::Version;
use serialize::{Encoder,Encodable};
use core::source::SourceId;
use core::{
    Dependency,
    PackageId,
    Summary
};
use core::package_id::Metadata;
use core::dependency::SerializedDependency;
use util::{CargoResult, human};

#[deriving(PartialEq,Clone)]
pub struct Manifest {
    summary: Summary,
    authors: Vec<String>,
    targets: Vec<Target>,
    target_dir: Path,
    sources: Vec<SourceId>,
    build: Vec<String>,
    unused_keys: Vec<String>,
}

impl Show for Manifest {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Manifest({}, authors={}, targets={}, target_dir={}, \
                   build={})",
               self.summary, self.authors, self.targets,
               self.target_dir.display(), self.build)
    }
}

#[deriving(PartialEq,Clone,Encodable)]
pub struct SerializedManifest {
    name: String,
    version: String,
    dependencies: Vec<SerializedDependency>,
    authors: Vec<String>,
    targets: Vec<Target>,
    target_dir: String,
    build: Option<Vec<String>>,
}

impl<E, S: Encoder<E>> Encodable<S, E> for Manifest {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        SerializedManifest {
            name: self.summary.get_name().to_string(),
            version: self.summary.get_version().to_string(),
            dependencies: self.summary.get_dependencies().iter().map(|d| {
                SerializedDependency::from_dependency(d)
            }).collect(),
            authors: self.authors.clone(),
            targets: self.targets.clone(),
            target_dir: self.target_dir.display().to_string(),
            build: if self.build.len() == 0 { None } else { Some(self.build.clone()) },
        }.encode(s)
    }
}

#[deriving(Show, Clone, PartialEq, Hash, Encodable)]
pub enum LibKind {
    Lib,
    Rlib,
    Dylib,
    StaticLib
}

impl LibKind {
    pub fn from_str(string: &str) -> CargoResult<LibKind> {
        match string {
            "lib" => Ok(Lib),
            "rlib" => Ok(Rlib),
            "dylib" => Ok(Dylib),
            "staticlib" => Ok(StaticLib),
            _ => Err(human(format!("{} was not one of lib|rlib|dylib|staticlib",
                                   string)))
        }
    }

    pub fn from_strs<S: Str>(strings: Vec<S>) -> CargoResult<Vec<LibKind>> {
        result::collect(strings.iter().map(|s| LibKind::from_str(s.as_slice())))
    }

    pub fn crate_type(&self) -> &'static str {
        match *self {
            Lib => "lib",
            Rlib => "rlib",
            Dylib => "dylib",
            StaticLib => "staticlib"
        }
    }
}

#[deriving(Show, Clone, Hash, PartialEq, Encodable)]
pub enum TargetKind {
    LibTarget(Vec<LibKind>),
    BinTarget
}

#[deriving(Encodable, Decodable, Clone, Hash, PartialEq)]
pub struct Profile {
    env: String, // compile, test, dev, bench, etc.
    opt_level: uint,
    debug: bool,
    test: bool,
    dest: Option<String>,
}

impl Profile {
    pub fn default_dev() -> Profile {
        Profile {
            env: "compile".to_string(), // run in the default environment only
            opt_level: 0,
            debug: true,
            test: false, // whether or not to pass --test
            dest: None
        }
    }

    pub fn default_test() -> Profile {
        Profile {
            env: "test".to_string(), // run in the default environment only
            opt_level: 0,
            debug: true,
            test: true, // whether or not to pass --test
            dest: Some("test".to_string())
        }
    }

    pub fn default_bench() -> Profile {
        Profile {
            env: "bench".to_string(), // run in the default environment only
            opt_level: 3,
            debug: false,
            test: true, // whether or not to pass --test
            dest: Some("bench".to_string())
        }
    }

    pub fn default_release() -> Profile {
        Profile {
            env: "release".to_string(), // run in the default environment only
            opt_level: 3,
            debug: false,
            test: false, // whether or not to pass --test
            dest: Some("release".to_string())
        }
    }

    pub fn is_compile(&self) -> bool {
        self.env.as_slice() == "compile"
    }

    pub fn is_test(&self) -> bool {
        self.test
    }

    pub fn get_opt_level(&self) -> uint {
        self.opt_level
    }

    pub fn get_debug(&self) -> bool {
        self.debug
    }

    pub fn get_env<'a>(&'a self) -> &'a str {
        self.env.as_slice()
    }

    pub fn get_dest<'a>(&'a self) -> Option<&'a str> {
        self.dest.as_ref().map(|d| d.as_slice())
    }

    pub fn opt_level(mut self, level: uint) -> Profile {
        self.opt_level = level;
        self
    }

    pub fn debug(mut self, debug: bool) -> Profile {
        self.debug = debug;
        self
    }

    pub fn test(mut self, test: bool) -> Profile {
        self.test = test;
        self
    }
}

#[deriving(Clone, Hash, PartialEq)]
pub struct Target {
    kind: TargetKind,
    name: String,
    src_path: Path,
    profile: Profile,
    metadata: Option<Metadata>
}

#[deriving(Encodable)]
pub struct SerializedTarget {
    kind: Vec<&'static str>,
    name: String,
    src_path: String,
    profile: Profile,
    metadata: Option<Metadata>
}

impl<E, S: Encoder<E>> Encodable<S, E> for Target {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        let kind = match self.kind {
            LibTarget(ref kinds) => kinds.iter().map(|k| k.crate_type()).collect(),
            BinTarget => vec!("bin")
        };

        SerializedTarget {
            kind: kind,
            name: self.name.clone(),
            src_path: self.src_path.display().to_string(),
            profile: self.profile.clone(),
            metadata: self.metadata.clone()
        }.encode(s)
    }
}

impl Show for Target {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}(name={}, path={})", self.kind, self.name,
               self.src_path.display())
    }
}

impl Manifest {
    pub fn new(summary: &Summary, targets: &[Target],
               target_dir: &Path, sources: Vec<SourceId>,
               build: Vec<String>) -> Manifest {
        Manifest {
            summary: summary.clone(),
            authors: Vec::new(),
            targets: Vec::from_slice(targets),
            target_dir: target_dir.clone(),
            sources: sources,
            build: build,
            unused_keys: Vec::new(),
        }
    }

    pub fn get_summary<'a>(&'a self) -> &'a Summary {
        &self.summary
    }

    pub fn get_package_id<'a>(&'a self) -> &'a PackageId {
        self.get_summary().get_package_id()
    }

    pub fn get_name<'a>(&'a self) -> &'a str {
        self.get_package_id().get_name()
    }

    pub fn get_version<'a>(&'a self) -> &'a Version {
        self.get_summary().get_package_id().get_version()
    }

    pub fn get_authors<'a>(&'a self) -> &'a [String] {
        self.authors.as_slice()
    }

    pub fn get_dependencies<'a>(&'a self) -> &'a [Dependency] {
        self.get_summary().get_dependencies()
    }

    pub fn get_targets<'a>(&'a self) -> &'a [Target] {
        self.targets.as_slice()
    }

    pub fn get_target_dir<'a>(&'a self) -> &'a Path {
        &self.target_dir
    }

    pub fn get_source_ids<'a>(&'a self) -> &'a [SourceId] {
        self.sources.as_slice()
    }

    pub fn get_build<'a>(&'a self) -> &'a [String] {
        self.build.as_slice()
    }

    pub fn add_unused_key(&mut self, s: String) {
        self.unused_keys.push(s)
    }

    pub fn get_unused_keys<'a>(&'a self) -> &'a [String] {
        self.unused_keys.as_slice()
    }
}

impl Target {
    pub fn file_stem(&self) -> String {
        match self.metadata {
            Some(ref metadata) => format!("{}{}", self.name, metadata.extra_filename),
            None => self.name.clone()
        }
    }

    pub fn lib_target(name: &str, crate_targets: Vec<LibKind>,
                      src_path: &Path, profile: &Profile,
                      metadata: &Metadata)
                      -> Target
    {
        Target {
            kind: LibTarget(crate_targets),
            name: name.to_string(),
            src_path: src_path.clone(),
            profile: profile.clone(),
            metadata: Some(metadata.clone())
        }
    }

    pub fn bin_target(name: &str, src_path: &Path, profile: &Profile) -> Target {
        Target {
            kind: BinTarget,
            name: name.to_string(),
            src_path: src_path.clone(),
            profile: profile.clone(),
            metadata: None
        }
    }

    pub fn get_name<'a>(&'a self) -> &'a str {
        self.name.as_slice()
    }

    pub fn get_src_path<'a>(&'a self) -> &'a Path {
        &self.src_path
    }

    pub fn is_lib(&self) -> bool {
        match self.kind {
            LibTarget(_) => true,
            _ => false
        }
    }

    pub fn is_dylib(&self) -> bool {
        match self.kind {
            LibTarget(ref kinds) => kinds.iter().any(|&k| k == Dylib),
            _ => false
        }
    }

    pub fn is_rlib(&self) -> bool {
        match self.kind {
            LibTarget(ref kinds) =>
                kinds.iter().any(|&k| k == Rlib || k == Lib),
            _ => false
        }
    }

    pub fn is_bin(&self) -> bool {
        match self.kind {
            BinTarget => true,
            _ => false
        }
    }

    pub fn get_profile<'a>(&'a self) -> &'a Profile {
        &self.profile
    }

    pub fn get_metadata<'a>(&'a self) -> Option<&'a Metadata> {
        self.metadata.as_ref()
    }

    pub fn rustc_crate_types(&self) -> Vec<&'static str> {
        match self.kind {
            LibTarget(ref kinds) => {
                kinds.iter().map(|kind| kind.crate_type()).collect()
            },
            BinTarget => vec!("bin")
        }
    }
}
<commit_msg>impl Show for Profile<commit_after>use std::result;
use std::fmt;
use std::fmt::{Show,Formatter};
use semver::Version;
use serialize::{Encoder,Encodable};
use core::source::SourceId;
use core::{
    Dependency,
    PackageId,
    Summary
};
use core::package_id::Metadata;
use core::dependency::SerializedDependency;
use util::{CargoResult, human};

#[deriving(PartialEq,Clone)]
pub struct Manifest {
    summary: Summary,
    authors: Vec<String>,
    targets: Vec<Target>,
    target_dir: Path,
    sources: Vec<SourceId>,
    build: Vec<String>,
    unused_keys: Vec<String>,
}

impl Show for Manifest {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Manifest({}, authors={}, targets={}, target_dir={}, \
                   build={})",
               self.summary, self.authors, self.targets,
               self.target_dir.display(), self.build)
    }
}

#[deriving(PartialEq,Clone,Encodable)]
pub struct SerializedManifest {
    name: String,
    version: String,
    dependencies: Vec<SerializedDependency>,
    authors: Vec<String>,
    targets: Vec<Target>,
    target_dir: String,
    build: Option<Vec<String>>,
}

impl<E, S: Encoder<E>> Encodable<S, E> for Manifest {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        SerializedManifest {
            name: self.summary.get_name().to_string(),
            version: self.summary.get_version().to_string(),
            dependencies: self.summary.get_dependencies().iter().map(|d| {
                SerializedDependency::from_dependency(d)
            }).collect(),
            authors: self.authors.clone(),
            targets: self.targets.clone(),
            target_dir: self.target_dir.display().to_string(),
            build: if self.build.len() == 0 { None } else { Some(self.build.clone()) },
        }.encode(s)
    }
}

#[deriving(Show, Clone, PartialEq, Hash, Encodable)]
pub enum LibKind {
    Lib,
    Rlib,
    Dylib,
    StaticLib
}

impl LibKind {
    pub fn from_str(string: &str) -> CargoResult<LibKind> {
        match string {
            "lib" => Ok(Lib),
            "rlib" => Ok(Rlib),
            "dylib" => Ok(Dylib),
            "staticlib" => Ok(StaticLib),
            _ => Err(human(format!("{} was not one of lib|rlib|dylib|staticlib",
                                   string)))
        }
    }

    pub fn from_strs<S: Str>(strings: Vec<S>) -> CargoResult<Vec<LibKind>> {
        result::collect(strings.iter().map(|s| LibKind::from_str(s.as_slice())))
    }

    pub fn crate_type(&self) -> &'static str {
        match *self {
            Lib => "lib",
            Rlib => "rlib",
            Dylib => "dylib",
            StaticLib => "staticlib"
        }
    }
}

#[deriving(Show, Clone, Hash, PartialEq, Encodable)]
pub enum TargetKind {
    LibTarget(Vec<LibKind>),
    BinTarget
}

#[deriving(Encodable, Decodable, Clone, Hash, PartialEq, Show)]
pub struct Profile {
    env: String, // compile, test, dev, bench, etc.
    opt_level: uint,
    debug: bool,
    test: bool,
    dest: Option<String>,
}

impl Profile {
    pub fn default_dev() -> Profile {
        Profile {
            env: "compile".to_string(), // run in the default environment only
            opt_level: 0,
            debug: true,
            test: false, // whether or not to pass --test
            dest: None
        }
    }

    pub fn default_test() -> Profile {
        Profile {
            env: "test".to_string(), // run in the default environment only
            opt_level: 0,
            debug: true,
            test: true, // whether or not to pass --test
            dest: Some("test".to_string())
        }
    }

    pub fn default_bench() -> Profile {
        Profile {
            env: "bench".to_string(), // run in the default environment only
            opt_level: 3,
            debug: false,
            test: true, // whether or not to pass --test
            dest: Some("bench".to_string())
        }
    }

    pub fn default_release() -> Profile {
        Profile {
            env: "release".to_string(), // run in the default environment only
            opt_level: 3,
            debug: false,
            test: false, // whether or not to pass --test
            dest: Some("release".to_string())
        }
    }

    pub fn is_compile(&self) -> bool {
        self.env.as_slice() == "compile"
    }

    pub fn is_test(&self) -> bool {
        self.test
    }

    pub fn get_opt_level(&self) -> uint {
        self.opt_level
    }

    pub fn get_debug(&self) -> bool {
        self.debug
    }

    pub fn get_env<'a>(&'a self) -> &'a str {
        self.env.as_slice()
    }

    pub fn get_dest<'a>(&'a self) -> Option<&'a str> {
        self.dest.as_ref().map(|d| d.as_slice())
    }

    pub fn opt_level(mut self, level: uint) -> Profile {
        self.opt_level = level;
        self
    }

    pub fn debug(mut self, debug: bool) -> Profile {
        self.debug = debug;
        self
    }

    pub fn test(mut self, test: bool) -> Profile {
        self.test = test;
        self
    }
}

#[deriving(Clone, Hash, PartialEq)]
pub struct Target {
    kind: TargetKind,
    name: String,
    src_path: Path,
    profile: Profile,
    metadata: Option<Metadata>
}

#[deriving(Encodable)]
pub struct SerializedTarget {
    kind: Vec<&'static str>,
    name: String,
    src_path: String,
    profile: Profile,
    metadata: Option<Metadata>
}

impl<E, S: Encoder<E>> Encodable<S, E> for Target {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        let kind = match self.kind {
            LibTarget(ref kinds) => kinds.iter().map(|k| k.crate_type()).collect(),
            BinTarget => vec!("bin")
        };

        SerializedTarget {
            kind: kind,
            name: self.name.clone(),
            src_path: self.src_path.display().to_string(),
            profile: self.profile.clone(),
            metadata: self.metadata.clone()
        }.encode(s)
    }
}

impl Show for Target {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}(name={}, path={}, profile={})", self.kind, self.name,
               self.src_path.display(), self.profile)
    }
}

impl Manifest {
    pub fn new(summary: &Summary, targets: &[Target],
               target_dir: &Path, sources: Vec<SourceId>,
               build: Vec<String>) -> Manifest {
        Manifest {
            summary: summary.clone(),
            authors: Vec::new(),
            targets: Vec::from_slice(targets),
            target_dir: target_dir.clone(),
            sources: sources,
            build: build,
            unused_keys: Vec::new(),
        }
    }

    pub fn get_summary<'a>(&'a self) -> &'a Summary {
        &self.summary
    }

    pub fn get_package_id<'a>(&'a self) -> &'a PackageId {
        self.get_summary().get_package_id()
    }

    pub fn get_name<'a>(&'a self) -> &'a str {
        self.get_package_id().get_name()
    }

    pub fn get_version<'a>(&'a self) -> &'a Version {
        self.get_summary().get_package_id().get_version()
    }

    pub fn get_authors<'a>(&'a self) -> &'a [String] {
        self.authors.as_slice()
    }

    pub fn get_dependencies<'a>(&'a self) -> &'a [Dependency] {
        self.get_summary().get_dependencies()
    }

    pub fn get_targets<'a>(&'a self) -> &'a [Target] {
        self.targets.as_slice()
    }

    pub fn get_target_dir<'a>(&'a self) -> &'a Path {
        &self.target_dir
    }

    pub fn get_source_ids<'a>(&'a self) -> &'a [SourceId] {
        self.sources.as_slice()
    }

    pub fn get_build<'a>(&'a self) -> &'a [String] {
        self.build.as_slice()
    }

    pub fn add_unused_key(&mut self, s: String) {
        self.unused_keys.push(s)
    }

    pub fn get_unused_keys<'a>(&'a self) -> &'a [String] {
        self.unused_keys.as_slice()
    }
}

impl Target {
    pub fn file_stem(&self) -> String {
        match self.metadata {
            Some(ref metadata) => format!("{}{}", self.name, metadata.extra_filename),
            None => self.name.clone()
        }
    }

    pub fn lib_target(name: &str, crate_targets: Vec<LibKind>,
                      src_path: &Path, profile: &Profile,
                      metadata: &Metadata)
                      -> Target
    {
        Target {
            kind: LibTarget(crate_targets),
            name: name.to_string(),
            src_path: src_path.clone(),
            profile: profile.clone(),
            metadata: Some(metadata.clone())
        }
    }

    pub fn bin_target(name: &str, src_path: &Path, profile: &Profile) -> Target {
        Target {
            kind: BinTarget,
            name: name.to_string(),
            src_path: src_path.clone(),
            profile: profile.clone(),
            metadata: None
        }
    }

    pub fn get_name<'a>(&'a self) -> &'a str {
        self.name.as_slice()
    }

    pub fn get_src_path<'a>(&'a self) -> &'a Path {
        &self.src_path
    }

    pub fn is_lib(&self) -> bool {
        match self.kind {
            LibTarget(_) => true,
            _ => false
        }
    }

    pub fn is_dylib(&self) -> bool {
        match self.kind {
            LibTarget(ref kinds) => kinds.iter().any(|&k| k == Dylib),
            _ => false
        }
    }

    pub fn is_rlib(&self) -> bool {
        match self.kind {
            LibTarget(ref kinds) =>
                kinds.iter().any(|&k| k == Rlib || k == Lib),
            _ => false
        }
    }

    pub fn is_bin(&self) -> bool {
        match self.kind {
            BinTarget => true,
            _ => false
        }
    }

    pub fn get_profile<'a>(&'a self) -> &'a Profile {
        &self.profile
    }

    pub fn get_metadata<'a>(&'a self) -> Option<&'a Metadata> {
        self.metadata.as_ref()
    }

    pub fn rustc_crate_types(&self) -> Vec<&'static str> {
        match self.kind {
            LibTarget(ref kinds) => {
                kinds.iter().map(|kind| kind.crate_type()).collect()
            },
            BinTarget => vec!("bin")
        }
    }
}
<|endoftext|>


<commit_before>use std::ascii::*;
use regex::Regex;

use cases::classcase::is_class_case;
use cases::snakecase::to_snake_case;
use cases::uppercase::to_upper_case;

pub fn to_camel_case<'a>(non_camelized_string: String) -> String {
    if is_camel_case(non_camelized_string.clone()) {
        return non_camelized_string
    } else {
        return to_camel_from_snake(to_snake_case(non_camelized_string));
    }
}

    fn to_camel_from_snake<'a>(non_camelized_string: String) -> String{
        let mut split_string: Vec<&str> = non_camelized_string.split("_").collect();
        let mut out_string: String;
        out_string = format!("{}", split_string.remove(0));
        for string in split_string {
            let mut string_chars: Vec<char> = string.chars().collect();
            let first_char: String = to_upper_case(string.chars().nth(0).unwrap().to_string());
            string_chars.remove(0);
            let end_of_word: String = string_chars.iter().cloned().collect::<String>();
            out_string = format!("{}{}{}", out_string, first_char, end_of_word);
        }
        println!("{}", out_string);
        return out_string;
    }

pub fn is_camel_case<'a>(test_string: String) -> bool{
    let camel_matcher = Regex::new(r"(^|[A-Z])([^-|^_|^ ]*[a-z]+)").unwrap();
    let kebab_snake_matcher = Regex::new(r"[-|_| ]").unwrap();
    let mut is_camel_case = false;
    if camel_matcher.is_match(test_string.as_ref())
        && !kebab_snake_matcher.is_match(test_string.as_ref())
        && !is_class_case(test_string){
            is_camel_case = true;
        }
    return is_camel_case;
}

#[cfg(test)]
mod camelcase_test;
<commit_msg>Removed an extra print<commit_after>use std::ascii::*;
use regex::Regex;

use cases::classcase::is_class_case;
use cases::snakecase::to_snake_case;
use cases::uppercase::to_upper_case;

pub fn to_camel_case<'a>(non_camelized_string: String) -> String {
    if is_camel_case(non_camelized_string.clone()) {
        return non_camelized_string
    } else {
        return to_camel_from_snake(to_snake_case(non_camelized_string));
    }
}

    fn to_camel_from_snake<'a>(non_camelized_string: String) -> String{
        let mut split_string: Vec<&str> = non_camelized_string.split("_").collect();
        let mut out_string: String;
        out_string = format!("{}", split_string.remove(0));
        for string in split_string {
            let mut string_chars: Vec<char> = string.chars().collect();
            let first_char: String = to_upper_case(string.chars().nth(0).unwrap().to_string());
            string_chars.remove(0);
            let end_of_word: String = string_chars.iter().cloned().collect::<String>();
            out_string = format!("{}{}{}", out_string, first_char, end_of_word);
        }
        return out_string;
    }

pub fn is_camel_case<'a>(test_string: String) -> bool{
    let camel_matcher = Regex::new(r"(^|[A-Z])([^-|^_|^ ]*[a-z]+)").unwrap();
    let kebab_snake_matcher = Regex::new(r"[-|_| ]").unwrap();
    let mut is_camel_case = false;
    if camel_matcher.is_match(test_string.as_ref())
        && !kebab_snake_matcher.is_match(test_string.as_ref())
        && !is_class_case(test_string){
            is_camel_case = true;
        }
    return is_camel_case;
}

#[cfg(test)]
mod camelcase_test;
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use std::collections::{HashMap};
use cgmath::{Vector2};
use common::types::{PlayerId, UnitId, MapPos, Size2, ZInt};
use core::{CoreEvent};
use unit::{Unit};
use object::{ObjectTypes};
use map::{Map, Terrain};
use fov;

pub struct GameState {
    // TODO: remove 'pub'?
    pub units: HashMap<UnitId, Unit>,
    pub map: Map<Terrain>,
    pub fow: Map<bool>, // Fog of War map
    pub player_id: Option<PlayerId>,
}

impl<'a> GameState {
    // TODO: Remove 'player_id'
    pub fn new(map_size: &Size2<ZInt>, player_id: Option<&PlayerId>) -> GameState {
        let mut map = Map::new(map_size, Terrain::Plain);
        *map.tile_mut(&MapPos{v: Vector2{x: 4, y: 3}}) = Terrain::Trees;
        *map.tile_mut(&MapPos{v: Vector2{x: 4, y: 4}}) = Terrain::Trees;
        *map.tile_mut(&MapPos{v: Vector2{x: 4, y: 5}}) = Terrain::Trees;
        *map.tile_mut(&MapPos{v: Vector2{x: 5, y: 5}}) = Terrain::Trees;
        *map.tile_mut(&MapPos{v: Vector2{x: 6, y: 4}}) = Terrain::Trees;
        GameState {
            units: HashMap::new(),
            map: map,
            fow: Map::new(map_size, false),
            player_id: if let Some(player_id) = player_id {
                Some(player_id.clone())
            } else {
                None
            },
        }
    }

    pub fn units_at(&'a self, pos: &MapPos) -> Vec<&'a Unit> {
        let mut units = Vec::new();
        for (_, unit) in self.units.iter() {
            if unit.pos == *pos {
                units.push(unit);
            }
        }
        units
    }

    pub fn is_tile_occupied(&self, pos: &MapPos) -> bool {
        self.units_at(pos).len() > 0
    }

    fn refresh_units(&mut self, object_types: &ObjectTypes, player_id: &PlayerId) {
        for (_, unit) in self.units.iter_mut() {
            if unit.player_id == *player_id {
                let unit_type = object_types.get_unit_type(&unit.type_id);
                unit.move_points = unit_type.move_points;
                unit.attack_points = unit_type.attack_points;
            }
        }
    }

    /*
    fn add_passive_ap(&mut self, player_id: &PlayerId) {
        for (_, unit) in self.units.iter_mut() {
            if unit.player_id == *player_id {
                unit.attack_points += 1;
            }
        }
    }
    */

    pub fn clear_fow(&mut self) {
        for pos in self.fow.get_iter() {
            *self.fow.tile_mut(&pos) = false;
        }
    }

    fn update_fow(&mut self) {
        let player_id = self.player_id.as_ref().unwrap();
        for (_, unit) in self.units.iter() {
            if unit.player_id == *player_id {
                *self.fow.tile_mut(&unit.pos) = true;
                fov::fov(&self.map, &mut self.fow, &unit.pos);
            }
        }
    }

    pub fn apply_event(&mut self, object_types: &ObjectTypes, event: &CoreEvent) {
        match event {
            &CoreEvent::Move{ref unit_id, ref path} => {
                let pos = path.destination().clone();
                let unit = self.units.get_mut(unit_id)
                    .expect("BAD MOVE UNIT ID");
                unit.pos = pos;
                assert!(unit.move_points > 0);
                unit.move_points -= path.total_cost().n;
                assert!(unit.move_points >= 0);
                if let Some(player_id) = self.player_id.clone() {
                    if unit.player_id == player_id {
                        for &(_, ref pos) in path.nodes() {
                            fov::fov(&self.map, &mut self.fow, pos);
                        }
                    }
                }
            },
            &CoreEvent::EndTurn{ref new_id, ..} => {
                // TODO: remove ugly '.clone()'?
                if let Some(player_id) = self.player_id.clone() {
                    if player_id == *new_id {
                        self.clear_fow();
                    }
                }
                self.refresh_units(object_types, new_id);
                // self.add_passive_ap(old_id);
            },
            &CoreEvent::CreateUnit {
                ref unit_id,
                ref pos,
                ref type_id,
                ref player_id,
            } => {
                assert!(self.units.get(unit_id).is_none());
                let unit_type = object_types.get_unit_type(type_id);
                let move_points = unit_type.move_points;
                let attack_points = unit_type.attack_points;
                self.units.insert(unit_id.clone(), Unit {
                    id: unit_id.clone(),
                    pos: pos.clone(),
                    player_id: player_id.clone(),
                    type_id: type_id.clone(),
                    move_points: move_points,
                    attack_points: attack_points,
                });
            },
            &CoreEvent::AttackUnit {
                ref attacker_id,
                ref defender_id,
                ref killed,
                ..
            } => {
                if *killed {
                    assert!(self.units.get(defender_id).is_some());
                    self.units.remove(defender_id);
                }
                if let Some(unit) = self.units.get_mut(attacker_id) {
                    assert!(unit.attack_points >= 1);
                    unit.attack_points -= 1;
                }
            },
        }
        if self.player_id.is_some() {
            self.update_fow();
        }
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>game_state.rs: Optimized FoW calculations<commit_after>// See LICENSE file for copyright and license details.

use std::collections::{HashMap};
use cgmath::{Vector2};
use common::types::{PlayerId, UnitId, MapPos, Size2, ZInt};
use core::{CoreEvent};
use unit::{Unit};
use object::{ObjectTypes};
use map::{Map, Terrain};
use fov;

pub struct GameState {
    // TODO: remove 'pub'?
    pub units: HashMap<UnitId, Unit>,
    pub map: Map<Terrain>,
    pub fow: Map<bool>, // Fog of War map
    pub player_id: Option<PlayerId>,
}

impl<'a> GameState {
    // TODO: Remove 'player_id'
    pub fn new(map_size: &Size2<ZInt>, player_id: Option<&PlayerId>) -> GameState {
        let mut map = Map::new(map_size, Terrain::Plain);
        *map.tile_mut(&MapPos{v: Vector2{x: 4, y: 3}}) = Terrain::Trees;
        *map.tile_mut(&MapPos{v: Vector2{x: 4, y: 4}}) = Terrain::Trees;
        *map.tile_mut(&MapPos{v: Vector2{x: 4, y: 5}}) = Terrain::Trees;
        *map.tile_mut(&MapPos{v: Vector2{x: 5, y: 5}}) = Terrain::Trees;
        *map.tile_mut(&MapPos{v: Vector2{x: 6, y: 4}}) = Terrain::Trees;
        GameState {
            units: HashMap::new(),
            map: map,
            fow: Map::new(map_size, false),
            player_id: if let Some(id) = player_id {
                Some(id.clone())
            } else {
                None
            },
        }
    }

    pub fn units_at(&'a self, pos: &MapPos) -> Vec<&'a Unit> {
        let mut units = Vec::new();
        for (_, unit) in self.units.iter() {
            if unit.pos == *pos {
                units.push(unit);
            }
        }
        units
    }

    pub fn is_tile_occupied(&self, pos: &MapPos) -> bool {
        self.units_at(pos).len() > 0
    }

    fn refresh_units(&mut self, object_types: &ObjectTypes, player_id: &PlayerId) {
        for (_, unit) in self.units.iter_mut() {
            if unit.player_id == *player_id {
                let unit_type = object_types.get_unit_type(&unit.type_id);
                unit.move_points = unit_type.move_points;
                unit.attack_points = unit_type.attack_points;
            }
        }
    }

    /*
    fn add_passive_ap(&mut self, player_id: &PlayerId) {
        for (_, unit) in self.units.iter_mut() {
            if unit.player_id == *player_id {
                unit.attack_points += 1;
            }
        }
    }
    */

    pub fn clear_fow(&mut self) {
        for pos in self.fow.get_iter() {
            *self.fow.tile_mut(&pos) = false;
        }
    }

    fn reset_fow(&mut self) {
        self.clear_fow();
        let player_id = self.player_id.as_ref().unwrap();
        for (_, unit) in self.units.iter() {
            if unit.player_id == *player_id {
                *self.fow.tile_mut(&unit.pos) = true;
                fov::fov(&self.map, &mut self.fow, &unit.pos);
            }
        }
    }

    pub fn apply_event(&mut self, object_types: &ObjectTypes, event: &CoreEvent) {
        match event {
            &CoreEvent::Move{ref unit_id, ref path} => {
                let pos = path.destination().clone();
                let unit = self.units.get_mut(unit_id)
                    .expect("BAD MOVE UNIT ID");
                unit.pos = pos;
                assert!(unit.move_points > 0);
                unit.move_points -= path.total_cost().n;
                assert!(unit.move_points >= 0);
                if let Some(player_id) = self.player_id.clone() {
                    if unit.player_id == player_id {
                        for &(_, ref pos) in path.nodes() {
                            fov::fov(&self.map, &mut self.fow, pos);
                        }
                    }
                }
            },
            &CoreEvent::EndTurn{ref new_id, ..} => {
                // TODO: remove ugly '.clone()'?
                if let Some(player_id) = self.player_id.clone() {
                    if player_id == *new_id {
                        self.reset_fow();
                    }
                }
                self.refresh_units(object_types, new_id);
                // self.add_passive_ap(old_id);
            },
            &CoreEvent::CreateUnit {
                ref unit_id,
                ref pos,
                ref type_id,
                ref player_id,
            } => {
                assert!(self.units.get(unit_id).is_none());
                let unit_type = object_types.get_unit_type(type_id);
                let move_points = unit_type.move_points;
                let attack_points = unit_type.attack_points;
                self.units.insert(unit_id.clone(), Unit {
                    id: unit_id.clone(),
                    pos: pos.clone(),
                    player_id: player_id.clone(),
                    type_id: type_id.clone(),
                    move_points: move_points,
                    attack_points: attack_points,
                });
                if let Some(id) = self.player_id.clone() {
                    if id == *player_id {
                        fov::fov(&self.map, &mut self.fow, pos);
                    }
                }
            },
            &CoreEvent::AttackUnit {
                ref attacker_id,
                ref defender_id,
                ref killed,
                ..
            } => {
                if *killed {
                    assert!(self.units.get(defender_id).is_some());
                    self.units.remove(defender_id);
                }
                if let Some(unit) = self.units.get_mut(attacker_id) {
                    assert!(unit.attack_points >= 1);
                    unit.attack_points -= 1;
                }
            },
        }
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use common::types::{ZInt, MapPos, Size2};
use object::{ObjectTypes};
use unit::{Unit, UnitClass};
use map::{Map, Terrain};
use game_state::{GameState};
use dir::{Dir};

#[derive(Clone)]
pub struct MoveCost{pub n: ZInt}

#[derive(Clone)]
pub struct MapPath {
    nodes: Vec<(MoveCost, MapPos)>,
}

impl MapPath {
    pub fn new(nodes: Vec<(MoveCost, MapPos)>) -> MapPath {
        MapPath{nodes: nodes}
    }

    // pub fn len(&self) -> ZInt {
    //     self.nodes.len() as ZInt
    // }

    pub fn destination(&self) -> &MapPos {
        let &(_, ref pos) = self.nodes.last().unwrap();
        pos
    }

    pub fn nodes(&self) -> &Vec<(MoveCost, MapPos)> {
        &self.nodes
    }

    pub fn total_cost(&self) -> &MoveCost {
        let &(ref total_cost, _) = self.nodes.last().unwrap();
        total_cost
    }
}

#[derive(Clone)]
pub struct Tile {
    cost: MoveCost,
    parent: Option<Dir>,
}

impl Tile {
    pub fn parent(&self) -> &Option<Dir> { &self.parent }
    pub fn cost(&self) -> &MoveCost { &self.cost }
}

const MAX_COST: MoveCost = MoveCost{n: 30000};

pub struct Pathfinder {
    queue: Vec<MapPos>,
    map: Map<Tile>,
}

impl Pathfinder {
    pub fn new(map_size: &Size2<ZInt>) -> Pathfinder {
        Pathfinder {
            queue: Vec::new(),
            map: Map::new(map_size, Tile {
                cost: MoveCost{n: 0},
                parent: None,
            }),
        }
    }

    pub fn get_map(&self) -> &Map<Tile> {
        &self.map
    }

    fn tile_cost(
        &self,
        object_types: &ObjectTypes,
        state: &GameState,
        unit: &Unit,
        pos: &MapPos,
    ) -> ZInt { // TODO: ZInt -> MoveCost
        let unit_type = object_types.get_unit_type(&unit.type_id);
        let tile = state.map.tile(pos);
        match unit_type.class {
            UnitClass::Infantry => match tile {
                &Terrain::Plain => 1,
                &Terrain::Trees => 2,
                &Terrain::Building => 2,
            },
            UnitClass::Vehicle => match tile {
                &Terrain::Plain => 1,
                &Terrain::Trees => 5,
                &Terrain::Building => 10,
            },
        }
    }

    fn process_neighbour_pos(
        &mut self,
        object_types: &ObjectTypes,
        state: &GameState,
        unit: &Unit,
        original_pos: &MapPos,
        neighbour_pos: &MapPos
    ) {
        let old_cost = self.map.tile(original_pos).cost.clone();
        let tile_cost = self.tile_cost(object_types, state, unit, neighbour_pos);
        let tile = self.map.tile_mut(neighbour_pos);
        let new_cost = MoveCost{n: old_cost.n + tile_cost};
        let units_count = state.units_at(neighbour_pos).len();
        if tile.cost.n > new_cost.n && units_count == 0 {
            tile.cost = new_cost;
            tile.parent = Some(Dir::get_dir_from_to(
                neighbour_pos, original_pos));
            self.queue.push(neighbour_pos.clone());
        }
    }

    fn clean_map(&mut self) {
        for pos in self.map.get_iter() {
            let tile = self.map.tile_mut(&pos);
            tile.cost = MAX_COST;
            tile.parent = None;
        }
    }

    fn try_to_push_neighbours(
        &mut self,
        object_types: &ObjectTypes,
        state: &GameState,
        unit: &Unit,
        pos: MapPos,
    ) {
        assert!(self.map.is_inboard(&pos));
        for i in range(0, 6) {
            let dir = Dir::from_int(i as ZInt);
            let neighbour_pos = Dir::get_neighbour_pos(&pos, &dir);
            if self.map.is_inboard(&neighbour_pos) {
                self.process_neighbour_pos(
                    object_types, state, unit, &pos, &neighbour_pos);
            }
        }
    }

    fn push_start_pos_to_queue(&mut self, start_pos: MapPos) {
        let start_tile = self.map.tile_mut(&start_pos);
        start_tile.cost = MoveCost{n: 0};
        start_tile.parent = None;
        self.queue.push(start_pos);
    }

    pub fn fill_map(&mut self, object_types: &ObjectTypes, state: &GameState, unit: &Unit) {
        assert!(self.queue.len() == 0);
        self.clean_map();
        self.push_start_pos_to_queue(unit.pos.clone());
        while self.queue.len() != 0 {
            let pos = self.queue.remove(0);
            self.try_to_push_neighbours(object_types, state, unit, pos);
        }
    }

    /*
    pub fn is_reachable(&self, pos: &MapPos) -> bool {
        self.map.tile(pos).cost.n != MAX_COST.n
    }
    */

    pub fn get_path(&self, destination: &MapPos) -> Option<MapPath> {
        let mut path = Vec::new();
        let mut pos = destination.clone();
        if self.map.tile(&pos).cost.n == MAX_COST.n {
            return None;
        }
        assert!(self.map.is_inboard(&pos));
        let start_cost = self.map.tile(&pos).cost.clone();
        path.push((start_cost, pos.clone()));
        while self.map.tile(&pos).cost.n != 0 {
            let parent_dir = match self.map.tile(&pos).parent() {
                &Some(ref dir) => dir,
                &None => return None,
            };
            pos = Dir::get_neighbour_pos(&pos, parent_dir);
            assert!(self.map.is_inboard(&pos));
            let cost = self.map.tile(&pos).cost.clone();
            path.push((cost, pos.clone()));
        }
        path.reverse();
        Some(MapPath {
            nodes: path,
        })
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>Pathfinder: tile_cost: ZInt -> MoveCost<commit_after>// See LICENSE file for copyright and license details.

use common::types::{ZInt, MapPos, Size2};
use object::{ObjectTypes};
use unit::{Unit, UnitClass};
use map::{Map, Terrain};
use game_state::{GameState};
use dir::{Dir};

// TODO: add `join` method
#[derive(Clone)]
pub struct MoveCost{pub n: ZInt}

#[derive(Clone)]
pub struct MapPath {
    nodes: Vec<(MoveCost, MapPos)>,
}

impl MapPath {
    pub fn new(nodes: Vec<(MoveCost, MapPos)>) -> MapPath {
        MapPath{nodes: nodes}
    }

    // pub fn len(&self) -> ZInt {
    //     self.nodes.len() as ZInt
    // }

    pub fn destination(&self) -> &MapPos {
        let &(_, ref pos) = self.nodes.last().unwrap();
        pos
    }

    pub fn nodes(&self) -> &Vec<(MoveCost, MapPos)> {
        &self.nodes
    }

    pub fn total_cost(&self) -> &MoveCost {
        let &(ref total_cost, _) = self.nodes.last().unwrap();
        total_cost
    }
}

#[derive(Clone)]
pub struct Tile {
    cost: MoveCost,
    parent: Option<Dir>,
}

impl Tile {
    pub fn parent(&self) -> &Option<Dir> { &self.parent }
    pub fn cost(&self) -> &MoveCost { &self.cost }
}

const MAX_COST: MoveCost = MoveCost{n: 30000};

pub struct Pathfinder {
    queue: Vec<MapPos>,
    map: Map<Tile>,
}

impl Pathfinder {
    pub fn new(map_size: &Size2<ZInt>) -> Pathfinder {
        Pathfinder {
            queue: Vec::new(),
            map: Map::new(map_size, Tile {
                cost: MoveCost{n: 0},
                parent: None,
            }),
        }
    }

    pub fn get_map(&self) -> &Map<Tile> {
        &self.map
    }

    fn tile_cost(
        &self,
        object_types: &ObjectTypes,
        state: &GameState,
        unit: &Unit,
        pos: &MapPos,
    ) -> MoveCost {
        let unit_type = object_types.get_unit_type(&unit.type_id);
        let tile = state.map.tile(pos);
        let n = match unit_type.class {
            UnitClass::Infantry => match tile {
                &Terrain::Plain => 1,
                &Terrain::Trees => 2,
                &Terrain::Building => 2,
            },
            UnitClass::Vehicle => match tile {
                &Terrain::Plain => 1,
                &Terrain::Trees => 5,
                &Terrain::Building => 10,
            },
        };
        MoveCost{n: n}
    }

    fn process_neighbour_pos(
        &mut self,
        object_types: &ObjectTypes,
        state: &GameState,
        unit: &Unit,
        original_pos: &MapPos,
        neighbour_pos: &MapPos
    ) {
        let old_cost = self.map.tile(original_pos).cost.clone();
        let tile_cost = self.tile_cost(object_types, state, unit, neighbour_pos);
        let tile = self.map.tile_mut(neighbour_pos);
        let new_cost = MoveCost{n: old_cost.n + tile_cost.n};
        let units_count = state.units_at(neighbour_pos).len();
        if tile.cost.n > new_cost.n && units_count == 0 {
            tile.cost = new_cost;
            tile.parent = Some(Dir::get_dir_from_to(
                neighbour_pos, original_pos));
            self.queue.push(neighbour_pos.clone());
        }
    }

    fn clean_map(&mut self) {
        for pos in self.map.get_iter() {
            let tile = self.map.tile_mut(&pos);
            tile.cost = MAX_COST;
            tile.parent = None;
        }
    }

    fn try_to_push_neighbours(
        &mut self,
        object_types: &ObjectTypes,
        state: &GameState,
        unit: &Unit,
        pos: MapPos,
    ) {
        assert!(self.map.is_inboard(&pos));
        for i in range(0, 6) {
            let dir = Dir::from_int(i as ZInt);
            let neighbour_pos = Dir::get_neighbour_pos(&pos, &dir);
            if self.map.is_inboard(&neighbour_pos) {
                self.process_neighbour_pos(
                    object_types, state, unit, &pos, &neighbour_pos);
            }
        }
    }

    fn push_start_pos_to_queue(&mut self, start_pos: MapPos) {
        let start_tile = self.map.tile_mut(&start_pos);
        start_tile.cost = MoveCost{n: 0};
        start_tile.parent = None;
        self.queue.push(start_pos);
    }

    pub fn fill_map(&mut self, object_types: &ObjectTypes, state: &GameState, unit: &Unit) {
        assert!(self.queue.len() == 0);
        self.clean_map();
        self.push_start_pos_to_queue(unit.pos.clone());
        while self.queue.len() != 0 {
            let pos = self.queue.remove(0);
            self.try_to_push_neighbours(object_types, state, unit, pos);
        }
    }

    /*
    pub fn is_reachable(&self, pos: &MapPos) -> bool {
        self.map.tile(pos).cost.n != MAX_COST.n
    }
    */

    pub fn get_path(&self, destination: &MapPos) -> Option<MapPath> {
        let mut path = Vec::new();
        let mut pos = destination.clone();
        if self.map.tile(&pos).cost.n == MAX_COST.n {
            return None;
        }
        assert!(self.map.is_inboard(&pos));
        let start_cost = self.map.tile(&pos).cost.clone();
        path.push((start_cost, pos.clone()));
        while self.map.tile(&pos).cost.n != 0 {
            let parent_dir = match self.map.tile(&pos).parent() {
                &Some(ref dir) => dir,
                &None => return None,
            };
            pos = Dir::get_neighbour_pos(&pos, parent_dir);
            assert!(self.map.is_inboard(&pos));
            let cost = self.map.tile(&pos).cost.clone();
            path.push((cost, pos.clone()));
        }
        path.reverse();
        Some(MapPath {
            nodes: path,
        })
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>//! Heap sort algorithm.
//!
//! The `efficient` module contains the efficient sorting algorithm "Heap sort".
//!
//! Source: https://en.wikipedia.org/wiki/Heapsort

extern crate libc;

use std::slice;

/// Heap sort
///
/// # Details
///
///
/// # Scaling
///
/// Heap sort has O(N log N) average case complexity and O(N) space complexity due to the
/// `sift_down()` implementation.
///
/// # Optimizations
///
/// None
///
/// # Notes
///
/// The type T of the vector elements to sort _must_ implement the `PartialOrd` trait so the
/// compiler knows how to compare the elements and sort them.
///
/// The design comes from the Wikipedia page on heap sort.
///
/// # Examples
///
/// ```
/// let mut data: Vec<i32> = vec![4, 2, 3, 1, 5];
/// sorting::efficientsorts::heap::sort(&mut data);
/// assert_eq!(vec![1, 2, 3, 4, 5], data);
/// ```
///
pub fn sort<T: PartialOrd>(input: &mut [T]) {
    let n = input.len();

    heapify(input);

    let mut end = n - 1;
    while end > 0 {
        input.swap(end, 0);
        end -= 1;
        sift_down(input, 0, end);
    }
}

fn node_parent_id(i: usize) -> usize {
    if i == 0 { 0 }
    else      { (i - 1) / 2 }
}

fn node_child_left(i: usize) -> usize {
    2 * i + 1
}

// fn node_child_right(i: usize) -> usize {
//     2 * i + 2
// }

fn heapify<T: PartialOrd>(input: &mut [T]) {
    let n = input.len();
    let end = n - 1;

    // Last element is at "n-1". Find its parent and start there:
    let mut start: usize = node_parent_id(n-1);

    loop {
        sift_down(input, start, end);
        if start == 0 { break; }
        start -= 1;
    }
}

fn sift_down<T: PartialOrd>(input: &mut [T], start: usize, end: usize) {
    let mut i = start;

    // Starting at the "start" element, loop "down" the vector and swap elements that are
    // not in max-heap order.
    while node_child_left(i) <= end {
        let child = node_child_left(i);
        let mut swap = i;

        if input[swap] < input[child] {
            swap = child;
        }
        if child+1 <= end && input[swap] < input[child+1] {
            swap = child + 1;
        }

        if swap == i {
            return;
        } else {
            input.swap(i, swap);
            i = swap;
        }
    }
}

#[no_mangle]
pub extern "C" fn ffi_heapsort_i8(array_pointer: *const libc::int8_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i8, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_heapsort_i16(array_pointer: *const libc::int16_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i16, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_heapsort_i32(array_pointer: *const libc::int32_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_heapsort_i64(array_pointer: *const libc::int64_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i64, n as usize)
    };
    sort(&mut to_sort);
}

#[no_mangle]
pub extern "C" fn ffi_heapsort_u8(array_pointer: *const libc::uint8_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u8, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_heapsort_u16(array_pointer: *const libc::uint16_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u16, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_heapsort_u32(array_pointer: *const libc::uint32_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_heapsort_u64(array_pointer: *const libc::uint64_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u64, n as usize)
    };
    sort(&mut to_sort);
}

#[no_mangle]
pub extern "C" fn ffi_heapsort_f32(array_pointer: *const libc::c_void, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut f32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_heapsort_f64(array_pointer: *const libc::c_void, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut f64, n as usize)
    };
    sort(&mut to_sort);
}
<commit_msg>Bug fix: don't perform heap sorting if one or zero elements.<commit_after>//! Heap sort algorithm.
//!
//! The `efficient` module contains the efficient sorting algorithm "Heap sort".
//!
//! Source: https://en.wikipedia.org/wiki/Heapsort

extern crate libc;

use std::slice;

/// Heap sort
///
/// # Details
///
///
/// # Scaling
///
/// Heap sort has O(N log N) average case complexity and O(N) space complexity due to the
/// `sift_down()` implementation.
///
/// # Optimizations
///
/// None
///
/// # Notes
///
/// The type T of the vector elements to sort _must_ implement the `PartialOrd` trait so the
/// compiler knows how to compare the elements and sort them.
///
/// The design comes from the Wikipedia page on heap sort.
///
/// # Examples
///
/// ```
/// let mut data: Vec<i32> = vec![4, 2, 3, 1, 5];
/// sorting::efficientsorts::heap::sort(&mut data);
/// assert_eq!(vec![1, 2, 3, 4, 5], data);
/// ```
///
pub fn sort<T: PartialOrd>(input: &mut [T]) {
    let n = input.len();

    if n > 2 {
        heapify(input);

        let mut end = n - 1;
        while end > 0 {
            input.swap(end, 0);
            end -= 1;
            sift_down(input, 0, end);
        }
    }
}

fn node_parent_id(i: usize) -> usize {
    if i == 0 { 0 }
    else      { (i - 1) / 2 }
}

fn node_child_left(i: usize) -> usize {
    2 * i + 1
}

// fn node_child_right(i: usize) -> usize {
//     2 * i + 2
// }

fn heapify<T: PartialOrd>(input: &mut [T]) {
    let n = input.len();
    let end = n - 1;

    // Last element is at "n-1". Find its parent and start there:
    let mut start: usize = node_parent_id(n-1);

    loop {
        sift_down(input, start, end);
        if start == 0 { break; }
        start -= 1;
    }
}

fn sift_down<T: PartialOrd>(input: &mut [T], start: usize, end: usize) {
    let mut i = start;

    // Starting at the "start" element, loop "down" the vector and swap elements that are
    // not in max-heap order.
    while node_child_left(i) <= end {
        let child = node_child_left(i);
        let mut swap = i;

        if input[swap] < input[child] {
            swap = child;
        }
        if child+1 <= end && input[swap] < input[child+1] {
            swap = child + 1;
        }

        if swap == i {
            return;
        } else {
            input.swap(i, swap);
            i = swap;
        }
    }
}

#[no_mangle]
pub extern "C" fn ffi_heapsort_i8(array_pointer: *const libc::int8_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i8, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_heapsort_i16(array_pointer: *const libc::int16_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i16, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_heapsort_i32(array_pointer: *const libc::int32_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_heapsort_i64(array_pointer: *const libc::int64_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i64, n as usize)
    };
    sort(&mut to_sort);
}

#[no_mangle]
pub extern "C" fn ffi_heapsort_u8(array_pointer: *const libc::uint8_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u8, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_heapsort_u16(array_pointer: *const libc::uint16_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u16, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_heapsort_u32(array_pointer: *const libc::uint32_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_heapsort_u64(array_pointer: *const libc::uint64_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u64, n as usize)
    };
    sort(&mut to_sort);
}

#[no_mangle]
pub extern "C" fn ffi_heapsort_f32(array_pointer: *const libc::c_void, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut f32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_heapsort_f64(array_pointer: *const libc::c_void, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut f64, n as usize)
    };
    sort(&mut to_sort);
}
<|endoftext|>


<commit_before>// Simple prometheus support. Still a work in progress.
// TODO
// We aren't collecting metrics properly we should be
// on the regular collecting metrics, and snapshoting them
// and sending them all up when prometheus comes to scrape.
use registry::{Registry, StdRegistry};
use std::thread;
use std::sync::Arc;
use reporter::base::Reporter;
use time;
use promo_proto::MetricFamily;
use router::Router;
use iron;
use iron::typemap::Key;
use iron::prelude::*;
use iron::status;

use promo_proto;
use persistent::Read;
use protobuf::Message;
use protobuf::repeated::RepeatedField;
use promo_proto::LabelPair;
use std::collections::HashMap;
use metrics::metric::MetricValue::{Counter, Gauge, Histogram, Meter};

#[derive(Copy, Clone)]
struct HandlerStorage;

#[allow(dead_code)] // until `prefix is used
pub struct PrometheusReporter {
    host_and_port: &'static str,
    // TODO to use as the application name?
    prefix: &'static str,
    registry: Arc<StdRegistry<'static>>,
    reporter_name: &'static str,
}

impl Key for HandlerStorage {
    type Value = Arc<StdRegistry<'static>>;
}

impl Reporter for PrometheusReporter {
    fn get_unique_reporter_name(&self) -> &'static str {
        self.reporter_name
    }
}

#[allow(dead_code)] // until `prefix is used
fn prefix(metric_line: String, prefix_str: &'static str) -> String {
    format!("{}.{}", prefix_str, metric_line)
}

impl PrometheusReporter {
    pub fn new(registry: Arc<StdRegistry<'static>>,
               reporter_name: &'static str,
               host_and_port: &'static str,
               prefix: &'static str)
               -> PrometheusReporter {
        PrometheusReporter {
            host_and_port: host_and_port,
            prefix: prefix,
            registry: registry,
            reporter_name: reporter_name,
        }
    }

    pub fn start(self) -> thread::JoinHandle<iron::Listening> {
        thread::spawn(move || {
            let mut router = Router::new();
            router.get("/metrics", handler);
            let mut chain = Chain::new(router);
            // The double long ARC pointer FTW!
            chain.link_before(Read::<HandlerStorage>::one(self.registry));
            // TODO -> Result<iron::Listening, iron::error::Error>
            Iron::new(chain).http(self.host_and_port).unwrap()
        })
    }
}

// TODO get an i64 instead?
fn timestamp() -> f64 {
    let timespec = time::get_time();
    // 1459440009.113178
    timespec.sec as f64 + (timespec.nsec as f64 / 1000.0 / 1000.0 / 1000.0)
}

fn handler(req: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok,
                       families_to_u8(to_pba(req.get::<Read<HandlerStorage>>().unwrap())))))
}

fn families_to_u8(metric_families: Vec<promo_proto::MetricFamily>) -> Vec<u8> {
    let mut buf = Vec::new();
    for family in metric_families {
        family.write_length_delimited_to_writer(&mut buf).unwrap();
    }
    buf
}

fn to_repeated_fields_labels(labels: HashMap<String, String>) -> RepeatedField<LabelPair> {
    let mut repeated_fields = Vec::new();
    // name/value is what they call it in the protobufs *shrug*
    for (name, value) in labels {
        let mut label_pair = LabelPair::new();
        label_pair.set_name(name);
        label_pair.set_value(value);
        repeated_fields.push(label_pair);
    }
    RepeatedField::from_vec(repeated_fields)
}

// This is totally terrible, it'd be much better to use macros
// and serde once nightly is stable. I'd consider setting a feature flag but
// it still might increase complexity to deploy
// To an array of MetricFamily
fn to_pba(registry: Arc<Arc<StdRegistry<'static>>>) -> Vec<promo_proto::MetricFamily> {
    let mut metric_families = Vec::new();
    let metric_names = registry.get_metrics_names();
    for metric_by_name in metric_names {
        let mut metric_family = MetricFamily::new();
        let mut pb_metric = promo_proto::Metric::new();
        let metric = registry.get(metric_by_name);
        let formated_metric = format!("{}_{}_{}", "application_name", metric_by_name, "bytes");
        metric_family.set_name(String::from(formated_metric));
        let ts = timestamp() as i64;
        pb_metric.set_timestamp_ms(ts);
        pb_metric.set_label(to_repeated_fields_labels(registry.labels()));

        match metric.export_metric() {
            Counter(x) => {
                let mut counter = promo_proto::Counter::new();
                counter.set_value(x.value);
                pb_metric.set_counter(counter);
                metric_family.set_field_type(promo_proto::MetricType::COUNTER);
            }
            Gauge(x) => {
                let mut gauge = promo_proto::Gauge::new();
                gauge.set_value(x.value);
                pb_metric.set_gauge(gauge);
                metric_family.set_field_type(promo_proto::MetricType::GAUGE);

            }
            Meter(x) => {
                // TODO ask the prometheus guys what we want to do
                pb_metric.set_summary(promo_proto::Summary::new());
                metric_family.set_field_type(promo_proto::MetricType::SUMMARY);

            }
            Histogram(x) => {
                pb_metric.set_histogram(promo_proto::Histogram::new());
                metric_family.set_field_type(promo_proto::MetricType::HISTOGRAM);
            }
        }

        metric_family.set_metric(RepeatedField::from_vec(vec![pb_metric,]));
        metric_families.push(metric_family);
    }
    metric_families
}

#[cfg(test)]
mod test {
    use metrics::meter::{Meter, StdMeter};
    use metrics::counter::{Counter, StdCounter};
    use metrics::gauge::{Gauge, StdGauge};
    use registry::{Registry, StdRegistry};
    use reporter::prometheus::PrometheusReporter;
    use std::sync::Arc;
    use std::time::Duration;
    use std::thread;
    use histogram::*;
    use std::collections::HashMap;

    #[test]
    fn add_some_stats_and_slurp_them_with_http() {
        extern crate hyper;
        let m = StdMeter::new();
        m.mark(100);

        let mut c: StdCounter = StdCounter::new();
        c.inc();

        let mut g: StdGauge = StdGauge { value: 0.0 };
        g.set(1.2);

        let mut hc = HistogramConfig::new();
        hc.max_value(100).precision(1);
        let mut h = Histogram::configured(hc).unwrap();

        h.record(1, 1);

        let mut r = StdRegistry::new_with_labels(HashMap::new());
        r.insert("meter1", m);
        r.insert("counter1", c);
        r.insert("gauge1", g);
        r.insert("histogram", h);

        let arc_registry = Arc::new(r);
        let reporter =
            PrometheusReporter::new(arc_registry.clone(), "test", "0.0.0.0:8080", "asd.asdf");
        reporter.start();

        let client = hyper::client::Client::new();
        // Seems as though iron isn't running maybe
        thread::sleep(Duration::from_millis(1024));
        let res = client.get("http://127.0.0.1:8080").send().unwrap();
        // TODO fix url and check to make sure we got a valid protobuf
    }
}
<commit_msg>Change unused variables to underscores<commit_after>// Simple prometheus support. Still a work in progress.
// TODO
// We aren't collecting metrics properly we should be
// on the regular collecting metrics, and snapshoting them
// and sending them all up when prometheus comes to scrape.
use registry::{Registry, StdRegistry};
use std::thread;
use std::sync::Arc;
use reporter::base::Reporter;
use time;
use promo_proto::MetricFamily;
use router::Router;
use iron;
use iron::typemap::Key;
use iron::prelude::*;
use iron::status;

use promo_proto;
use persistent::Read;
use protobuf::Message;
use protobuf::repeated::RepeatedField;
use promo_proto::LabelPair;
use std::collections::HashMap;
use metrics::metric::MetricValue::{Counter, Gauge, Histogram, Meter};

#[derive(Copy, Clone)]
struct HandlerStorage;

#[allow(dead_code)] // until `prefix is used
pub struct PrometheusReporter {
    host_and_port: &'static str,
    // TODO to use as the application name?
    prefix: &'static str,
    registry: Arc<StdRegistry<'static>>,
    reporter_name: &'static str,
}

impl Key for HandlerStorage {
    type Value = Arc<StdRegistry<'static>>;
}

impl Reporter for PrometheusReporter {
    fn get_unique_reporter_name(&self) -> &'static str {
        self.reporter_name
    }
}

#[allow(dead_code)] // until `prefix is used
fn prefix(metric_line: String, prefix_str: &'static str) -> String {
    format!("{}.{}", prefix_str, metric_line)
}

impl PrometheusReporter {
    pub fn new(registry: Arc<StdRegistry<'static>>,
               reporter_name: &'static str,
               host_and_port: &'static str,
               prefix: &'static str)
               -> PrometheusReporter {
        PrometheusReporter {
            host_and_port: host_and_port,
            prefix: prefix,
            registry: registry,
            reporter_name: reporter_name,
        }
    }

    pub fn start(self) -> thread::JoinHandle<iron::Listening> {
        thread::spawn(move || {
            let mut router = Router::new();
            router.get("/metrics", handler);
            let mut chain = Chain::new(router);
            // The double long ARC pointer FTW!
            chain.link_before(Read::<HandlerStorage>::one(self.registry));
            // TODO -> Result<iron::Listening, iron::error::Error>
            Iron::new(chain).http(self.host_and_port).unwrap()
        })
    }
}

// TODO get an i64 instead?
fn timestamp() -> f64 {
    let timespec = time::get_time();
    // 1459440009.113178
    timespec.sec as f64 + (timespec.nsec as f64 / 1000.0 / 1000.0 / 1000.0)
}

fn handler(req: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok,
                       families_to_u8(to_pba(req.get::<Read<HandlerStorage>>().unwrap())))))
}

fn families_to_u8(metric_families: Vec<promo_proto::MetricFamily>) -> Vec<u8> {
    let mut buf = Vec::new();
    for family in metric_families {
        family.write_length_delimited_to_writer(&mut buf).unwrap();
    }
    buf
}

fn to_repeated_fields_labels(labels: HashMap<String, String>) -> RepeatedField<LabelPair> {
    let mut repeated_fields = Vec::new();
    // name/value is what they call it in the protobufs *shrug*
    for (name, value) in labels {
        let mut label_pair = LabelPair::new();
        label_pair.set_name(name);
        label_pair.set_value(value);
        repeated_fields.push(label_pair);
    }
    RepeatedField::from_vec(repeated_fields)
}

// This is totally terrible, it'd be much better to use macros
// and serde once nightly is stable. I'd consider setting a feature flag but
// it still might increase complexity to deploy
// To an array of MetricFamily
fn to_pba(registry: Arc<Arc<StdRegistry<'static>>>) -> Vec<promo_proto::MetricFamily> {
    let mut metric_families = Vec::new();
    let metric_names = registry.get_metrics_names();
    for metric_by_name in metric_names {
        let mut metric_family = MetricFamily::new();
        let mut pb_metric = promo_proto::Metric::new();
        let metric = registry.get(metric_by_name);
        let formated_metric = format!("{}_{}_{}", "application_name", metric_by_name, "bytes");
        metric_family.set_name(String::from(formated_metric));
        let ts = timestamp() as i64;
        pb_metric.set_timestamp_ms(ts);
        pb_metric.set_label(to_repeated_fields_labels(registry.labels()));

        match metric.export_metric() {
            Counter(x) => {
                let mut counter = promo_proto::Counter::new();
                counter.set_value(x.value);
                pb_metric.set_counter(counter);
                metric_family.set_field_type(promo_proto::MetricType::COUNTER);
            }
            Gauge(x) => {
                let mut gauge = promo_proto::Gauge::new();
                gauge.set_value(x.value);
                pb_metric.set_gauge(gauge);
                metric_family.set_field_type(promo_proto::MetricType::GAUGE);

            }
            Meter(_) => {
                // TODO ask the prometheus guys what we want to do
                pb_metric.set_summary(promo_proto::Summary::new());
                metric_family.set_field_type(promo_proto::MetricType::SUMMARY);

            }
            Histogram(_) => {
                pb_metric.set_histogram(promo_proto::Histogram::new());
                metric_family.set_field_type(promo_proto::MetricType::HISTOGRAM);
            }
        }

        metric_family.set_metric(RepeatedField::from_vec(vec![pb_metric,]));
        metric_families.push(metric_family);
    }
    metric_families
}

#[cfg(test)]
mod test {
    use metrics::meter::{Meter, StdMeter};
    use metrics::counter::{Counter, StdCounter};
    use metrics::gauge::{Gauge, StdGauge};
    use registry::{Registry, StdRegistry};
    use reporter::prometheus::PrometheusReporter;
    use std::sync::Arc;
    use std::time::Duration;
    use std::thread;
    use histogram::*;
    use std::collections::HashMap;

    #[test]
    fn add_some_stats_and_slurp_them_with_http() {
        extern crate hyper;
        let m = StdMeter::new();
        m.mark(100);

        let mut c: StdCounter = StdCounter::new();
        c.inc();

        let mut g: StdGauge = StdGauge { value: 0.0 };
        g.set(1.2);

        let mut hc = HistogramConfig::new();
        hc.max_value(100).precision(1);
        let mut h = Histogram::configured(hc).unwrap();

        h.record(1, 1);

        let mut r = StdRegistry::new_with_labels(HashMap::new());
        r.insert("meter1", m);
        r.insert("counter1", c);
        r.insert("gauge1", g);
        r.insert("histogram", h);

        let arc_registry = Arc::new(r);
        let reporter =
            PrometheusReporter::new(arc_registry.clone(), "test", "0.0.0.0:8080", "asd.asdf");
        reporter.start();

        let client = hyper::client::Client::new();
        // Seems as though iron isn't running maybe
        thread::sleep(Duration::from_millis(1024));
        let res = client.get("http://127.0.0.1:8080").send().unwrap();
        // TODO fix url and check to make sure we got a valid protobuf
    }
}
<|endoftext|>


<commit_before>use audio::ac97::AC97;
use audio::intelhda::IntelHDA;

use core::cell::UnsafeCell;

use common::debug;

use disk::ahci::Ahci;
use disk::ide::Ide;

use env::Environment;

use network::intel8254x::Intel8254x;
use network::rtl8139::Rtl8139;

use schemes::file::FileScheme;

use usb::ehci::Ehci;
use usb::ohci::Ohci;
use usb::uhci::Uhci;
use usb::xhci::Xhci;

use super::config::PciConfig;
use super::common::class::*;
use super::common::subclass::*;
use super::common::programming_interface::*;
use super::common::vendorid::*;
use super::common::deviceid::*;

/// PCI device
pub unsafe fn pci_device(env: &mut Environment,
                         mut pci: PciConfig,
                         class_id: u8,
                         subclass_id: u8,
                         interface_id: u8,
                         vendor_code: u16,
                         device_code: u16) {
    if class_id == MASS_STORAGE {
        if subclass_id == IDE {
            if let Some(module) = FileScheme::new(Ide::disks(pci)) {
                env.schemes.push(UnsafeCell::new(module));
            }
        } else if subclass_id == SATA && interface_id == AHCI {
            if let Some(module) = FileScheme::new(Ahci::disks(pci)) {
                env.schemes.push(UnsafeCell::new(module));
            }
        }
    } else if class_id == SERIAL_BUS && subclass_id == USB {
        if interface_id == XHCI {
            let base = pci.read(0x10) as usize;

            let mut module = box Xhci {
                pci: pci,
                base: base & 0xFFFFFFF0,
                memory_mapped: base & 1 == 0,
                irq: pci.read(0x3C) as u8 & 0xF,
            };
            module.init();
            env.schemes.push(UnsafeCell::new(module));
        } else if interface_id == EHCI {
            env.schemes.push(UnsafeCell::new(Ehci::new(pci)));
        } else if interface_id == OHCI {
            env.schemes.push(UnsafeCell::new(Ohci::new(pci)));
        } else if interface_id == UHCI {
            env.schemes.push(UnsafeCell::new(Uhci::new(pci)));
        } else {
            debug!("Unknown USB interface version {:X}\n", interface_id);
        }
    } else {
        match vendor_code {
            REALTEK => match device_code {
                RTL8139 => env.schemes.push(UnsafeCell::new(Rtl8139::new(pci))),
                _ => (),
            },
            INTEL => match device_code {
                GBE_82540EM => env.schemes.push(UnsafeCell::new(Intel8254x::new(pci))),
                AC97_82801AA | AC97_ICH4 => env.schemes.push(UnsafeCell::new(AC97::new(pci))),
                INTELHDA_ICH6 => {
                    let base = pci.read(0x10) as usize;
                    let mut module = box IntelHDA {
                        pci: pci,
                        base: base & 0xFFFFFFF0,
                        memory_mapped: base & 1 == 0,
                        irq: pci.read(0x3C) as u8 & 0xF,
                    };
                    module.init();
                    env.schemes.push(UnsafeCell::new(module));
                }
                _ => (),
            },
            _ => (),
        }
    }
}

/// Initialize PCI session
pub unsafe fn pci_init(env: &mut Environment) {
    for bus in 0..256 {
        for slot in 0..32 {
            for func in 0..8 {
                let mut pci = PciConfig::new(bus as u8, slot as u8, func as u8);
                let id = pci.read(0);

                if (id & 0xFFFF) != 0xFFFF {
                    let class_id = pci.read(8);

                    debug!(" * PCI {}, {}, {}: ID {:X} CL {:X}",
                           bus,
                           slot,
                           func,
                           id,
                           class_id);

                    for i in 0..6 {
                        let bar = pci.read(i * 4 + 0x10);
                        if bar > 0 {
                            debug!(" BAR{}: {:X}", i, bar);

                            pci.write(i * 4 + 0x10, 0xFFFFFFFF);
                            let size = (0xFFFFFFFF - (pci.read(i * 4 + 0x10) & 0xFFFFFFF0)) + 1;
                            pci.write(i * 4 + 0x10, bar);

                            if size > 0 {
                                debug!(" {}", size);
                            }
                        }
                    }

                    debug::dl();

                    pci_device(env,
                               pci,
                               ((class_id >> 24) & 0xFF) as u8,
                               ((class_id >> 16) & 0xFF) as u8,
                               ((class_id >> 8) & 0xFF) as u8,
                               (id & 0xFFFF) as u16,
                               ((id >> 16) & 0xFFFF) as u16);
                }
            }
        }
    }
}
<commit_msg>rustfmt<commit_after>use audio::ac97::AC97;
use audio::intelhda::IntelHDA;

use core::cell::UnsafeCell;

use common::debug;

use disk::ahci::Ahci;
use disk::ide::Ide;

use env::Environment;

use network::intel8254x::Intel8254x;
use network::rtl8139::Rtl8139;

use schemes::file::FileScheme;

use usb::ehci::Ehci;
use usb::ohci::Ohci;
use usb::uhci::Uhci;
use usb::xhci::Xhci;

use super::config::PciConfig;
use super::common::class::*;
use super::common::subclass::*;
use super::common::programming_interface::*;
use super::common::vendorid::*;
use super::common::deviceid::*;

/// PCI device
pub unsafe fn pci_device(env: &mut Environment,
                         mut pci: PciConfig,
                         class_id: u8,
                         subclass_id: u8,
                         interface_id: u8,
                         vendor_code: u16,
                         device_code: u16) {
    if class_id == MASS_STORAGE {
        if subclass_id == IDE {
            if let Some(module) = FileScheme::new(Ide::disks(pci)) {
                env.schemes.push(UnsafeCell::new(module));
            }
        } else if subclass_id == SATA && interface_id == AHCI {
            if let Some(module) = FileScheme::new(Ahci::disks(pci)) {
                env.schemes.push(UnsafeCell::new(module));
            }
        }
    } else if class_id == SERIAL_BUS && subclass_id == USB {
        if interface_id == XHCI {
            let base = pci.read(0x10) as usize;

            let mut module = box Xhci {
                pci: pci,
                base: base & 0xFFFFFFF0,
                memory_mapped: base & 1 == 0,
                irq: pci.read(0x3C) as u8 & 0xF,
            };
            module.init();
            env.schemes.push(UnsafeCell::new(module));
        } else if interface_id == EHCI {
            env.schemes.push(UnsafeCell::new(Ehci::new(pci)));
        } else if interface_id == OHCI {
            env.schemes.push(UnsafeCell::new(Ohci::new(pci)));
        } else if interface_id == UHCI {
            env.schemes.push(UnsafeCell::new(Uhci::new(pci)));
        } else {
            debug!("Unknown USB interface version {:X}\n", interface_id);
        }
    } else {
        match vendor_code {
            REALTEK => {
                match device_code {
                    RTL8139 => env.schemes.push(UnsafeCell::new(Rtl8139::new(pci))),
                    _ => (),
                }
            }
            INTEL => {
                match device_code {
                    GBE_82540EM => env.schemes.push(UnsafeCell::new(Intel8254x::new(pci))),
                    AC97_82801AA | AC97_ICH4 => env.schemes.push(UnsafeCell::new(AC97::new(pci))),
                    INTELHDA_ICH6 => {
                        let base = pci.read(0x10) as usize;
                        let mut module = box IntelHDA {
                            pci: pci,
                            base: base & 0xFFFFFFF0,
                            memory_mapped: base & 1 == 0,
                            irq: pci.read(0x3C) as u8 & 0xF,
                        };
                        module.init();
                        env.schemes.push(UnsafeCell::new(module));
                    }
                    _ => (),
                }
            }
            _ => (),
        }
    }
}

/// Initialize PCI session
pub unsafe fn pci_init(env: &mut Environment) {
    for bus in 0..256 {
        for slot in 0..32 {
            for func in 0..8 {
                let mut pci = PciConfig::new(bus as u8, slot as u8, func as u8);
                let id = pci.read(0);

                if (id & 0xFFFF) != 0xFFFF {
                    let class_id = pci.read(8);

                    debug!(" * PCI {}, {}, {}: ID {:X} CL {:X}",
                           bus,
                           slot,
                           func,
                           id,
                           class_id);

                    for i in 0..6 {
                        let bar = pci.read(i * 4 + 0x10);
                        if bar > 0 {
                            debug!(" BAR{}: {:X}", i, bar);

                            pci.write(i * 4 + 0x10, 0xFFFFFFFF);
                            let size = (0xFFFFFFFF - (pci.read(i * 4 + 0x10) & 0xFFFFFFF0)) + 1;
                            pci.write(i * 4 + 0x10, bar);

                            if size > 0 {
                                debug!(" {}", size);
                            }
                        }
                    }

                    debug::dl();

                    pci_device(env,
                               pci,
                               ((class_id >> 24) & 0xFF) as u8,
                               ((class_id >> 16) & 0xFF) as u8,
                               ((class_id >> 8) & 0xFF) as u8,
                               (id & 0xFFFF) as u16,
                               ((id >> 16) & 0xFFFF) as u16);
                }
            }
        }
    }
}
<|endoftext|>