<commit_before>extern crate byteorder;
extern crate clap;

#[macro_use]
extern crate futures;
extern crate futures_cpupool;

#[macro_use]
extern crate tokio_core;

use futures::{Async, Poll, Future};

mod all {
    use futures::{Async, Poll, Future};
    enum ElemState<T> where T: Future {
        Pending(T),
        Done(T::Item),
    }

    pub struct All<T> where T: Future {
        elems: Vec<ElemState<T>>,
    }

    impl <T> All<T> where T: Future {
        pub fn new<I>(futures: I) -> All<T> where I: Iterator<Item=T> {
            let mut result = All { elems: Vec::new() };
            for f in futures {
                result.elems.push(ElemState::Pending(f))
            }
            result
        }
    }

    impl <T> Future for All<T> where T: Future {
        type Item = Vec<T::Item>;
        type Error = T::Error;

        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            let mut all_done = true;

            for idx in 0 .. self.elems.len() {
                let done_val = match &mut self.elems[idx] {
                    &mut ElemState::Pending(ref mut t) => {
                        match t.poll() {
                            Ok(Async::Ready(t)) => t,
                            Ok(Async::NotReady) => {
                                all_done = false;
                                continue
                            }
                            Err(e) => return Err(e),
                        }
                    }
                    &mut ElemState::Done(ref mut _v) => continue,
                };

                self.elems[idx] = ElemState::Done(done_val);
            }

            if all_done {
                let mut result = Vec::new();
                let elems = ::std::mem::replace(&mut self.elems, Vec::new());
                for e in elems.into_iter() {
                    match e {
                        ElemState::Done(t) => result.push(t),
                        _ => unreachable!(),
                    }
                }
                Ok(Async::Ready(result))
            } else {
                Ok(Async::NotReady)
            }
        }
    }
}

struct Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>
{
    f: F,
    in_progress: T,
}

fn tie_knot<F, S, T, E>(initial_state: S, f: F) -> Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>,
{
    let in_progress = f(initial_state);
    Knot {
        f: f,
        in_progress: in_progress,
    }
}

impl <F, S, T, E> Future for Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>
{
    type Item = S;
    type Error = E;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            let (s, more) = try_ready!(self.in_progress.poll());
            if more {
                self.in_progress = (self.f)(s);
            } else {
                return Ok(Async::Ready(s))
            }
        }
    }
}

struct Reading<R> where R: ::std::io::Read {
    reader: Option<R>,
    buffer: Vec<u8>,
    pos: usize,
    frame_end: Option<u8>,
}

impl <R> Reading<R> where R: ::std::io::Read {
    fn new(reader: R) -> Reading<R> {
        Reading {
            reader: Some(reader),
            buffer: Vec::new(),
            pos: 0,
            frame_end: None,
        }
    }
}

impl <R> Future for Reading<R> where R: ::std::io::Read {
    type Item = (Option<Vec<u8>>, R);
    type Error = ::std::io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            if let Some(frame_end) = self.frame_end {
                let n = try_nb!(self.reader.as_mut().unwrap().read(&mut self.buffer[self.pos..frame_end as usize]));
                self.pos += n;
                if self.pos == frame_end as usize {
                    self.pos = 0;
                    let result = ::std::mem::replace(&mut self.buffer, Vec::new());
                    self.frame_end = None;
                    return Ok(Async::Ready((Some(result), self.reader.take().unwrap())))
                }
            } else {
                let mut buf = [0u8];
                let n = try_nb!(self.reader.as_mut().unwrap().read(&mut buf));
                if n == 0 { // EOF
                    return Ok(Async::Ready((None, self.reader.take().unwrap())))
                }

                self.frame_end = Some(buf[0]);
                self.buffer = vec![0; buf[0] as usize];
            }
        }
    }
}

pub struct Writing<W> where W: ::std::io::Write {
    writer: Option<W>,
    message: Vec<u8>,
    pos: usize,
    wrote_header: bool,
}

impl <W> Writing<W> where W: ::std::io::Write {
    fn new(writer: W, message: Vec<u8>) -> Writing<W> {
        Writing {
            writer: Some(writer),
            message: message,
            pos: 0,
            wrote_header: false,
        }
    }
}

impl <W> Future for Writing<W> where W: ::std::io::Write {
    type Item = W;
    type Error = ::std::io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            if !self.wrote_header {
                let buf = [self.message.len() as u8];
                try_nb!(self.writer.as_mut().unwrap().write(&buf));
            } else {
                let n = try_nb!(self.writer.as_mut().unwrap().write(&self.message[self.pos..]));
                self.pos += n;
                if self.pos >= self.message.len() {
                    return Ok(Async::Ready(self.writer.take().unwrap()))
                }
            }
        }
    }
}

fn new_task(handle: &::tokio_core::reactor::Handle,
            addr: &::std::net::SocketAddr) -> Box<Future<Item=(), Error=::std::io::Error> + Send> {
    let publisher = ::tokio_core::net::TcpStream::connect(addr, handle);
    let mut subscribers = Vec::new();
    for _ in 0..3 {
        subscribers.push(::tokio_core::net::TcpStream::connect(addr, handle));
    }
    Box::new(publisher.join(::all::All::new(subscribers.into_iter())).and_then(|(publisher, subscribers)| {
        println!("connected");

// TODO
//        publisher.write_all([0]).join(::all::All::new(subscibers.into_iter()))

        tie_knot((publisher, subscribers, 10u32), |(publisher, subscribers, n)| {
            Writing::new(publisher, vec![n as u8, 1,2,3]).and_then(move |publisher| {
                println!("looping {}", n);
                futures::finished(((publisher, subscribers, n - 1), n > 0))
            })
        }).map(|_| ())
    }))
}

pub fn run() -> Result<(), ::std::io::Error> {
    use clap::{App, Arg};
    let matches = App::new("Zillions benchmarker")
        .version("0.0.0")
        .about("Does awesome things")
        .arg(Arg::with_name("EXECUTABLE")
             .required(true)
             .index(1)
             .help("The executable to benchmark"))
        .get_matches();

    let executable = matches.value_of("EXECUTABLE").unwrap();

    println!("exectuable: {}", executable);

    let addr_str = "127.0.0.1:8080";
    let addr = match addr_str.parse::<::std::net::SocketAddr>() {
        Ok(a) => a,
        Err(e) => {
            panic!("failed to parse socket address {}", e);
        }
    };

    let _child = ::std::process::Command::new(executable)
        .arg(addr_str)
        .spawn();

    // start tokio reactor
    let mut core = try!(::tokio_core::reactor::Core::new());

    let handle = core.handle();

    let pool = ::futures_cpupool::CpuPool::new_num_cpus();

    let f = pool.spawn(new_task(&handle, &addr));

    try!(core.run(f));

    Ok(())
}

pub fn main() {
    run().expect("top level error");
}
<commit_msg>write initial bytes<commit_after>extern crate byteorder;
extern crate clap;

#[macro_use]
extern crate futures;
extern crate futures_cpupool;

#[macro_use]
extern crate tokio_core;

use futures::{Async, Poll, Future};

mod all {
    use futures::{Async, Poll, Future};
    enum ElemState<T> where T: Future {
        Pending(T),
        Done(T::Item),
    }

    pub struct All<T> where T: Future {
        elems: Vec<ElemState<T>>,
    }

    impl <T> All<T> where T: Future {
        pub fn new<I>(futures: I) -> All<T> where I: Iterator<Item=T> {
            let mut result = All { elems: Vec::new() };
            for f in futures {
                result.elems.push(ElemState::Pending(f))
            }
            result
        }
    }

    impl <T> Future for All<T> where T: Future {
        type Item = Vec<T::Item>;
        type Error = T::Error;

        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            let mut all_done = true;

            for idx in 0 .. self.elems.len() {
                let done_val = match &mut self.elems[idx] {
                    &mut ElemState::Pending(ref mut t) => {
                        match t.poll() {
                            Ok(Async::Ready(t)) => t,
                            Ok(Async::NotReady) => {
                                all_done = false;
                                continue
                            }
                            Err(e) => return Err(e),
                        }
                    }
                    &mut ElemState::Done(ref mut _v) => continue,
                };

                self.elems[idx] = ElemState::Done(done_val);
            }

            if all_done {
                let mut result = Vec::new();
                let elems = ::std::mem::replace(&mut self.elems, Vec::new());
                for e in elems.into_iter() {
                    match e {
                        ElemState::Done(t) => result.push(t),
                        _ => unreachable!(),
                    }
                }
                Ok(Async::Ready(result))
            } else {
                Ok(Async::NotReady)
            }
        }
    }
}

struct Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>
{
    f: F,
    in_progress: T,
}

fn tie_knot<F, S, T, E>(initial_state: S, f: F) -> Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>,
{
    let in_progress = f(initial_state);
    Knot {
        f: f,
        in_progress: in_progress,
    }
}

impl <F, S, T, E> Future for Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>
{
    type Item = S;
    type Error = E;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            let (s, more) = try_ready!(self.in_progress.poll());
            if more {
                self.in_progress = (self.f)(s);
            } else {
                return Ok(Async::Ready(s))
            }
        }
    }
}

struct Reading<R> where R: ::std::io::Read {
    reader: Option<R>,
    buffer: Vec<u8>,
    pos: usize,
    frame_end: Option<u8>,
}

impl <R> Reading<R> where R: ::std::io::Read {
    fn new(reader: R) -> Reading<R> {
        Reading {
            reader: Some(reader),
            buffer: Vec::new(),
            pos: 0,
            frame_end: None,
        }
    }
}

impl <R> Future for Reading<R> where R: ::std::io::Read {
    type Item = (Option<Vec<u8>>, R);
    type Error = ::std::io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            if let Some(frame_end) = self.frame_end {
                let n = try_nb!(self.reader.as_mut().unwrap().read(&mut self.buffer[self.pos..frame_end as usize]));
                self.pos += n;
                if self.pos == frame_end as usize {
                    self.pos = 0;
                    let result = ::std::mem::replace(&mut self.buffer, Vec::new());
                    self.frame_end = None;
                    return Ok(Async::Ready((Some(result), self.reader.take().unwrap())))
                }
            } else {
                let mut buf = [0u8];
                let n = try_nb!(self.reader.as_mut().unwrap().read(&mut buf));
                if n == 0 { // EOF
                    return Ok(Async::Ready((None, self.reader.take().unwrap())))
                }

                self.frame_end = Some(buf[0]);
                self.buffer = vec![0; buf[0] as usize];
            }
        }
    }
}

