<commit_before>use std::default::Default;
use std::fmt;
use std::path::{PathBuf, Path};

use semver::Version;
use rustc_serialize::{Encoder, Encodable};

use core::{Dependency, PackageId, Summary};
use core::package_id::Metadata;
use util::{CargoResult, human};

/// Contains all the information about a package, as loaded from a Cargo.toml.
#[derive(Clone, Debug)]
pub struct Manifest {
    summary: Summary,
    targets: Vec<Target>,
    links: Option<String>,
    warnings: Vec<String>,
    exclude: Vec<String>,
    include: Vec<String>,
    metadata: ManifestMetadata,
    profiles: Profiles,
}

/// General metadata about a package which is just blindly uploaded to the
/// registry.
///
/// Note that many of these fields can contain invalid values such as the
/// homepage, repository, documentation, or license. These fields are not
/// validated by cargo itself, but rather it is up to the registry when uploaded
/// to validate these fields. Cargo will itself accept any valid TOML
/// specification for these values.
#[derive(PartialEq, Clone, Debug)]
pub struct ManifestMetadata {
    pub authors: Vec<String>,
    pub keywords: Vec<String>,
    pub license: Option<String>,
    pub license_file: Option<String>,
    pub description: Option<String>,    // not markdown
    pub readme: Option<String>,         // file, not contents
    pub homepage: Option<String>,       // url
    pub repository: Option<String>,     // url
    pub documentation: Option<String>,  // url
}

#[derive(RustcEncodable)]
struct SerializedManifest<'a> {
    name: String,
    version: String,
    dependencies: &'a [Dependency],
    targets: Vec<Target>,
}

impl Encodable for Manifest {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        SerializedManifest {
            name: self.summary.name().to_string(),
            version: self.summary.version().to_string(),
            dependencies: self.summary.dependencies(),
            targets: self.targets.clone(),
        }.encode(s)
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, RustcEncodable, Copy)]
pub enum LibKind {
    Lib,
    Rlib,
    Dylib,
    StaticLib
}

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

    /// Returns the argument suitable for `--crate-type` to pass to rustc.
    pub fn crate_type(&self) -> &'static str {
        match *self {
            LibKind::Lib => "lib",
            LibKind::Rlib => "rlib",
            LibKind::Dylib => "dylib",
            LibKind::StaticLib => "staticlib"
        }
    }
}

#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum TargetKind {
    Lib(Vec<LibKind>),
    Bin,
    Test,
    Bench,
    Example,
    CustomBuild,
}

impl Encodable for TargetKind {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        match *self {
            TargetKind::Lib(ref kinds) => {
                kinds.iter().map(|k| k.crate_type()).collect()
            }
            TargetKind::Bin => vec!["bin"],
            TargetKind::Example => vec!["example"],
            TargetKind::Test => vec!["test"],
            TargetKind::CustomBuild => vec!["custom-build"],
            TargetKind::Bench => vec!["bench"],
        }.encode(s)
    }
}

#[derive(RustcEncodable, RustcDecodable, Clone, PartialEq, Eq, Debug, Hash)]
pub struct Profile {
    pub opt_level: u32,
    pub lto: bool,
    pub codegen_units: Option<u32>,    // None = use rustc default
    pub rustc_args: Option<Vec<String>>,
    pub rustdoc_args: Option<Vec<String>>,
    pub debuginfo: bool,
    pub debug_assertions: bool,
    pub rpath: bool,
    pub test: bool,
    pub doc: bool,
    pub run_custom_build: bool,
}

#[derive(Default, Clone, Debug)]
pub struct Profiles {
    pub release: Profile,
    pub dev: Profile,
    pub test: Profile,
    pub bench: Profile,
    pub doc: Profile,
    pub custom_build: Profile,
}

/// Information about a binary, a library, an example, etc. that is part of the
/// package.
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
pub struct Target {
    kind: TargetKind,
    name: String,
    src_path: PathBuf,
    metadata: Option<Metadata>,
    tested: bool,
    benched: bool,
    doc: bool,
    doctest: bool,
    harness: bool, // whether to use the test harness (--test)
    for_host: bool,
}

#[derive(RustcEncodable)]
struct SerializedTarget<'a> {
    kind: &'a TargetKind,
    name: &'a str,
    src_path: &'a str,
}

impl Encodable for Target {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        SerializedTarget {
            kind: &self.kind,
            name: &self.name,
            src_path: &self.src_path.display().to_string(),
        }.encode(s)
    }
}

impl Manifest {
    pub fn new(summary: Summary, targets: Vec<Target>,
               exclude: Vec<String>,
               include: Vec<String>,
               links: Option<String>,
               metadata: ManifestMetadata,
               profiles: Profiles) -> Manifest {
        Manifest {
            summary: summary,
            targets: targets,
            warnings: Vec::new(),
            exclude: exclude,
            include: include,
            links: links,
            metadata: metadata,
            profiles: profiles,
        }
    }

    pub fn dependencies(&self) -> &[Dependency] { self.summary.dependencies() }
    pub fn exclude(&self) -> &[String] { &self.exclude }
    pub fn include(&self) -> &[String] { &self.include }
    pub fn metadata(&self) -> &ManifestMetadata { &self.metadata }
    pub fn name(&self) -> &str { self.package_id().name() }
    pub fn package_id(&self) -> &PackageId { self.summary.package_id() }
    pub fn summary(&self) -> &Summary { &self.summary }
    pub fn targets(&self) -> &[Target] { &self.targets }
    pub fn version(&self) -> &Version { self.package_id().version() }
    pub fn warnings(&self) -> &[String] { &self.warnings }
    pub fn profiles(&self) -> &Profiles { &self.profiles }
    pub fn links(&self) -> Option<&str> {
        self.links.as_ref().map(|s| &s[..])
    }

    pub fn add_warning(&mut self, s: String) {
        self.warnings.push(s)
    }

    pub fn set_summary(&mut self, summary: Summary) {
        self.summary = summary;
    }
}

impl Target {
    fn blank() -> Target {
        Target {
            kind: TargetKind::Bin,
            name: String::new(),
            src_path: PathBuf::new(),
            metadata: None,
            doc: false,
            doctest: false,
            harness: true,
            for_host: false,
            tested: true,
            benched: true,
        }
    }

    pub fn lib_target(name: &str, crate_targets: Vec<LibKind>,
                      src_path: &Path,
                      metadata: Metadata) -> Target {
        Target {
            kind: TargetKind::Lib(crate_targets),
            name: name.to_string(),
            src_path: src_path.to_path_buf(),
            metadata: Some(metadata),
            doctest: true,
            doc: true,
            ..Target::blank()
        }
    }

    pub fn bin_target(name: &str, src_path: &Path,
                      metadata: Option<Metadata>) -> Target {
        Target {
            kind: TargetKind::Bin,
            name: name.to_string(),
            src_path: src_path.to_path_buf(),
            metadata: metadata,
            doc: true,
            ..Target::blank()
        }
    }

    /// Builds a `Target` corresponding to the `build = "build.rs"` entry.
    pub fn custom_build_target(name: &str, src_path: &Path,
                               metadata: Option<Metadata>) -> Target {
        Target {
            kind: TargetKind::CustomBuild,
            name: name.to_string(),
            src_path: src_path.to_path_buf(),
            metadata: metadata,
            for_host: true,
            benched: false,
            tested: false,
            ..Target::blank()
        }
    }

    pub fn example_target(name: &str, src_path: &Path) -> Target {
        Target {
            kind: TargetKind::Example,
            name: name.to_string(),
            src_path: src_path.to_path_buf(),
            benched: false,
            ..Target::blank()
        }
    }

    pub fn test_target(name: &str, src_path: &Path,
                       metadata: Metadata) -> Target {
        Target {
            kind: TargetKind::Test,
            name: name.to_string(),
            src_path: src_path.to_path_buf(),
            metadata: Some(metadata),
            benched: false,
            ..Target::blank()
        }
    }

    pub fn bench_target(name: &str, src_path: &Path,
                        metadata: Metadata) -> Target {
        Target {
            kind: TargetKind::Bench,
            name: name.to_string(),
            src_path: src_path.to_path_buf(),
            metadata: Some(metadata),
            tested: false,
            ..Target::blank()
        }
    }

    pub fn name(&self) -> &str { &self.name }
    pub fn crate_name(&self) -> String { self.name.replace("-", "_") }
    pub fn src_path(&self) -> &Path { &self.src_path }
    pub fn metadata(&self) -> Option<&Metadata> { self.metadata.as_ref() }
    pub fn kind(&self) -> &TargetKind { &self.kind }
    pub fn tested(&self) -> bool { self.tested }
    pub fn harness(&self) -> bool { self.harness }
    pub fn documented(&self) -> bool { self.doc }
    pub fn for_host(&self) -> bool { self.for_host }
    pub fn benched(&self) -> bool { self.benched }

    pub fn doctested(&self) -> bool {
        self.doctest && match self.kind {
            TargetKind::Lib(ref kinds) => {
                kinds.contains(&LibKind::Rlib) || kinds.contains(&LibKind::Lib)
            }
            _ => false,
        }
    }

    pub fn allows_underscores(&self) -> bool {
        self.is_bin() || self.is_example() || self.is_custom_build()
    }

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

    pub fn linkable(&self) -> bool {
        match self.kind {
            TargetKind::Lib(ref kinds) => {
                kinds.iter().any(|k| {
                    match *k {
                        LibKind::Lib | LibKind::Rlib | LibKind::Dylib => true,
                        LibKind::StaticLib => false,
                    }
                })
            }
            _ => false
        }
    }

    pub fn is_bin(&self) -> bool { self.kind == TargetKind::Bin }
    pub fn is_example(&self) -> bool { self.kind == TargetKind::Example }
    pub fn is_test(&self) -> bool { self.kind == TargetKind::Test }
    pub fn is_bench(&self) -> bool { self.kind == TargetKind::Bench }
    pub fn is_custom_build(&self) -> bool { self.kind == TargetKind::CustomBuild }

    /// Returns the arguments suitable for `--crate-type` to pass to rustc.
    pub fn rustc_crate_types(&self) -> Vec<&'static str> {
        match self.kind {
            TargetKind::Lib(ref kinds) => {
                kinds.iter().map(|kind| kind.crate_type()).collect()
            },
            TargetKind::CustomBuild |
            TargetKind::Bench |
            TargetKind::Test |
            TargetKind::Example |
            TargetKind::Bin => vec!["bin"],
        }
    }

    pub fn can_lto(&self) -> bool {
        match self.kind {
            TargetKind::Lib(ref v) => *v == [LibKind::StaticLib],
            _ => true,
        }
    }

    pub fn set_tested(&mut self, tested: bool) -> &mut Target {
        self.tested = tested;
        self
    }
    pub fn set_benched(&mut self, benched: bool) -> &mut Target {
        self.benched = benched;
        self
    }
    pub fn set_doctest(&mut self, doctest: bool) -> &mut Target {
        self.doctest = doctest;
        self
    }
    pub fn set_for_host(&mut self, for_host: bool) -> &mut Target {
        self.for_host = for_host;
        self
    }
    pub fn set_harness(&mut self, harness: bool) -> &mut Target {
        self.harness = harness;
        self
    }
    pub fn set_doc(&mut self, doc: bool) -> &mut Target {
        self.doc = doc;
        self
    }
}

