<commit_before>use self::block_producer_service::{BeaconBlockGrpcClient, BlockProducerService};
use self::duties::{DutiesManager, DutiesManagerService, EpochDutiesMap};
use crate::config::ClientConfig;
use block_proposer::{test_utils::LocalSigner, BlockProducer};
use bls::Keypair;
use clap::{App, Arg};
use grpcio::{ChannelBuilder, EnvBuilder};
use protos::services_grpc::{BeaconBlockServiceClient, ValidatorServiceClient};
use slog::{error, info, o, Drain};
use slot_clock::SystemTimeSlotClock;
use std::path::PathBuf;
use std::sync::Arc;
use std::thread;
use types::ChainSpec;

mod block_producer_service;
mod config;
mod duties;

fn main() {
    // Logging
    let decorator = slog_term::TermDecorator::new().build();
    let drain = slog_term::CompactFormat::new(decorator).build().fuse();
    let drain = slog_async::Async::new(drain).build().fuse();
    let log = slog::Logger::root(drain, o!());

    // CLI
    let matches = App::new("Lighthouse Validator Client")
        .version("0.0.1")
        .author("Sigma Prime <contact@sigmaprime.io>")
        .about("Eth 2.0 Validator Client")
        .arg(
            Arg::with_name("datadir")
                .long("datadir")
                .value_name("DIR")
                .help("Data directory for keys and databases.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("server")
                .long("server")
                .value_name("server")
                .help("Address to connect to BeaconNode.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("spec")
                .long("spec")
                .value_name("spec")
                .short("s")
                .help("Configuration of Beacon Chain")
                .takes_value(true)
                .possible_values(&["foundation", "few_validators"]),
        )
        .get_matches();

    let mut config = ClientConfig::default();

    // Custom datadir
    if let Some(dir) = matches.value_of("datadir") {
        config.data_dir = PathBuf::from(dir.to_string());
    }

    // Custom server port
    if let Some(server_str) = matches.value_of("server") {
        if let Ok(addr) = server_str.parse::<u16>() {
            config.server = addr.to_string();
        } else {
            error!(log, "Invalid address"; "server" => server_str);
            return;
        }
    }

    // TODO: Permit loading a custom spec from file.
    // Custom spec
    if let Some(spec_str) = matches.value_of("spec") {
        match spec_str {
            "foundation" => config.spec = ChainSpec::foundation(),
            "few_validators" => config.spec = ChainSpec::few_validators(),
            // Should be impossible
            _ => error!(log, "Invalid spec defined"; "spec" => format!("{:?}", config.spec)),
        };
    }

    // Log configuration
    info!(log, "";
          "data_dir" => &config.data_dir.to_str(),
          "server" => &config.server);

    // Beacon node gRPC beacon block endpoints.
    let beacon_block_grpc_client = {
        let env = Arc::new(EnvBuilder::new().build());
        let ch = ChannelBuilder::new(env).connect(&config.server);
        Arc::new(BeaconBlockServiceClient::new(ch))
    };

    // Beacon node gRPC validator endpoints.
    let validator_grpc_client = {
        let env = Arc::new(EnvBuilder::new().build());
        let ch = ChannelBuilder::new(env).connect(&config.server);
        Arc::new(ValidatorServiceClient::new(ch))
    };

    // Spec
    let spec = Arc::new(config.spec.clone());

    // Clock for determining the present slot.
    // TODO: this shouldn't be a static time, instead it should be pulled from the beacon node.
    // https://github.com/sigp/lighthouse/issues/160
    let genesis_time = 1_549_935_547;
    let slot_clock = {
        info!(log, "Genesis time"; "unix_epoch_seconds" => genesis_time);
        let clock = SystemTimeSlotClock::new(genesis_time, spec.slot_duration)
            .expect("Unable to instantiate SystemTimeSlotClock.");
        Arc::new(clock)
    };

    let poll_interval_millis = spec.slot_duration * 1000 / 10; // 10% epoch time precision.
    info!(log, "Starting block producer service"; "polls_per_epoch" => spec.slot_duration * 1000 / poll_interval_millis);

    /*
     * Start threads.
     */
    let mut threads = vec![];
    // TODO: keypairs are randomly generated; they should be loaded from a file or generated.
    // https://github.com/sigp/lighthouse/issues/160
    let keypairs = vec![Keypair::random()];

    for keypair in keypairs {
        info!(log, "Starting validator services"; "validator" => keypair.pk.concatenated_hex_id());
        let duties_map = Arc::new(EpochDutiesMap::new(spec.epoch_length));

        // Spawn a new thread to maintain the validator's `EpochDuties`.
        let duties_manager_thread = {
            let spec = spec.clone();
            let duties_map = duties_map.clone();
            let slot_clock = slot_clock.clone();
            let log = log.clone();
            let beacon_node = validator_grpc_client.clone();
            let pubkey = keypair.pk.clone();
            thread::spawn(move || {
                let manager = DutiesManager {
                    duties_map,
                    pubkey,
                    spec,
                    slot_clock,
                    beacon_node,
                };
                let mut duties_manager_service = DutiesManagerService {
                    manager,
                    poll_interval_millis,
                    log,
                };

                duties_manager_service.run();
            })
        };

        // Spawn a new thread to perform block production for the validator.
        let producer_thread = {
            let spec = spec.clone();
            let signer = Arc::new(LocalSigner::new(keypair.clone()));
            let duties_map = duties_map.clone();
            let slot_clock = slot_clock.clone();
            let log = log.clone();
            let client = Arc::new(BeaconBlockGrpcClient::new(beacon_block_grpc_client.clone()));
            thread::spawn(move || {
                let block_producer =
                    BlockProducer::new(spec, duties_map, slot_clock, client, signer);
                let mut block_producer_service = BlockProducerService {
                    block_producer,
                    poll_interval_millis,
                    log,
                };

                block_producer_service.run();
            })
        };

        threads.push((duties_manager_thread, producer_thread));
    }

    // Naively wait for all the threads to complete.
    for tuple in threads {
        let (manager, producer) = tuple;
        let _ = producer.join();
        let _ = manager.join();
    }
}
<commit_msg>slightly adapted impossible error for validator_client (lighthouse-252)<commit_after>use self::block_producer_service::{BeaconBlockGrpcClient, BlockProducerService};
use self::duties::{DutiesManager, DutiesManagerService, EpochDutiesMap};
use crate::config::ClientConfig;
use block_proposer::{test_utils::LocalSigner, BlockProducer};
use bls::Keypair;
use clap::{App, Arg};
use grpcio::{ChannelBuilder, EnvBuilder};
use protos::services_grpc::{BeaconBlockServiceClient, ValidatorServiceClient};
use slog::{error, info, o, Drain};
use slot_clock::SystemTimeSlotClock;
use std::path::PathBuf;
use std::sync::Arc;
use std::thread;
use types::ChainSpec;

mod block_producer_service;
mod config;
mod duties;

fn main() {
    // Logging
    let decorator = slog_term::TermDecorator::new().build();
    let drain = slog_term::CompactFormat::new(decorator).build().fuse();
    let drain = slog_async::Async::new(drain).build().fuse();
    let log = slog::Logger::root(drain, o!());

    // CLI
    let matches = App::new("Lighthouse Validator Client")
        .version("0.0.1")
        .author("Sigma Prime <contact@sigmaprime.io>")
        .about("Eth 2.0 Validator Client")
        .arg(
            Arg::with_name("datadir")
                .long("datadir")
                .value_name("DIR")
                .help("Data directory for keys and databases.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("server")
                .long("server")
                .value_name("server")
                .help("Address to connect to BeaconNode.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("spec")
                .long("spec")
                .value_name("spec")
                .short("s")
                .help("Configuration of Beacon Chain")
                .takes_value(true)
                .possible_values(&["foundation", "few_validators"]),
        )
        .get_matches();

    let mut config = ClientConfig::default();

    // Custom datadir
    if let Some(dir) = matches.value_of("datadir") {
        config.data_dir = PathBuf::from(dir.to_string());
    }

    // Custom server port
    if let Some(server_str) = matches.value_of("server") {
        if let Ok(addr) = server_str.parse::<u16>() {
            config.server = addr.to_string();
        } else {
            error!(log, "Invalid address"; "server" => server_str);
            return;
        }
    }

    // TODO: Permit loading a custom spec from file.
    // Custom spec
    if let Some(spec_str) = matches.value_of("spec") {
        match spec_str {
            "foundation" => config.spec = ChainSpec::foundation(),
            "few_validators" => config.spec = ChainSpec::few_validators(),
            // Should be impossible
            _ => {
                error!(log, "Invalid ChainSpec defined"; "spec" => spec_str);
                return;
            }
        };
    }

    // Log configuration
    info!(log, "";
          "data_dir" => &config.data_dir.to_str(),
          "server" => &config.server);

    // Beacon node gRPC beacon block endpoints.
    let beacon_block_grpc_client = {
        let env = Arc::new(EnvBuilder::new().build());
        let ch = ChannelBuilder::new(env).connect(&config.server);
        Arc::new(BeaconBlockServiceClient::new(ch))
    };

    // Beacon node gRPC validator endpoints.
    let validator_grpc_client = {
        let env = Arc::new(EnvBuilder::new().build());
        let ch = ChannelBuilder::new(env).connect(&config.server);
        Arc::new(ValidatorServiceClient::new(ch))
    };

    // Spec
    let spec = Arc::new(config.spec.clone());

    // Clock for determining the present slot.
    // TODO: this shouldn't be a static time, instead it should be pulled from the beacon node.
    // https://github.com/sigp/lighthouse/issues/160
    let genesis_time = 1_549_935_547;
    let slot_clock = {
        info!(log, "Genesis time"; "unix_epoch_seconds" => genesis_time);
        let clock = SystemTimeSlotClock::new(genesis_time, spec.slot_duration)
            .expect("Unable to instantiate SystemTimeSlotClock.");
        Arc::new(clock)
    };

    let poll_interval_millis = spec.slot_duration * 1000 / 10; // 10% epoch time precision.
    info!(log, "Starting block producer service"; "polls_per_epoch" => spec.slot_duration * 1000 / poll_interval_millis);

    /*
     * Start threads.
     */
    let mut threads = vec![];
    // TODO: keypairs are randomly generated; they should be loaded from a file or generated.
    // https://github.com/sigp/lighthouse/issues/160
    let keypairs = vec![Keypair::random()];

    for keypair in keypairs {
        info!(log, "Starting validator services"; "validator" => keypair.pk.concatenated_hex_id());
        let duties_map = Arc::new(EpochDutiesMap::new(spec.epoch_length));

        // Spawn a new thread to maintain the validator's `EpochDuties`.
        let duties_manager_thread = {
            let spec = spec.clone();
            let duties_map = duties_map.clone();
            let slot_clock = slot_clock.clone();
            let log = log.clone();
            let beacon_node = validator_grpc_client.clone();
            let pubkey = keypair.pk.clone();
            thread::spawn(move || {
                let manager = DutiesManager {
                    duties_map,
                    pubkey,
                    spec,
                    slot_clock,
                    beacon_node,
                };
                let mut duties_manager_service = DutiesManagerService {
                    manager,
                    poll_interval_millis,
                    log,
                };

                duties_manager_service.run();
            })
        };

        // Spawn a new thread to perform block production for the validator.
        let producer_thread = {
            let spec = spec.clone();
            let signer = Arc::new(LocalSigner::new(keypair.clone()));
            let duties_map = duties_map.clone();
            let slot_clock = slot_clock.clone();
            let log = log.clone();
            let client = Arc::new(BeaconBlockGrpcClient::new(beacon_block_grpc_client.clone()));
            thread::spawn(move || {
                let block_producer =
                    BlockProducer::new(spec, duties_map, slot_clock, client, signer);
                let mut block_producer_service = BlockProducerService {
                    block_producer,
                    poll_interval_millis,
                    log,
                };

                block_producer_service.run();
            })
        };

        threads.push((duties_manager_thread, producer_thread));
    }

    // Naively wait for all the threads to complete.
    for tuple in threads {
        let (manager, producer) = tuple;
        let _ = producer.join();
        let _ = manager.join();
    }
}
<|endoftext|>


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

extern crate toml;
extern crate rustc_serialize;

use std::collections::{BTreeMap, HashMap};
use std::env;
use std::fs::File;
use std::io::{self, Read, Write};
use std::path::{PathBuf, Path};
use std::process::{Command, Stdio};

static HOSTS: &'static [&'static str] = &[
    "aarch64-unknown-linux-gnu",
    "arm-unknown-linux-gnueabi",
    "arm-unknown-linux-gnueabihf",
    "armv7-unknown-linux-gnueabihf",
    "i686-apple-darwin",
    "i686-pc-windows-gnu",
    "i686-pc-windows-msvc",
    "i686-unknown-linux-gnu",
    "mips-unknown-linux-gnu",
    "mips64-unknown-linux-gnuabi64",
    "mips64el-unknown-linux-gnuabi64",
    "mipsel-unknown-linux-gnu",
    "powerpc-unknown-linux-gnu",
    "powerpc64-unknown-linux-gnu",
    "powerpc64le-unknown-linux-gnu",
    "s390x-unknown-linux-gnu",
    "x86_64-apple-darwin",
    "x86_64-pc-windows-gnu",
    "x86_64-pc-windows-msvc",
    "x86_64-unknown-freebsd",
    "x86_64-unknown-linux-gnu",
    "x86_64-unknown-netbsd",
];

static TARGETS: &'static [&'static str] = &[
    "aarch64-apple-ios",
    "aarch64-unknown-fuchsia",
    "aarch64-linux-android",
    "aarch64-unknown-linux-gnu",
    "arm-linux-androideabi",
    "arm-unknown-linux-gnueabi",
    "arm-unknown-linux-gnueabihf",
    "arm-unknown-linux-musleabi",
    "arm-unknown-linux-musleabihf",
    "armv7-apple-ios",
    "armv7-linux-androideabi",
    "armv7-unknown-linux-gnueabihf",
    "armv7-unknown-linux-musleabihf",
    "armv7s-apple-ios",
    "asmjs-unknown-emscripten",
    "i386-apple-ios",
    "i586-pc-windows-msvc",
    "i586-unknown-linux-gnu",
    "i686-apple-darwin",
    "i686-linux-android",
    "i686-pc-windows-gnu",
    "i686-pc-windows-msvc",
    "i686-unknown-freebsd",
    "i686-unknown-linux-gnu",
    "i686-unknown-linux-musl",
    "mips-unknown-linux-gnu",
    "mips-unknown-linux-musl",
    "mips64-unknown-linux-gnuabi64",
    "mips64el-unknown-linux-gnuabi64",
    "mipsel-unknown-linux-gnu",
    "mipsel-unknown-linux-musl",
    "powerpc-unknown-linux-gnu",
    "powerpc64-unknown-linux-gnu",
    "powerpc64le-unknown-linux-gnu",
    "s390x-unknown-linux-gnu",
    "sparc64-unknown-linux-gnu",
    "wasm32-unknown-emscripten",
    "x86_64-apple-darwin",
    "x86_64-apple-ios",
    "x86_64-pc-windows-gnu",
    "x86_64-pc-windows-msvc",
    "x86_64-rumprun-netbsd",
    "x86_64-unknown-freebsd",
    "x86_64-unknown-fuchsia",
    "x86_64-unknown-linux-gnu",
    "x86_64-unknown-linux-musl",
    "x86_64-unknown-netbsd",
];

static MINGW: &'static [&'static str] = &[
    "i686-pc-windows-gnu",
    "x86_64-pc-windows-gnu",
];

struct Manifest {
    manifest_version: String,
    date: String,
    pkg: HashMap<String, Package>,
}

#[derive(RustcEncodable)]
struct Package {
    version: String,
    target: HashMap<String, Target>,
}

#[derive(RustcEncodable)]
struct Target {
    available: bool,
    url: Option<String>,
    hash: Option<String>,
    components: Option<Vec<Component>>,
    extensions: Option<Vec<Component>>,
}

#[derive(RustcEncodable)]
struct Component {
    pkg: String,
    target: String,
}

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

struct Builder {
    rust_release: String,
    cargo_release: String,
    input: PathBuf,
    output: PathBuf,
    gpg_passphrase: String,
    digests: HashMap<String, String>,
    s3_address: String,
    date: String,
    rust_version: String,
    cargo_version: String,
}

fn main() {
    let mut args = env::args().skip(1);
    let input = PathBuf::from(args.next().unwrap());
    let output = PathBuf::from(args.next().unwrap());
    let date = args.next().unwrap();
    let rust_release = args.next().unwrap();
    let cargo_release = args.next().unwrap();
    let s3_address = args.next().unwrap();
    let mut passphrase = String::new();
    t!(io::stdin().read_to_string(&mut passphrase));

    Builder {
        rust_release: rust_release,
        cargo_release: cargo_release,
        input: input,
        output: output,
        gpg_passphrase: passphrase,
        digests: HashMap::new(),
        s3_address: s3_address,
        date: date,
        rust_version: String::new(),
        cargo_version: String::new(),
    }.build();
}

impl Builder {
    fn build(&mut self) {
        self.rust_version = self.version("rust", "x86_64-unknown-linux-gnu");
        self.cargo_version = self.version("cargo", "x86_64-unknown-linux-gnu");

        self.digest_and_sign();
        let Manifest { manifest_version, date, pkg } = self.build_manifest();

        // Unfortunately we can't use derive(RustcEncodable) here because the
        // version field is called `manifest-version`, not `manifest_version`.
        // In lieu of that just create the table directly here with a `BTreeMap`
        // and wrap it up in a `Value::Table`.
        let mut manifest = BTreeMap::new();
        manifest.insert("manifest-version".to_string(),
                        toml::Value::String(manifest_version));
        manifest.insert("date".to_string(), toml::Value::String(date.clone()));
        manifest.insert("pkg".to_string(), toml::encode(&pkg));
        let manifest = toml::Value::Table(manifest).to_string();

        let filename = format!("channel-rust-{}.toml", self.rust_release);
        self.write_manifest(&manifest, &filename);

        let filename = format!("channel-rust-{}-date.txt", self.rust_release);
        self.write_date_stamp(&date, &filename);

        if self.rust_release != "beta" && self.rust_release != "nightly" {
            self.write_manifest(&manifest, "channel-rust-stable.toml");
            self.write_date_stamp(&date, "channel-rust-stable-date.txt");
        }
    }

    fn digest_and_sign(&mut self) {
        for file in t!(self.input.read_dir()).map(|e| t!(e).path()) {
            let filename = file.file_name().unwrap().to_str().unwrap();
            let digest = self.hash(&file);
            self.sign(&file);
            assert!(self.digests.insert(filename.to_string(), digest).is_none());
        }
    }

    fn build_manifest(&mut self) -> Manifest {
        let mut manifest = Manifest {
            manifest_version: "2".to_string(),
            date: self.date.to_string(),
            pkg: HashMap::new(),
        };

        self.package("rustc", &mut manifest.pkg, HOSTS);
        self.package("cargo", &mut manifest.pkg, HOSTS);
        self.package("rust-mingw", &mut manifest.pkg, MINGW);
        self.package("rust-std", &mut manifest.pkg, TARGETS);
        self.package("rust-docs", &mut manifest.pkg, TARGETS);
        self.package("rust-src", &mut manifest.pkg, &["*"]);

        if self.rust_release == "nightly" {
            self.package("rust-analysis", &mut manifest.pkg, TARGETS);
        }

        let mut pkg = Package {
            version: self.cached_version("rust").to_string(),
            target: HashMap::new(),
        };
        for host in HOSTS {
            let filename = self.filename("rust", host);
            let digest = match self.digests.remove(&filename) {
                Some(digest) => digest,
                None => {
                    pkg.target.insert(host.to_string(), Target {
                        available: false,
                        url: None,
                        hash: None,
                        components: None,
                        extensions: None,
                    });
                    continue
                }
            };
            let mut components = Vec::new();
            let mut extensions = Vec::new();

            // rustc/rust-std/cargo/docs are all required, and so is rust-mingw
            // if it's available for the target.
            components.extend(vec![
                Component { pkg: "rustc".to_string(), target: host.to_string() },
                Component { pkg: "rust-std".to_string(), target: host.to_string() },
                Component { pkg: "cargo".to_string(), target: host.to_string() },
                Component { pkg: "rust-docs".to_string(), target: host.to_string() },
            ]);
            if host.contains("pc-windows-gnu") {
                components.push(Component {
                    pkg: "rust-mingw".to_string(),
                    target: host.to_string(),
                });
            }

            for target in TARGETS {
                if target != host {
                    extensions.push(Component {
                        pkg: "rust-std".to_string(),
                        target: target.to_string(),
                    });
                }
                if self.rust_release == "nightly" {
                    extensions.push(Component {
                        pkg: "rust-analysis".to_string(),
                        target: target.to_string(),
                    });
                }
            }
            extensions.push(Component {
                pkg: "rust-src".to_string(),
                target: "*".to_string(),
            });

            pkg.target.insert(host.to_string(), Target {
                available: true,
                url: Some(self.url("rust", host)),
                hash: Some(digest),
                components: Some(components),
                extensions: Some(extensions),
            });
        }
        manifest.pkg.insert("rust".to_string(), pkg);

        return manifest
    }

    fn package(&mut self,
               pkgname: &str,
               dst: &mut HashMap<String, Package>,
               targets: &[&str]) {
        let targets = targets.iter().map(|name| {
            let filename = self.filename(pkgname, name);
            let digest = match self.digests.remove(&filename) {
                Some(digest) => digest,
                None => {
                    return (name.to_string(), Target {
                        available: false,
                        url: None,
                        hash: None,
                        components: None,
                        extensions: None,
                    })
                }
            };

            (name.to_string(), Target {
                available: true,
                url: Some(self.url(pkgname, name)),
                hash: Some(digest),
                components: None,
                extensions: None,
            })
        }).collect();

        dst.insert(pkgname.to_string(), Package {
            version: self.cached_version(pkgname).to_string(),
            target: targets,
        });
    }

    fn url(&self, component: &str, target: &str) -> String {
        format!("{}/{}/{}",
                self.s3_address,
                self.date,
                self.filename(component, target))
    }

    fn filename(&self, component: &str, target: &str) -> String {
        if component == "rust-src" {
            format!("rust-src-{}.tar.gz", self.rust_release)
        } else if component == "cargo" {
            format!("cargo-{}-{}.tar.gz", self.cargo_release, target)
        } else {
            format!("{}-{}-{}.tar.gz", component, self.rust_release, target)
        }
    }

    fn cached_version(&self, component: &str) -> &str {
        if component == "cargo" {
            &self.cargo_version
        } else {
            &self.rust_version
        }
    }

    fn version(&self, component: &str, target: &str) -> String {
        let mut cmd = Command::new("tar");
        let filename = self.filename(component, target);
        cmd.arg("xf")
           .arg(self.input.join(&filename))
           .arg(format!("{}/version", filename.replace(".tar.gz", "")))
           .arg("-O");
        let version = t!(cmd.output());
        if !version.status.success() {
            panic!("failed to learn version:\n\n{:?}\n\n{}\n\n{}",
                   cmd,
                   String::from_utf8_lossy(&version.stdout),
                   String::from_utf8_lossy(&version.stderr));
        }
        String::from_utf8_lossy(&version.stdout).trim().to_string()
    }

    fn hash(&self, path: &Path) -> String {
        let sha = t!(Command::new("shasum")
                        .arg("-a").arg("256")
                        .arg(path.file_name().unwrap())
                        .current_dir(path.parent().unwrap())
                        .output());
        assert!(sha.status.success());

        let filename = path.file_name().unwrap().to_str().unwrap();
        let sha256 = self.output.join(format!("{}.sha256", filename));
        t!(t!(File::create(&sha256)).write_all(&sha.stdout));

        let stdout = String::from_utf8_lossy(&sha.stdout);
        stdout.split_whitespace().next().unwrap().to_string()
    }

    fn sign(&self, path: &Path) {
        let filename = path.file_name().unwrap().to_str().unwrap();
        let asc = self.output.join(format!("{}.asc", filename));
        println!("signing: {:?}", path);
        let mut cmd = Command::new("gpg");
        cmd.arg("--no-tty")
            .arg("--yes")
            .arg("--passphrase-fd").arg("0")
            .arg("--armor")
            .arg("--output").arg(&asc)
            .arg("--detach-sign").arg(path)
            .stdin(Stdio::piped());
        let mut child = t!(cmd.spawn());
        t!(child.stdin.take().unwrap().write_all(self.gpg_passphrase.as_bytes()));
        assert!(t!(child.wait()).success());
    }

    fn write_manifest(&self, manifest: &str, name: &str) {
        let dst = self.output.join(name);
        t!(t!(File::create(&dst)).write_all(manifest.as_bytes()));
        self.hash(&dst);
        self.sign(&dst);
    }

    fn write_date_stamp(&self, date: &str, name: &str) {
        let dst = self.output.join(name);
        t!(t!(File::create(&dst)).write_all(date.as_bytes()));
        self.hash(&dst);
        self.sign(&dst);
    }
}
<commit_msg>Rollup merge of #41202 - brson:btree, r=nikomatsakis<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate toml;
extern crate rustc_serialize;

use std::collections::BTreeMap;
use std::env;
use std::fs::File;
use std::io::{self, Read, Write};
use std::path::{PathBuf, Path};
use std::process::{Command, Stdio};

static HOSTS: &'static [&'static str] = &[
    "aarch64-unknown-linux-gnu",
    "arm-unknown-linux-gnueabi",
    "arm-unknown-linux-gnueabihf",
    "armv7-unknown-linux-gnueabihf",
    "i686-apple-darwin",
    "i686-pc-windows-gnu",
    "i686-pc-windows-msvc",
    "i686-unknown-linux-gnu",
    "mips-unknown-linux-gnu",
    "mips64-unknown-linux-gnuabi64",
    "mips64el-unknown-linux-gnuabi64",
    "mipsel-unknown-linux-gnu",
    "powerpc-unknown-linux-gnu",
    "powerpc64-unknown-linux-gnu",
    "powerpc64le-unknown-linux-gnu",
    "s390x-unknown-linux-gnu",
    "x86_64-apple-darwin",
    "x86_64-pc-windows-gnu",
    "x86_64-pc-windows-msvc",
    "x86_64-unknown-freebsd",
    "x86_64-unknown-linux-gnu",
    "x86_64-unknown-netbsd",
];