pub struct Writing<W> where W: ::std::io::Write {
    writer: Option<W>,
    message: Vec<u8>,
    pos: usize,
    wrote_header: bool,
}

impl <W> Writing<W> where W: ::std::io::Write {
    fn new(writer: W, message: Vec<u8>) -> Writing<W> {
        Writing {
            writer: Some(writer),
            message: message,
            pos: 0,
            wrote_header: false,
        }
    }
}

impl <W> Future for Writing<W> where W: ::std::io::Write {
    type Item = W;
    type Error = ::std::io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            if !self.wrote_header {
                let buf = [self.message.len() as u8];
                try_nb!(self.writer.as_mut().unwrap().write(&buf));
            } else {
                let n = try_nb!(self.writer.as_mut().unwrap().write(&self.message[self.pos..]));
                self.pos += n;
                if self.pos >= self.message.len() {
                    return Ok(Async::Ready(self.writer.take().unwrap()))
                }
            }
        }
    }
}

fn new_task(handle: &::tokio_core::reactor::Handle,
            addr: &::std::net::SocketAddr) -> Box<Future<Item=(), Error=::std::io::Error> + Send> {
    let publisher = ::tokio_core::net::TcpStream::connect(addr, handle).and_then(|stream| {
        tokio_core::io::write_all(stream, [0]).map(|(a,_)| a)
    });

    let mut subscribers = Vec::new();
    for _ in 0..3 {
        subscribers.push(::tokio_core::net::TcpStream::connect(addr, handle).and_then(|stream| {
            tokio_core::io::write_all(stream, [1]).map(|(a,_)| a)
        }));
    }

    Box::new(publisher.join(::all::All::new(subscribers.into_iter())).and_then(|(publisher, subscribers)| {
        println!("connected");

        tie_knot((publisher, subscribers, 10u32), |(publisher, subscribers, n)| {
            println!("looping {}", n);
            Writing::new(publisher, vec![n as u8, 1,2,3]).and_then(move |publisher| {
                futures::finished(((publisher, subscribers, n - 1), n > 0))
            })
        }).map(|_| ())
    }))
}

pub fn run() -> Result<(), ::std::io::Error> {
    use clap::{App, Arg};
    let matches = App::new("Zillions benchmarker")
        .version("0.0.0")
        .about("Does awesome things")
        .arg(Arg::with_name("EXECUTABLE")
             .required(true)
             .index(1)
             .help("The executable to benchmark"))
        .get_matches();

    let executable = matches.value_of("EXECUTABLE").unwrap();

    println!("exectuable: {}", executable);

    let addr_str = "127.0.0.1:8080";
    let addr = match addr_str.parse::<::std::net::SocketAddr>() {
        Ok(a) => a,
        Err(e) => {
            panic!("failed to parse socket address {}", e);
        }
    };

    let _child = ::std::process::Command::new(executable)
        .arg(addr_str)
        .spawn();

    // start tokio reactor
    let mut core = try!(::tokio_core::reactor::Core::new());

    let handle = core.handle();

    let pool = ::futures_cpupool::CpuPool::new_num_cpus();

    let f = pool.spawn(new_task(&handle, &addr));

    try!(core.run(f));

    Ok(())
}

pub fn main() {
    run().expect("top level error");
}
<|endoftext|>


<commit_before>use std::os;

use cargo::core::MultiShell;
use cargo::ops::CompileOptions;
use cargo::ops;
use cargo::util::important_paths::{find_root_manifest_for_cwd};
use cargo::util::{CliResult, CliError};
use docopt;

docopt!(Options, "
Compile a local package and all of its dependencies

Usage:
    cargo build [options]

Options:
    -h, --help               Print this message
    -p SPEC, --package SPEC  Package to run benchmarks for
    -j N, --jobs N           The number of jobs to run in parallel
    --release                Build artifacts in release mode, with optimizations
    --features FEATURES      Space-separated list of features to also build
    --no-default-features    Do not build the `default` feature
    --target TRIPLE          Build for the target triple
    --manifest-path PATH     Path to the manifest to compile
    -v, --verbose            Use verbose output

If the --package argument is given, then SPEC is a package id specification
which indicates which package should be built. If it is not given, then the
current package built tested. For more information on SPEC and its format, see the
`cargo help pkgid` command.
",  flag_jobs: Option<uint>, flag_target: Option<String>,
    flag_manifest_path: Option<String>, flag_features: Vec<String>,
    flag_package: Option<String>)

pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>> {
    debug!("executing; cmd=cargo-build; args={}", os::args());
    shell.set_verbose(options.flag_verbose);

    let root = try!(find_root_manifest_for_cwd(options.flag_manifest_path));

    let env = if options.flag_release {
        "release"
    } else {
        "compile"
    };

    let mut opts = CompileOptions {
        env: env,
        shell: shell,
        jobs: options.flag_jobs,
        target: options.flag_target.as_ref().map(|t| t.as_slice()),
        dev_deps: false,
        features: options.flag_features.as_slice(),
        no_default_features: options.flag_no_default_features,
        spec: options.flag_package.as_ref().map(|s| s.as_slice()),
    };

    ops::compile(&root, &mut opts).map(|_| None).map_err(|err| {
        CliError::from_boxed(err, 101)
    })
}
<commit_msg>Fix typos in `cargo build -h`<commit_after>use std::os;

use cargo::core::MultiShell;
use cargo::ops::CompileOptions;
use cargo::ops;
use cargo::util::important_paths::{find_root_manifest_for_cwd};
use cargo::util::{CliResult, CliError};
use docopt;

docopt!(Options, "
Compile a local package and all of its dependencies

Usage:
    cargo build [options]

Options:
    -h, --help               Print this message
    -p SPEC, --package SPEC  Package to build
    -j N, --jobs N           The number of jobs to run in parallel
    --release                Build artifacts in release mode, with optimizations
    --features FEATURES      Space-separated list of features to also build
    --no-default-features    Do not build the `default` feature
    --target TRIPLE          Build for the target triple
    --manifest-path PATH     Path to the manifest to compile
    -v, --verbose            Use verbose output

If the --package argument is given, then SPEC is a package id specification
which indicates which package should be built. If it is not given, then the
current package is built. For more information on SPEC and its format, see the
`cargo help pkgid` command.
",  flag_jobs: Option<uint>, flag_target: Option<String>,
    flag_manifest_path: Option<String>, flag_features: Vec<String>,
    flag_package: Option<String>)

pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>> {
    debug!("executing; cmd=cargo-build; args={}", os::args());
    shell.set_verbose(options.flag_verbose);

    let root = try!(find_root_manifest_for_cwd(options.flag_manifest_path));

    let env = if options.flag_release {
        "release"
    } else {
        "compile"
    };

    let mut opts = CompileOptions {
        env: env,
        shell: shell,
        jobs: options.flag_jobs,
        target: options.flag_target.as_ref().map(|t| t.as_slice()),
        dev_deps: false,
        features: options.flag_features.as_slice(),
        no_default_features: options.flag_no_default_features,
        spec: options.flag_package.as_ref().map(|s| s.as_slice()),
    };

    ops::compile(&root, &mut opts).map(|_| None).map_err(|err| {
        CliError::from_boxed(err, 101)
    })
}
<|endoftext|>


<commit_before>#![feature(phase)]

extern crate cargo;
extern crate hammer;
extern crate serialize;
#[phase(plugin, link)]
extern crate log;

use hammer::{FlagConfig,FlagConfiguration};
use std::os;
use std::io::process::{Command,InheritFd,ExitStatus,ExitSignal};
use serialize::Encodable;
use cargo::{GlobalFlags, NoFlags, execute_main_without_stdin, handle_error, shell};
use cargo::core::MultiShell;
use cargo::util::important_paths::find_project;
use cargo::util::{CliError, CliResult, Require, config, human};

fn main() {
    execute();
}

#[deriving(Encodable)]
struct ProjectLocation {
    root: String
}

/**
  The top-level `cargo` command handles configuration and project location
  because they are fundamental (and intertwined). Other commands can rely
  on this top-level information.
*/
fn execute() {
    debug!("executing; cmd=cargo; args={}", os::args());

    let (cmd, args) = process(os::args());

    match cmd.as_slice() {
        "config-for-key" => {
            log!(4, "cmd == config-for-key");
            execute_main_without_stdin(config_for_key)
        },
        "config-list" => {
            log!(4, "cmd == config-list");
            execute_main_without_stdin(config_list)
        },
        "locate-project" => {
            log!(4, "cmd == locate-project");
            execute_main_without_stdin(locate_project)
        },
        "--help" | "-h" | "help" | "-?" => {
            println!("Commands:");
            println!("  build          # compile the current project\n");

            let (_, options) = hammer::usage::<GlobalFlags>(false);
            println!("Options (for all commands):\n\n{}", options);
        },
        _ => {
            let command = Command::new(format!("cargo-{}", cmd))
                .args(args.as_slice())
                .stdin(InheritFd(0))
                .stdout(InheritFd(1))
                .stderr(InheritFd(2))
                .status();

            match command {
                Ok(ExitStatus(0)) => (),
                Ok(ExitStatus(i)) | Ok(ExitSignal(i)) => {
                    handle_error(CliError::new("", i as uint), &mut shell(false))
                }
                Err(_) => handle_error(CliError::new("No such subcommand", 127), &mut shell(false))
            }
        }
    }
}

fn process(args: Vec<String>) -> (String, Vec<String>) {
    let mut args = Vec::from_slice(args.tail());
    let head = args.shift().unwrap_or("--help".to_str());

    (head, args)
}

#[deriving(Encodable)]
struct ConfigOut {
    values: std::collections::HashMap<String, config::ConfigValue>
}

#[deriving(Decodable)]
struct ConfigForKeyFlags {
    key: String,
    human: bool
}

impl FlagConfig for ConfigForKeyFlags {
    fn config(_: Option<ConfigForKeyFlags>,
              config: FlagConfiguration) -> FlagConfiguration {
        config.short("human", 'h')
    }
}

fn config_for_key(args: ConfigForKeyFlags, _: &mut MultiShell) -> CliResult<Option<ConfigOut>> {
    let value = try!(config::get_config(os::getcwd(),
                                        args.key.as_slice()).map_err(|_| {
        CliError::new("Couldn't load configuration",  1)
    }));

    if args.human {
        println!("{}", value);
        Ok(None)
    } else {
        let mut map = std::collections::HashMap::new();
        map.insert(args.key.clone(), value);
        Ok(Some(ConfigOut { values: map }))
    }
}