impl fmt::Display for Target {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.kind {
            TargetKind::Lib(..) => write!(f, "Target(lib)"),
            TargetKind::Bin => write!(f, "Target(bin: {})", self.name),
            TargetKind::Test => write!(f, "Target(test: {})", self.name),
            TargetKind::Bench => write!(f, "Target(bench: {})", self.name),
            TargetKind::Example => write!(f, "Target(example: {})", self.name),
            TargetKind::CustomBuild => write!(f, "Target(script)"),
        }
    }
}

impl Profile {
    pub fn default_dev() -> Profile {
        Profile {
            debuginfo: true,
            debug_assertions: true,
            ..Profile::default()
        }
    }

    pub fn default_release() -> Profile {
        Profile {
            opt_level: 3,
            debuginfo: false,
            ..Profile::default()
        }
    }

    pub fn default_test() -> Profile {
        Profile {
            test: true,
            ..Profile::default_dev()
        }
    }

    pub fn default_bench() -> Profile {
        Profile {
            test: true,
            ..Profile::default_release()
        }
    }

    pub fn default_doc() -> Profile {
        Profile {
            doc: true,
            ..Profile::default_dev()
        }
    }

    pub fn default_custom_build() -> Profile {
        Profile {
            run_custom_build: true,
            ..Profile::default_dev()
        }
    }
}

impl Default for Profile {
    fn default() -> Profile {
        Profile {
            opt_level: 0,
            lto: false,
            codegen_units: None,
            rustc_args: None,
            rustdoc_args: None,
            debuginfo: false,
            debug_assertions: false,
            rpath: false,
            test: false,
            doc: false,
            run_custom_build: false,
        }
    }
}

impl fmt::Display for Profile {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.test {
            write!(f, "Profile(test)")
        } else if self.doc {
            write!(f, "Profile(doc)")
        } else if self.run_custom_build {
            write!(f, "Profile(run)")
        } else {
            write!(f, "Profile(build)")
        }

    }
}
<commit_msg>remove unused Encodable impl for Manifest<commit_after>use std::default::Default;
use std::fmt;
use std::path::{PathBuf, Path};

use semver::Version;
use rustc_serialize::{Encoder, Encodable};

use core::{Dependency, PackageId, Summary};
use core::package_id::Metadata;
use util::{CargoResult, human};

/// Contains all the information about a package, as loaded from a Cargo.toml.
#[derive(Clone, Debug)]
pub struct Manifest {
    summary: Summary,
    targets: Vec<Target>,
    links: Option<String>,
    warnings: Vec<String>,
    exclude: Vec<String>,
    include: Vec<String>,
    metadata: ManifestMetadata,
    profiles: Profiles,
}

/// General metadata about a package which is just blindly uploaded to the
/// registry.
///
/// Note that many of these fields can contain invalid values such as the
/// homepage, repository, documentation, or license. These fields are not
/// validated by cargo itself, but rather it is up to the registry when uploaded
/// to validate these fields. Cargo will itself accept any valid TOML
/// specification for these values.
#[derive(PartialEq, Clone, Debug)]
pub struct ManifestMetadata {
    pub authors: Vec<String>,
    pub keywords: Vec<String>,
    pub license: Option<String>,
    pub license_file: Option<String>,
    pub description: Option<String>,    // not markdown
    pub readme: Option<String>,         // file, not contents
    pub homepage: Option<String>,       // url
    pub repository: Option<String>,     // url
    pub documentation: Option<String>,  // url
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, RustcEncodable, Copy)]
pub enum LibKind {
    Lib,
    Rlib,
    Dylib,
    StaticLib
}

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

    /// Returns the argument suitable for `--crate-type` to pass to rustc.
    pub fn crate_type(&self) -> &'static str {
        match *self {
            LibKind::Lib => "lib",
            LibKind::Rlib => "rlib",
            LibKind::Dylib => "dylib",
            LibKind::StaticLib => "staticlib"
        }
    }
}

#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum TargetKind {
    Lib(Vec<LibKind>),
    Bin,
    Test,
    Bench,
    Example,
    CustomBuild,
}

impl Encodable for TargetKind {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        match *self {
            TargetKind::Lib(ref kinds) => {
                kinds.iter().map(|k| k.crate_type()).collect()
            }
            TargetKind::Bin => vec!["bin"],
            TargetKind::Example => vec!["example"],
            TargetKind::Test => vec!["test"],
            TargetKind::CustomBuild => vec!["custom-build"],
            TargetKind::Bench => vec!["bench"],
        }.encode(s)
    }
}

#[derive(RustcEncodable, RustcDecodable, Clone, PartialEq, Eq, Debug, Hash)]
pub struct Profile {
    pub opt_level: u32,
    pub lto: bool,
    pub codegen_units: Option<u32>,    // None = use rustc default
    pub rustc_args: Option<Vec<String>>,
    pub rustdoc_args: Option<Vec<String>>,
    pub debuginfo: bool,
    pub debug_assertions: bool,
    pub rpath: bool,
    pub test: bool,
    pub doc: bool,
    pub run_custom_build: bool,
}

#[derive(Default, Clone, Debug)]
pub struct Profiles {
    pub release: Profile,
    pub dev: Profile,
    pub test: Profile,
    pub bench: Profile,
    pub doc: Profile,
    pub custom_build: Profile,
}

/// Information about a binary, a library, an example, etc. that is part of the
/// package.
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
pub struct Target {
    kind: TargetKind,
    name: String,
    src_path: PathBuf,
    metadata: Option<Metadata>,
    tested: bool,
    benched: bool,
    doc: bool,
    doctest: bool,
    harness: bool, // whether to use the test harness (--test)
    for_host: bool,
}

#[derive(RustcEncodable)]
struct SerializedTarget<'a> {
    kind: &'a TargetKind,
    name: &'a str,
    src_path: &'a str,
}

impl Encodable for Target {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        SerializedTarget {
            kind: &self.kind,
            name: &self.name,
            src_path: &self.src_path.display().to_string(),
        }.encode(s)
    }
}

impl Manifest {
    pub fn new(summary: Summary, targets: Vec<Target>,
               exclude: Vec<String>,
               include: Vec<String>,
               links: Option<String>,
               metadata: ManifestMetadata,
               profiles: Profiles) -> Manifest {
        Manifest {
            summary: summary,
            targets: targets,
            warnings: Vec::new(),
            exclude: exclude,
            include: include,
            links: links,
            metadata: metadata,
            profiles: profiles,
        }
    }

    pub fn dependencies(&self) -> &[Dependency] { self.summary.dependencies() }
    pub fn exclude(&self) -> &[String] { &self.exclude }
    pub fn include(&self) -> &[String] { &self.include }
    pub fn metadata(&self) -> &ManifestMetadata { &self.metadata }
    pub fn name(&self) -> &str { self.package_id().name() }
    pub fn package_id(&self) -> &PackageId { self.summary.package_id() }
    pub fn summary(&self) -> &Summary { &self.summary }
    pub fn targets(&self) -> &[Target] { &self.targets }
    pub fn version(&self) -> &Version { self.package_id().version() }
    pub fn warnings(&self) -> &[String] { &self.warnings }
    pub fn profiles(&self) -> &Profiles { &self.profiles }
    pub fn links(&self) -> Option<&str> {
        self.links.as_ref().map(|s| &s[..])
    }

    pub fn add_warning(&mut self, s: String) {
        self.warnings.push(s)
    }

    pub fn set_summary(&mut self, summary: Summary) {
        self.summary = summary;
    }
}

impl Target {
    fn blank() -> Target {
        Target {
            kind: TargetKind::Bin,
            name: String::new(),
            src_path: PathBuf::new(),
            metadata: None,
            doc: false,
            doctest: false,
            harness: true,
            for_host: false,
            tested: true,
            benched: true,
        }
    }

    pub fn lib_target(name: &str, crate_targets: Vec<LibKind>,
                      src_path: &Path,
                      metadata: Metadata) -> Target {
        Target {
            kind: TargetKind::Lib(crate_targets),
            name: name.to_string(),
            src_path: src_path.to_path_buf(),
            metadata: Some(metadata),
            doctest: true,
            doc: true,
            ..Target::blank()
        }
    }

    pub fn bin_target(name: &str, src_path: &Path,
                      metadata: Option<Metadata>) -> Target {
        Target {
            kind: TargetKind::Bin,
            name: name.to_string(),
            src_path: src_path.to_path_buf(),
            metadata: metadata,
            doc: true,
            ..Target::blank()
        }
    }

    /// Builds a `Target` corresponding to the `build = "build.rs"` entry.
    pub fn custom_build_target(name: &str, src_path: &Path,
                               metadata: Option<Metadata>) -> Target {
        Target {
            kind: TargetKind::CustomBuild,
            name: name.to_string(),
            src_path: src_path.to_path_buf(),
            metadata: metadata,
            for_host: true,
            benched: false,
            tested: false,
            ..Target::blank()
        }
    }

    pub fn example_target(name: &str, src_path: &Path) -> Target {
        Target {
            kind: TargetKind::Example,
            name: name.to_string(),
            src_path: src_path.to_path_buf(),
            benched: false,
            ..Target::blank()
        }
    }

    pub fn test_target(name: &str, src_path: &Path,
                       metadata: Metadata) -> Target {
        Target {
            kind: TargetKind::Test,
            name: name.to_string(),
            src_path: src_path.to_path_buf(),
            metadata: Some(metadata),
            benched: false,
            ..Target::blank()
        }
    }

    pub fn bench_target(name: &str, src_path: &Path,
                        metadata: Metadata) -> Target {
        Target {
            kind: TargetKind::Bench,
            name: name.to_string(),
            src_path: src_path.to_path_buf(),
            metadata: Some(metadata),
            tested: false,
            ..Target::blank()
        }
    }

    pub fn name(&self) -> &str { &self.name }
    pub fn crate_name(&self) -> String { self.name.replace("-", "_") }
    pub fn src_path(&self) -> &Path { &self.src_path }
    pub fn metadata(&self) -> Option<&Metadata> { self.metadata.as_ref() }
    pub fn kind(&self) -> &TargetKind { &self.kind }
    pub fn tested(&self) -> bool { self.tested }
    pub fn harness(&self) -> bool { self.harness }
    pub fn documented(&self) -> bool { self.doc }
    pub fn for_host(&self) -> bool { self.for_host }
    pub fn benched(&self) -> bool { self.benched }

    pub fn doctested(&self) -> bool {
        self.doctest && match self.kind {
            TargetKind::Lib(ref kinds) => {
                kinds.contains(&LibKind::Rlib) || kinds.contains(&LibKind::Lib)
            }
            _ => false,
        }
    }

    pub fn allows_underscores(&self) -> bool {
        self.is_bin() || self.is_example() || self.is_custom_build()
    }

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

    pub fn linkable(&self) -> bool {
        match self.kind {
            TargetKind::Lib(ref kinds) => {
                kinds.iter().any(|k| {
                    match *k {
                        LibKind::Lib | LibKind::Rlib | LibKind::Dylib => true,
                        LibKind::StaticLib => false,
                    }
                })
            }
            _ => false
        }
    }