static TARGETS: &'static [&'static str] = &[
    "aarch64-apple-ios",
    "aarch64-unknown-fuchsia",
    "aarch64-linux-android",
    "aarch64-unknown-linux-gnu",
    "arm-linux-androideabi",
    "arm-unknown-linux-gnueabi",
    "arm-unknown-linux-gnueabihf",
    "arm-unknown-linux-musleabi",
    "arm-unknown-linux-musleabihf",
    "armv7-apple-ios",
    "armv7-linux-androideabi",
    "armv7-unknown-linux-gnueabihf",
    "armv7-unknown-linux-musleabihf",
    "armv7s-apple-ios",
    "asmjs-unknown-emscripten",
    "i386-apple-ios",
    "i586-pc-windows-msvc",
    "i586-unknown-linux-gnu",
    "i686-apple-darwin",
    "i686-linux-android",
    "i686-pc-windows-gnu",
    "i686-pc-windows-msvc",
    "i686-unknown-freebsd",
    "i686-unknown-linux-gnu",
    "i686-unknown-linux-musl",
    "mips-unknown-linux-gnu",
    "mips-unknown-linux-musl",
    "mips64-unknown-linux-gnuabi64",
    "mips64el-unknown-linux-gnuabi64",
    "mipsel-unknown-linux-gnu",
    "mipsel-unknown-linux-musl",
    "powerpc-unknown-linux-gnu",
    "powerpc64-unknown-linux-gnu",
    "powerpc64le-unknown-linux-gnu",
    "s390x-unknown-linux-gnu",
    "sparc64-unknown-linux-gnu",
    "wasm32-unknown-emscripten",
    "x86_64-apple-darwin",
    "x86_64-apple-ios",
    "x86_64-pc-windows-gnu",
    "x86_64-pc-windows-msvc",
    "x86_64-rumprun-netbsd",
    "x86_64-unknown-freebsd",
    "x86_64-unknown-fuchsia",
    "x86_64-unknown-linux-gnu",
    "x86_64-unknown-linux-musl",
    "x86_64-unknown-netbsd",
];