#[deriving(Decodable)]
struct ConfigListFlags {
    human: bool
}

impl FlagConfig for ConfigListFlags {
    fn config(_: Option<ConfigListFlags>,
              config: FlagConfiguration) -> FlagConfiguration {
        config.short("human", 'h')
    }
}

fn config_list(args: ConfigListFlags, _: &mut MultiShell) -> CliResult<Option<ConfigOut>> {
    let configs = try!(config::all_configs(os::getcwd()).map_err(|_|
        CliError::new("Couldn't load configuration", 1)));

    if args.human {
        for (key, value) in configs.iter() {
            println!("{} = {}", key, value);
        }
        Ok(None)
    } else {
        Ok(Some(ConfigOut { values: configs }))
    }
}

fn locate_project(_: NoFlags, _: &mut MultiShell) -> CliResult<Option<ProjectLocation>> {
    let root = try!(find_project(os::getcwd(), "Cargo.toml").map_err(|e| {
        CliError::from_boxed(e, 1)
    }));

    let string = try!(root.as_str()
                      .require(|| human("Your project path contains characters \
                                         not representable in Unicode"))
                      .map_err(|e| CliError::from_boxed(e, 1)));

    Ok(Some(ProjectLocation { root: string.to_str() }))
}
<commit_msg>Add command line help text for new subcommand 'cargo test'<commit_after>#![feature(phase)]

extern crate cargo;
extern crate hammer;
extern crate serialize;
#[phase(plugin, link)]
extern crate log;

use hammer::{FlagConfig,FlagConfiguration};
use std::os;
use std::io::process::{Command,InheritFd,ExitStatus,ExitSignal};
use serialize::Encodable;
use cargo::{GlobalFlags, NoFlags, execute_main_without_stdin, handle_error, shell};
use cargo::core::MultiShell;
use cargo::util::important_paths::find_project;
use cargo::util::{CliError, CliResult, Require, config, human};

fn main() {
    execute();
}

#[deriving(Encodable)]
struct ProjectLocation {
    root: String
}

/**
  The top-level `cargo` command handles configuration and project location
  because they are fundamental (and intertwined). Other commands can rely
  on this top-level information.
*/
fn execute() {
    debug!("executing; cmd=cargo; args={}", os::args());

    let (cmd, args) = process(os::args());

    match cmd.as_slice() {
        "config-for-key" => {
            log!(4, "cmd == config-for-key");
            execute_main_without_stdin(config_for_key)
        },
        "config-list" => {
            log!(4, "cmd == config-list");
            execute_main_without_stdin(config_list)
        },
        "locate-project" => {
            log!(4, "cmd == locate-project");
            execute_main_without_stdin(locate_project)
        },
        "--help" | "-h" | "help" | "-?" => {
            println!("Commands:");
            println!("  build          # compile the current project\n");
            println!("  test           # run the tests\n");

            let (_, options) = hammer::usage::<GlobalFlags>(false);
            println!("Options (for all commands):\n\n{}", options);
        },
        _ => {
            let command = Command::new(format!("cargo-{}", cmd))
                .args(args.as_slice())
                .stdin(InheritFd(0))
                .stdout(InheritFd(1))
                .stderr(InheritFd(2))
                .status();

            match command {
                Ok(ExitStatus(0)) => (),
                Ok(ExitStatus(i)) | Ok(ExitSignal(i)) => {
                    handle_error(CliError::new("", i as uint), &mut shell(false))
                }
                Err(_) => handle_error(CliError::new("No such subcommand", 127), &mut shell(false))
            }
        }
    }
}

fn process(args: Vec<String>) -> (String, Vec<String>) {
    let mut args = Vec::from_slice(args.tail());
    let head = args.shift().unwrap_or("--help".to_str());

    (head, args)
}

#[deriving(Encodable)]
struct ConfigOut {
    values: std::collections::HashMap<String, config::ConfigValue>
}

#[deriving(Decodable)]
struct ConfigForKeyFlags {
    key: String,
    human: bool
}

impl FlagConfig for ConfigForKeyFlags {
    fn config(_: Option<ConfigForKeyFlags>,
              config: FlagConfiguration) -> FlagConfiguration {
        config.short("human", 'h')
    }
}

fn config_for_key(args: ConfigForKeyFlags, _: &mut MultiShell) -> CliResult<Option<ConfigOut>> {
    let value = try!(config::get_config(os::getcwd(),
                                        args.key.as_slice()).map_err(|_| {
        CliError::new("Couldn't load configuration",  1)
    }));

    if args.human {
        println!("{}", value);
        Ok(None)
    } else {
        let mut map = std::collections::HashMap::new();
        map.insert(args.key.clone(), value);
        Ok(Some(ConfigOut { values: map }))
    }
}

#[deriving(Decodable)]
struct ConfigListFlags {
    human: bool
}

impl FlagConfig for ConfigListFlags {
    fn config(_: Option<ConfigListFlags>,
              config: FlagConfiguration) -> FlagConfiguration {
        config.short("human", 'h')
    }
}

fn config_list(args: ConfigListFlags, _: &mut MultiShell) -> CliResult<Option<ConfigOut>> {
    let configs = try!(config::all_configs(os::getcwd()).map_err(|_|
        CliError::new("Couldn't load configuration", 1)));

    if args.human {
        for (key, value) in configs.iter() {
            println!("{} = {}", key, value);
        }
        Ok(None)
    } else {
        Ok(Some(ConfigOut { values: configs }))
    }
}

fn locate_project(_: NoFlags, _: &mut MultiShell) -> CliResult<Option<ProjectLocation>> {
    let root = try!(find_project(os::getcwd(), "Cargo.toml").map_err(|e| {
        CliError::from_boxed(e, 1)
    }));

    let string = try!(root.as_str()
                      .require(|| human("Your project path contains characters \
                                         not representable in Unicode"))
                      .map_err(|e| CliError::from_boxed(e, 1)));

    Ok(Some(ProjectLocation { root: string.to_str() }))
}
<|endoftext|>


<commit_before>use raw_cpuid::CpuId;
use termimad::{minimad::TextTemplate, minimad::TextTemplateExpander, MadSkin};

fn string_to_static_str(s: String) -> &'static str {
    Box::leak(s.into_boxed_str())
}