    pub fn is_bin(&self) -> bool { self.kind == TargetKind::Bin }
    pub fn is_example(&self) -> bool { self.kind == TargetKind::Example }
    pub fn is_test(&self) -> bool { self.kind == TargetKind::Test }
    pub fn is_bench(&self) -> bool { self.kind == TargetKind::Bench }
    pub fn is_custom_build(&self) -> bool { self.kind == TargetKind::CustomBuild }

    /// Returns the arguments suitable for `--crate-type` to pass to rustc.
    pub fn rustc_crate_types(&self) -> Vec<&'static str> {
        match self.kind {
            TargetKind::Lib(ref kinds) => {
                kinds.iter().map(|kind| kind.crate_type()).collect()
            },
            TargetKind::CustomBuild |
            TargetKind::Bench |
            TargetKind::Test |
            TargetKind::Example |
            TargetKind::Bin => vec!["bin"],
        }
    }

    pub fn can_lto(&self) -> bool {
        match self.kind {
            TargetKind::Lib(ref v) => *v == [LibKind::StaticLib],
            _ => true,
        }
    }

    pub fn set_tested(&mut self, tested: bool) -> &mut Target {
        self.tested = tested;
        self
    }
    pub fn set_benched(&mut self, benched: bool) -> &mut Target {
        self.benched = benched;
        self
    }
    pub fn set_doctest(&mut self, doctest: bool) -> &mut Target {
        self.doctest = doctest;
        self
    }
    pub fn set_for_host(&mut self, for_host: bool) -> &mut Target {
        self.for_host = for_host;
        self
    }
    pub fn set_harness(&mut self, harness: bool) -> &mut Target {
        self.harness = harness;
        self
    }
    pub fn set_doc(&mut self, doc: bool) -> &mut Target {
        self.doc = doc;
        self
    }
}

impl fmt::Display for Target {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.kind {
            TargetKind::Lib(..) => write!(f, "Target(lib)"),
            TargetKind::Bin => write!(f, "Target(bin: {})", self.name),
            TargetKind::Test => write!(f, "Target(test: {})", self.name),
            TargetKind::Bench => write!(f, "Target(bench: {})", self.name),
            TargetKind::Example => write!(f, "Target(example: {})", self.name),
            TargetKind::CustomBuild => write!(f, "Target(script)"),
        }
    }
}

impl Profile {
    pub fn default_dev() -> Profile {
        Profile {
            debuginfo: true,
            debug_assertions: true,
            ..Profile::default()
        }
    }

    pub fn default_release() -> Profile {
        Profile {
            opt_level: 3,
            debuginfo: false,
            ..Profile::default()
        }
    }

    pub fn default_test() -> Profile {
        Profile {
            test: true,
            ..Profile::default_dev()
        }
    }

    pub fn default_bench() -> Profile {
        Profile {
            test: true,
            ..Profile::default_release()
        }
    }

    pub fn default_doc() -> Profile {
        Profile {
            doc: true,
            ..Profile::default_dev()
        }
    }

    pub fn default_custom_build() -> Profile {
        Profile {
            run_custom_build: true,
            ..Profile::default_dev()
        }
    }
}

impl Default for Profile {
    fn default() -> Profile {
        Profile {
            opt_level: 0,
            lto: false,
            codegen_units: None,
            rustc_args: None,
            rustdoc_args: None,
            debuginfo: false,
            debug_assertions: false,
            rpath: false,
            test: false,
            doc: false,
            run_custom_build: false,
        }
    }
}

impl fmt::Display for Profile {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.test {
            write!(f, "Profile(test)")
        } else if self.doc {
            write!(f, "Profile(doc)")
        } else if self.run_custom_build {
            write!(f, "Profile(run)")
        } else {
            write!(f, "Profile(build)")
        }

    }
}
<|endoftext|>


<commit_before>use std::sync::Arc;
use std::time::{Instant, Duration};
use std::collections::{HashMap, HashSet};

use rustc_serialize::json::Json;
use futures::sync::mpsc::{UnboundedSender as Sender};

use intern::{Topic, SessionId, SessionPoolName, Lattice as Namespace};
use config;
use chat::Cid;
use super::{ConnectionMessage, PoolMessage};
use super::session::Session;
use super::connection::{NewConnection, Connection};
use super::heap::HeapMap;
use super::lattice::{Lattice, Delta};

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum Subscription {
    Pending,
    Session,
}

pub struct Pool {
    name: SessionPoolName,
    channel: Sender<PoolMessage>,
    active_sessions: HeapMap<SessionId, Instant, Session>,
    inactive_sessions: HashMap<SessionId, Session>,

    pending_connections: HashMap<Cid, NewConnection>,
    connections: HashMap<Cid, Connection>,
    topics: HashMap<Topic, HashMap<Cid, Subscription>>,
    lattices: HashMap<Namespace, Lattice>,

    // Setings
    new_connection_timeout: Duration,
}

impl Pool {

    pub fn new(name: SessionPoolName, _cfg: Arc<config::SessionPool>,
        channel: Sender<PoolMessage>)
        -> Pool
    {
        Pool {
            name: name,
            channel: channel,
            active_sessions: HeapMap::new(),
            inactive_sessions: HashMap::new(),
            pending_connections: HashMap::new(),
            connections: HashMap::new(),
            topics: HashMap::new(),
            lattices: HashMap::new(),

            // TODO(tailhook) from config
            new_connection_timeout: Duration::new(60, 0),
        }
    }

    pub fn add_connection(&mut self, conn_id: Cid,
        channel: Sender<ConnectionMessage>)
    {
        let old = self.pending_connections.insert(conn_id,
            NewConnection::new(conn_id, channel));
        debug_assert!(old.is_none());
    }

    pub fn associate(&mut self, conn_id: Cid, session_id: SessionId,
        timestamp: Instant, metadata: Arc<Json>)
    {
        let conn = if let Some(p) = self.pending_connections.remove(&conn_id) {
            p.associate(session_id.clone())
        } else {
            debug!("Connection {:?} does not exist any more", conn_id);
            return;
        };

        for top in &conn.topics {
            let ptr = self.topics
                .get_mut(top)
                .and_then(|m| m.get_mut(&conn_id))
                .expect("topics are consistent");
            *ptr = Subscription::Session;
        }

        let expire = timestamp + self.new_connection_timeout;
        if let Some(mut session) = self.inactive_sessions.remove(&session_id) {
            session.connections.insert(conn_id);
            session.metadata = metadata;
            let val = self.active_sessions.insert(session_id.clone(),
                timestamp, session);
            debug_assert!(val.is_none());
        } else if self.active_sessions.contains_key(&session_id) {
            self.active_sessions.update(&session_id, expire);
            let session = self.active_sessions.get_mut(&session_id).unwrap();
            session.connections.insert(conn_id);
            session.metadata = metadata;
        } else {
            let mut session = Session::new();
            session.connections.insert(conn_id);
            session.metadata = metadata;
            self.active_sessions.insert(session_id.clone(), expire, session);
        }

        let ins = self.connections.insert(conn_id, conn);
        debug_assert!(ins.is_none());
    }

    pub fn del_connection(&mut self, conn_id: Cid) {
        if let Some(conn) = self.pending_connections.remove(&conn_id) {
            for top in &conn.topics {
                unsubscribe(&mut self.topics, top, conn_id);
            }
            return;
        }
        let conn = self.connections.remove(&conn_id)
            .expect("valid connection");
        for topic in &conn.topics {
            unsubscribe(&mut self.topics, &topic, conn_id);
        }
        let session_id = conn.session_id;

        if self.inactive_sessions.contains_key(&session_id) {
            let conns = {
                let mut session = self.inactive_sessions.get_mut(&session_id)
                                  .unwrap();
                session.connections.remove(&conn_id);
                session.connections.len()
            };
            if conns == 0 {
                self.inactive_sessions.remove(&session_id);
            }
        } if let Some(mut session) = self.active_sessions.get_mut(&session_id)
        {
            session.connections.remove(&conn_id);
            // We delete it on inactivation
        }
    }

    pub fn update_activity(&mut self, conn_id: Cid, activity_ts: Instant)
    {
        let sess_id = if let Some(conn) = self.connections.get(&conn_id) {
            &conn.session_id
        } else {
            return;
        };
        if let Some(session) = self.inactive_sessions.remove(sess_id) {
            self.active_sessions.insert(sess_id.clone(), activity_ts, session);
        } else {
            self.active_sessions.update_if_smaller(sess_id, activity_ts)
        }
    }

    pub fn cleanup(&mut self, timestamp: Instant) -> Option<Instant> {
        while self.active_sessions.peek()
            .map(|(_, &x, _)| x < timestamp).unwrap_or(false)
        {
            let (sess_id, _, session) = self.active_sessions.pop().unwrap();
            self.channel.send(PoolMessage::InactiveSession {
                session_id: sess_id.clone(),
                connections_active: session.connections.len(),
                metadata: session.metadata.clone(),
            }).expect("can't send pool message");
            if session.connections.len() == 0 {
                // TODO(tailhook) Maybe do session cleanup ?
            } else {
                let val = self.inactive_sessions.insert(sess_id, session);
                debug_assert!(val.is_none());
            }
            // TODO(tailhook) send inactiity message to IO thread
        }
        self.active_sessions.peek().map(|(_, &x, _)| x)
    }

    pub fn subscribe(&mut self, cid: Cid, topic: Topic) {
        if let Some(conn) = self.connections.get_mut(&cid) {
            conn.topics.insert(topic.clone());
            self.topics.entry(topic).or_insert_with(HashMap::new)
                .insert(cid, Subscription::Session);
        } else if let Some(conn) = self.pending_connections.get_mut(&cid) {
            conn.topics.insert(topic.clone());
            self.topics.entry(topic).or_insert_with(HashMap::new)
                .insert(cid, Subscription::Pending);
        } else {
            debug!("Connection {:?} does not exist any more", cid);
        }
    }

    pub fn unsubscribe(&mut self, cid: Cid, topic: Topic) {
        match unsubscribe(&mut self.topics, &topic, cid) {
            Some(Subscription::Pending) => {
                self.pending_connections.get_mut(&cid)
                    .expect("pending conns and topics are in sync")
                    .topics.remove(&topic);
            }
            Some(Subscription::Session) => {
                self.connections.get_mut(&cid)
                    .expect("pending conns and topics are in sync")
                    .topics.remove(&topic);
            }
            None => {
                debug!("Connection {:?} does not exist any more", cid);
            }
        }
    }

    pub fn publish(&mut self, topic: Topic, data: Arc<Json>) {
        if let Some(cids) = self.topics.get(&topic) {
            for (cid, typ) in cids {
                match *typ {
                    Subscription::Pending => {
                        self.pending_connections.get_mut(cid)
                            .expect("subscriptions out of sync")
                            .message(topic.clone(), data.clone())
                    }
                    Subscription::Session => {
                        self.connections.get_mut(cid)
                            .expect("subscriptions out of sync")
                            .message(topic.clone(), data.clone())
                    }
                }
            }
        }
    }