static MINGW: &'static [&'static str] = &[
    "i686-pc-windows-gnu",
    "x86_64-pc-windows-gnu",
];

struct Manifest {
    manifest_version: String,
    date: String,
    pkg: BTreeMap<String, Package>,
}

#[derive(RustcEncodable)]
struct Package {
    version: String,
    target: BTreeMap<String, Target>,
}

#[derive(RustcEncodable)]
struct Target {
    available: bool,
    url: Option<String>,
    hash: Option<String>,
    components: Option<Vec<Component>>,
    extensions: Option<Vec<Component>>,
}

#[derive(RustcEncodable)]
struct Component {
    pkg: String,
    target: String,
}

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

struct Builder {
    rust_release: String,
    cargo_release: String,
    input: PathBuf,
    output: PathBuf,
    gpg_passphrase: String,
    digests: BTreeMap<String, String>,
    s3_address: String,
    date: String,
    rust_version: String,
    cargo_version: String,
}

fn main() {
    let mut args = env::args().skip(1);
    let input = PathBuf::from(args.next().unwrap());
    let output = PathBuf::from(args.next().unwrap());
    let date = args.next().unwrap();
    let rust_release = args.next().unwrap();
    let cargo_release = args.next().unwrap();
    let s3_address = args.next().unwrap();
    let mut passphrase = String::new();
    t!(io::stdin().read_to_string(&mut passphrase));

    Builder {
        rust_release: rust_release,
        cargo_release: cargo_release,
        input: input,
        output: output,
        gpg_passphrase: passphrase,
        digests: BTreeMap::new(),
        s3_address: s3_address,
        date: date,
        rust_version: String::new(),
        cargo_version: String::new(),
    }.build();
}

impl Builder {
    fn build(&mut self) {
        self.rust_version = self.version("rust", "x86_64-unknown-linux-gnu");
        self.cargo_version = self.version("cargo", "x86_64-unknown-linux-gnu");

        self.digest_and_sign();
        let Manifest { manifest_version, date, pkg } = self.build_manifest();

        // Unfortunately we can't use derive(RustcEncodable) here because the
        // version field is called `manifest-version`, not `manifest_version`.
        // In lieu of that just create the table directly here with a `BTreeMap`
        // and wrap it up in a `Value::Table`.
        let mut manifest = BTreeMap::new();
        manifest.insert("manifest-version".to_string(),
                        toml::Value::String(manifest_version));
        manifest.insert("date".to_string(), toml::Value::String(date.clone()));
        manifest.insert("pkg".to_string(), toml::encode(&pkg));
        let manifest = toml::Value::Table(manifest).to_string();

        let filename = format!("channel-rust-{}.toml", self.rust_release);
        self.write_manifest(&manifest, &filename);

        let filename = format!("channel-rust-{}-date.txt", self.rust_release);
        self.write_date_stamp(&date, &filename);

        if self.rust_release != "beta" && self.rust_release != "nightly" {
            self.write_manifest(&manifest, "channel-rust-stable.toml");
            self.write_date_stamp(&date, "channel-rust-stable-date.txt");
        }
    }

    fn digest_and_sign(&mut self) {
        for file in t!(self.input.read_dir()).map(|e| t!(e).path()) {
            let filename = file.file_name().unwrap().to_str().unwrap();
            let digest = self.hash(&file);
            self.sign(&file);
            assert!(self.digests.insert(filename.to_string(), digest).is_none());
        }
    }