fn make_table<'a, 'b>(
    text_template: &'a TextTemplate<'b>,
    attrs: &[(&'b str, u64)],
) -> TextTemplateExpander<'a, 'b> {
    let mut expander = text_template.expander();
    expander.set("app-version", "2");

    for &(attr, desc) in attrs {
        let sdesc = string_to_static_str(format!("{}", desc));
        expander
            .sub("feature-rows")
            .set("attr-name", attr)
            .set("attr-avail", sdesc);
    }

    expander
}

fn make_feature_table<'a, 'b>(
    text_template: &'a TextTemplate<'b>,
    attrs: &[(&'b str, bool)],
) -> TextTemplateExpander<'a, 'b> {
    let mut expander = text_template.expander();
    expander.set("app-version", "2");

    for &(attr, desc) in attrs {
        let desc = if desc { "✅" } else { "❌" };
        expander
            .sub("feature-rows")
            .set("attr-name", attr)
            .set("attr-avail", desc);
    }

    expander
}

fn print_title_line(title: &str, attr: Option<&str>) {
    let mut skin = MadSkin::default();
    skin.print_text(format!("## {}\n", title).as_str());
}

fn print_title_attr(title: &str, attr: &str) {
    print_title_line(title, Some(attr));
}

fn print_title(title: &str) {
    print_title_line(title, None)
}

fn main() {
    let cpuid = CpuId::new();
    let mut skin = MadSkin::default();

    skin.print_text("# CpuId\n");

    let table_template = TextTemplate::from(
        r#"
    |-:|-:|
    ${feature-rows
    |**${attr-name}**|${attr-avail}|
    }
    |-|-|
    "#,
    );

    if let Some(info) = cpuid.get_vendor_info() {
        print_title_attr("vendor_id (0x00)", info.as_str());
    }

    if let Some(info) = cpuid.get_feature_info() {
        print_title("version information (1/eax):");
        let table = make_table(
            &table_template,
            &[
                ("base family", info.base_family_id().into()),
                ("base model", info.base_model_id().into()),
                ("stepping", info.stepping_id().into()),
                ("extended family", info.extended_family_id().into()),
                ("extended model", info.extended_model_id().into()),
                ("family", info.family_id().into()),
                ("model", info.model_id().into()),
            ],
        );
        skin.print_expander(table);

        print_title("miscellaneous (1/ebx):");
        let table = make_table(
            &table_template,
            &[
                (
                    "processor APIC physical id",
                    info.initial_local_apic_id().into(),
                ),
                ("max. cpus", info.max_logical_processor_ids().into()),
                ("CLFLUSH line size", info.cflush_cache_line_size().into()),
                ("brand index", info.brand_index().into()),
            ],
        );
        skin.print_expander(table);

        print_title("feature information (1/edx):");
        let table = make_feature_table(
            &table_template,
            &[
                ("fpu", info.has_fpu()),
                ("vme", info.has_vme()),
                ("de", info.has_de()),
                ("pse", info.has_pse()),
                ("tsc", info.has_tsc()),
                ("msr", info.has_msr()),
                ("pae", info.has_pae()),
                ("mce", info.has_mce()),
                ("cmpxchg8b", info.has_cmpxchg8b()),
                ("apic", info.has_apic()),
                ("sysenter_sysexit", info.has_sysenter_sysexit()),
                ("mtrr", info.has_mtrr()),
                ("pge", info.has_pge()),
                ("mca", info.has_mca()),
                ("cmov", info.has_cmov()),
                ("pat", info.has_pat()),
                ("pse36", info.has_pse36()),
                ("psn", info.has_psn()),
                ("clflush", info.has_clflush()),
                ("ds", info.has_ds()),
                ("acpi", info.has_acpi()),
                ("mmx", info.has_mmx()),
                ("fxsave_fxstor", info.has_fxsave_fxstor()),
                ("sse", info.has_sse()),
                ("sse2", info.has_sse2()),
                ("ss", info.has_ss()),
                ("htt", info.has_htt()),
                ("tm", info.has_tm()),
                ("pbe", info.has_pbe()),
            ],
        );
        skin.print_expander(table);

        print_title("feature information (1/ecx):");

        let table = make_feature_table(
            &table_template,
            &[
                ("sse3", info.has_sse3()),
                ("pclmulqdq", info.has_pclmulqdq()),
                ("ds_area", info.has_ds_area()),
                ("monitor_mwait", info.has_monitor_mwait()),
                ("cpl", info.has_cpl()),
                ("vmx", info.has_vmx()),
                ("smx", info.has_smx()),
                ("eist", info.has_eist()),
                ("tm2", info.has_tm2()),
                ("ssse3", info.has_ssse3()),
                ("cnxtid", info.has_cnxtid()),
                ("fma", info.has_fma()),
                ("cmpxchg16b", info.has_cmpxchg16b()),
                ("pdcm", info.has_pdcm()),
                ("pcid", info.has_pcid()),
                ("dca", info.has_dca()),
                ("sse41", info.has_sse41()),
                ("sse42", info.has_sse42()),
                ("x2apic", info.has_x2apic()),
                ("movbe", info.has_movbe()),
                ("popcnt", info.has_popcnt()),
                ("tsc_deadline", info.has_tsc_deadline()),
                ("aesni", info.has_aesni()),
                ("xsave", info.has_xsave()),
                ("oxsave", info.has_oxsave()),
                ("avx", info.has_avx()),
                ("f16c", info.has_f16c()),
                ("rdrand", info.has_rdrand()),
                ("hypervisor", info.has_hypervisor()),
            ],
        );
        skin.print_expander(table);
    }

    if let Some(info) = cpuid.get_cache_info() {
        println!("Cache");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_processor_serial() {
        println!("Processor Serial");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_cache_parameters() {
        println!("Cache Parameters");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_monitor_mwait_info() {
        println!("Monitor/MWait");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_thermal_power_info() {
        println!("Thermal Power");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_extended_feature_info() {
        println!("Extended Features");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_direct_cache_access_info() {
        println!("Direct Cache Access");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_performance_monitoring_info() {
        println!("Performance Monitoring");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_extended_topology_info() {
        println!("Extended Topology");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_extended_state_info() {
        println!("Extended State");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_rdt_monitoring_info() {
        println!("RDT Monitoring");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_rdt_allocation_info() {
        println!("RDT Allocation");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_sgx_info() {
        println!("Software Guard Extensions");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_processor_trace_info() {
        println!("Processor Trace");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_tsc_info() {
        println!("TSC");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_processor_frequency_info() {
        println!("Processor Frequency");
        println!("{:?}", info);
    }
    if let Some(dats) = cpuid.get_deterministic_address_translation_info() {
        println!("Deterministic Address Translation");
        for dat in dats {
            println!("{:?}", dat);
        }
    }
    if let Some(info) = cpuid.get_soc_vendor_info() {
        println!("SoC Vendor Info");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_processor_brand_string() {
        println!("Processor Brand String");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_memory_encryption_info() {
        println!("Memory Encryption Info");
        println!("{:?}", info);
    }
}
<commit_msg>More pretty-print for CPUID bin.<commit_after>use std::fmt::Display;

use raw_cpuid::CpuId;
use termimad::{minimad::TextTemplate, minimad::TextTemplateExpander, MadSkin};

fn string_to_static_str(s: String) -> &'static str {
    Box::leak(s.into_boxed_str())
}

fn make_table<'a, 'b>(
    text_template: &'a TextTemplate<'b>,
    attrs: &[(&'b str, u64)],
) -> TextTemplateExpander<'a, 'b> {
    let mut expander = text_template.expander();
    expander.set("app-version", "2");

    for &(attr, desc) in attrs {
        let sdesc = string_to_static_str(format!("{}", desc));
        expander
            .sub("feature-rows")
            .set("attr-name", attr)
            .set("attr-avail", sdesc);
    }

    expander
}

fn make_table_display<'a, 'b, D: Display>(
    text_template: &'a TextTemplate<'b>,
    attrs: &[(&'b str, D)],
) -> TextTemplateExpander<'a, 'b> {
    let mut expander = text_template.expander();
    expander.set("app-version", "2");

    for (attr, desc) in attrs {
        let sdesc = string_to_static_str(format!("{}", desc));
        expander
            .sub("feature-rows")
            .set("attr-name", attr)
            .set("attr-avail", sdesc);
    }

    expander
}

fn make_feature_table<'a, 'b>(
    text_template: &'a TextTemplate<'b>,
    attrs: &[(&'b str, bool)],
) -> TextTemplateExpander<'a, 'b> {
    let mut expander = text_template.expander();
    expander.set("app-version", "2");

    for &(attr, desc) in attrs {
        let desc = if desc { "✅" } else { "❌" };
        expander
            .sub("feature-rows")
            .set("attr-name", attr)
            .set("attr-avail", desc);
    }

    expander
}

fn print_title_line(title: &str, attr: Option<&str>) {
    let skin = MadSkin::default();
    if let Some(opt) = attr {
        skin.print_text(format!("## {} = \"{}\"\n", title, opt).as_str());
    } else {
        skin.print_text(format!("## {}\n", title).as_str());
    }
}

fn print_title_attr(title: &str, attr: &str) {
    print_title_line(title, Some(attr));
}

fn print_title(title: &str) {
    print_title_line(title, None)
}

fn print_subtitle(title: &str) {
    let skin = MadSkin::default();
    skin.print_text(format!("### {}\n", title).as_str());
}

fn main() {
    let cpuid = CpuId::new();
    let skin = MadSkin::default();

    skin.print_text("# CpuId\n");

    let table_template = TextTemplate::from(
        r#"
    |-:|-:|
    ${feature-rows
    |**${attr-name}**|${attr-avail}|
    }
    |-|-|
    "#,
    );

    if let Some(info) = cpuid.get_vendor_info() {
        print_title_attr("vendor_id (0x00)", info.as_str());
    }

    if let Some(info) = cpuid.get_feature_info() {
        print_title("version information (1/eax):");
        let table = make_table(
            &table_template,
            &[
                ("base family", info.base_family_id().into()),
                ("base model", info.base_model_id().into()),
                ("stepping", info.stepping_id().into()),
                ("extended family", info.extended_family_id().into()),
                ("extended model", info.extended_model_id().into()),
                ("family", info.family_id().into()),
                ("model", info.model_id().into()),
            ],
        );
        skin.print_expander(table);

        print_title("miscellaneous (1/ebx):");
        let table = make_table(
            &table_template,
            &[
                (
                    "processor APIC physical id",
                    info.initial_local_apic_id().into(),
                ),
                ("max. cpus", info.max_logical_processor_ids().into()),
                ("CLFLUSH line size", info.cflush_cache_line_size().into()),
                ("brand index", info.brand_index().into()),
            ],
        );
        skin.print_expander(table);

        print_title("feature information (1/edx):");
        let table = make_feature_table(
            &table_template,
            &[
                ("fpu", info.has_fpu()),
                ("vme", info.has_vme()),
                ("de", info.has_de()),
                ("pse", info.has_pse()),
                ("tsc", info.has_tsc()),
                ("msr", info.has_msr()),
                ("pae", info.has_pae()),
                ("mce", info.has_mce()),
                ("cmpxchg8b", info.has_cmpxchg8b()),
                ("apic", info.has_apic()),
                ("sysenter_sysexit", info.has_sysenter_sysexit()),
                ("mtrr", info.has_mtrr()),
                ("pge", info.has_pge()),
                ("mca", info.has_mca()),
                ("cmov", info.has_cmov()),
                ("pat", info.has_pat()),
                ("pse36", info.has_pse36()),
                ("psn", info.has_psn()),
                ("clflush", info.has_clflush()),
                ("ds", info.has_ds()),
                ("acpi", info.has_acpi()),
                ("mmx", info.has_mmx()),
                ("fxsave_fxstor", info.has_fxsave_fxstor()),
                ("sse", info.has_sse()),
                ("sse2", info.has_sse2()),
                ("ss", info.has_ss()),
                ("htt", info.has_htt()),
                ("tm", info.has_tm()),
                ("pbe", info.has_pbe()),
            ],
        );
        skin.print_expander(table);

        print_title("feature information (1/ecx):");

        let table = make_feature_table(
            &table_template,
            &[
                ("sse3", info.has_sse3()),
                ("pclmulqdq", info.has_pclmulqdq()),
                ("ds_area", info.has_ds_area()),
                ("monitor_mwait", info.has_monitor_mwait()),
                ("cpl", info.has_cpl()),
                ("vmx", info.has_vmx()),
                ("smx", info.has_smx()),
                ("eist", info.has_eist()),
                ("tm2", info.has_tm2()),
                ("ssse3", info.has_ssse3()),
                ("cnxtid", info.has_cnxtid()),
                ("fma", info.has_fma()),
                ("cmpxchg16b", info.has_cmpxchg16b()),
                ("pdcm", info.has_pdcm()),
                ("pcid", info.has_pcid()),
                ("dca", info.has_dca()),
                ("sse41", info.has_sse41()),
                ("sse42", info.has_sse42()),
                ("x2apic", info.has_x2apic()),
                ("movbe", info.has_movbe()),
                ("popcnt", info.has_popcnt()),
                ("tsc_deadline", info.has_tsc_deadline()),
                ("aesni", info.has_aesni()),
                ("xsave", info.has_xsave()),
                ("oxsave", info.has_oxsave()),
                ("avx", info.has_avx()),
                ("f16c", info.has_f16c()),
                ("rdrand", info.has_rdrand()),
                ("hypervisor", info.has_hypervisor()),
            ],
        );
        skin.print_expander(table);
    }

    if let Some(info) = cpuid.get_cache_info() {
        println!("Cache");
        println!("{:?}", info);
    }

    if let Some(info) = cpuid.get_processor_serial() {
        print_title_attr(
            "processor serial number (0x03)",
            format!(
                "{:0>8x}-{:0>8x}-{:0>8x}",
                info.serial_upper(),
                info.serial_middle(),
                info.serial_lower()
            )
            .as_str(),
        );
    }

    if let Some(iter) = cpuid.get_cache_parameters() {
        print_title("deterministic cache parameters (0x04):");
        for cache in iter {
            print_subtitle(format!("L{} Cache:", cache.level()).as_str());

            let size = (cache.associativity()
                * cache.physical_line_partitions()
                * cache.coherency_line_size()
                * cache.sets()) as u64;

            let mut attrs = vec![
                ("cache type", format!("{:?}", cache.cache_type())),
                ("cache level", format!("{}", cache.level())),
                (
                    "self-initializing cache level",
                    if cache.is_self_initializing() {
                        "✅".to_string()
                    } else {
                        "❌".to_string()
                    },
                ),
                (
                    "fully associative cache",
                    if cache.is_fully_associative() {
                        "✅".to_string()
                    } else {
                        "❌".to_string()
                    },
                ),
                (
                    "threads sharing this cache",
                    format!("{}", cache.max_cores_for_cache()),
                ),
                (
                    "processor cores on this die",
                    format!("{}", cache.max_cores_for_package()),
                ),
                (
                    "system coherency line size",
                    format!("{}", cache.coherency_line_size()),
                ),
                (
                    "physical line partitions",
                    format!("{}", cache.physical_line_partitions()),
                ),
                (
                    "ways of associativity",
                    format!("{}", cache.associativity()),
                ),
                (
                    "WBINVD/INVD acts on lower caches",
                    if cache.is_write_back_invalidate() {
                        "✅".to_string()
                    } else {
                        "❌".to_string()
                    },
                ),
                (
                    "inclusive to lower caches",
                    if cache.is_inclusive() {
                        "✅".to_string()
                    } else {
                        "❌".to_string()
                    },
                ),
                (
                    "complex cache indexing",
                    if cache.has_complex_indexing() {
                        "✅".to_string()
                    } else {
                        "❌".to_string()
                    },
                ),
                ("number of sets", format!("{}", cache.sets())),
                ("(size synth.)", format!("{}", size)),
            ];

            let table = make_table_display(&table_template, &*attrs);
            skin.print_expander(table);
        }
    }

    if let Some(info) = cpuid.get_monitor_mwait_info() {
        print_title("MONITOR/MWAIT (0x05):");

        let mut attrs = vec![
            (
                "smallest monitor-line size",
                format!("{:?}", info.smallest_monitor_line()),
            ),
            (
                "largest monitor-line size",
                format!("{}", info.largest_monitor_line()),
            ),
            (
                "MONITOR/MWAIT exts supported",
                if info.extensions_supported() {
                    "✅".to_string()
                } else {
                    "❌".to_string()
                },
            ),
        ];

        let table = make_table_display(&table_template, &*attrs);
        skin.print_expander(table);

        println!("{:?}", info);
    }

    /*
    ///   MONITOR/MWAIT (5):
    ///      smallest monitor-line size (bytes)       = 0x40 (64)
    ///      largest monitor-line size (bytes)        = 0x40 (64)
    ///      enum of Monitor-MWAIT exts supported     = true
    ///      supports intrs as break-event for MWAIT  = true
    ///      number of C0 sub C-states using MWAIT    = 0x1 (1)
    ///      number of C1 sub C-states using MWAIT    = 0x1 (1)
    ///      number of C2 sub C-states using MWAIT    = 0x0 (0)
    ///      number of C3 sub C-states using MWAIT    = 0x0 (0)
    ///      number of C4 sub C-states using MWAIT    = 0x0 (0)
    ///      number of C5 sub C-states using MWAIT    = 0x0 (0)
    ///      number of C6 sub C-states using MWAIT    = 0x0 (0)
    ///      number of C7 sub C-states using MWAIT    = 0x0 (0)

        */

    /*
    if let Some(info) = cpuid.get_thermal_power_info() {
        println!("Thermal Power");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_extended_feature_info() {
        println!("Extended Features");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_direct_cache_access_info() {
        println!("Direct Cache Access");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_performance_monitoring_info() {
        println!("Performance Monitoring");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_extended_topology_info() {
        println!("Extended Topology");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_extended_state_info() {
        println!("Extended State");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_rdt_monitoring_info() {
        println!("RDT Monitoring");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_rdt_allocation_info() {
        println!("RDT Allocation");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_sgx_info() {
        println!("Software Guard Extensions");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_processor_trace_info() {
        println!("Processor Trace");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_tsc_info() {
        println!("TSC");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_processor_frequency_info() {
        println!("Processor Frequency");
        println!("{:?}", info);
    }
    if let Some(dats) = cpuid.get_deterministic_address_translation_info() {
        println!("Deterministic Address Translation");
        for dat in dats {
            println!("{:?}", dat);
        }
    }
    if let Some(info) = cpuid.get_soc_vendor_info() {
        println!("SoC Vendor Info");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_processor_brand_string() {
        println!("Processor Brand String");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_memory_encryption_info() {
        println!("Memory Encryption Info");
        println!("{:?}", info);
    }
    */
}
<|endoftext|>


<commit_before>/*
  Copyright (c) 2015, Al Poole <netstar@gmail.com>

  Permission to use, copy, modify, and/or distribute this software for any
  purpose with or without fee is hereby granted, provided that the above
  copyright notice and this permission notice appear in all copies.

  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  PERFORMANCE OF THIS SOFTWARE.
*/

//   This is a HTTP proxy written in Rust!
//   DONE: POST+GET+OPTIONS

use std::string::{String};
use std::net::{SocketAddrV4,Ipv4Addr,TcpListener,TcpStream};
use std::io::{Write, Read};

const REQUEST_LEN: usize = 65535;

fn substr(buf: [u8;REQUEST_LEN], needle: &str, byte: u8) -> String
{
	let mut i = 0;
	let mut x = 0;
	let mut request = String::new();

	let srch = needle.as_bytes();

	if srch.len() == 0 {
		return request;
	}

	while buf[i] as char != '\0' {
		if buf[i] as char == srch[0] as char {
			while x < srch.len() && buf[i] as char  == srch[x] as char {
				i = i + 1;
				x = x + 1;
			}
			break;
		} else {
			i = i + 1;
		}
	}

	if x == srch.len()
	{
		//println!("match");
		let mut end = i;
		while buf[end] as char != byte as char && buf[end] as char != '\n' {
			end = end + 1;
		}

		for y in i..end {
			request.push(buf[y] as char);
		}
	}

	return request;
}

const CHUNK: usize = 4096; // PAGESIZEish

fn get_with_content_length(mut instream: &TcpStream, mut outstream: &TcpStream, total: usize) {
	let mut current = 0;
	let mut buf = [0u8; CHUNK];

	while current < total {
		let bytes = outstream.read(&mut buf). unwrap();
		if bytes == 0 {
			break;
		}

		let mut chunk = 0;

		while chunk < bytes {
			let sent = instream.write(&mut buf[0..bytes]).unwrap();
			if sent <= 0 {
				break;
			}
			chunk = chunk + sent;
			current = current + chunk;
		}
	}
}

fn get_with_no_content_length(mut instream: &TcpStream, mut outstream: &TcpStream)
{
	loop {
		let mut buf = [0u8; CHUNK];

		let bytes = outstream.read(&mut buf).unwrap();
		if bytes == 0 {
			break; // please!!!
		}

		let mut chunk = 0;

		while chunk < bytes {
			let sent = instream.write(&mut buf[0..bytes]).unwrap();
			if sent == 0 {
				break;
			}
			chunk = chunk + sent;
		}
	}
}

fn http_options_request(mut instream: TcpStream)
{
	let allow = "GET,POST,HEAD,CONNECT,OPTIONS";
	let code: String = "HTTP/1.1 200 OK\r\n".to_string();
	let request: String  = "Allow: ".to_string() + allow + "\r\n\r\n";

	let response = format!("{}{}", code, request);

	instream.write(response.as_bytes()).unwrap();
}

fn http_head_request(hdr: Header)
{
	let bogus_fix = &format!("{}:{}", hdr.hostname, 80);

	let mut outstream = TcpStream::connect::<(&str)>(bogus_fix).unwrap();

	let query: String = format!("HEAD /{} HTTP/1.1\r\nHost: {}\r\n\r\n", hdr.resource, hdr.hostname);

	outstream.write(query.as_bytes()).unwrap();
}

fn http_post_request(mut instream: TcpStream, headers: Header)
{
	let bogus_fix = &format!("{}:{}", headers.hostname, 80);
	let mut outstream = TcpStream::connect::<(&str)>(bogus_fix).unwrap();

	let query: String = format!("POST {}Host: {}\r\nContent-Type: {}\r\nContent-Length: {}\r\n\r\n", headers.resource, headers.hostname, headers.content, headers.length);
	outstream.write(query.as_bytes()).unwrap();

	println!("QUERY: {}", query);

	let mut buf = [0u8; CHUNK];
	let mut current = 0;

	while current < headers.length {
		let bytes = instream.read(&mut buf).unwrap();
		if bytes == 0 {
			break;
		}

		let mut chunk = 0;

		while chunk < bytes {
			let sent = outstream.write(&mut buf[0..bytes]).unwrap();
			if sent == 0 {
				break;
			}

			chunk += sent;
			current = current + chunk;
		}
	}

	let terminate = "\r\n\r\n";

	outstream.write(terminate.as_bytes()).unwrap();

	get_with_no_content_length(&instream, &outstream);
}

fn http_get_request(instream: TcpStream, headers: Header)
{
	let bogus_fix = &format!("{}:{}", headers.hostname, 80);

	let mut outstream = TcpStream::connect::<(&str)>(bogus_fix).unwrap();

	let query: String = format!("GET {}Host: {}\r\nConnection: close\r\n\r\n", headers.resource, headers.hostname);
	outstream.write(query.as_bytes()).unwrap();

	println!("QUERY: {}", query);

	if headers.length > 0 {
		get_with_content_length(&instream, &outstream, headers.length);
	} else {
		get_with_no_content_length(&instream, &outstream);
	}
}

fn http_connect_request(instream: TcpStream, hdr: Header)
{
	let bogus_fix = &format!("{}:{}", hdr.hostname, 443);
	// this needs fixing!!!

	let outstream = TcpStream::connect::<(&str)>(bogus_fix).unwrap();

	get_with_no_content_length(&instream, &outstream);
}

fn req_resource(buf: [u8;REQUEST_LEN]) -> String
{
	let mut i = 0;
	let bytes = buf;
	let mut request: String = String::new();

	// FIXME WORDPRESS DOESN't WORK!
	while bytes[i] as char != '\0' {
		request.push(bytes[i] as char);
		i += 1;
	}

	return request;
}

fn req_content(buf: [u8;REQUEST_LEN]) -> String
{
	let content = substr(buf, "Content-Type: ", '\r' as u8);

	return content;
}

fn req_hostname(buf: [u8;REQUEST_LEN]) -> String
{
	let hostname: String = substr(buf, "http://", '/' as u8);

	return hostname;
}

fn req_length(buf: [u8;REQUEST_LEN]) -> usize
{
	let request: String = substr(buf, "Content-Length: ", '\r' as u8);
	if ! request.is_empty() {
		return request.trim().parse().unwrap();
	}

	return 0;
}

struct Header {
	pub hostname: String,
	pub resource: String,
	pub content: String,
	pub length: usize,
	pub method: String,
}

impl Header {

pub fn new() -> Header
{
	let hostname = String::new();
	let resource = String::new();
	let content  = String::new();
	let method   = String::new();
	let length   = 0;

	let h = Header {
		hostname: hostname,
		resource: resource ,
		content: content,
		length: length,
		method: method
	};

	return h;
}

}

fn check_headers(buffer: [u8;REQUEST_LEN], headers: &mut Header) -> bool
{
	if headers.hostname.is_empty() {
		headers.hostname = req_hostname(buffer);
	}

	if headers.resource.is_empty() {
		headers.resource = req_resource(buffer);
	}

	if headers.content.is_empty() {
		headers.content = req_content(buffer);
	}

	if headers.length == 0 {
		headers.length = req_length(buffer);
	}

	if headers.hostname.is_empty() || headers.resource.is_empty() || headers.method.is_empty() {
		return false;
	}

	return true;
}

fn request_headers(mut instream: &TcpStream, headers: &mut Header)
{
	let mut byte = [0u8;1];

	// bit better for now it'll do!
	while byte[0] as char != ' ' {
		instream.read(&mut byte).unwrap();
		if byte[0] as char != ' '
		{
			headers.method.push(byte[0] as char);
		}
	}

	match headers.method.as_ref() {
		"GET" | "POST" | "OPTIONS" | "HEAD" | "CONNECT" =>
		{
			// all good do not return!!!
		}

		_ =>
		{
			return;
		}
	}

	loop {
		let mut buffer = [0u8; REQUEST_LEN];
		let mut byte = [0u8; 1];
		let mut len = 0;

		while byte[0] as char != '\n' {
			let bytes = instream.read(&mut byte).unwrap();
			buffer[len] = byte[0];
			len += bytes;
		}

		buffer[len] = '\0' as u8;

		if check_headers(buffer, headers) && len == 2 {
			let mut i = 0;

			while i < REQUEST_LEN {
				buffer[i] = 0;
				i += 1;
			}
			return;
		}
	}
}

fn proxy(stream: TcpStream) {
	let mut headers: Header = Header::new();
	request_headers(&stream, &mut headers);

	match headers.method.as_ref() {
		"GET" =>
		{
			http_get_request(stream, headers);
		}

		"POST" =>
		{
			http_post_request(stream, headers);
		}

		"HEAD" =>
		{
			http_head_request(headers);
		}

		"OPTIONS" =>
		{
			http_options_request(stream);
		}

		"CONNECT" =>
		{
			println!("here {} and {}", headers.hostname, headers.resource);
			http_connect_request(stream, headers);
		}

		_ =>
		{
			println!("REQUEST UNKNOWN");
		}
	}
}

extern crate threadpool;
use threadpool::ThreadPool;

fn proxy_time(port: u16, threads: usize) {
	let ip = Ipv4Addr::new(127, 0, 0, 1);
	let host = SocketAddrV4::new(ip, port);
	let listener = TcpListener::bind(host).unwrap();

	let pool = ThreadPool::new(threads);

	for stream in listener.incoming()
	{
		match stream
		{
			Ok(stream) =>
			{
				pool.execute(move || { proxy(stream); });
			}

			Err(_) =>
			{
				println!("NET error");
				1 << 7;
			}
		}
	}

	drop (listener);
}

fn main () {
	let threads = 128;
	let port: u16 = 9999;

	proxy_time(port, threads);
	println!("Blocking all badness");
}

<commit_msg>meh weird<commit_after>/*
  Copyright (c) 2015, Al Poole <netstar@gmail.com>

  Permission to use, copy, modify, and/or distribute this software for any
  purpose with or without fee is hereby granted, provided that the above
  copyright notice and this permission notice appear in all copies.

  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  PERFORMANCE OF THIS SOFTWARE.
*/

//   This is a HTTP proxy written in Rust!
//   DONE: POST+GET+OPTIONS

use std::string::{String};
use std::net::{SocketAddrV4,Ipv4Addr,TcpListener,TcpStream};
use std::io::{Write, Read};

const REQUEST_LEN: usize = 65535;

fn substr(buf: [u8;REQUEST_LEN], needle: &str, byte: u8) -> String
{
	let mut i = 0;
	let mut x = 0;
	let mut request = String::new();

	let srch = needle.as_bytes();

	if srch.len() == 0 {
		return request;
	}

	while buf[i] as char != '\0' {
		if buf[i] as char == srch[0] as char {
			while x < srch.len() && buf[i] as char  == srch[x] as char {
				i = i + 1;
				x = x + 1;
			}
			break;
		} else {
			i = i + 1;
		}
	}

	if x == srch.len()
	{
		//println!("match");
		let mut end = i;
		while buf[end] as char != byte as char && buf[end] as char != '\n' {
			end = end + 1;
		}

		for y in i..end {
			request.push(buf[y] as char);
		}
	}

	return request;
}

const CHUNK: usize = 4096; // PAGESIZEish

fn get_with_content_length(mut instream: &TcpStream, mut outstream: &TcpStream, total: usize) {
	let mut current = 0;
	let mut buf = [0u8; CHUNK];

	while current < total {
		let bytes = outstream.read(&mut buf). unwrap();
		if bytes == 0 {
			break;
		}

		let mut chunk = 0;

		while chunk < bytes {
			let sent = instream.write(&mut buf[0..bytes]).unwrap();
			if sent <= 0 {
				break;
			}
			chunk = chunk + sent;
			current = current + chunk;
		}
	}
}

fn get_with_no_content_length(mut instream: &TcpStream, mut outstream: &TcpStream)
{
	loop {
		let mut buf = [0u8; CHUNK];

		let bytes = outstream.read(&mut buf).unwrap();
		if bytes == 0 {
			break; // please!!!
		}

		let mut chunk = 0;

		while chunk < bytes {
			let sent = instream.write(&mut buf[0..bytes]).unwrap();
			if sent == 0 {
				break;
			}
			chunk = chunk + sent;
		}
	}
}

fn http_options_request(mut instream: TcpStream)
{
	let allow = "GET,POST,HEAD,CONNECT,OPTIONS";
	let code: String = "HTTP/1.1 200 OK\r\n".to_string();
	let request: String  = "Allow: ".to_string() + allow + "\r\n\r\n";

	let response = format!("{}{}", code, request);

	instream.write(response.as_bytes()).unwrap();
}

fn http_head_request(hdr: Header)
{
	let bogus_fix = &format!("{}:{}", hdr.hostname, 80);

	let mut outstream = TcpStream::connect::<(&str)>(bogus_fix).unwrap();

	let query: String = format!("HEAD /{} HTTP/1.1\r\nHost: {}\r\n\r\n", hdr.resource, hdr.hostname);

	outstream.write(query.as_bytes()).unwrap();
}

fn http_post_request(mut instream: TcpStream, headers: Header)
{
	let bogus_fix = &format!("{}:{}", headers.hostname, 80);
	let mut outstream = TcpStream::connect::<(&str)>(bogus_fix).unwrap();

	let query: String = format!("POST {}Host: {}\r\nContent-Type: {}\r\nContent-Length: {}\r\n\r\n", headers.resource, headers.hostname, headers.content, headers.length);
	outstream.write(query.as_bytes()).unwrap();

	println!("QUERY: {}", query);

	let mut buf = [0u8; CHUNK];
	let mut current = 0;

	while current < headers.length {
		let bytes = instream.read(&mut buf).unwrap();
		if bytes == 0 {
			break;
		}

		let mut chunk = 0;

		while chunk < bytes {
			let sent = outstream.write(&mut buf[0..bytes]).unwrap();
			if sent == 0 {
				break;
			}

			chunk += sent;
			current = current + chunk;
		}
	}

	let terminate = "\r\n\r\n";

	outstream.write(terminate.as_bytes()).unwrap();

	get_with_no_content_length(&instream, &outstream);
}

fn http_get_request(instream: TcpStream, headers: Header)
{
	let bogus_fix = &format!("{}:{}", headers.hostname, 80);

	let mut outstream = TcpStream::connect::<(&str)>(bogus_fix).unwrap();

	let query: String = format!("GET {}Host: {}\r\nConnection: close\r\n\r\n", headers.resource, headers.hostname);
	outstream.write(query.as_bytes()).unwrap();

	println!("QUERY: {}", query);

	if headers.length > 0 {
		get_with_content_length(&instream, &outstream, headers.length);
	} else {
		get_with_no_content_length(&instream, &outstream);
	}
}

fn http_connect_request(instream: TcpStream, hdr: Header)
{
	let bogus_fix = &format!("{}:{}", hdr.hostname, 443);
	// this needs fixing!!!

	let outstream = TcpStream::connect::<(&str)>(bogus_fix).unwrap();

	get_with_no_content_length(&instream, &outstream);
}

fn req_resource(buf: [u8;REQUEST_LEN]) -> String
{
	let mut i = 0;
	let bytes = buf;
	let mut request: String = String::new();

	// FIXME WORDPRESS DOESN't WORK!
	while bytes[i] as char != '\0' {
		request.push(bytes[i] as char);
		i += 1;
	}

	return request;
}

fn req_content(buf: [u8;REQUEST_LEN]) -> String
{
	let content = substr(buf, "Content-Type: ", '\r' as u8);

	return content;
}

fn req_hostname(buf: [u8;REQUEST_LEN]) -> String
{
	let hostname: String = substr(buf, "http://", '/' as u8);

	return hostname;
}

fn req_length(buf: [u8;REQUEST_LEN]) -> usize
{
	let request: String = substr(buf, "Content-Length: ", '\r' as u8);
	if ! request.is_empty() {
		return request.trim().parse().unwrap();
	}

	return 0;
}

struct Header {
	pub hostname: String,
	pub resource: String,
	pub content: String,
	pub length: usize,
	pub method: String,
}

impl Header {

pub fn new() -> Header
{
	let hostname = String::new();
	let resource = String::new();
	let content  = String::new();
	let method   = String::new();
	let length   = 0;

	let h = Header {
		hostname: hostname,
		resource: resource ,
		content: content,
		length: length,
		method: method
	};

	return h;
}

}

fn check_headers(buffer: [u8;REQUEST_LEN], headers: &mut Header) -> bool
{
	if headers.hostname.is_empty() {
		headers.hostname = req_hostname(buffer);
	}

	if headers.resource.is_empty() {
		headers.resource = req_resource(buffer);
	}

	if headers.content.is_empty() {
		headers.content = req_content(buffer);
	}

	if headers.length == 0 {
		headers.length = req_length(buffer);
	}

	if headers.hostname.is_empty() || headers.resource.is_empty() || headers.method.is_empty() {
		return false;
	}

	return true;
}

fn request_headers(mut instream: &TcpStream, headers: &mut Header)
{
	let mut byte = [0u8;1];

	// bit better for now it'll do!
	while byte[0] as char != ' ' {
		instream.read(&mut byte).unwrap();
		if byte[0] as char != ' '
		{
			headers.method.push(byte[0] as char);
		}
	}

	match headers.method.as_ref() {
		"GET" | "POST" | "OPTIONS" | "HEAD" | "CONNECT" =>
		{
			// all good do not return!!!
		}

		_ =>
		{
			return;
		}
	}

	loop {
		let mut buffer = [0u8; REQUEST_LEN];
		let mut byte = [0u8; 1];
		let mut len = 0;

		while byte[0] as char != '\n' {
			let bytes = instream.read(&mut byte).unwrap();
			buffer[len] = byte[0];
			len += bytes;
		}

		buffer[len] = '\0' as u8;

		if check_headers(buffer, headers) && len == 2 {
			let mut i = 0;

			while i < REQUEST_LEN {
				buffer[i] = 0;
				i += 1;
			}
			return;
		}
	}
}

fn proxy(stream: TcpStream) {
	let mut headers: Header = Header::new();
	request_headers(&stream, &mut headers);

	match headers.method.as_ref() {
		"GET" =>
		{
			http_get_request(stream, headers);
		}

		"POST" =>
		{
			http_post_request(stream, headers);
		}

		"HEAD" =>
		{
			http_head_request(headers);
		}

		"OPTIONS" =>
		{
			http_options_request(stream);
		}

		"CONNECT" =>
		{
			println!("here {} and {}", headers.hostname, headers.resource);
			http_connect_request(stream, headers);
		}

		_ =>
		{
			println!("REQUEST UNKNOWN");
		}
	}
}

extern crate threadpool;
use threadpool::ThreadPool;

fn proxy_time(port: u16, threads: usize) {
	let ip = Ipv4Addr::new(127, 0, 0, 1);
	let host = SocketAddrV4::new(ip, port);
	let listener = TcpListener::bind(host).unwrap();

	let pool = ThreadPool::new(threads);

	for stream in listener.incoming()
	{
		match stream
		{
			Ok(stream) =>
			{
				pool.execute(move || { proxy(stream); });
			}

			Err(_) =>
			{
				println!("NET error");
				1 << 7;
			}
		}
	}

	drop (listener);
}

fn main () {
	let threads = 128;
	let port: u16 = 9999;

	println!("Blocking all badness");
	proxy_time(port, threads);
}

<|endoftext|>


<commit_before>use std::path::Path;
use std::io::fs::File;
use std::os;

fn main() {
    let args = os::args();

    if args.len() != 2 {
        fail!("invalid argument");
    }

    let path: Path = Path::new(args[1]);
    let file: File = File::open(&path).unwrap();
}

fn tokenize(text: ~str) -> Vec<Token> {
    let mut tokens: Vec<Token> = Vec::new();
    for c in text.chars() {
       match c {
           '>' => {tokens.push(Right)},
           '<' => {tokens.push(Left)},
           '+' => {tokens.push(Plus)},
           '-' => {tokens.push(Minus)},
           '.' => {tokens.push(Out)},
           ',' => {tokens.push(In)},
           '[' => {tokens.push(Jump)},
           ']' => {tokens.push(Loop)},
           _ => {}
       };
    }

    return tokens;
}

#[deriving(Clone, Eq, Show, TotalEq)]
enum Token {
    Right,
    Left,
    Plus,
    Minus,
    Out,
    In,
    Jump,
    Loop
}

#[test]
fn testTokenizer() {
    assert_eq!(tokenize("><+-.,[]".to_owned()).as_slice(),
               [Right, Left, Plus, Minus, Out, In, Jump, Loop].as_slice());

    assert_eq!(tokenize(">a<b+c-d. ,1[2]3 ".to_owned()).as_slice(),
               [Right, Left, Plus, Minus, Out, In, Jump, Loop].as_slice());
}
<commit_msg>Allow first argument to be parsed. Resolve #2.<commit_after>use std::path::Path;
use std::io::fs::File;
use std::os;

fn main() {
    let args = os::args();

    if args.len() == 1 {
        fail!("no arguments");
    }

    tokenize(parse_args(args));
}

fn parse_args(args: ~[~str]) -> ~str {
    args[1]
}

fn tokenize(text: ~str) -> Vec<Token> {
    let mut tokens: Vec<Token> = Vec::new();
    for c in text.chars() {
       match c {
           '>' => {tokens.push(Right)},
           '<' => {tokens.push(Left)},
           '+' => {tokens.push(Plus)},
           '-' => {tokens.push(Minus)},
           '.' => {tokens.push(Out)},
           ',' => {tokens.push(In)},
           '[' => {tokens.push(Jump)},
           ']' => {tokens.push(Loop)},
           _ => {}
       };
    }

    return tokens;
}

#[deriving(Clone, Eq, Show, TotalEq)]
enum Token {
    Right,
    Left,
    Plus,
    Minus,
    Out,
    In,
    Jump,
    Loop
}

#[test]
fn testTokenizer() {
    // Check the tokenizer is getting the right outputs.
    assert_eq!(tokenize("><+-.,[]".to_owned()).as_slice(),
               [Right, Left, Plus, Minus, Out, In, Jump, Loop].as_slice());

    // Make sure junk is ignored.
    assert_eq!(tokenize(">a<b+c-d. ,1[2]3 ".to_owned()).as_slice(),
               [Right, Left, Plus, Minus, Out, In, Jump, Loop].as_slice());
}

#[test]
fn testArgParser() {
    assert_eq!(parse_args(["brainruck".to_owned(), "><+-.,[]".to_owned()].to_owned()),
               "><+-.,[]".to_owned());
}
<|endoftext|>


<commit_before>//! Implementations of the callbacks exposed by wlc.
//! These functions are the main entry points into Way Cooler from user action.
use rustwlc::handle::{WlcOutput, WlcView};
use rustwlc::types::*;

use super::keys;
use super::layout::{lock_tree, try_lock_tree, TreeError};
use super::lua;

use ::modes::{read_current_mode, EVENT_PASS_THROUGH};

pub extern fn output_created(output: WlcOutput) -> bool {
    trace!("output_created: {:?}: {}", output, output.get_name());
    if let Ok(mode) = read_current_mode() {
        mode.output_created(output)
    } else {
        false
    }
}

pub extern fn output_destroyed(output: WlcOutput) {
    trace!("output_destroyed: {:?}", output);
    if let Ok(mode) = read_current_mode() {
        mode.output_destroyed(output)
    }
}

pub extern fn output_focus(output: WlcOutput, focused: bool) {
    trace!("output_focus: {:?} focus={}", output, focused);
    if let Ok(mode) = read_current_mode() {
        mode.output_focused(output, focused)
    }
}

pub extern fn output_resolution(output: WlcOutput,
                                old_size_ptr: &Size, new_size_ptr: &Size) {
    trace!("output_resolution: {:?} from  {:?} to {:?}",
           output, *old_size_ptr, *new_size_ptr);
    if let Ok(mode) = read_current_mode() {
        mode.output_resolution(output, *old_size_ptr, *new_size_ptr)
    }
}

pub extern fn post_render(output: WlcOutput) {
    if let Ok(mode) = read_current_mode() {
        mode.output_render_post(output)
    }
}

pub extern fn view_created(view: WlcView) -> bool {
    trace!("view_created: {:?}: \"{}\"", view, view.get_title());
    if let Ok(mode) = read_current_mode() {
        mode.view_created(view)
    } else {
        false
    }
}

pub extern fn view_destroyed(view: WlcView) {
    trace!("view_destroyed: {:?}", view);
    if let Ok(mode) = read_current_mode() {
        mode.view_destroyed(view)
    }
}

pub extern fn view_focus(current: WlcView, focused: bool) {
    if let Ok(lock_screen) = try_lock_lock_screen() {
        if let Some(ref lock_screen) = *lock_screen {
            lock_screen.view().map(|v| v.set_state(VIEW_ACTIVATED, focused));
            return
        }
    }
    trace!("view_focus: {:?} {}", current, focused);
    if let Ok(mode) = read_current_mode() {
        mode.view_focused(current, focused)
    }
}

pub extern fn view_props_changed(view: WlcView, prop: ViewPropertyType) {
    trace!("view_props_changed for view {:?}: {:?}", view, prop);
    if let Ok(mode) = read_current_mode() {
        mode.view_props_changed(view, prop)
    }
}

pub extern fn view_move_to_output(current: WlcView,
                                  o1: WlcOutput, o2: WlcOutput) {
    trace!("view_move_to_output: {:?}, {:?}, {:?}", current, o1, o2);
    if let Ok(mode) = read_current_mode() {
        mode.view_moved_to_output(current, o1, o2)
    }
}

pub extern fn view_request_state(view: WlcView, state: ViewState, toggle: bool) {
    if let Ok(lock_screen) = lock_lock_screen() {
        if lock_screen.is_some() {
            return
        }
    }
    trace!("Setting {:?} to state {:?}", view, state);
    if let Ok(mode) = read_current_mode() {
        mode.view_request_state(view, state, toggle)
    }
}

pub extern fn view_request_move(view: WlcView, dest: &Point) {
    trace!("View {:?} request to move to {:?}", view, dest);
    if let Ok(mode) = read_current_mode() {
        mode.view_request_move(view, *dest)
    }
}

pub extern fn view_request_resize(view: WlcView, edge: ResizeEdge, point: &Point) {
    trace!("View {:?} request resize w/ edge {:?} to point {:?}",
           view, edge, point);
    if let Ok(mode) = read_current_mode() {
        mode.view_request_resize(view, edge, *point)
    }
}

pub extern fn view_request_geometry(view: WlcView, geometry: &Geometry) {
    trace!("View {:?} requested geometry {:?}", view, geometry);
    if let Ok(mode) = read_current_mode() {
        mode.view_request_geometry(view, *geometry)
    }
}

pub extern fn keyboard_key(view: WlcView, time: u32, mods: &KeyboardModifiers,
                           key: u32, state: KeyState) -> bool {
    // NOTE We read the mode out here, so that if there is a keybinding
    // that changes the mode we can do that without being blocked!
    let mode = if let Ok(mode) = read_current_mode() {
        *mode
    } else {
        return EVENT_PASS_THROUGH
    };
    mode.on_keyboard_key(view, time, *mods, key, state)
}

pub extern fn pointer_button(view: WlcView, time: u32,
                         mods: &KeyboardModifiers, button: u32,
                             state: ButtonState, point: &Point) -> bool {
    if let Ok(mode) = read_current_mode() {
        mode.on_pointer_button(view, time, *mods, button, state, *point)
    } else {
        EVENT_PASS_THROUGH
    }
}

pub extern fn pointer_scroll(view: WlcView, time: u32,
                         mods_ptr: &KeyboardModifiers, axis: ScrollAxis,
                         heights: [f64; 2]) -> bool {
    if let Ok(mode) = read_current_mode() {
        mode.on_pointer_scroll(view, time, *mods_ptr, axis, heights)
    } else {
        EVENT_PASS_THROUGH
    }
}

pub extern fn pointer_motion(view: WlcView, time: u32, point: &Point) -> bool {
    if let Ok(mode) = read_current_mode() {
        mode.on_pointer_motion(view, time, *point)
    } else {
        EVENT_PASS_THROUGH
    }
}

pub extern fn compositor_ready() {
    info!("Preparing compositor!");
    info!("Initializing Lua...");
    lua::init();
    keys::init();
}

pub extern fn compositor_terminating() {
    info!("Compositor terminating!");
    lua::send(lua::LuaQuery::Terminate).ok();
    if let Ok(mut tree) = try_lock_tree() {
        if tree.destroy_tree().is_err() {
            error!("Could not destroy tree");
        }
    }

}

pub extern fn view_pre_render(view: WlcView) {
    if let Ok(mut tree) = lock_tree() {
        tree.render_borders(view).unwrap_or_else(|err| {
            match err {
                // TODO Only filter if background or bar
                TreeError::ViewNotFound(_) => {},
                err => warn!("Error while rendering borders: {:?}", err)
            }
        })
    }
}

pub fn init() {
    use rustwlc::callback;

    callback::output_created(output_created);
    callback::output_destroyed(output_destroyed);
    callback::output_focus(output_focus);
    callback::output_resolution(output_resolution);
    callback::output_render_post(post_render);
    callback::view_created(view_created);
    callback::view_destroyed(view_destroyed);
    callback::view_focus(view_focus);
    callback::view_move_to_output(view_move_to_output);
    callback::view_request_geometry(view_request_geometry);
    callback::view_request_state(view_request_state);
    callback::view_request_move(view_request_move);
    callback::view_request_resize(view_request_resize);
    callback::view_properties_changed(view_props_changed);
    callback::keyboard_key(keyboard_key);
    callback::pointer_button(pointer_button);
    callback::pointer_scroll(pointer_scroll);
    callback::pointer_motion(pointer_motion);
    callback::compositor_ready(compositor_ready);
    callback::compositor_terminate(compositor_terminating);
    callback::view_render_pre(view_pre_render);
    trace!("Registered wlc callbacks");
}
<commit_msg>Removed old lock_screen checks from callbacks<commit_after>//! Implementations of the callbacks exposed by wlc.
//! These functions are the main entry points into Way Cooler from user action.
use rustwlc::handle::{WlcOutput, WlcView};
use rustwlc::types::*;

use super::keys;
use super::layout::{lock_tree, try_lock_tree, TreeError};
use super::lua;

use ::modes::{read_current_mode, EVENT_PASS_THROUGH};

pub extern fn output_created(output: WlcOutput) -> bool {
    trace!("output_created: {:?}: {}", output, output.get_name());
    if let Ok(mode) = read_current_mode() {
        mode.output_created(output)
    } else {
        false
    }
}

pub extern fn output_destroyed(output: WlcOutput) {
    trace!("output_destroyed: {:?}", output);
    if let Ok(mode) = read_current_mode() {
        mode.output_destroyed(output)
    }
}

pub extern fn output_focus(output: WlcOutput, focused: bool) {
    trace!("output_focus: {:?} focus={}", output, focused);
    if let Ok(mode) = read_current_mode() {
        mode.output_focused(output, focused)
    }
}

pub extern fn output_resolution(output: WlcOutput,
                                old_size_ptr: &Size, new_size_ptr: &Size) {
    trace!("output_resolution: {:?} from  {:?} to {:?}",
           output, *old_size_ptr, *new_size_ptr);
    if let Ok(mode) = read_current_mode() {
        mode.output_resolution(output, *old_size_ptr, *new_size_ptr)
    }
}

pub extern fn post_render(output: WlcOutput) {
    if let Ok(mode) = read_current_mode() {
        mode.output_render_post(output)
    }
}

pub extern fn view_created(view: WlcView) -> bool {
    trace!("view_created: {:?}: \"{}\"", view, view.get_title());
    if let Ok(mode) = read_current_mode() {
        mode.view_created(view)
    } else {
        false
    }
}

pub extern fn view_destroyed(view: WlcView) {
    trace!("view_destroyed: {:?}", view);
    if let Ok(mode) = read_current_mode() {
        mode.view_destroyed(view)
    }
}

pub extern fn view_focus(current: WlcView, focused: bool) {
    trace!("view_focus: {:?} {}", current, focused);
    if let Ok(mode) = read_current_mode() {
        mode.view_focused(current, focused)
    }
}

pub extern fn view_props_changed(view: WlcView, prop: ViewPropertyType) {
    trace!("view_props_changed for view {:?}: {:?}", view, prop);
    if let Ok(mode) = read_current_mode() {
        mode.view_props_changed(view, prop)
    }
}

pub extern fn view_move_to_output(current: WlcView,
                                  o1: WlcOutput, o2: WlcOutput) {
    trace!("view_move_to_output: {:?}, {:?}, {:?}", current, o1, o2);
    if let Ok(mode) = read_current_mode() {
        mode.view_moved_to_output(current, o1, o2)
    }
}

pub extern fn view_request_state(view: WlcView, state: ViewState, toggle: bool) {
    trace!("Setting {:?} to state {:?}", view, state);
    if let Ok(mode) = read_current_mode() {
        mode.view_request_state(view, state, toggle)
    }
}

pub extern fn view_request_move(view: WlcView, dest: &Point) {
    trace!("View {:?} request to move to {:?}", view, dest);
    if let Ok(mode) = read_current_mode() {
        mode.view_request_move(view, *dest)
    }
}

pub extern fn view_request_resize(view: WlcView, edge: ResizeEdge, point: &Point) {
    trace!("View {:?} request resize w/ edge {:?} to point {:?}",
           view, edge, point);
    if let Ok(mode) = read_current_mode() {
        mode.view_request_resize(view, edge, *point)
    }
}

pub extern fn view_request_geometry(view: WlcView, geometry: &Geometry) {
    trace!("View {:?} requested geometry {:?}", view, geometry);
    if let Ok(mode) = read_current_mode() {
        mode.view_request_geometry(view, *geometry)
    }
}

pub extern fn keyboard_key(view: WlcView, time: u32, mods: &KeyboardModifiers,
                           key: u32, state: KeyState) -> bool {
    // NOTE We read the mode out here, so that if there is a keybinding
    // that changes the mode we can do that without being blocked!
    let mode = if let Ok(mode) = read_current_mode() {
        *mode
    } else {
        return EVENT_PASS_THROUGH
    };
    mode.on_keyboard_key(view, time, *mods, key, state)
}

pub extern fn pointer_button(view: WlcView, time: u32,
                         mods: &KeyboardModifiers, button: u32,
                             state: ButtonState, point: &Point) -> bool {
    if let Ok(mode) = read_current_mode() {
        mode.on_pointer_button(view, time, *mods, button, state, *point)
    } else {
        EVENT_PASS_THROUGH
    }
}

pub extern fn pointer_scroll(view: WlcView, time: u32,
                         mods_ptr: &KeyboardModifiers, axis: ScrollAxis,
                         heights: [f64; 2]) -> bool {
    if let Ok(mode) = read_current_mode() {
        mode.on_pointer_scroll(view, time, *mods_ptr, axis, heights)
    } else {
        EVENT_PASS_THROUGH
    }
}

pub extern fn pointer_motion(view: WlcView, time: u32, point: &Point) -> bool {
    if let Ok(mode) = read_current_mode() {
        mode.on_pointer_motion(view, time, *point)
    } else {
        EVENT_PASS_THROUGH
    }
}

pub extern fn compositor_ready() {
    info!("Preparing compositor!");
    info!("Initializing Lua...");
    lua::init();
    keys::init();
}

pub extern fn compositor_terminating() {
    info!("Compositor terminating!");
    lua::send(lua::LuaQuery::Terminate).ok();
    if let Ok(mut tree) = try_lock_tree() {
        if tree.destroy_tree().is_err() {
            error!("Could not destroy tree");
        }
    }

}

pub extern fn view_pre_render(view: WlcView) {
    if let Ok(mut tree) = lock_tree() {
        tree.render_borders(view).unwrap_or_else(|err| {
            match err {
                // TODO Only filter if background or bar
                TreeError::ViewNotFound(_) => {},
                err => warn!("Error while rendering borders: {:?}", err)
            }
        })
    }
}

pub fn init() {
    use rustwlc::callback;

    callback::output_created(output_created);
    callback::output_destroyed(output_destroyed);
    callback::output_focus(output_focus);
    callback::output_resolution(output_resolution);
    callback::output_render_post(post_render);
    callback::view_created(view_created);
    callback::view_destroyed(view_destroyed);
    callback::view_focus(view_focus);
    callback::view_move_to_output(view_move_to_output);
    callback::view_request_geometry(view_request_geometry);
    callback::view_request_state(view_request_state);
    callback::view_request_move(view_request_move);
    callback::view_request_resize(view_request_resize);
    callback::view_properties_changed(view_props_changed);
    callback::keyboard_key(keyboard_key);
    callback::pointer_button(pointer_button);
    callback::pointer_scroll(pointer_scroll);
    callback::pointer_motion(pointer_motion);
    callback::compositor_ready(compositor_ready);
    callback::compositor_terminate(compositor_terminating);
    callback::view_render_pre(view_pre_render);
    trace!("Registered wlc callbacks");
}
<|endoftext|>