    pub fn lattice_attach(&mut self, cid: Cid, namespace: Namespace) {
        let conn = if let Some(conn) = self.connections.get_mut(&cid) {
            conn
        } else {
            error!("Attach of {:?} for non-existing connection {:?}",
                   namespace, cid);
            return
        };
        conn.lattices.insert(namespace.clone());
        let lat = if let Some(lat) = self.lattices.get(&namespace) {
            lat
        } else {
            error!("No lattice {:?} at the time of attach (connection {:?})",
                   namespace, cid);
            return
        };
        let mut data = lat.private.get(&conn.session_id)
            .map(|x| x.clone())
            .unwrap_or_else(HashMap::new);
        for (key, values) in &mut data {
            lat.public.get(key).map(|pubval| {
                values.update(pubval);
            });
        }
        conn.lattice(&namespace, &Arc::new(data));
    }

    pub fn lattice_detach(&mut self, cid: Cid, namespace: Namespace) {
        unimplemented!();
    }

    pub fn lattice_update(&mut self,
        namespace: Namespace, delta: Delta)
    {
        let delta = {
            let lat = self.lattices.entry(namespace.clone())
                .or_insert_with(Lattice::new);

            // Update subscriptions on **original delta**
            for (session_id, rooms) in delta.private.iter() {
                for key in rooms.keys() {
                    lat.subscriptions.entry(key.clone())
                        .or_insert_with(HashSet::new)
                        .insert(session_id.clone());
                }
            }

            // Then make minimal delta
            lat.update(delta)
        };

        // Fighting with borrow checker
        let lat = self.lattices.get(&namespace).unwrap();

        // Send public-only changes
        let pubdata = Arc::new(delta.public);
        let mut already_sent = HashSet::new();
        for room in pubdata.keys() {
            if let Some(sessions) = lat.subscriptions.get(room) {
                for sid in sessions {
                    if !already_sent.contains(sid) &&
                       !delta.private.contains_key(sid)
                    {
                        // Can't easily abstract all this away because of borrow checker
                        let sess = if let Some(sess) = self.active_sessions.get(sid) {
                            sess
                        } else if let Some(sess) = self.inactive_sessions.get(sid) {
                            sess
                        } else {
                            continue;
                        };
                        if let Some(connections) = sess.lattices.get(&namespace) {
                            for cid in connections {
                                if let Some(conn) = self.connections.get_mut(cid) {
                                    conn.lattice(&namespace, &pubdata);
                                }
                            }
                        }
                        already_sent.insert(sid.clone());
                    }
                }
            }
        }

        // Send public *and* private
        for (session_id, mut rooms) in delta.private.into_iter() {
            for (room, values) in rooms.iter_mut() {
                pubdata.get(room).map(|pubval| {
                    values.update(pubval);
                });
            }
            // Can't easily abstract all this away because of borrow checker
            let sess = if let Some(sess) = self.active_sessions.get(&session_id) {
                sess
            } else if let Some(sess) = self.inactive_sessions.get(&session_id) {
                sess
            } else {
                continue;
            };
            if let Some(connections) = sess.lattices.get(&namespace) {
                let update = Arc::new(rooms);
                for cid in connections {
                    if let Some(conn) = self.connections.get_mut(cid) {
                        conn.lattice(&namespace, &update);
                    }
                }
            }
        }
    }
}

fn unsubscribe(topics: &mut HashMap<Topic, HashMap<Cid, Subscription>>,
    topic: &Topic, cid: Cid)
    -> Option<Subscription>
{
    let left = topics.get_mut(topic)
        .map(|set| {
            (set.remove(&cid), set.len())
        });
    left.and_then(|(sub, len)| {
        if len == 0 {
            topics.remove(topic);
        }
        return sub;
    })
}

#[cfg(test)]
mod test {
    use std::sync::Arc;
    use std::time::{Instant, Duration};
    use rustc_serialize::json::Json;
    use futures::Future;
    use futures::stream::Stream;
    use futures::sync::mpsc::{unbounded as channel};
    use futures::sync::mpsc::{UnboundedReceiver as Receiver};
    use intern::{SessionId, SessionPoolName};
    use config;
    use chat::Cid;

    use super::Pool;
    use super::super::PoolMessage;

    fn pool() -> (Pool, Receiver<PoolMessage>) {
        let (tx, rx) = channel();
        let pool = Pool::new(SessionPoolName::from("test_pool"),
            Arc::new(config::SessionPool {
                listen: config::ListenSocket::Tcp(
                    "127.0.0.1:65535".parse().unwrap()),
                inactivity_handlers: Vec::new(),
            }),
            tx);
        return (pool, rx);
    }

    #[test]
    fn add_conn() {
        let (mut pool, _rx) = pool();
        let cid = Cid::new();
        let (tx, _rx) = channel();
        pool.add_connection(cid, tx);
        pool.associate(cid, SessionId::from("user1"), Instant::now(),
            Arc::new(Json::Object(vec![
                ("user_id", "user1"),
            ].into_iter().map(|(x, y)| {
                (x.into(), Json::String(y.into()))
            }).collect())));
    }

    fn first_item<S: Stream>(s: S) -> S::Item {
        s.into_future().wait().map(|(x, _)| x).map_err(|_|{})
            .expect("stream error")
            .expect("stream eof")
    }

    #[test]
    fn disconnect_after_inactive() {
        let (mut pool, rx) = pool();
        let cid = Cid::new();
        let (tx, _rx) = channel();
        pool.add_connection(cid, tx);
        pool.associate(cid, SessionId::from("user1"), Instant::now(),
            Arc::new(Json::Object(vec![
                ("user_id", "user1"),
            ].into_iter().map(|(x, y)| {
                (x.into(), Json::String(y.into()))
            }).collect())));
        assert_eq!(pool.active_sessions.len(), 1);
        assert_eq!(pool.inactive_sessions.len(), 0);
        pool.cleanup(Instant::now() + Duration::new(10, 0));
        // New connection timeout is expected to be ~ 60 seconds
        assert_eq!(pool.active_sessions.len(), 1);
        assert_eq!(pool.inactive_sessions.len(), 0);
        pool.cleanup(Instant::now() + Duration::new(120, 0));
        assert!(matches!(first_item(rx),
            PoolMessage::InactiveSession { ref session_id, ..}
            if *session_id == SessionId::from("user1")));
        assert_eq!(pool.active_sessions.len(), 0);
        assert_eq!(pool.inactive_sessions.len(), 1);
        pool.del_connection(cid);
        assert_eq!(pool.active_sessions.len(), 0);
        assert_eq!(pool.inactive_sessions.len(), 0);
    }

    #[test]
    fn disconnect_before_inactive() {
        let (mut pool, rx) = pool();
        let cid = Cid::new();
        let (tx, _rx) = channel();
        pool.add_connection(cid, tx);
        pool.associate(cid, SessionId::from("user1"), Instant::now(),
            Arc::new(Json::Object(vec![
                ("user_id", "user1"),
            ].into_iter().map(|(x, y)| {
                (x.into(), Json::String(y.into()))
            }).collect())));
        assert_eq!(pool.active_sessions.len(), 1);
        assert_eq!(pool.inactive_sessions.len(), 0);
        pool.cleanup(Instant::now() + Duration::new(10, 0));
        // New connection timeout is expected to be ~ 60 seconds
        assert_eq!(pool.active_sessions.len(), 1);
        assert_eq!(pool.inactive_sessions.len(), 0);
        pool.del_connection(cid);
        assert_eq!(pool.active_sessions.len(), 1);
        assert_eq!(pool.inactive_sessions.len(), 0);
        pool.cleanup(Instant::now() + Duration::new(120, 0));
        assert!(matches!(first_item(rx),
            PoolMessage::InactiveSession { ref session_id, ..}
            if *session_id == SessionId::from("user1")));
        assert_eq!(pool.active_sessions.len(), 0);
        assert_eq!(pool.inactive_sessions.len(), 0);
    }
}
<commit_msg>Simplified tests even more<commit_after>use std::sync::Arc;
use std::time::{Instant, Duration};
use std::collections::{HashMap, HashSet};

use rustc_serialize::json::Json;
use futures::sync::mpsc::{UnboundedSender as Sender};

use intern::{Topic, SessionId, SessionPoolName, Lattice as Namespace};
use config;
use chat::Cid;
use super::{ConnectionMessage, PoolMessage};
use super::session::Session;
use super::connection::{NewConnection, Connection};
use super::heap::HeapMap;
use super::lattice::{Lattice, Delta};

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum Subscription {
    Pending,
    Session,
}

pub struct Pool {
    name: SessionPoolName,
    channel: Sender<PoolMessage>,
    active_sessions: HeapMap<SessionId, Instant, Session>,
    inactive_sessions: HashMap<SessionId, Session>,

    pending_connections: HashMap<Cid, NewConnection>,
    connections: HashMap<Cid, Connection>,
    topics: HashMap<Topic, HashMap<Cid, Subscription>>,
    lattices: HashMap<Namespace, Lattice>,

    // Setings
    new_connection_timeout: Duration,
}

impl Pool {

    pub fn new(name: SessionPoolName, _cfg: Arc<config::SessionPool>,
        channel: Sender<PoolMessage>)
        -> Pool
    {
        Pool {
            name: name,
            channel: channel,
            active_sessions: HeapMap::new(),
            inactive_sessions: HashMap::new(),
            pending_connections: HashMap::new(),
            connections: HashMap::new(),
            topics: HashMap::new(),
            lattices: HashMap::new(),

            // TODO(tailhook) from config
            new_connection_timeout: Duration::new(60, 0),
        }
    }

    pub fn add_connection(&mut self, conn_id: Cid,
        channel: Sender<ConnectionMessage>)
    {
        let old = self.pending_connections.insert(conn_id,
            NewConnection::new(conn_id, channel));
        debug_assert!(old.is_none());
    }

    pub fn associate(&mut self, conn_id: Cid, session_id: SessionId,
        timestamp: Instant, metadata: Arc<Json>)
    {
        let conn = if let Some(p) = self.pending_connections.remove(&conn_id) {
            p.associate(session_id.clone())
        } else {
            debug!("Connection {:?} does not exist any more", conn_id);
            return;
        };

        for top in &conn.topics {
            let ptr = self.topics
                .get_mut(top)
                .and_then(|m| m.get_mut(&conn_id))
                .expect("topics are consistent");
            *ptr = Subscription::Session;
        }

        let expire = timestamp + self.new_connection_timeout;
        if let Some(mut session) = self.inactive_sessions.remove(&session_id) {
            session.connections.insert(conn_id);
            session.metadata = metadata;
            let val = self.active_sessions.insert(session_id.clone(),
                timestamp, session);
            debug_assert!(val.is_none());
        } else if self.active_sessions.contains_key(&session_id) {
            self.active_sessions.update(&session_id, expire);
            let session = self.active_sessions.get_mut(&session_id).unwrap();
            session.connections.insert(conn_id);
            session.metadata = metadata;
        } else {
            let mut session = Session::new();
            session.connections.insert(conn_id);
            session.metadata = metadata;
            self.active_sessions.insert(session_id.clone(), expire, session);
        }

        let ins = self.connections.insert(conn_id, conn);
        debug_assert!(ins.is_none());
    }