    fn build_manifest(&mut self) -> Manifest {
        let mut manifest = Manifest {
            manifest_version: "2".to_string(),
            date: self.date.to_string(),
            pkg: BTreeMap::new(),
        };

        self.package("rustc", &mut manifest.pkg, HOSTS);
        self.package("cargo", &mut manifest.pkg, HOSTS);
        self.package("rust-mingw", &mut manifest.pkg, MINGW);
        self.package("rust-std", &mut manifest.pkg, TARGETS);
        self.package("rust-docs", &mut manifest.pkg, TARGETS);
        self.package("rust-src", &mut manifest.pkg, &["*"]);

        if self.rust_release == "nightly" {
            self.package("rust-analysis", &mut manifest.pkg, TARGETS);
        }

        let mut pkg = Package {
            version: self.cached_version("rust").to_string(),
            target: BTreeMap::new(),
        };
        for host in HOSTS {
            let filename = self.filename("rust", host);
            let digest = match self.digests.remove(&filename) {
                Some(digest) => digest,
                None => {
                    pkg.target.insert(host.to_string(), Target {
                        available: false,
                        url: None,
                        hash: None,
                        components: None,
                        extensions: None,
                    });
                    continue
                }
            };
            let mut components = Vec::new();
            let mut extensions = Vec::new();

            // rustc/rust-std/cargo/docs are all required, and so is rust-mingw
            // if it's available for the target.
            components.extend(vec![
                Component { pkg: "rustc".to_string(), target: host.to_string() },
                Component { pkg: "rust-std".to_string(), target: host.to_string() },
                Component { pkg: "cargo".to_string(), target: host.to_string() },
                Component { pkg: "rust-docs".to_string(), target: host.to_string() },
            ]);
            if host.contains("pc-windows-gnu") {
                components.push(Component {
                    pkg: "rust-mingw".to_string(),
                    target: host.to_string(),
                });
            }

            for target in TARGETS {
                if target != host {
                    extensions.push(Component {
                        pkg: "rust-std".to_string(),
                        target: target.to_string(),
                    });
                }
                if self.rust_release == "nightly" {
                    extensions.push(Component {
                        pkg: "rust-analysis".to_string(),
                        target: target.to_string(),
                    });
                }
            }
            extensions.push(Component {
                pkg: "rust-src".to_string(),
                target: "*".to_string(),
            });

            pkg.target.insert(host.to_string(), Target {
                available: true,
                url: Some(self.url("rust", host)),
                hash: Some(digest),
                components: Some(components),
                extensions: Some(extensions),
            });
        }
        manifest.pkg.insert("rust".to_string(), pkg);

        return manifest
    }

    fn package(&mut self,
               pkgname: &str,
               dst: &mut BTreeMap<String, Package>,
               targets: &[&str]) {
        let targets = targets.iter().map(|name| {
            let filename = self.filename(pkgname, name);
            let digest = match self.digests.remove(&filename) {
                Some(digest) => digest,
                None => {
                    return (name.to_string(), Target {
                        available: false,
                        url: None,
                        hash: None,
                        components: None,
                        extensions: None,
                    })
                }
            };

            (name.to_string(), Target {
                available: true,
                url: Some(self.url(pkgname, name)),
                hash: Some(digest),
                components: None,
                extensions: None,
            })
        }).collect();

        dst.insert(pkgname.to_string(), Package {
            version: self.cached_version(pkgname).to_string(),
            target: targets,
        });
    }

    fn url(&self, component: &str, target: &str) -> String {
        format!("{}/{}/{}",
                self.s3_address,
                self.date,
                self.filename(component, target))
    }

    fn filename(&self, component: &str, target: &str) -> String {
        if component == "rust-src" {
            format!("rust-src-{}.tar.gz", self.rust_release)
        } else if component == "cargo" {
            format!("cargo-{}-{}.tar.gz", self.cargo_release, target)
        } else {
            format!("{}-{}-{}.tar.gz", component, self.rust_release, target)
        }
    }

    fn cached_version(&self, component: &str) -> &str {
        if component == "cargo" {
            &self.cargo_version
        } else {
            &self.rust_version
        }
    }

    fn version(&self, component: &str, target: &str) -> String {
        let mut cmd = Command::new("tar");
        let filename = self.filename(component, target);
        cmd.arg("xf")
           .arg(self.input.join(&filename))
           .arg(format!("{}/version", filename.replace(".tar.gz", "")))
           .arg("-O");
        let version = t!(cmd.output());
        if !version.status.success() {
            panic!("failed to learn version:\n\n{:?}\n\n{}\n\n{}",
                   cmd,
                   String::from_utf8_lossy(&version.stdout),
                   String::from_utf8_lossy(&version.stderr));
        }
        String::from_utf8_lossy(&version.stdout).trim().to_string()
    }

    fn hash(&self, path: &Path) -> String {
        let sha = t!(Command::new("shasum")
                        .arg("-a").arg("256")
                        .arg(path.file_name().unwrap())
                        .current_dir(path.parent().unwrap())
                        .output());
        assert!(sha.status.success());

        let filename = path.file_name().unwrap().to_str().unwrap();
        let sha256 = self.output.join(format!("{}.sha256", filename));
        t!(t!(File::create(&sha256)).write_all(&sha.stdout));

        let stdout = String::from_utf8_lossy(&sha.stdout);
        stdout.split_whitespace().next().unwrap().to_string()
    }

    fn sign(&self, path: &Path) {
        let filename = path.file_name().unwrap().to_str().unwrap();
        let asc = self.output.join(format!("{}.asc", filename));
        println!("signing: {:?}", path);
        let mut cmd = Command::new("gpg");
        cmd.arg("--no-tty")
            .arg("--yes")
            .arg("--passphrase-fd").arg("0")
            .arg("--armor")
            .arg("--output").arg(&asc)
            .arg("--detach-sign").arg(path)
            .stdin(Stdio::piped());
        let mut child = t!(cmd.spawn());
        t!(child.stdin.take().unwrap().write_all(self.gpg_passphrase.as_bytes()));
        assert!(t!(child.wait()).success());
    }

    fn write_manifest(&self, manifest: &str, name: &str) {
        let dst = self.output.join(name);
        t!(t!(File::create(&dst)).write_all(manifest.as_bytes()));
        self.hash(&dst);
        self.sign(&dst);
    }

    fn write_date_stamp(&self, date: &str, name: &str) {
        let dst = self.output.join(name);
        t!(t!(File::create(&dst)).write_all(date.as_bytes()));
        self.hash(&dst);
        self.sign(&dst);
    }
}
<|endoftext|>


<commit_before><commit_msg>Added test to tests<commit_after>#[cfg(test)]
mod tests {
    #[test]
    fn it_works(){

    }
}<|endoftext|>


<commit_before>extern crate libc;
use std::ptr;
use std::mem;
use std::ffi;
use std::str;
use std::slice::from_raw_parts;
use std::string::String;
use std::collections::HashMap;
use std::boxed::Box;
use x11::xlib;
use x11::keysym;

use super::config::Config;
use super::workspace::{ Workspace, Workspaces };
use super::handler;

unsafe extern fn error_handler(display: *mut xlib::Display, event: *mut xlib::XErrorEvent) -> libc::c_int {
    // match event.error_code {
    //     xlib::BadAtom => {
    //         println!("bad atom");
    //     }
    //     _ => {}
    // }
    1
}

fn get_atom_name(display: *mut xlib::Display, atom: xlib::Atom) -> Result<String, i32>{
    unsafe{
        let name = xlib::XGetAtomName(display, atom);
        if name == ptr::null_mut() {
            return Err(0);
        }
        let s = ffi::CStr::from_ptr(name);
        let s = s.to_bytes();
        match str::from_utf8(s) {
            Ok(v) => {
                let tmp = Ok(v.to_string());
                xlib::XFree(name as *mut libc::c_void);
                tmp
            }
            _ => Err(0)
        }
    }
}

fn get_text_property(display: *mut xlib::Display, window: xlib::Window, atom: xlib::Atom) -> Option<String>{
    unsafe{
        let mut prop: xlib::XTextProperty = mem::zeroed();
        let r = xlib::XGetTextProperty(display, window, &mut prop, atom);
        if r == 0 {
            None
        }else{
            let s = String::from_raw_parts(prop.value, prop.nitems as usize, prop.nitems as usize + 1 ).clone();
            let text = Some(s);
            xlib::XFree(prop.value as *mut libc::c_void);
            text
        }
    }
}

fn get_window_property(display: *mut xlib::Display, window: xlib::Window, atom: xlib::Atom) {
    unsafe {
        let mut actual_type_return: u64 = 0;
        let mut actual_format_return: i32 = 0;
        let mut nitem_return: libc::c_ulong = 0;
        let mut bytes_after_return: libc::c_ulong = 0;
        let mut prop_return: *mut libc::c_uchar = mem::zeroed();

        let r = xlib::XGetWindowProperty(display, window, xlib::XA_WM_NAME,
                                         0, 0xFFFFFFFF, 0, 0,
                                         &mut actual_type_return,
                                         &mut actual_format_return,
                                         &mut nitem_return,
                                         &mut bytes_after_return,
                                         &mut prop_return);

        debug!("result get wp {}", r);
        if r == 0 {

        }else{
            debug!("actual format return {}", actual_format_return);
            if actual_format_return == 0 {

            }
            else {
                // let s = from_raw_parts(prop_return as *const libc::c_ulong, nitems_return as usize).iter()
                //     .map(|&c| c as u64)
                //     .collect();
                let s = String::from_raw_parts(prop_return, nitem_return as usize, nitem_return as usize + 1 );
                println!("{}", s);

            }
        }
    }
}

pub struct WindowManager {
    pub display: *mut xlib::Display,
    pub screen_num: libc::c_int,
    pub root:    xlib::Window,

    pub workspaces: Workspaces,
    config: Config
}

impl WindowManager {
    pub fn new() -> WindowManager {
	unsafe {
	    let display = xlib::XOpenDisplay(ptr::null());
            if display == ptr::null_mut() {
                panic!("can't open display")
            }
	    let screen_num  = xlib::XDefaultScreen(display);
	    let root    = xlib::XRootWindow(display, screen_num);

	    let mut wm = WindowManager {
	        display: display,
                screen_num: screen_num,
	        root:    root,

                config: Config::load(),
                workspaces: Workspaces::new()
            };
            wm.workspaces.create('1');
            wm
	}
    }

    pub fn run(&mut self) {
        let mask = xlib::SubstructureRedirectMask | xlib::SubstructureNotifyMask;
        let keymask = xlib::KeyPressMask | xlib::KeyReleaseMask;
        unsafe{
            xlib::XSetErrorHandler(Some(error_handler));
            xlib::XSelectInput(self.display, self.root,
                               mask | keymask);
            xlib::XSync(self.display, 0);
        }

        loop {
            //handle events here
            let mut e = xlib::XEvent{
                pad: [0; 24],
            };

            unsafe {
                xlib::XNextEvent(self.display, &mut e);
                let t = e.get_type();
                match t {
                    xlib::CreateNotify => {
                        let event: xlib::XCreateWindowEvent = From::from(e);

                        if event.override_redirect != 0 {
                            continue;
                        }

                        // change attributes before display
                        let mut attrs: xlib::XSetWindowAttributes = mem::zeroed();
                        attrs.event_mask = xlib::KeyReleaseMask;
                        let valuemask = xlib::CWEventMask;
                        xlib::XChangeWindowAttributes(self.display, event.window, valuemask, &mut attrs);

                        // add to workspace
                        // let mut w = self.workspaces.get_mut(&'1');
                        // match w {
                        //     Some(workspace) => {
                        //         workspace.add(event.window);
                        //         workspace.config(self);
                        //     }
                        //     None => {}
                        // }

                        // get window property
                        let n = get_text_property(self.display, event.window, xlib::XA_WM_NAME);
                        match n {
                            Some(s) => {debug!("create window {} for {}", event.window, s);}
                            None => {}
                        }
                    }
                    xlib::DestroyNotify => {
                        debug!("destroy notify");
                        let event: xlib::XDestroyWindowEvent = From::from(e);
                    }
                    xlib::MapNotify => {
                        debug!("map notify");
                        let event: xlib::XMapEvent = From::from(e);
                        println!("event {}", event.event);
                        println!("w {}", event.window);
                    }
                    xlib::UnmapNotify => {
                        debug!("unmap notify");
                        let event: xlib::XUnmapEvent = From::from(e);
                        let workspace = self.workspaces.current_workspace();
                        match workspace.contain(event.window) {
                            Some(index) => {
                                workspace.remove(event.window);
                                workspace.config(self.display, self.screen_num);
                            }
                            None => {}
                        }
                    }
                    xlib::MapRequest => {
                        debug!("map request");
                        let event: xlib::XMapRequestEvent = From::from(e);
                        println!("w {}", event.window);
                        xlib::XMapWindow(self.display, event.window);

                        // add app top-level window to workspace
                        let mut attrs: xlib::XWindowAttributes = mem::zeroed();
                        xlib::XGetWindowAttributes(self.display, event.window, &mut attrs);

                        let mut window_return: xlib::Window = 0;
                        let transientfor_hint = xlib::XGetTransientForHint(self.display, event.window, &mut window_return);
                        println!("trans hint {}", transientfor_hint);
                        if attrs.override_redirect == 0 && transientfor_hint == 0 {
                            debug!("top level window");
                            let mut workspace = self.workspaces.current();
                            if workspace.contain(event.window).is_none() {
                                workspace.add(event.window);
                                workspace.config(self.display, self.screen_num);
                            }
                        }

                    }
                    xlib::ClientMessage => {
                        debug!("client message");
                        // let event = cast_event::<xlib::XClientMessageEvent>(&e);
                        let event: xlib::XClientMessageEvent = From::from(e);
                        let s = get_atom_name(self.display, event.message_type);
                        match s {
                            Ok(v) => println!("{}", v),
                            _ => {}
                        }

                        match event.format {
                            8 => {
                                for i in 0..20 {
                                    println!("{}", event.data.get_byte(i))
                                }
                            }
                            16 => {
                                for i in 0..10 {
                                    println!("{}", event.data.get_short(i))
                                }
                            }
                            32 => {
                                for i in 0..5 {
                                    let a = event.data.get_long(i);
                                    let s = get_atom_name(self.display, a as u64);
                                    match s {
                                        Ok(v) => println!("{}", v),
                                        _ => {}
                                    }
                                }
                            }
                            _ => {}
                        }
                    }
                    xlib::KeyRelease => {
                        debug!("key release");
                        let mut event: xlib::XKeyEvent = From::from(e);

                        if event.state > 0 {
                            let mut sym: xlib::KeySym = 0;
                            let status: *mut xlib::XComposeStatus = ptr::null_mut();
                            xlib::XLookupString(&mut event, ptr::null_mut(), 0, &mut sym, status);

                            let b = handler::KeyBind {
                                key: sym,
                                mask: event.state,
                            };
                            debug!("key {} {}", event.state, sym);
                            // let mut h: Box<handler::Handler>;
                            match self.config.bindsyms.get_mut(&b) {
                                Some(handler) => {
                                    handler.handle(&mut self.workspaces, self.display, self.screen_num);
                                }
                                None => {
                                    println!("no bind");
                                    continue;
                                }
                            }
                        }
                    }
                    xlib::ConfigureNotify => {
                        debug!("configure notify");
                    }
                    xlib::ConfigureRequest =>{
                        debug!("configure request");
                        // let mut change = xlib::XWindowChanges {
                        //     x: event.x,
                        //     y: event.y,
                        //     width: event.width,
                        //     height: event.height,
                        //     border_width: event.border_width,
                        //     sibling: event.above,
                        //     stack_mode: event.detail
                        // };
                        // debug!("config x: {}, y: {}, width: {}, height: {}",
                        //        change.x, change.y, change.width, change.height);
                        let mut event: xlib::XConfigureRequestEvent = From::from(e);
                        // xlib::XConfigureWindow(event.display, event.window, event.value_mask as u32, &mut change);

                    }
                    _ => {
                        debug!("unhandled event {}", t);
                    }
                }
            }
        }
    }
}
<commit_msg>remove window when distroy<commit_after>extern crate libc;
use std::ptr;
use std::mem;
use std::ffi;
use std::str;
use std::slice::from_raw_parts;
use std::string::String;
use std::collections::HashMap;
use std::boxed::Box;
use x11::xlib;
use x11::keysym;

use super::config::Config;
use super::workspace::{ Workspace, Workspaces };
use super::handler;

unsafe extern fn error_handler(display: *mut xlib::Display, event: *mut xlib::XErrorEvent) -> libc::c_int {
    // match event.error_code {
    //     xlib::BadAtom => {
    //         println!("bad atom");
    //     }
    //     _ => {}
    // }
    1
}

fn get_atom_name(display: *mut xlib::Display, atom: xlib::Atom) -> Result<String, i32>{
    unsafe{
        let name = xlib::XGetAtomName(display, atom);
        if name == ptr::null_mut() {
            return Err(0);
        }
        let s = ffi::CStr::from_ptr(name);
        let s = s.to_bytes();
        match str::from_utf8(s) {
            Ok(v) => {
                let tmp = Ok(v.to_string());
                xlib::XFree(name as *mut libc::c_void);
                tmp
            }
            _ => Err(0)
        }
    }
}

fn get_text_property(display: *mut xlib::Display, window: xlib::Window, atom: xlib::Atom) -> Option<String>{
    unsafe{
        let mut prop: xlib::XTextProperty = mem::zeroed();
        let r = xlib::XGetTextProperty(display, window, &mut prop, atom);
        if r == 0 {
            None
        }else{
            let s = String::from_raw_parts(prop.value, prop.nitems as usize, prop.nitems as usize + 1 ).clone();
            let text = Some(s);
            xlib::XFree(prop.value as *mut libc::c_void);
            text
        }
    }
}

fn get_window_property(display: *mut xlib::Display, window: xlib::Window, atom: xlib::Atom) {
    unsafe {
        let mut actual_type_return: u64 = 0;
        let mut actual_format_return: i32 = 0;
        let mut nitem_return: libc::c_ulong = 0;
        let mut bytes_after_return: libc::c_ulong = 0;
        let mut prop_return: *mut libc::c_uchar = mem::zeroed();

        let r = xlib::XGetWindowProperty(display, window, xlib::XA_WM_NAME,
                                         0, 0xFFFFFFFF, 0, 0,
                                         &mut actual_type_return,
                                         &mut actual_format_return,
                                         &mut nitem_return,
                                         &mut bytes_after_return,
                                         &mut prop_return);

        debug!("result get wp {}", r);
        if r == 0 {

        }else{
            debug!("actual format return {}", actual_format_return);
            if actual_format_return == 0 {

            }
            else {
                // let s = from_raw_parts(prop_return as *const libc::c_ulong, nitems_return as usize).iter()
                //     .map(|&c| c as u64)
                //     .collect();
                let s = String::from_raw_parts(prop_return, nitem_return as usize, nitem_return as usize + 1 );
                println!("{}", s);

            }
        }
    }
}

pub struct WindowManager {
    pub display: *mut xlib::Display,
    pub screen_num: libc::c_int,
    pub root:    xlib::Window,

    pub workspaces: Workspaces,
    config: Config
}

impl WindowManager {
    pub fn new() -> WindowManager {
	unsafe {
	    let display = xlib::XOpenDisplay(ptr::null());
            if display == ptr::null_mut() {
                panic!("can't open display")
            }
	    let screen_num  = xlib::XDefaultScreen(display);
	    let root    = xlib::XRootWindow(display, screen_num);

	    let mut wm = WindowManager {
	        display: display,
                screen_num: screen_num,
	        root:    root,

                config: Config::load(),
                workspaces: Workspaces::new()
            };
            wm.workspaces.create('1');
            wm
	}
    }