    pub fn del_connection(&mut self, conn_id: Cid) {
        if let Some(conn) = self.pending_connections.remove(&conn_id) {
            for top in &conn.topics {
                unsubscribe(&mut self.topics, top, conn_id);
            }
            return;
        }
        let conn = self.connections.remove(&conn_id)
            .expect("valid connection");
        for topic in &conn.topics {
            unsubscribe(&mut self.topics, &topic, conn_id);
        }
        let session_id = conn.session_id;

        if self.inactive_sessions.contains_key(&session_id) {
            let conns = {
                let mut session = self.inactive_sessions.get_mut(&session_id)
                                  .unwrap();
                session.connections.remove(&conn_id);
                session.connections.len()
            };
            if conns == 0 {
                self.inactive_sessions.remove(&session_id);
            }
        } if let Some(mut session) = self.active_sessions.get_mut(&session_id)
        {
            session.connections.remove(&conn_id);
            // We delete it on inactivation
        }
    }

    pub fn update_activity(&mut self, conn_id: Cid, activity_ts: Instant)
    {
        let sess_id = if let Some(conn) = self.connections.get(&conn_id) {
            &conn.session_id
        } else {
            return;
        };
        if let Some(session) = self.inactive_sessions.remove(sess_id) {
            self.active_sessions.insert(sess_id.clone(), activity_ts, session);
        } else {
            self.active_sessions.update_if_smaller(sess_id, activity_ts)
        }
    }

    pub fn cleanup(&mut self, timestamp: Instant) -> Option<Instant> {
        while self.active_sessions.peek()
            .map(|(_, &x, _)| x < timestamp).unwrap_or(false)
        {
            let (sess_id, _, session) = self.active_sessions.pop().unwrap();
            self.channel.send(PoolMessage::InactiveSession {
                session_id: sess_id.clone(),
                connections_active: session.connections.len(),
                metadata: session.metadata.clone(),
            }).expect("can't send pool message");
            if session.connections.len() == 0 {
                // TODO(tailhook) Maybe do session cleanup ?
            } else {
                let val = self.inactive_sessions.insert(sess_id, session);
                debug_assert!(val.is_none());
            }
            // TODO(tailhook) send inactiity message to IO thread
        }
        self.active_sessions.peek().map(|(_, &x, _)| x)
    }

    pub fn subscribe(&mut self, cid: Cid, topic: Topic) {
        if let Some(conn) = self.connections.get_mut(&cid) {
            conn.topics.insert(topic.clone());
            self.topics.entry(topic).or_insert_with(HashMap::new)
                .insert(cid, Subscription::Session);
        } else if let Some(conn) = self.pending_connections.get_mut(&cid) {
            conn.topics.insert(topic.clone());
            self.topics.entry(topic).or_insert_with(HashMap::new)
                .insert(cid, Subscription::Pending);
        } else {
            debug!("Connection {:?} does not exist any more", cid);
        }
    }

    pub fn unsubscribe(&mut self, cid: Cid, topic: Topic) {
        match unsubscribe(&mut self.topics, &topic, cid) {
            Some(Subscription::Pending) => {
                self.pending_connections.get_mut(&cid)
                    .expect("pending conns and topics are in sync")
                    .topics.remove(&topic);
            }
            Some(Subscription::Session) => {
                self.connections.get_mut(&cid)
                    .expect("pending conns and topics are in sync")
                    .topics.remove(&topic);
            }
            None => {
                debug!("Connection {:?} does not exist any more", cid);
            }
        }
    }

    pub fn publish(&mut self, topic: Topic, data: Arc<Json>) {
        if let Some(cids) = self.topics.get(&topic) {
            for (cid, typ) in cids {
                match *typ {
                    Subscription::Pending => {
                        self.pending_connections.get_mut(cid)
                            .expect("subscriptions out of sync")
                            .message(topic.clone(), data.clone())
                    }
                    Subscription::Session => {
                        self.connections.get_mut(cid)
                            .expect("subscriptions out of sync")
                            .message(topic.clone(), data.clone())
                    }
                }
            }
        }
    }

    pub fn lattice_attach(&mut self, cid: Cid, namespace: Namespace) {
        let conn = if let Some(conn) = self.connections.get_mut(&cid) {
            conn
        } else {
            error!("Attach of {:?} for non-existing connection {:?}",
                   namespace, cid);
            return
        };
        conn.lattices.insert(namespace.clone());
        let lat = if let Some(lat) = self.lattices.get(&namespace) {
            lat
        } else {
            error!("No lattice {:?} at the time of attach (connection {:?})",
                   namespace, cid);
            return
        };
        let mut data = lat.private.get(&conn.session_id)
            .map(|x| x.clone())
            .unwrap_or_else(HashMap::new);
        for (key, values) in &mut data {
            lat.public.get(key).map(|pubval| {
                values.update(pubval);
            });
        }
        conn.lattice(&namespace, &Arc::new(data));
    }

    pub fn lattice_detach(&mut self, cid: Cid, namespace: Namespace) {
        unimplemented!();
    }

    pub fn lattice_update(&mut self,
        namespace: Namespace, delta: Delta)
    {
        let delta = {
            let lat = self.lattices.entry(namespace.clone())
                .or_insert_with(Lattice::new);

            // Update subscriptions on **original delta**
            for (session_id, rooms) in delta.private.iter() {
                for key in rooms.keys() {
                    lat.subscriptions.entry(key.clone())
                        .or_insert_with(HashSet::new)
                        .insert(session_id.clone());
                }
            }

            // Then make minimal delta
            lat.update(delta)
        };

        // Fighting with borrow checker
        let lat = self.lattices.get(&namespace).unwrap();

        // Send public-only changes
        let pubdata = Arc::new(delta.public);
        let mut already_sent = HashSet::new();
        for room in pubdata.keys() {
            if let Some(sessions) = lat.subscriptions.get(room) {
                for sid in sessions {
                    if !already_sent.contains(sid) &&
                       !delta.private.contains_key(sid)
                    {
                        // Can't easily abstract all this away because of borrow checker
                        let sess = if let Some(sess) = self.active_sessions.get(sid) {
                            sess
                        } else if let Some(sess) = self.inactive_sessions.get(sid) {
                            sess
                        } else {
                            continue;
                        };
                        if let Some(connections) = sess.lattices.get(&namespace) {
                            for cid in connections {
                                if let Some(conn) = self.connections.get_mut(cid) {
                                    conn.lattice(&namespace, &pubdata);
                                }
                            }
                        }
                        already_sent.insert(sid.clone());
                    }
                }
            }
        }

        // Send public *and* private
        for (session_id, mut rooms) in delta.private.into_iter() {
            for (room, values) in rooms.iter_mut() {
                pubdata.get(room).map(|pubval| {
                    values.update(pubval);
                });
            }
            // Can't easily abstract all this away because of borrow checker
            let sess = if let Some(sess) = self.active_sessions.get(&session_id) {
                sess
            } else if let Some(sess) = self.inactive_sessions.get(&session_id) {
                sess
            } else {
                continue;
            };
            if let Some(connections) = sess.lattices.get(&namespace) {
                let update = Arc::new(rooms);
                for cid in connections {
                    if let Some(conn) = self.connections.get_mut(cid) {
                        conn.lattice(&namespace, &update);
                    }
                }
            }
        }
    }
}

fn unsubscribe(topics: &mut HashMap<Topic, HashMap<Cid, Subscription>>,
    topic: &Topic, cid: Cid)
    -> Option<Subscription>
{
    let left = topics.get_mut(topic)
        .map(|set| {
            (set.remove(&cid), set.len())
        });
    left.and_then(|(sub, len)| {
        if len == 0 {
            topics.remove(topic);
        }
        return sub;
    })
}

#[cfg(test)]
mod test {
    use std::sync::Arc;
    use std::time::{Instant, Duration};
    use rustc_serialize::json::Json;
    use futures::Future;
    use futures::stream::Stream;
    use futures::sync::mpsc::{unbounded as channel};
    use futures::sync::mpsc::{UnboundedReceiver as Receiver};
    use intern::{SessionId, SessionPoolName};
    use config;
    use chat::Cid;

    use super::Pool;
    use super::super::{PoolMessage, ConnectionMessage};

    fn pool() -> (Pool, Receiver<PoolMessage>) {
        let (tx, rx) = channel();
        let pool = Pool::new(SessionPoolName::from("test_pool"),
            Arc::new(config::SessionPool {
                listen: config::ListenSocket::Tcp(
                    "127.0.0.1:65535".parse().unwrap()),
                inactivity_handlers: Vec::new(),
            }),
            tx);
        return (pool, rx);
    }

    fn add_u1(pool: &mut Pool) -> (Cid, Receiver<ConnectionMessage>) {
        let cid = Cid::new();
        let (tx, rx) = channel();
        pool.add_connection(cid, tx);
        pool.associate(cid, SessionId::from("user1"), Instant::now(),
            Arc::new(Json::Object(vec![
                ("user_id", "user1"),
            ].into_iter().map(|(x, y)| {
                (x.into(), Json::String(y.into()))
            }).collect())));
        return (cid, rx);
    }

    #[test]
    fn add_conn() {
        let (mut pool, _rx) = pool();
        add_u1(&mut pool);
    }

    fn first_item<S: Stream>(s: S) -> S::Item {
        s.into_future().wait().map(|(x, _)| x).map_err(|_|{})
            .expect("stream error")
            .expect("stream eof")
    }

    #[test]
    fn disconnect_after_inactive() {
        let (mut pool, rx) = pool();
        let (cid, _) = add_u1(&mut pool);
        assert_eq!(pool.active_sessions.len(), 1);
        assert_eq!(pool.inactive_sessions.len(), 0);
        pool.cleanup(Instant::now() + Duration::new(10, 0));
        // New connection timeout is expected to be ~ 60 seconds
        assert_eq!(pool.active_sessions.len(), 1);
        assert_eq!(pool.inactive_sessions.len(), 0);
        pool.cleanup(Instant::now() + Duration::new(120, 0));
        assert!(matches!(first_item(rx),
            PoolMessage::InactiveSession { ref session_id, ..}
            if *session_id == SessionId::from("user1")));
        assert_eq!(pool.active_sessions.len(), 0);
        assert_eq!(pool.inactive_sessions.len(), 1);
        pool.del_connection(cid);
        assert_eq!(pool.active_sessions.len(), 0);
        assert_eq!(pool.inactive_sessions.len(), 0);
    }

    #[test]
    fn disconnect_before_inactive() {
        let (mut pool, rx) = pool();
        let (cid, _) = add_u1(&mut pool);
        assert_eq!(pool.active_sessions.len(), 1);
        assert_eq!(pool.inactive_sessions.len(), 0);
        pool.cleanup(Instant::now() + Duration::new(10, 0));
        // New connection timeout is expected to be ~ 60 seconds
        assert_eq!(pool.active_sessions.len(), 1);
        assert_eq!(pool.inactive_sessions.len(), 0);
        pool.del_connection(cid);
        assert_eq!(pool.active_sessions.len(), 1);
        assert_eq!(pool.inactive_sessions.len(), 0);
        pool.cleanup(Instant::now() + Duration::new(120, 0));
        assert!(matches!(first_item(rx),
            PoolMessage::InactiveSession { ref session_id, ..}
            if *session_id == SessionId::from("user1")));
        assert_eq!(pool.active_sessions.len(), 0);
        assert_eq!(pool.inactive_sessions.len(), 0);
    }
}
<|endoftext|>


<commit_before>use std::error;
use clap;

use config;

use super::params::ParamsExecuter;

use std::process::Command;

type Program<'a> = &'a str;
type Arguments<'a> = Vec<&'a str>;

pub struct ParamsExecCommand<'c> {
    config: &'c config::command::Config,
    program: Program<'c>,
    args: Arguments<'c>,
}

impl<'c> ParamsExecCommand<'c> {
    pub fn from_args(
        config: &'c config::command::Config,
        clap_args: &'c clap::ArgMatches<'c>,
    ) -> Self {
        debug!("ParamsExecCommand::from_args");

        let program = clap_args.value_of("PROGRAM").unwrap();
        let args = match clap_args.values_of("ARGS") {
            Some(args) => args.collect(),
            None => Vec::new(),
        };

        ParamsExecCommand {
            config: config,
            program: program,
            args: args,
        }
    }

    pub fn new(
        config: &'c config::command::Config,
        program: &'c Program<'c>,
        args: &'c Arguments<'c>,
    ) -> Self {
        debug!("ParamsExecCommand::new");

        ParamsExecCommand {
            config: config,
            program: program,
            args: args.to_owned(),
        }
    }

    pub fn run(&self) -> Result<(), Box<error::Error>> {
        debug!("ParamsExecCommand::run");
        if let Some(params_config) = self.config.params.as_ref() {
            let exec = ParamsExecExecuter::from_config(params_config);
            try!(exec.run(&self.program, &self.args));
        }
        Ok(())
    }
}

pub struct ParamsExecExecuter<'c> {
    config: &'c config::command::ParamsConfig,
}

impl<'c> ParamsExecExecuter<'c> {
    pub fn from_config(config: &'c config::command::ParamsConfig) -> Self {
        debug!("ParamsGetExecuter::new");

        ParamsExecExecuter { config: config }
    }

    pub fn run(
        &self,
        program: &'c Program<'c>,
        args: &'c Arguments<'c>,
    ) -> Result<(), Box<error::Error>> {
        debug!("ParamsExecExecuter::run");

        info!("exec: {} {}", program, args.join(" "));
        let maybe_params = try!(self.params());
        let mut cmd = Command::new(program);

        cmd.args(args);

        if let Some(params) = maybe_params {
            for param in params.iter() {
                if let (Some(name_with_path), Some(value)) =
                    (param.name.as_ref(), param.value.as_ref())
                {
                    if let Ok(name) = self.strip_path(name_with_path) {
                        cmd.env(name, value);
                    }
                }
            }
        }

        let _result = cmd.spawn();

        Ok(())
    }
}

impl<'c> ParamsExecuter for ParamsExecExecuter<'c> {
    fn config(&self) -> &config::command::ParamsConfig { &self.config }
}
<commit_msg>wait commands to exit<commit_after>use std::error;
use clap;

use config;

use super::params::ParamsExecuter;

use std::process::Command;

type Program<'a> = &'a str;
type Arguments<'a> = Vec<&'a str>;

pub struct ParamsExecCommand<'c> {
    config: &'c config::command::Config,
    program: Program<'c>,
    args: Arguments<'c>,
}

impl<'c> ParamsExecCommand<'c> {
    pub fn from_args(
        config: &'c config::command::Config,
        clap_args: &'c clap::ArgMatches<'c>,
    ) -> Self {
        debug!("ParamsExecCommand::from_args");

        let program = clap_args.value_of("PROGRAM").unwrap();
        let args = match clap_args.values_of("ARGS") {
            Some(args) => args.collect(),
            None => Vec::new(),
        };

        ParamsExecCommand {
            config: config,
            program: program,
            args: args,
        }
    }

    pub fn new(
        config: &'c config::command::Config,
        program: &'c Program<'c>,
        args: &'c Arguments<'c>,
    ) -> Self {
        debug!("ParamsExecCommand::new");

        ParamsExecCommand {
            config: config,
            program: program,
            args: args.to_owned(),
        }
    }

    pub fn run(&self) -> Result<(), Box<error::Error>> {
        debug!("ParamsExecCommand::run");
        if let Some(params_config) = self.config.params.as_ref() {
            let exec = ParamsExecExecuter::from_config(params_config);
            try!(exec.run(&self.program, &self.args));
        }
        Ok(())
    }
}

pub struct ParamsExecExecuter<'c> {
    config: &'c config::command::ParamsConfig,
}

impl<'c> ParamsExecExecuter<'c> {
    pub fn from_config(config: &'c config::command::ParamsConfig) -> Self {
        debug!("ParamsGetExecuter::new");

        ParamsExecExecuter { config: config }
    }

    pub fn run(
        &self,
        program: &'c Program<'c>,
        args: &'c Arguments<'c>,
    ) -> Result<(), Box<error::Error>> {
        debug!("ParamsExecExecuter::run");

        info!("exec: {} {}", program, args.join(" "));
        let maybe_params = try!(self.params());
        let mut cmd = Command::new(program);

        cmd.args(args);

        if let Some(params) = maybe_params {
            for param in params.iter() {
                if let (Some(name_with_path), Some(value)) =
                    (param.name.as_ref(), param.value.as_ref())
                {
                    if let Ok(name) = self.strip_path(name_with_path) {
                        cmd.env(name, value);
                    }
                }
            }
        }

        let mut child = try!(cmd.spawn());
        let _output = try!(child.wait());

        Ok(())
    }
}

impl<'c> ParamsExecuter for ParamsExecExecuter<'c> {
    fn config(&self) -> &config::command::ParamsConfig { &self.config }
}
<|endoftext|>


<commit_before>
import front::ast;
import front::codemap;
import util::common::span;
import util::common::ty_mach;
import std::uint;
import std::term;
import std::io;
import std::map;
import std::option;
import std::option::some;
import std::option::none;

tag os { os_win32; os_macos; os_linux; }

tag arch { arch_x86; arch_x64; arch_arm; }

type config =
    rec(os os,
        arch arch,
        ty_mach int_type,
        ty_mach uint_type,
        ty_mach float_type);

type options =
    rec(bool shared,
        uint optimize,
        bool debuginfo,
        bool verify,
        bool run_typestate,
        bool save_temps,
        bool stats,
        bool time_passes,
        bool time_llvm_passes,
        back::link::output_type output_type,
        vec[str] library_search_paths,
        str sysroot);

type crate_metadata = rec(str name, vec[u8] data);

fn span_to_str(span sp, codemap::codemap cm) -> str {
    auto lo = codemap::lookup_pos(cm, sp.lo);
    auto hi = codemap::lookup_pos(cm, sp.hi);
    ret #fmt("%s:%u:%u:%u:%u", lo.filename, lo.line, lo.col, hi.line, hi.col);
}