    pub fn run(&mut self) {
        let mask = xlib::SubstructureRedirectMask | xlib::SubstructureNotifyMask;
        let keymask = xlib::KeyPressMask | xlib::KeyReleaseMask;
        unsafe{
            xlib::XSetErrorHandler(Some(error_handler));
            xlib::XSelectInput(self.display, self.root,
                               mask | keymask);
            xlib::XSync(self.display, 0);
        }

        loop {
            //handle events here
            let mut e = xlib::XEvent{
                pad: [0; 24],
            };

            unsafe {
                xlib::XNextEvent(self.display, &mut e);
                let t = e.get_type();
                match t {
                    xlib::CreateNotify => {
                        let event: xlib::XCreateWindowEvent = From::from(e);

                        if event.override_redirect != 0 {
                            continue;
                        }

                        // change attributes before display
                        let mut attrs: xlib::XSetWindowAttributes = mem::zeroed();
                        attrs.event_mask = xlib::KeyReleaseMask;
                        let valuemask = xlib::CWEventMask;
                        xlib::XChangeWindowAttributes(self.display, event.window, valuemask, &mut attrs);

                        // add to workspace
                        // let mut w = self.workspaces.get_mut(&'1');
                        // match w {
                        //     Some(workspace) => {
                        //         workspace.add(event.window);
                        //         workspace.config(self);
                        //     }
                        //     None => {}
                        // }

                        // get window property
                        let n = get_text_property(self.display, event.window, xlib::XA_WM_NAME);
                        match n {
                            Some(s) => {debug!("create window {} for {}", event.window, s);}
                            None => {}
                        }
                    }
                    xlib::DestroyNotify => {
                        debug!("destroy notify");
                        let event: xlib::XDestroyWindowEvent = From::from(e);

                        let workspace = self.workspaces.current();
                        match workspace.contain(event.window) {
                            Some(index) => {
                                workspace.remove(event.window);
                                workspace.config(self.display, self.screen_num);
                            }
                            None => {}
                        }
                    }
                    xlib::MapNotify => {
                        debug!("map notify");
                        let event: xlib::XMapEvent = From::from(e);

                    }
                    xlib::UnmapNotify => {
                        debug!("unmap notify");
                        let event: xlib::XUnmapEvent = From::from(e);
                    }
                    xlib::MapRequest => {
                        debug!("map request");
                        let event: xlib::XMapRequestEvent = From::from(e);
                        xlib::XMapWindow(self.display, event.window);

                        // add app top-level window to workspace
                        let mut attrs: xlib::XWindowAttributes = mem::zeroed();
                        xlib::XGetWindowAttributes(self.display, event.window, &mut attrs);

                        let mut window_return: xlib::Window = 0;
                        let transientfor_hint = xlib::XGetTransientForHint(self.display, event.window, &mut window_return);
                        println!("trans hint {}", transientfor_hint);
                        if attrs.override_redirect == 0 && transientfor_hint == 0 {
                            debug!("top level window");
                            let mut workspace = self.workspaces.current();
                            if workspace.contain(event.window).is_none() {
                                workspace.add(event.window);
                                workspace.config(self.display, self.screen_num);
                            }
                        }

                    }
                    xlib::ClientMessage => {
                        debug!("client message");
                        // let event = cast_event::<xlib::XClientMessageEvent>(&e);
                        let event: xlib::XClientMessageEvent = From::from(e);
                        let s = get_atom_name(self.display, event.message_type);
                        match s {
                            Ok(v) => println!("{}", v),
                            _ => {}
                        }

                        match event.format {
                            8 => {
                                for i in 0..20 {
                                    println!("{}", event.data.get_byte(i))
                                }
                            }
                            16 => {
                                for i in 0..10 {
                                    println!("{}", event.data.get_short(i))
                                }
                            }
                            32 => {
                                for i in 0..5 {
                                    let a = event.data.get_long(i);
                                    let s = get_atom_name(self.display, a as u64);
                                    match s {
                                        Ok(v) => println!("{}", v),
                                        _ => {}
                                    }
                                }
                            }
                            _ => {}
                        }
                    }
                    xlib::KeyRelease => {
                        debug!("key release");
                        let mut event: xlib::XKeyEvent = From::from(e);

                        if event.state > 0 {
                            let mut sym: xlib::KeySym = 0;
                            let status: *mut xlib::XComposeStatus = ptr::null_mut();
                            xlib::XLookupString(&mut event, ptr::null_mut(), 0, &mut sym, status);

                            let b = handler::KeyBind {
                                key: sym,
                                mask: event.state,
                            };
                            debug!("key {} {}", event.state, sym);
                            // let mut h: Box<handler::Handler>;
                            match self.config.bindsyms.get_mut(&b) {
                                Some(handler) => {
                                    handler.handle(&mut self.workspaces, self.display, self.screen_num);
                                }
                                None => {
                                    println!("no bind");
                                    continue;
                                }
                            }
                        }
                    }
                    xlib::ConfigureNotify => {
                        debug!("configure notify");
                    }
                    xlib::ConfigureRequest =>{
                        debug!("configure request");
                        // let mut change = xlib::XWindowChanges {
                        //     x: event.x,
                        //     y: event.y,
                        //     width: event.width,
                        //     height: event.height,
                        //     border_width: event.border_width,
                        //     sibling: event.above,
                        //     stack_mode: event.detail
                        // };
                        // debug!("config x: {}, y: {}, width: {}, height: {}",
                        //        change.x, change.y, change.width, change.height);
                        let mut event: xlib::XConfigureRequestEvent = From::from(e);
                        // xlib::XConfigureWindow(event.display, event.window, event.value_mask as u32, &mut change);

                    }
                    _ => {
                        debug!("unhandled event {}", t);
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use crate::controls;

pub mod imp;

pub mod adapter {
	pub use crate::inner::adapter::{Node, Change};
}

pub use crate::inner::{
    auto::{AsAny, Spawnable},
    adapter::{Adapter},
};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Visibility {
    Visible,
    Invisible,
    Gone,
}
impl Default for Visibility {
    fn default() -> Self {
        Visibility::Visible
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum WindowStartSize {
    Exact(u16, u16),
    Fullscreen,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Progress {
    Value(u32, u32),
    Undefined,
    None,
}
impl Default for Progress {
    fn default() -> Self {
        Progress::Undefined
    }
}

pub type Menu = Option<Vec<MenuItem>>;

#[derive(Debug, PartialEq)]
pub enum MenuItem {
    Action(String, crate::callbacks::Action, MenuItemRole),
    Delimiter,
    Sub(String, Vec<MenuItem>, MenuItemRole),
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MenuItemRole {
    None,
    Options,
    Help,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MessageSeverity {
    Info,
    Warning,
    Alert,
}

#[derive(Debug, Clone, PartialEq)]
pub enum TextContent {
    Plain(String),
    LabelDescription(String, String),
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ImageScalePolicy {
    CropCenter, // TODO variants
    FitCenter,  // TODO variants
                // TODO Tile
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum FindBy<'a> {
    Id(crate::ids::Id),
    Tag(&'a str),
}

#[derive(Debug, Clone)]
pub struct RecursiveTupleVec<K: Sized>{ pub id: K, pub value: Option<Vec<RecursiveTupleVec<K>>> }

impl<K: Sized + Default> Default for RecursiveTupleVec<K> {
    fn default() -> Self {
        Self {
            id: Default::default(), value: None,
        }
    }
}
impl<K: Sized + Default> RecursiveTupleVec<K> {
    fn put_with_defaults_inner<'a, 'b: 'a>(value: Option<&'a mut Vec<RecursiveTupleVec<K>>>, indexes: &'b [usize], passed: usize, mut new: Option<RecursiveTupleVec<K>>) -> Result<Option<RecursiveTupleVec<K>>, &'b [usize]> {
        if indexes.len() == (passed+1) {
            if let Some(value) = value {
                if value.len() > indexes[passed] {
                    if new.is_some() {
                        if let Some(ref mut new) = new {
                            ::std::mem::swap(new, &mut value[indexes[passed]]);
                        }
                        Ok(new)
                    } else {
                        Ok(Some(value.remove(indexes[passed])))
                    }
                } else {
                    if value.len() == indexes[passed] {
                        if new.is_some() {
                            value.push(new.unwrap());
                        }
                        Ok(None)
                    } else {
                        value.push(Default::default());
                        Self::put_with_defaults_inner(value[indexes[passed]].value.as_mut(), indexes, passed+1, new)
                    }
                }
            } else {
                Err(indexes)
            }
        } else if indexes.len() > (passed+1) {
            if let Some(value) = value {
                Self::put_with_defaults_inner(value[indexes[passed]].value.as_mut(), indexes, passed+1, new)
            } else {
                Err(&indexes[..passed])
            }
        } else {
            panic!("Should not happen: indexes.len({}) < passed=1({})", indexes.len(), (passed+1))
        }
    }
    pub fn put_with_defaults<'a, 'b: 'a>(&'a mut self, indexes: &'b [usize], value: Option<RecursiveTupleVec<K>>) -> Result<Option<RecursiveTupleVec<K>>, &'b [usize]> {
        Self::put_with_defaults_inner(self.value.as_mut(), indexes, 0, value)
    }
}

impl<K: Sized> RecursiveTupleVec<K> {
    pub fn get_mut_at_vec<'a, 'b:'a, A: AsMut<[Self]>>(this: &'a mut A, indexes: &'b [usize]) -> Option<&'a mut RecursiveTupleVec<K>> {
        let this = this.as_mut();
        if indexes.len() == 0 || this.len() == 0 {
            return None;
        }
        let index = indexes[0];
        let valid_index = this.len()-1;
        if valid_index == index {
            Some(&mut this[index])
        } else if valid_index > index {
            this[index].get_mut(&indexes[1..])
        } else {
            None
        }
    }
    pub fn get_at_vec<'a, 'b:'a, A: AsRef<[Self]>>(this: &'a A, indexes: &'b [usize]) -> Option<&'a RecursiveTupleVec<K>> {
        let this = this.as_ref();
        if indexes.len() == 0 || this.len() == 0 {
            return None;
        }
        let index = indexes[0];
        let valid_index = this.len()-1;
        if valid_index == index {
            Some(&this[index])
        } else if valid_index > index {
            this[index].get(&indexes[1..])
        } else {
            None
        }
    }
    pub fn with_value(id: K, value: Option<Vec<RecursiveTupleVec<K>>>) -> Self {
        Self { id, value }
    }
    fn put_inner<'a, 'b: 'a>(value: Option<&'a mut Vec<RecursiveTupleVec<K>>>, indexes: &'b [usize], passed: usize, mut new: Option<RecursiveTupleVec<K>>) -> Result<Option<RecursiveTupleVec<K>>, &'b [usize]> {
        if indexes.len() == (passed+1) {
            if let Some(value) = value {
                if value.len() > indexes[passed] {
                    if new.is_some() {
                        if let Some(ref mut new) = new {
                            ::std::mem::swap(new, &mut value[indexes[passed]]);
                        }
                        Ok(new)
                    } else {
                        Ok(Some(value.remove(indexes[passed])))
                    }
                } else {
                    if value.len() == indexes[passed] {
                        if new.is_some() {
                            value.push(new.unwrap());
                        }
                        Ok(None)
                    } else {// here
                        Err(indexes)
                    }
                }
            } else {
                Err(indexes)
            }
        } else if indexes.len() > (passed+1) {
            if let Some(value) = value {
                Self::put_inner(value[indexes[passed]].value.as_mut(), indexes, passed+1, new)
            } else {
                Err(&indexes[..passed])
            }
        } else {
            Err(indexes)
        }
    }
    pub fn put<'a, 'b: 'a>(&'a mut self, indexes: &'b [usize], value: Option<RecursiveTupleVec<K>>) -> Result<Option<RecursiveTupleVec<K>>, &'b [usize]> {
        Self::put_inner(self.value.as_mut(), indexes, 0, value)
    }

    fn get_mut_inner<'a, 'b: 'a>(value: Option<&'a mut Vec<RecursiveTupleVec<K>>>, indexes: &'b [usize]) -> Option<&'a mut RecursiveTupleVec<K>> {
        if indexes.len() < 1 {
            return None;
        }
        if let Some(ivalue) = value {
            let len = ivalue.len();
            if indexes[0] < len {
                if len <= 1 {
                    return Some(&mut ivalue[indexes[0]]);
                } else {
                    return Self::get_mut_inner(ivalue[indexes[0]].value.as_mut(), &indexes[1..]);
                }
            }
        }
        None
    }
    pub fn get_mut<'a, 'b: 'a>(&'a mut self, indexes: &'b [usize]) -> Option<&'a mut RecursiveTupleVec<K>> {
        Self::get_mut_inner(self.value.as_mut(), indexes)
    }

    fn get_inner<'a, 'b: 'a>(value: Option<&'a Vec<RecursiveTupleVec<K>>>, indexes: &'b [usize]) -> Option<&'a RecursiveTupleVec<K>> {
        if indexes.len() < 1 {
            return None;
        }
        if let Some(ivalue) = value {
            let len = ivalue.len();
            if indexes[0] < len {
                if len <= 1 {
                    return Some(&ivalue[indexes[0]]);
                } else {
                    return Self::get_inner(ivalue[indexes[0]].value.as_ref(), &indexes[1..]);
                }
            }
        }
        None
    }
    pub fn get<'a, 'b: 'a>(&'a self, indexes: &'b [usize]) -> Option<&'a RecursiveTupleVec<K>> {
        Self::get_inner(self.value.as_ref(), indexes)
    }
}

pub enum ApplicationResult {
    New(Box<dyn controls::Application>),
    Existing(Box<dyn controls::Application>),
    ErrorNonUiThread,
    ErrorUnspecified,
}
impl ApplicationResult {
    pub fn unwrap(self) -> Box<dyn controls::Application> {
        match self {
            ApplicationResult::New(app) | ApplicationResult::Existing(app) => app,
            ApplicationResult::ErrorNonUiThread => panic!("Application requested from non-UI thread"),
            ApplicationResult::ErrorUnspecified => panic!("Error getting Application"),
        }
    }
}
<commit_msg>Test case<commit_after>use crate::controls;

pub mod imp;

pub mod adapter {
	pub use crate::inner::adapter::{Node, Change};
}

pub use crate::inner::{
    auto::{AsAny, Spawnable},
    adapter::{Adapter},
};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Visibility {
    Visible,
    Invisible,
    Gone,
}
impl Default for Visibility {
    fn default() -> Self {
        Visibility::Visible
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum WindowStartSize {
    Exact(u16, u16),
    Fullscreen,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Progress {
    Value(u32, u32),
    Undefined,
    None,
}
impl Default for Progress {
    fn default() -> Self {
        Progress::Undefined
    }
}

pub type Menu = Option<Vec<MenuItem>>;

#[derive(Debug, PartialEq)]
pub enum MenuItem {
    Action(String, crate::callbacks::Action, MenuItemRole),
    Delimiter,
    Sub(String, Vec<MenuItem>, MenuItemRole),
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MenuItemRole {
    None,
    Options,
    Help,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MessageSeverity {
    Info,
    Warning,
    Alert,
}

#[derive(Debug, Clone, PartialEq)]
pub enum TextContent {
    Plain(String),
    LabelDescription(String, String),
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ImageScalePolicy {
    CropCenter, // TODO variants
    FitCenter,  // TODO variants
                // TODO Tile
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum FindBy<'a> {
    Id(crate::ids::Id),
    Tag(&'a str),
}

#[derive(Debug, Clone)]
pub struct RecursiveTupleVec<K: Sized>{ pub id: K, pub value: Option<Vec<RecursiveTupleVec<K>>> }

impl<K: Sized + Default> Default for RecursiveTupleVec<K> {
    fn default() -> Self {
        Self {
            id: Default::default(), value: None,
        }
    }
}
impl<K: Sized + Default> RecursiveTupleVec<K> {
    fn put_with_defaults_inner<'a, 'b: 'a>(value: Option<&'a mut Vec<RecursiveTupleVec<K>>>, indexes: &'b [usize], passed: usize, mut new: Option<RecursiveTupleVec<K>>) -> Result<Option<RecursiveTupleVec<K>>, &'b [usize]> {
        if indexes.len() == (passed+1) {
            if let Some(value) = value {
                if value.len() > indexes[passed] {
                    if new.is_some() {
                        if let Some(ref mut new) = new {
                            ::std::mem::swap(new, &mut value[indexes[passed]]);
                        }
                        Ok(new)
                    } else {
                        Ok(Some(value.remove(indexes[passed])))
                    }
                } else {
                    if value.len() == indexes[passed] {
                        if new.is_some() {
                            value.push(new.unwrap());
                        }
                        Ok(None)
                    } else {
                        value.push(Default::default());
                        Self::put_with_defaults_inner(value[indexes[passed]].value.as_mut(), indexes, passed+1, new)
                    }
                }
            } else {
                Err(indexes)
            }
        } else if indexes.len() > (passed+1) {
            if let Some(value) = value {
                Self::put_with_defaults_inner(value[indexes[passed]].value.as_mut(), indexes, passed+1, new)
            } else {
                Err(&indexes[..passed])
            }
        } else {
            panic!("Should not happen: indexes.len({}) < passed=1({})", indexes.len(), (passed+1))
        }
    }
    pub fn put_with_defaults<'a, 'b: 'a>(&'a mut self, indexes: &'b [usize], value: Option<RecursiveTupleVec<K>>) -> Result<Option<RecursiveTupleVec<K>>, &'b [usize]> {
        Self::put_with_defaults_inner(self.value.as_mut(), indexes, 0, value)
    }
}

impl<K: Sized + ::std::fmt::Debug> RecursiveTupleVec<K> {
    pub fn get_mut_at_vec<'a, 'b:'a, A: AsMut<[Self]>>(this: &'a mut A, indexes: &'b [usize]) -> Option<&'a mut RecursiveTupleVec<K>> {
        let this = this.as_mut();
        println!("+{:?} - {:?}", indexes, this);
        if indexes.len() == 0 || this.len() == 0 {
            return None;
        }

        let index = indexes[0];
        let total = this.len();
        let ret = if indexes.len() == 1 {
            if total > index {
                Some(&mut this[index])
            } else {
                None
            }
        } else {
            if total > index {
                this[index].get_mut(&indexes[1..])
            } else {
                None
            }
        };
        println!("-{:?} - {:?}", indexes, ret);
        ret
    }
    pub fn get_at_vec<'a, 'b:'a, A: AsRef<[Self]>>(this: &'a A, indexes: &'b [usize]) -> Option<&'a RecursiveTupleVec<K>> {
        let this = this.as_ref();
        println!("+{:?} - {:?}", indexes, this);
        if indexes.len() == 0 || this.len() == 0 {
            return None;
        }
        let index = indexes[0];
        let valid_index = this.len()-1;
        let ret = if valid_index == index {
            Some(&this[index])
        } else if valid_index > index {
            this[index].get(&indexes[1..])
        } else {
            None
        };
        println!("-{:?} - {:?}", indexes, ret);
        ret
    }
    pub fn with_value(id: K, value: Option<Vec<RecursiveTupleVec<K>>>) -> Self {
        Self { id, value }
    }
    fn put_inner<'a, 'b: 'a>(value: Option<&'a mut Vec<RecursiveTupleVec<K>>>, indexes: &'b [usize], passed: usize, mut new: Option<RecursiveTupleVec<K>>) -> Result<Option<RecursiveTupleVec<K>>, &'b [usize]> {
        if indexes.len() == (passed+1) {
            if let Some(value) = value {
                if value.len() > indexes[passed] {
                    if new.is_some() {
                        if let Some(ref mut new) = new {
                            ::std::mem::swap(new, &mut value[indexes[passed]]);
                        }
                        Ok(new)
                    } else {
                        Ok(Some(value.remove(indexes[passed])))
                    }
                } else {
                    if value.len() == indexes[passed] {
                        if new.is_some() {
                            value.push(new.unwrap());
                        }
                        Ok(None)
                    } else {// here
                        Err(indexes)
                    }
                }
            } else {
                Err(indexes)
            }
        } else if indexes.len() > (passed+1) {
            if let Some(value) = value {
                Self::put_inner(value[indexes[passed]].value.as_mut(), indexes, passed+1, new)
            } else {
                Err(&indexes[..passed])
            }
        } else {
            Err(indexes)
        }
    }
    pub fn put<'a, 'b: 'a>(&'a mut self, indexes: &'b [usize], value: Option<RecursiveTupleVec<K>>) -> Result<Option<RecursiveTupleVec<K>>, &'b [usize]> {
        Self::put_inner(self.value.as_mut(), indexes, 0, value)
    }

    fn get_mut_inner<'a, 'b: 'a>(value: Option<&'a mut Vec<RecursiveTupleVec<K>>>, indexes: &'b [usize]) -> Option<&'a mut RecursiveTupleVec<K>> {
        println!("{:?} - {:?}", indexes, value);
        if indexes.len() < 1 {
            return None;
        }
        if let Some(ivalue) = value {
            let len = ivalue.len();
            if indexes[0] < len {
                if len <= 1 {
                    return Some(&mut ivalue[indexes[0]]);
                } else {
                    return Self::get_mut_inner(ivalue[indexes[0]].value.as_mut(), &indexes[1..]);
                }
            }
        }
        None
    }
    pub fn get_mut<'a, 'b: 'a>(&'a mut self, indexes: &'b [usize]) -> Option<&'a mut RecursiveTupleVec<K>> {
        Self::get_mut_inner(self.value.as_mut(), indexes)
    }

    fn get_inner<'a, 'b: 'a>(value: Option<&'a Vec<RecursiveTupleVec<K>>>, indexes: &'b [usize]) -> Option<&'a RecursiveTupleVec<K>> {
        println!("{:?} - {:?}", indexes, value);
        if indexes.len() < 1 {
            return None;
        }
        if let Some(ivalue) = value {
            let len = ivalue.len();
            if indexes[0] < len {
                if len <= 1 {
                    return Some(&ivalue[indexes[0]]);
                } else {
                    return Self::get_inner(ivalue[indexes[0]].value.as_ref(), &indexes[1..]);
                }
            }
        }
        None
    }
    pub fn get<'a, 'b: 'a>(&'a self, indexes: &'b [usize]) -> Option<&'a RecursiveTupleVec<K>> {
        Self::get_inner(self.value.as_ref(), indexes)
    }
}

pub enum ApplicationResult {
    New(Box<dyn controls::Application>),
    Existing(Box<dyn controls::Application>),
    ErrorNonUiThread,
    ErrorUnspecified,
}
impl ApplicationResult {
    pub fn unwrap(self) -> Box<dyn controls::Application> {
        match self {
            ApplicationResult::New(app) | ApplicationResult::Existing(app) => app,
            ApplicationResult::ErrorNonUiThread => panic!("Application requested from non-UI thread"),
            ApplicationResult::ErrorUnspecified => panic!("Error getting Application"),
        }
    }
}
<|endoftext|>


<commit_before>extern crate futures;

use std::sync::Arc;
use std::sync::atomic::*;

use futures::{Future, Async, Stream, Sink};
use futures::future::result;
use futures::executor;
use futures::sync::mpsc;

mod support;
use support::*;

#[test]
fn sequence() {
    let (tx, mut rx) = mpsc::channel(1);

    sassert_empty(&mut rx);
    sassert_empty(&mut rx);

    let amt = 20;
    send(amt, tx).forget();
    let mut rx = rx.wait();
    for i in (1..amt + 1).rev() {
        assert_eq!(rx.next(), Some(Ok(i)));
    }
    assert_eq!(rx.next(), None);

    fn send(n: u32, sender: mpsc::Sender<u32>)
            -> Box<Future<Item=(), Error=()> + Send> {
        if n == 0 {
            return result(Ok(())).boxed()
        }
        sender.send(n).map_err(|_| ()).and_then(move |sender| {
            send(n - 1, sender)
        }).boxed()
    }
}

#[test]
fn drop_sender() {
    let (tx, mut rx) = mpsc::channel::<u32>(1);
    drop(tx);
    sassert_done(&mut rx);
}

#[test]
fn drop_rx() {
    let (tx, rx) = mpsc::channel::<u32>(1);
    let tx = tx.send(1).wait().ok().unwrap();
    drop(rx);
    assert!(tx.send(1).wait().is_err());
}

struct Unpark;

impl executor::Unpark for Unpark {
    fn unpark(&self) {
    }
}

#[test]
fn poll_future_then_drop() {
    let (tx, _rx) = mpsc::channel::<u32>(1);

    let tx = tx.send(1);
    let mut t = executor::spawn(tx);

    // First poll succeeds
    let tx = match t.poll_future(Arc::new(Unpark)) {
        Ok(Async::Ready(tx)) => tx,
        _ => panic!(),
    };

    // Send another value
    let tx = tx.send(2);
    let mut t = executor::spawn(tx);

    // Second poll doesn't
    match t.poll_future(Arc::new(Unpark)) {
        Ok(Async::NotReady) => {},
        _ => panic!(),
    };

    drop(t);
}

#[test]
fn drop_order() {
    static DROPS: AtomicUsize = ATOMIC_USIZE_INIT;
    let (tx, rx) = mpsc::channel(1);

    struct A;

    impl Drop for A {
        fn drop(&mut self) {
            DROPS.fetch_add(1, Ordering::SeqCst);
        }
    }

    let tx = tx.send(A).wait().unwrap();
    assert_eq!(DROPS.load(Ordering::SeqCst), 0);
    drop(rx);
    assert_eq!(DROPS.load(Ordering::SeqCst), 1);
    assert!(tx.send(A).wait().is_err());
    assert_eq!(DROPS.load(Ordering::SeqCst), 2);
}
<commit_msg>Remove no longer relevant test<commit_after>extern crate futures;

use std::sync::Arc;
use std::sync::atomic::*;

use futures::{Future, Async, Stream, Sink};
use futures::future::result;
use futures::executor;
use futures::sync::mpsc;

mod support;
use support::*;

#[test]
fn sequence() {
    let (tx, mut rx) = mpsc::channel(1);

    sassert_empty(&mut rx);
    sassert_empty(&mut rx);

    let amt = 20;
    send(amt, tx).forget();
    let mut rx = rx.wait();
    for i in (1..amt + 1).rev() {
        assert_eq!(rx.next(), Some(Ok(i)));
    }
    assert_eq!(rx.next(), None);

    fn send(n: u32, sender: mpsc::Sender<u32>)
            -> Box<Future<Item=(), Error=()> + Send> {
        if n == 0 {
            return result(Ok(())).boxed()
        }
        sender.send(n).map_err(|_| ()).and_then(move |sender| {
            send(n - 1, sender)
        }).boxed()
    }
}

#[test]
fn drop_sender() {
    let (tx, mut rx) = mpsc::channel::<u32>(1);
    drop(tx);
    sassert_done(&mut rx);
}

#[test]
fn drop_rx() {
    let (tx, rx) = mpsc::channel::<u32>(1);
    let tx = tx.send(1).wait().ok().unwrap();
    drop(rx);
    assert!(tx.send(1).wait().is_err());
}

struct Unpark;

impl executor::Unpark for Unpark {
    fn unpark(&self) {
    }
}

#[test]
fn drop_order() {
    static DROPS: AtomicUsize = ATOMIC_USIZE_INIT;
    let (tx, rx) = mpsc::channel(1);

    struct A;

    impl Drop for A {
        fn drop(&mut self) {
            DROPS.fetch_add(1, Ordering::SeqCst);
        }
    }

    let tx = tx.send(A).wait().unwrap();
    assert_eq!(DROPS.load(Ordering::SeqCst), 0);
    drop(rx);
    assert_eq!(DROPS.load(Ordering::SeqCst), 1);
    assert!(tx.send(A).wait().is_err());
    assert_eq!(DROPS.load(Ordering::SeqCst), 2);
}
<|endoftext|>


<commit_before>//! The geometric distribution.

use crate::{Distribution, Exp, Exp1};
use num_traits::Float;
use rand::Rng;
use core::fmt;

/// The geometric distribution `Geo(p)`.
///
/// This is the probability distribution of the number of failures before the
/// first success in a series of Bernoulli trials. It has the density function
/// `f(k) = (1 - p)^k p` for `k >= 0`, where `p` is the probability of success
/// on each trial.
///
/// This is the discrete analogue of the [exponential distribution](crate::Exp).
///
/// # Example
///
/// ```
/// use rand_distr::{Geo, Distribution};
///
/// let geo = Geo::new(0.5).unwrap();
/// let x = geo.sample(&mut rand::thread_rng());
/// println!("{} is from a Geo(0.5) distribution", x);
/// ```
#[derive(Copy, Clone, Debug)]
pub struct Geo<F>
where F: Float, Exp1: Distribution<F>
{
    exp: Exp<F>
}

/// Error type returned from `Geo::new`.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Error {
    /// `p < 0 || p > 1` or `nan`
    InvalidProbability,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(match self {
            Error::InvalidProbability => "p is NaN or outside the interval [0, 1] in geometric distribution",
        })
    }
}

#[cfg(feature = "std")]
impl std::error::Error for Error {}

impl<F> Geo<F>
where F: Float, Exp1: Distribution<F>
{
    /// Construct a new `Geo` with the given shape parameter `p`
    /// (probablity of success on each trial).
    pub fn new(p: F) -> Result<Self, Error> {
        let lambda = -F::ln(F::one() - p);
        match Exp::new(lambda) {
            Ok(exp) => Ok(Geo { exp }),
            Err(_) => Err(Error::InvalidProbability)
        }
    }
}

impl<F> Distribution<u64> for Geo<F>
where F: Float, Exp1: Distribution<F>
{
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u64 {
        let f = self.exp.sample(rng).floor();
        num_traits::NumCast::from(f).unwrap_or(u64::max_value())
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_geo_invalid_p() {
        assert!(Geo::new(f64::NAN).is_err());
        assert!(Geo::new(f64::INFINITY).is_err());
        assert!(Geo::new(f64::NEG_INFINITY).is_err());

        assert!(Geo::new(-0.5).is_err());
        assert!(Geo::new(0.0).is_ok());
        assert!(Geo::new(1.0).is_ok());
        assert!(Geo::new(2.0).is_err());
    }

    fn test_geo_mean_and_variance<R: Rng>(p: f64, rng: &mut R) {
        let distr = Geo::new(p).unwrap();

        let expected_mean = (1.0 - p) / p;
        let expected_variance = (1.0 - p) / (p * p);

        let mut results = [0.0; 1000];
        for i in results.iter_mut() {
            *i = distr.sample(rng) as f64;
        }

        let mean = results.iter().sum::<f64>() / results.len() as f64;
        assert!((mean as f64 - expected_mean).abs() < expected_mean / 20.0);

        let variance =
            results.iter().map(|x| (x - mean) * (x - mean)).sum::<f64>() / results.len() as f64;
        assert!((variance - expected_variance).abs() < expected_variance / 5.0);
    }

    #[test]
    fn test_geometric() {
        let mut rng = crate::test::rng(12345);

        test_geo_mean_and_variance(0.10, &mut rng);
        test_geo_mean_and_variance(0.25, &mut rng);
        test_geo_mean_and_variance(0.50, &mut rng);
        test_geo_mean_and_variance(0.75, &mut rng);
        test_geo_mean_and_variance(0.90, &mut rng);
    }
}<commit_msg>Fix constant paths for older rustc versions<commit_after>//! The geometric distribution.

use crate::{Distribution, Exp, Exp1};
use num_traits::Float;
use rand::Rng;
use core::fmt;

/// The geometric distribution `Geo(p)`.
///
/// This is the probability distribution of the number of failures before the
/// first success in a series of Bernoulli trials. It has the density function
/// `f(k) = (1 - p)^k p` for `k >= 0`, where `p` is the probability of success
/// on each trial.
///
/// This is the discrete analogue of the [exponential distribution](crate::Exp).
///
/// # Example
///
/// ```
/// use rand_distr::{Geo, Distribution};
///
/// let geo = Geo::new(0.5).unwrap();
/// let x = geo.sample(&mut rand::thread_rng());
/// println!("{} is from a Geo(0.5) distribution", x);
/// ```
#[derive(Copy, Clone, Debug)]
pub struct Geo<F>
where F: Float, Exp1: Distribution<F>
{
    exp: Exp<F>
}

/// Error type returned from `Geo::new`.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Error {
    /// `p < 0 || p > 1` or `nan`
    InvalidProbability,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(match self {
            Error::InvalidProbability => "p is NaN or outside the interval [0, 1] in geometric distribution",
        })
    }
}

#[cfg(feature = "std")]
impl std::error::Error for Error {}

impl<F> Geo<F>
where F: Float, Exp1: Distribution<F>
{
    /// Construct a new `Geo` with the given shape parameter `p`
    /// (probablity of success on each trial).
    pub fn new(p: F) -> Result<Self, Error> {
        let lambda = -F::ln(F::one() - p);
        match Exp::new(lambda) {
            Ok(exp) => Ok(Geo { exp }),
            Err(_) => Err(Error::InvalidProbability)
        }
    }
}

impl<F> Distribution<u64> for Geo<F>
where F: Float, Exp1: Distribution<F>
{
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u64 {
        let f = self.exp.sample(rng).floor();
        num_traits::NumCast::from(f).unwrap_or(u64::max_value())
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_geo_invalid_p() {
        assert!(Geo::new(core::f64::NAN).is_err());
        assert!(Geo::new(core::f64::INFINITY).is_err());
        assert!(Geo::new(core::f64::NEG_INFINITY).is_err());

        assert!(Geo::new(-0.5).is_err());
        assert!(Geo::new(0.0).is_ok());
        assert!(Geo::new(1.0).is_ok());
        assert!(Geo::new(2.0).is_err());
    }

    fn test_geo_mean_and_variance<R: Rng>(p: f64, rng: &mut R) {
        let distr = Geo::new(p).unwrap();

        let expected_mean = (1.0 - p) / p;
        let expected_variance = (1.0 - p) / (p * p);

        let mut results = [0.0; 1000];
        for i in results.iter_mut() {
            *i = distr.sample(rng) as f64;
        }

        let mean = results.iter().sum::<f64>() / results.len() as f64;
        assert!((mean as f64 - expected_mean).abs() < expected_mean / 20.0);

        let variance =
            results.iter().map(|x| (x - mean) * (x - mean)).sum::<f64>() / results.len() as f64;
        assert!((variance - expected_variance).abs() < expected_variance / 5.0);
    }

    #[test]
    fn test_geometric() {
        let mut rng = crate::test::rng(12345);

        test_geo_mean_and_variance(0.10, &mut rng);
        test_geo_mean_and_variance(0.25, &mut rng);
        test_geo_mean_and_variance(0.50, &mut rng);
        test_geo_mean_and_variance(0.75, &mut rng);
        test_geo_mean_and_variance(0.90, &mut rng);
    }
}<|endoftext|>