fn emit_diagnostic(option::t[span] sp, str msg, str kind, u8 color,
                   codemap::codemap cm) {
    auto ss = "<input>:0:0:0:0";
    alt (sp) {
        case (some(?ssp)) { ss = span_to_str(ssp, cm); }
        case (none) { }
    }
    io::stdout().write_str(ss + ": ");
    if (term::color_supported()) {
        term::fg(io::stdout().get_buf_writer(), color);
    }
    io::stdout().write_str(#fmt("%s:", kind));
    if (term::color_supported()) {
        term::reset(io::stdout().get_buf_writer());
    }
    io::stdout().write_str(#fmt(" %s\n", msg));
}

obj session(ast::crate_num cnum,
            @config targ_cfg,
            @options opts,
            map::hashmap[int, crate_metadata] crates,
            mutable vec[str] used_libraries,
            codemap::codemap cm,
            mutable uint err_count) {
    fn get_targ_cfg() -> @config { ret targ_cfg; }
    fn get_opts() -> @options { ret opts; }
    fn get_targ_crate_num() -> ast::crate_num { ret cnum; }
    fn span_fatal(span sp, str msg) -> ! {
        // FIXME: Use constants, but rustboot doesn't know how to export them.

        emit_diagnostic(some(sp), msg, "error", 9u8, cm);
        fail;
    }
    fn fatal(str msg) -> ! {
        emit_diagnostic(none[span], msg, "error", 9u8, cm);
        fail;
    }
    fn span_err(span sp, str msg) {
        emit_diagnostic(some(sp), msg, "error", 9u8, cm);
        err_count += 1u;
    }
    fn err(span sp, str msg) {
        emit_diagnostic(some(sp), msg, "error", 9u8, cm);
        err_count += 1u;
    }
    fn abort_if_errors() {
        if (err_count > 0u) {
            self.fatal("aborting due to previous errors");
        }
    }
    fn span_warn(span sp, str msg) {
        // FIXME: Use constants, but rustboot doesn't know how to export them.

        emit_diagnostic(some(sp), msg, "warning", 11u8, cm);
    }
    fn warn(str msg) {
        emit_diagnostic(none[span], msg, "warning", 11u8, cm);
    }
    fn span_note(span sp, str msg) {
        // FIXME: Use constants, but rustboot doesn't know how to export them.

        emit_diagnostic(some(sp), msg, "note", 10u8, cm);
    }
    fn span_bug(span sp, str msg) -> ! {
        self.span_fatal(sp, #fmt("internal compiler error %s", msg));
    }
    fn bug(str msg) -> ! {
        self.fatal(#fmt("internal compiler error %s", msg));
    }
    fn span_unimpl(span sp, str msg) -> ! {
        self.span_bug(sp, "unimplemented " + msg);
    }
    fn unimpl(str msg) -> ! { self.bug("unimplemented " + msg); }
    fn get_external_crate(int num) -> crate_metadata { ret crates.get(num); }
    fn set_external_crate(int num, &crate_metadata metadata) {
        crates.insert(num, metadata);
    }
    fn has_external_crate(int num) -> bool { ret crates.contains_key(num); }
    fn add_used_library(&str lib) {
        // A program has a small number of libraries, so a vector is probably a
        // good data structure in here.
        for (str l in used_libraries) {
            if (l == lib) {
                ret;
            }
        }
        used_libraries += [lib];
    }
    fn get_used_libraries() -> vec[str] {
       ret used_libraries;
    }
    fn get_codemap() -> codemap::codemap { ret cm; }
    fn lookup_pos(uint pos) -> codemap::loc {
        ret codemap::lookup_pos(cm, pos);
    }
    fn span_str(span sp) -> str { ret span_to_str(sp, self.get_codemap()); }
}
// Local Variables:
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Fix line length.<commit_after>
import front::ast;
import front::codemap;
import util::common::span;
import util::common::ty_mach;
import std::uint;
import std::term;
import std::io;
import std::map;
import std::option;
import std::option::some;
import std::option::none;

tag os { os_win32; os_macos; os_linux; }

tag arch { arch_x86; arch_x64; arch_arm; }

type config =
    rec(os os,
        arch arch,
        ty_mach int_type,
        ty_mach uint_type,
        ty_mach float_type);

type options =
    rec(bool shared,
        uint optimize,
        bool debuginfo,
        bool verify,
        bool run_typestate,
        bool save_temps,
        bool stats,
        bool time_passes,
        bool time_llvm_passes,
        back::link::output_type output_type,
        vec[str] library_search_paths,
        str sysroot);

type crate_metadata = rec(str name, vec[u8] data);

fn span_to_str(span sp, codemap::codemap cm) -> str {
    auto lo = codemap::lookup_pos(cm, sp.lo);
    auto hi = codemap::lookup_pos(cm, sp.hi);
    ret #fmt("%s:%u:%u:%u:%u", lo.filename, lo.line, lo.col, hi.line, hi.col);
}

fn emit_diagnostic(option::t[span] sp, str msg, str kind, u8 color,
                   codemap::codemap cm) {
    auto ss = "<input>:0:0:0:0";
    alt (sp) {
        case (some(?ssp)) { ss = span_to_str(ssp, cm); }
        case (none) { }
    }
    io::stdout().write_str(ss + ": ");
    if (term::color_supported()) {
        term::fg(io::stdout().get_buf_writer(), color);
    }
    io::stdout().write_str(#fmt("%s:", kind));
    if (term::color_supported()) {
        term::reset(io::stdout().get_buf_writer());
    }
    io::stdout().write_str(#fmt(" %s\n", msg));
}

obj session(ast::crate_num cnum,
            @config targ_cfg,
            @options opts,
            map::hashmap[int, crate_metadata] crates,
            mutable vec[str] used_libraries,
            codemap::codemap cm,
            mutable uint err_count) {
    fn get_targ_cfg() -> @config { ret targ_cfg; }
    fn get_opts() -> @options { ret opts; }
    fn get_targ_crate_num() -> ast::crate_num { ret cnum; }
    fn span_fatal(span sp, str msg) -> ! {
        // FIXME: Use constants, but rustboot doesn't know how to export them.

        emit_diagnostic(some(sp), msg, "error", 9u8, cm);
        fail;
    }
    fn fatal(str msg) -> ! {
        emit_diagnostic(none[span], msg, "error", 9u8, cm);
        fail;
    }
    fn span_err(span sp, str msg) {
        emit_diagnostic(some(sp), msg, "error", 9u8, cm);
        err_count += 1u;
    }
    fn err(span sp, str msg) {
        emit_diagnostic(some(sp), msg, "error", 9u8, cm);
        err_count += 1u;
    }
    fn abort_if_errors() {
        if (err_count > 0u) {
            self.fatal("aborting due to previous errors");
        }
    }
    fn span_warn(span sp, str msg) {
        // FIXME: Use constants, but rustboot doesn't know how to export them.

        emit_diagnostic(some(sp), msg, "warning", 11u8, cm);
    }
    fn warn(str msg) {
        emit_diagnostic(none[span], msg, "warning", 11u8, cm);
    }
    fn span_note(span sp, str msg) {
        // FIXME: Use constants, but rustboot doesn't know how to export them.

        emit_diagnostic(some(sp), msg, "note", 10u8, cm);
    }
    fn span_bug(span sp, str msg) -> ! {
        self.span_fatal(sp, #fmt("internal compiler error %s", msg));
    }
    fn bug(str msg) -> ! {
        self.fatal(#fmt("internal compiler error %s", msg));
    }
    fn span_unimpl(span sp, str msg) -> ! {
        self.span_bug(sp, "unimplemented " + msg);
    }
    fn unimpl(str msg) -> ! { self.bug("unimplemented " + msg); }
    fn get_external_crate(int num) -> crate_metadata { ret crates.get(num); }
    fn set_external_crate(int num, &crate_metadata metadata) {
        crates.insert(num, metadata);
    }
    fn has_external_crate(int num) -> bool { ret crates.contains_key(num); }
    fn add_used_library(&str lib) {
        // A program has a small number of libraries, so a vector is probably
        // a good data structure in here.
        for (str l in used_libraries) {
            if (l == lib) {
                ret;
            }
        }
        used_libraries += [lib];
    }
    fn get_used_libraries() -> vec[str] {
       ret used_libraries;
    }
    fn get_codemap() -> codemap::codemap { ret cm; }
    fn lookup_pos(uint pos) -> codemap::loc {
        ret codemap::lookup_pos(cm, pos);
    }
    fn span_str(span sp) -> str { ret span_to_str(sp, self.get_codemap()); }
}
// Local Variables:
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>use system::*;

pub struct TileMap
{
    pub tiles: Vec<TileData>,
}

impl TileMap {
     pub fn new() -> TileMap
     {
         return TileMap
         {
             tiles: vec![TileData::new();256],
         }
     }

     pub fn populate_tile_map(&mut self, lcdc_data_select: u8){
         ;
     }
}

#[derive(Clone)]
pub struct TileData
{
    pub data: Vec<u8>,
}

impl TileData
{
    pub fn new() -> TileData
    {
        return TileData
        {
            data: vec![0; 64],
        }
    }
}

pub fn get_tile_data(tile_index: u8, system_data: &mut SystemData, lcdc_data_select: u8) -> TileData
{
    let mut tile_data = TileData::new();
    let mut vram_offset: u16 = 0;

    if lcdc_data_select == 1
    {
        vram_offset = 0x8000;
    }
    else {
        vram_offset = 0x8800
    }

    let mem_loc: u16 = vram_offset + (tile_index as u16 * 16);
    for byte_pair in 0..8
    {
        for bit in 0..8
        {
            let upper_bit: u8 = (system_data.mem_map[(mem_loc + (2 * byte_pair as u16)) as usize] >> (7 - bit)) & 0x01;
            let lower_bit: u8 = (system_data.mem_map[(mem_loc + (2 * byte_pair as u16)) as usize + 1] >> (7 - bit)) & 0x01;
            tile_data.data[(byte_pair as usize * 8) + bit as usize] = (upper_bit << 1) | lower_bit;
        }
    }
    return tile_data;
}

pub fn update_gpu(system_data_original: &mut SystemData, registers_original: &mut Registers, gpu_registers_original: &mut GPU_Registers)
{
    let mut system_data = system_data_original;
    let mut registers = registers_original;
    let mut gpu_registers = gpu_registers_original;
    LCD_Y_Coordinate_Update(&mut system_data, &mut gpu_registers);
}

pub fn LCD_Y_Coordinate_Update(system_data: &mut SystemData, gpu_registers: &mut GPU_Registers)
{
    gpu_registers.ly_cycle_count += system_data.cycles as u32;
    gpu_registers.ly_sub_cycle_count += system_data.cycles as u16;
    if (gpu_registers.ly_cycle_count >= 70224)
    {
        gpu_registers.ly_cycle_count -= 70224;
    }
    if (gpu_registers.ly_sub_cycle_count >= 456)
    {
        gpu_registers.ly_register += 1;
        if gpu_registers.ly_register == 154
        {
            gpu_registers.ly_register = 0;
        }
        system_data.mem_map[0xFF44] = gpu_registers.ly_register;
        gpu_registers.ly_sub_cycle_count -= 456;
    }
}

#[cfg(test)]
mod gpu_tests
{
    use system::get_system_data;
    use gpu::gpu::*;

    #[test]
    fn get_tile_data_test() {
        let mut system_data : SystemData = get_system_data(&String::from("CLASSIC"));

        system_data.mem_map[0x8000] = 0b00001111;
        system_data.mem_map[0x8001] = 0b00110011;
        system_data.mem_map[0x8002] = 0b11110000;
        system_data.mem_map[0x8003] = 0b11001100;

        system_data.mem_map[0x8800] = 0b00001111;
        system_data.mem_map[0x8801] = 0b00110011;
        system_data.mem_map[0x8802] = 0b11110000;
        system_data.mem_map[0x8803] = 0b11001100;

        let tile_data = get_tile_data(0, &mut system_data, 0);
        for i in 0..4
        {
            assert_eq!(tile_data.data[i as usize * 2], i);
            assert_eq!(tile_data.data[(i as usize * 2) + 1 ], i);
        }
        for i in 0..4
        {
            assert_eq!(tile_data.data[8 + (i as usize * 2)], 3 - i);
            assert_eq!(tile_data.data[(8 + (i as usize * 2)) + 1], 3 - i);
        }

        let tile_data = get_tile_data(0, &mut system_data, 1);
        for i in 0..4
        {
            assert_eq!(tile_data.data[i as usize * 2], i);
            assert_eq!(tile_data.data[(i as usize * 2) + 1 ], i);
        }
        for i in 0..4
        {
            assert_eq!(tile_data.data[8 + (i as usize * 2)], 3 - i);
            assert_eq!(tile_data.data[(8 + (i as usize * 2)) + 1], 3 - i);
        }
    }

}
<commit_msg>Simplified tile data test<commit_after>use system::*;

pub struct TileMap
{
    pub tiles: Vec<TileData>,
}

impl TileMap {
     pub fn new() -> TileMap
     {
         return TileMap
         {
             tiles: vec![TileData::new();256],
         }
     }

     pub fn populate_tile_map(&mut self, lcdc_data_select: u8){
         ;
     }
}

#[derive(Clone)]
pub struct TileData
{
    pub data: Vec<u8>,
}

impl TileData
{
    pub fn new() -> TileData
    {
        return TileData
        {
            data: vec![0; 64],
        }
    }
}

pub fn get_tile_data(tile_index: u8, system_data: &mut SystemData, lcdc_data_select: u8) -> TileData
{
    let mut tile_data = TileData::new();
    let mut vram_offset: u16 = 0;

    if lcdc_data_select == 1
    {
        vram_offset = 0x8000;
    }
    else {
        vram_offset = 0x8800
    }

    let mem_loc: u16 = vram_offset + (tile_index as u16 * 16);
    for byte_pair in 0..8
    {
        for bit in 0..8
        {
            let upper_bit: u8 = (system_data.mem_map[(mem_loc + (2 * byte_pair as u16)) as usize] >> (7 - bit)) & 0x01;
            let lower_bit: u8 = (system_data.mem_map[(mem_loc + (2 * byte_pair as u16)) as usize + 1] >> (7 - bit)) & 0x01;
            tile_data.data[(byte_pair as usize * 8) + bit as usize] = (upper_bit << 1) | lower_bit;
        }
    }
    return tile_data;
}

pub fn update_gpu(system_data_original: &mut SystemData, registers_original: &mut Registers, gpu_registers_original: &mut GPU_Registers)
{
    let mut system_data = system_data_original;
    let mut registers = registers_original;
    let mut gpu_registers = gpu_registers_original;
    LCD_Y_Coordinate_Update(&mut system_data, &mut gpu_registers);
}

pub fn LCD_Y_Coordinate_Update(system_data: &mut SystemData, gpu_registers: &mut GPU_Registers)
{
    gpu_registers.ly_cycle_count += system_data.cycles as u32;
    gpu_registers.ly_sub_cycle_count += system_data.cycles as u16;
    if (gpu_registers.ly_cycle_count >= 70224)
    {
        gpu_registers.ly_cycle_count -= 70224;
    }
    if (gpu_registers.ly_sub_cycle_count >= 456)
    {
        gpu_registers.ly_register += 1;
        if gpu_registers.ly_register == 154
        {
            gpu_registers.ly_register = 0;
        }
        system_data.mem_map[0xFF44] = gpu_registers.ly_register;
        gpu_registers.ly_sub_cycle_count -= 456;
    }
}

#[cfg(test)]
mod gpu_tests
{
    use system::get_system_data;
    use gpu::gpu::*;

    #[test]
    fn get_tile_data_test() {
        let mut system_data : SystemData = get_system_data(&String::from("CLASSIC"));

        let temp_memory_values : Vec<u8> = vec![0b00001111, 0b00110011, 0b11110000, 0b11001100];

        for vram_offset in vec![0x8000, 0x8800].iter()
        {
            for i in 0..temp_memory_values.len()
            {
                system_data.mem_map[*vram_offset + i] = temp_memory_values[i];
            }
        }

        let tiles = vec![get_tile_data(0, &mut system_data, 0), get_tile_data(0, &mut system_data, 1)];
        for tile in tiles.iter()
        {
            for i in 0..4
            {
                assert_eq!(tile.data[i as usize * 2], i);
                assert_eq!(tile.data[(i as usize * 2) + 1 ], i);
                assert_eq!(tile.data[8 + (i as usize * 2)], 3 - i);
                assert_eq!(tile.data[(8 + (i as usize * 2)) + 1], 3 - i);
            }
        }
    }

}
<|endoftext|>


<commit_before>use super::prelude::*;

use crate::controllers::helpers::pagination::PaginationOptions;
use crate::controllers::helpers::{pagination::Paginated, Paginate};
use crate::models::Keyword;
use crate::views::EncodableKeyword;

/// Handles the `GET /keywords` route.
pub fn index(req: &mut dyn RequestExt) -> EndpointResult {
    use crate::schema::keywords;

    let query = req.query();
    let sort = query.get("sort").map(|s| &s[..]).unwrap_or("alpha");

    let mut query = keywords::table.into_boxed();

    if sort == "crates" {
        query = query.order(keywords::crates_cnt.desc());
    } else {
        query = query.order(keywords::keyword.asc());
    }

    let query = query.pages_pagination(PaginationOptions::builder().gather(req)?);
    let conn = req.db_read_only()?;
    let data: Paginated<Keyword> = query.load(&*conn)?;
    let total = data.total();
    let kws = data.into_iter().map(Keyword::into).collect::<Vec<_>>();

    #[derive(Serialize)]
    struct R {
        keywords: Vec<EncodableKeyword>,
        meta: Meta,
    }
    #[derive(Serialize)]
    struct Meta {
        total: Option<i64>,
    }

    Ok(req.json(&R {
        keywords: kws,
        meta: Meta { total: Some(total) },
    }))
}

/// Handles the `GET /keywords/:keyword_id` route.
pub fn show(req: &mut dyn RequestExt) -> EndpointResult {
    let name = &req.params()["keyword_id"];
    let conn = req.db_read_only()?;

    let kw = Keyword::find_by_keyword(&conn, name)?;

    #[derive(Serialize)]
    struct R {
        keyword: EncodableKeyword,
    }
    Ok(req.json(&R { keyword: kw.into() }))
}
<commit_msg>controllers::keyword: Use `json!` macro to simplify JSON serialization code<commit_after>use super::prelude::*;

use crate::controllers::helpers::pagination::PaginationOptions;
use crate::controllers::helpers::{pagination::Paginated, Paginate};
use crate::models::Keyword;
use crate::views::EncodableKeyword;

/// Handles the `GET /keywords` route.
pub fn index(req: &mut dyn RequestExt) -> EndpointResult {
    use crate::schema::keywords;

    let query = req.query();
    let sort = query.get("sort").map(|s| &s[..]).unwrap_or("alpha");

    let mut query = keywords::table.into_boxed();

    if sort == "crates" {
        query = query.order(keywords::crates_cnt.desc());
    } else {
        query = query.order(keywords::keyword.asc());
    }

    let query = query.pages_pagination(PaginationOptions::builder().gather(req)?);
    let conn = req.db_read_only()?;
    let data: Paginated<Keyword> = query.load(&*conn)?;
    let total = data.total();
    let kws = data
        .into_iter()
        .map(Keyword::into)
        .collect::<Vec<EncodableKeyword>>();

    Ok(req.json(&json!({
        "keywords": kws,
        "meta": { "total": total },
    })))
}

/// Handles the `GET /keywords/:keyword_id` route.
pub fn show(req: &mut dyn RequestExt) -> EndpointResult {
    let name = &req.params()["keyword_id"];
    let conn = req.db_read_only()?;

    let kw = Keyword::find_by_keyword(&conn, name)?;

    Ok(req.json(&json!({ "keyword": EncodableKeyword::from(kw) })))
}
<|endoftext|>


<commit_before>// Copyright 2021 Developers of the Rand project.

use crate::distributions::{Distribution, Uniform};

/// A distribution to sample items uniformly from a slice.
///
/// [`Slice::new`] constructs a distribution referencing a slice and uniformly
/// samples references from the items in the slice. It may do extra work up
/// front to make sampling of multiple values faster; if only one sample from
/// the slice is required, [`SliceRandom::choose`] can be more efficient.
///
/// Steps are taken to avoid bias which might be present in naive
/// implementations; for example `slice[rng.gen() % slice.len()]` samples from
/// the slice, but may be more likely to select numbers in the low range than
/// other values.
///
/// This distribution samples with replacement; each sample is independent.
/// Sampling without replacement requires state to be retained, and therefore
/// cannot be handled by a distribution; you should instead consider methods
/// on [`SliceRandom`], such as [`SliceRandom::choose_multiple`].
///
/// # Example
///
/// ```
/// use rand::Rng;
/// use rand::distributions::Slice;
///
/// let vowels = ['a', 'e', 'i', 'o', 'u'];
/// let vowels_dist = Slice::new(&vowels).unwrap();
/// let rng = rand::thread_rng();
///
/// // build a string of 10 vowels
/// let vowel_string: String = rng
///     .sample_iter(&vowels_dist)
///     .take(10)
///     .collect();
///
/// println!("{}", vowel_string);
/// assert_eq!(vowel_string.len(), 10);
/// assert!(vowel_string.chars().all(|c| vowels.contains(&c)));
/// ```
///
/// For a single sample, [`SliceRandom::choose`][crate::seq::SliceRandom::choose]
/// may be preferred:
///
/// ```
/// use rand::seq::SliceRandom;
///
/// let vowels = ['a', 'e', 'i', 'o', 'u'];
/// let mut rng = rand::thread_rng();
///
/// println!("{}", vowels.choose(&mut rng).unwrap())
/// ```
///
/// [`SliceRandom`]: crate::seq::SliceRandom
/// [`SliceRandom::choose`]: crate::seq::SliceRandom::choose
/// [`SliceRandom::choose_multiple`]: crate::seq::SliceRandom::choose_multiple
#[derive(Debug)]
pub struct Slice<'a, T> {
    slice: &'a [T],
    range: Uniform<usize>,
}

impl<'a, T> Slice<'a, T> {
    /// Create a new `Slice` instance which samples uniformly from the slice.
    /// Returns `None` if the slice is empty.
    pub fn new(slice: &'a [T]) -> Option<Self> {
        match slice.len() {
            0 => None,
            len => Some(Self {
                slice,
                range: Uniform::new(0, len),
            }),
        }
    }
}

impl<T> Clone for Slice<'_, T> {
    fn clone(&self) -> Self {
        *self
    }
}

impl<T> Copy for Slice<'_, T> {}

impl<'a, T> Distribution<&'a T> for Slice<'a, T> {
    fn sample<R: crate::Rng + ?Sized>(&self, rng: &mut R) -> &'a T {
        let idx = self.range.sample(rng);

        // Safety: at construction time, it was ensured that the slice was
        // non-empty, and that the `Uniform` range produces values in range
        // for the slice
        unsafe { self.slice.get_unchecked(idx) }
    }
}
<commit_msg>Code review updates<commit_after>// Copyright 2021 Developers of the Rand project.

use crate::distributions::{Distribution, Uniform};

/// A distribution to sample items uniformly from a slice.
///
/// [`Slice::new`] constructs a distribution referencing a slice and uniformly
/// samples references from the items in the slice. It may do extra work up
/// front to make sampling of multiple values faster; if only one sample from
/// the slice is required, [`SliceRandom::choose`] can be more efficient.
///
/// Steps are taken to avoid bias which might be present in naive
/// implementations; for example `slice[rng.gen() % slice.len()]` samples from
/// the slice, but may be more likely to select numbers in the low range than
/// other values.
///
/// This distribution samples with replacement; each sample is independent.
/// Sampling without replacement requires state to be retained, and therefore
/// cannot be handled by a distribution; you should instead consider methods
/// on [`SliceRandom`], such as [`SliceRandom::choose_multiple`].
///
/// # Example
///
/// ```
/// use rand::Rng;
/// use rand::distributions::Slice;
///
/// let vowels = ['a', 'e', 'i', 'o', 'u'];
/// let vowels_dist = Slice::new(&vowels).unwrap();
/// let rng = rand::thread_rng();
///
/// // build a string of 10 vowels
/// let vowel_string: String = rng
///     .sample_iter(&vowels_dist)
///     .take(10)
///     .collect();
///
/// println!("{}", vowel_string);
/// assert_eq!(vowel_string.len(), 10);
/// assert!(vowel_string.chars().all(|c| vowels.contains(&c)));
/// ```
///
/// For a single sample, [`SliceRandom::choose`][crate::seq::SliceRandom::choose]
/// may be preferred:
///
/// ```
/// use rand::seq::SliceRandom;
///
/// let vowels = ['a', 'e', 'i', 'o', 'u'];
/// let mut rng = rand::thread_rng();
///
/// println!("{}", vowels.choose(&mut rng).unwrap())
/// ```
///
/// [`SliceRandom`]: crate::seq::SliceRandom
/// [`SliceRandom::choose`]: crate::seq::SliceRandom::choose
/// [`SliceRandom::choose_multiple`]: crate::seq::SliceRandom::choose_multiple
#[derive(Debug)]
pub struct Slice<'a, T> {
    slice: &'a [T],
    range: Uniform<usize>,
}

impl<'a, T> Slice<'a, T> {
    /// Create a new `Slice` instance which samples uniformly from the slice.
    /// Returns `None` if the slice is empty.
    pub fn new(slice: &'a [T]) -> Result<Self, EmptySlice> {
        match slice.len() {
            0 => Err(EmptySlice),
            len => Ok(Self {
                slice,
                range: Uniform::new(0, len),
            }),
        }
    }
}

impl<T> Clone for Slice<'_, T> {
    fn clone(&self) -> Self {
        *self
    }
}

impl<T> Copy for Slice<'_, T> {}

impl<'a, T> Distribution<&'a T> for Slice<'a, T> {
    fn sample<R: crate::Rng + ?Sized>(&self, rng: &mut R) -> &'a T {
        let idx = self.range.sample(rng);

        debug_assert!(
            idx < self.slice.len(),
            "Uniform::new(0, {}) somehow returned {}",
            self.slice.len(),
            idx
        );

        // Safety: at construction time, it was ensured that the slice was
        // non-empty, and that the `Uniform` range produces values in range
        // for the slice
        unsafe { self.slice.get_unchecked(idx) }
    }
}

/// Error type indicating that a [`Slice`] distribution was improperly
/// constructed with an empty slice.
#[derive(Debug, Clone, Copy)]
pub struct EmptySlice;

impl core::fmt::Display for EmptySlice {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        write!(
            f,
            "Tried to create a `distributions::Slice` with an empty slice"
        )
    }
}

#[cfg(feature = "std")]
impl std::error::Error for EmptySlice {}
<|endoftext|>