<commit_before>use lucky_commit_lib::{iterate_for_match, parse_prefix, HashMatch, HashPrefix, SearchParams};
use std::cmp::min;
use std::env;
use std::io;
use std::io::Write;
use std::process::{exit, Command, Stdio};
use std::sync::mpsc;
use std::thread;

fn main() {
    let args: Vec<String> = env::args().collect();

    if args.len() == 2 && args[1] == "--benchmark" {
        run_single_core_benchmark();
        return;
    }

    match args.len() {
        1 => run_lucky_commit(&parse_prefix("0000000").unwrap()),
        2 => match parse_prefix(&args[1]) {
            Some(prefix) => run_lucky_commit(&prefix),
            None => print_usage_and_exit(),
        },
        _ => print_usage_and_exit(),
    }
}

fn print_usage_and_exit() -> ! {
    fail_with_message("Usage: lucky_commit [commit-hash-prefix]")
}

fn fail_with_message(message: &str) -> ! {
    eprintln!("{}", message);
    exit(1)
}

fn run_lucky_commit(desired_prefix: &HashPrefix) {
    let current_commit = run_command("git", &["cat-file", "commit", "HEAD"]);

    match find_match(&current_commit, desired_prefix) {
        Some(hash_match) => {
            create_git_commit(&hash_match)
                .expect("Found a commit, but failed to write it to the git object database.");
            run_command("git", &["reset", &to_hex_string(&hash_match.hash)]);
        }
        None => fail_with_message(
            "Sorry, failed to find a commit matching the given prefix despite searching hundreds\
             of trillions of possible commits. Hopefully you haven't just been sitting here \
             waiting the whole time.",
        ),
    }
}

fn run_command(command: &str, args: &[&str]) -> Vec<u8> {
    let output = Command::new(command)
        .args(args)
        .stderr(Stdio::inherit())
        .output()
        .unwrap_or_else(|_| {
            panic!(
                "Failed to spawn command `{}` with args `{:?}`",
                command, args
            )
        });

    if !output.status.success() {
        panic!(
            "Command finished with non-zero exit code: {} {:?}",
            command, args
        );
    }

    output.stdout
}

fn find_match(current_commit: &[u8], desired_prefix: &HashPrefix) -> Option<HashMatch> {
    let (shared_sender, receiver) = mpsc::channel();
    let num_threads = min(num_cpus::get_physical(), 65535) as u64;
    let workload_per_thread = 1 << 48;

    for thread_index in 0..num_threads {
        let search_params = SearchParams {
            current_commit: current_commit.to_vec(),
            desired_prefix: desired_prefix.clone(),
            counter_range: (thread_index * workload_per_thread)
                ..((thread_index + 1) * workload_per_thread),
        };
        let result_sender = shared_sender.clone();
        thread::spawn(move || {
            /*
             * If an error occurs when sending, then the receiver has already received
             * a match from another thread, so ignore the error.
             */
            let _ = result_sender.send(iterate_for_match(&search_params));
        });
    }

    for _ in 0..num_threads {
        let result = receiver.recv().unwrap();
        if result.is_some() {
            return result;
        }
    }

    None
}

fn create_git_commit(search_result: &HashMatch) -> io::Result<()> {
    assert!(&search_result.raw_object[0..7] == b"commit ");
    let commit_start_index = search_result
        .raw_object
        .iter()
        .position(|byte| *byte == 0)
        .expect("No null character found in constructed raw git object?")
        + 1;

    let mut git_hash_object_child = Command::new("git")
        .args(&["hash-object", "-t", "commit", "-w", "--stdin"])
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .stderr(Stdio::inherit())
        .spawn()?;

    git_hash_object_child
        .stdin
        .as_mut()
        .unwrap()
        .write_all(&search_result.raw_object[commit_start_index..])?;
    let output = git_hash_object_child.wait_with_output()?;

    if !output.status.success() {
        panic!("Found a commit, but failed to write it to the git object database.");
    }
    let git_hash_output =
        String::from_utf8(output.stdout).expect("Git produced a hash containing invalid utf8?");
    assert!(
        git_hash_output.trim_end() == to_hex_string(&search_result.hash),
        "Found a commit ({}), but git unexpectedly computed a different hash for it ({})",
        to_hex_string(&search_result.hash),
        git_hash_output.trim_end(),
    );
    Ok(())
}

fn to_hex_string(hash: &[u8]) -> String {
    hash.iter()
        .map(|byte| format!("{:02x}", *byte))
        .collect::<String>()
}

fn run_single_core_benchmark() {
    // Runs a benchmark for performance testing. Using a single core, this does a constant
    // hash search. This benchmark should take roughly the same amount of time as running
    // `lucky_commit` with no arguments, but the performance should be much more consistent.
    // Caveats:
    // * Assumes perfect parallelization by scaling the workload down when there are multiple
    //   CPUs. While hash searching is perfectly parallelizable in theory, this benchmark might
    //   fail to catch performance bugs resulting from contention.
    // * Assumes that CPU utilization would remain the same when adding threads (this might
    //   not be the case if the other CPUs are being used for something else)
    // * Might overestimate the available cache space, since in reality multiple threads would
    //   be sharing the cache.
    // * The benchmark uses an unusually long desired prefix to make it implausible that it ends
    //   early. While this shouldn't result in substantially more instructions executed, in theory
    //   it could have an effect on things like alignment and the cache.
    // * The benchmark doesn't spawn any git commands or interact with the filesystem, whereas
    // * a real run does a ~single-digit number of filesystem operations.
    //
    // To use: run `time target/release/lucky_commit --benchmark` and look at the user time.
    // The observed standard deviation for this benchmark is somewhere around 0.05 seconds.
    //
    // For a more end-to-end benchmark without the above caveats and with more noise, see the
    // `benchmark-branch` branch. The observed standard deviation for that benchmark is somewhere
    // around 0.5 seconds.
    assert_eq!(
        None,
        iterate_for_match(&SearchParams {
            current_commit: b"\
                    tree 6f4e79123e206448f80ec73b9a53e07eb0784fef\n\
                    author Foo Bar <foo@example.com> 1611912738 -0500\n\
                    committer Foo Bar <foo@example.com> 1611912738 -0500\n\
                    \n\
                    Test commit for benchmarking performance changes\n"
                .to_vec(),
            desired_prefix: HashPrefix {
                data: vec![0; 19],
                half_byte: Some(0x0)
            },
            counter_range: 1..((1 << 28) / num_cpus::get_physical() as u64)
        })
    );
}
<commit_msg>Ensure the threads are actually doing different work<commit_after>use lucky_commit_lib::{iterate_for_match, parse_prefix, HashMatch, HashPrefix, SearchParams};
use std::env;
use std::io;
use std::io::Write;
use std::process::{exit, Command, Stdio};
use std::sync::mpsc;
use std::thread;

fn main() {
    let args: Vec<String> = env::args().collect();

    if args.len() == 2 && args[1] == "--benchmark" {
        run_single_core_benchmark();
        return;
    }

    match args.len() {
        1 => run_lucky_commit(&parse_prefix("0000000").unwrap()),
        2 => match parse_prefix(&args[1]) {
            Some(prefix) => run_lucky_commit(&prefix),
            None => print_usage_and_exit(),
        },
        _ => print_usage_and_exit(),
    }
}

fn print_usage_and_exit() -> ! {
    fail_with_message("Usage: lucky_commit [commit-hash-prefix]")
}

fn fail_with_message(message: &str) -> ! {
    eprintln!("{}", message);
    exit(1)
}

fn run_lucky_commit(desired_prefix: &HashPrefix) {
    let current_commit = run_command("git", &["cat-file", "commit", "HEAD"]);

    match find_match(&current_commit, desired_prefix) {
        Some(hash_match) => {
            create_git_commit(&hash_match)
                .expect("Found a commit, but failed to write it to the git object database.");
            run_command("git", &["reset", &to_hex_string(&hash_match.hash)]);
        }
        None => fail_with_message(
            "Sorry, failed to find a commit matching the given prefix despite searching hundreds\
             of trillions of possible commits. Hopefully you haven't just been sitting here \
             waiting the whole time.",
        ),
    }
}

fn run_command(command: &str, args: &[&str]) -> Vec<u8> {
    let output = Command::new(command)
        .args(args)
        .stderr(Stdio::inherit())
        .output()
        .unwrap_or_else(|_| {
            panic!(
                "Failed to spawn command `{}` with args `{:?}`",
                command, args
            )
        });

    if !output.status.success() {
        panic!(
            "Command finished with non-zero exit code: {} {:?}",
            command, args
        );
    }

    output.stdout
}

fn find_match(current_commit: &[u8], desired_prefix: &HashPrefix) -> Option<HashMatch> {
    let (shared_sender, receiver) = mpsc::channel();
    let num_threads = num_cpus::get_physical() as u64;
    let workload_per_thread = (1 << 48) / num_threads;

    for thread_index in 0..num_threads {
        let search_params = SearchParams {
            current_commit: current_commit.to_vec(),
            desired_prefix: desired_prefix.clone(),
            counter_range: (thread_index * workload_per_thread)
                ..((thread_index + 1) * workload_per_thread),
        };
        let result_sender = shared_sender.clone();
        thread::spawn(move || {
            /*
             * If an error occurs when sending, then the receiver has already received
             * a match from another thread, so ignore the error.
             */
            let _ = result_sender.send(iterate_for_match(&search_params));
        });
    }

    for _ in 0..num_threads {
        let result = receiver.recv().unwrap();
        if result.is_some() {
            return result;
        }
    }

    None
}

fn create_git_commit(search_result: &HashMatch) -> io::Result<()> {
    assert!(&search_result.raw_object[0..7] == b"commit ");
    let commit_start_index = search_result
        .raw_object
        .iter()
        .position(|byte| *byte == 0)
        .expect("No null character found in constructed raw git object?")
        + 1;

    let mut git_hash_object_child = Command::new("git")
        .args(&["hash-object", "-t", "commit", "-w", "--stdin"])
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .stderr(Stdio::inherit())
        .spawn()?;

    git_hash_object_child
        .stdin
        .as_mut()
        .unwrap()
        .write_all(&search_result.raw_object[commit_start_index..])?;
    let output = git_hash_object_child.wait_with_output()?;

    if !output.status.success() {
        panic!("Found a commit, but failed to write it to the git object database.");
    }
    let git_hash_output =
        String::from_utf8(output.stdout).expect("Git produced a hash containing invalid utf8?");
    assert!(
        git_hash_output.trim_end() == to_hex_string(&search_result.hash),
        "Found a commit ({}), but git unexpectedly computed a different hash for it ({})",
        to_hex_string(&search_result.hash),
        git_hash_output.trim_end(),
    );
    Ok(())
}

fn to_hex_string(hash: &[u8]) -> String {
    hash.iter()
        .map(|byte| format!("{:02x}", *byte))
        .collect::<String>()
}

fn run_single_core_benchmark() {
    // Runs a benchmark for performance testing. Using a single core, this does a constant
    // hash search. This benchmark should take roughly the same amount of time as running
    // `lucky_commit` with no arguments, but the performance should be much more consistent.
    // Caveats:
    // * Assumes perfect parallelization by scaling the workload down when there are multiple
    //   CPUs. While hash searching is perfectly parallelizable in theory, this benchmark might
    //   fail to catch performance bugs resulting from contention.
    // * Assumes that CPU utilization would remain the same when adding threads (this might
    //   not be the case if the other CPUs are being used for something else)
    // * Might overestimate the available cache space, since in reality multiple threads would
    //   be sharing the cache.
    // * The benchmark uses an unusually long desired prefix to make it implausible that it ends
    //   early. While this shouldn't result in substantially more instructions executed, in theory
    //   it could have an effect on things like alignment and the cache.
    // * The benchmark doesn't spawn any git commands or interact with the filesystem, whereas
    // * a real run does a ~single-digit number of filesystem operations.
    //
    // To use: run `time target/release/lucky_commit --benchmark` and look at the user time.
    // The observed standard deviation for this benchmark is somewhere around 0.05 seconds.
    //
    // For a more end-to-end benchmark without the above caveats and with more noise, see the
    // `benchmark-branch` branch. The observed standard deviation for that benchmark is somewhere
    // around 0.5 seconds.
    assert_eq!(
        None,
        iterate_for_match(&SearchParams {
            current_commit: b"\
                    tree 6f4e79123e206448f80ec73b9a53e07eb0784fef\n\
                    author Foo Bar <foo@example.com> 1611912738 -0500\n\
                    committer Foo Bar <foo@example.com> 1611912738 -0500\n\
                    \n\
                    Test commit for benchmarking performance changes\n"
                .to_vec(),
            desired_prefix: HashPrefix {
                data: vec![0; 19],
                half_byte: Some(0x0)
            },
            counter_range: 1..((1 << 28) / num_cpus::get_physical() as u64)
        })
    );
}
<|endoftext|>


<commit_before>use std::ops::Not;
use std::ops::BitAnd;
use std::ops::BitOr;

#[derive(PartialEq, Debug)]
pub enum Bit { Zero, One }

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

    #[test]
    fn eq_zero_zero_test() {
        assert!(Bit::Zero == Bit::Zero);
    }

    #[test]
    #[should_panic]
    fn eq_zero_one_test() {
        assert!(Bit::Zero == Bit::One);
    }

    #[test]
    #[should_panic]
    fn eq_one_zero_test() {
        assert!(Bit::One == Bit::Zero);
    }

    #[test]
    fn eq_one_one_test() {
        assert!(Bit::One == Bit::One);
    }

    #[test]
    #[should_panic]
    fn neq_zero_zero_test() {
        assert!(Bit::Zero != Bit::Zero);
    }

    #[test]
    fn neq_zero_one_test() {
        assert!(Bit::Zero != Bit::One);
    }

    #[test]
    fn neq_one_zero_test() {
        assert!(Bit::One != Bit::Zero);
    }

    #[test]
    #[should_panic]
    fn neq_one_one_test() {
        assert!(Bit::One != Bit::One);
    }
}

impl Bit {
    pub fn to_i32(&self) -> i32 {
        match *self {
            Bit::Zero => 0,
            Bit::One => 1
        }
    }

    pub fn to_u32(&self) -> u32 {
        match *self {
            Bit::Zero => 0u32,
            Bit::One => 1u32
        }
    }
}

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

    #[test]
    fn zero_test() {
        assert_eq!(Bit::Zero.to_i32(), 0);
    }

    #[test]
    fn one_test() {
        assert_eq!(Bit::One.to_i32(), 1);
    }
}

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

    #[test]
    fn zero_test() {
        assert_eq!(Bit::Zero.to_u32(), 0);
    }

    #[test]
    fn one_test() {
        assert_eq!(Bit::One.to_u32(), 1);
    }
}

impl Not for Bit {
    type Output = Bit;

    fn not(self) -> Bit {
        not_impl(&self)
    }
}

fn not_impl(x: &Bit) -> Bit
{
    match *x {
        Bit::Zero => Bit::One,
        Bit::One => Bit::Zero
    }
}

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

    #[test]
    fn zero_test() {
        assert_eq!(!Bit::Zero, Bit::One);
    }

    #[test]
    fn one_test() {
        assert_eq!(!Bit::One, Bit::Zero);
    }
}

impl<'a> Not for &'a Bit {
    type Output = <Bit as Not>::Output;

    fn not(self) -> <Bit as Not>::Output {
        not_impl(self)
    }
}

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

    #[test]
    fn zero_test() {
        assert_eq!(!&Bit::Zero, Bit::One);
    }

    #[test]
    fn one_test() {
        assert_eq!(!&Bit::One, Bit::Zero);
    }
}

impl BitAnd<Bit> for Bit {
    type Output = Bit;

    fn bitand(self, rhs: Bit) -> Bit {
        bitand_impl(&self, &rhs)
    }
}

fn bitand_impl(x: &Bit, y: &Bit) -> Bit {
    match (x, y) {
        (&Bit::Zero, &Bit::Zero) => Bit::Zero,
        (&Bit::Zero, &Bit::One) => Bit::Zero,
        (&Bit::One, &Bit::Zero) => Bit::Zero,
        (&Bit::One, &Bit::One) => Bit::One
    }
}

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

    #[test]
    fn zero_zero_test() {
        assert_eq!(Bit::Zero & Bit::Zero, Bit::Zero);
    }

    #[test]
    fn zero_one_test() {
        assert_eq!(Bit::Zero & Bit::One, Bit::Zero);
    }

    #[test]
    fn one_zero_test() {
        assert_eq!(Bit::One & Bit::Zero, Bit::Zero);
    }

    #[test]
    fn one_one_test() {
        assert_eq!(Bit::One & Bit::One, Bit::One);
    }
}

impl<'a> BitAnd<Bit> for &'a Bit {
    type Output = <Bit as BitAnd<Bit>>::Output;

    fn bitand(self, rhs: Bit) -> <Bit as BitAnd<Bit>>::Output {
        bitand_impl(self, &rhs)
    }
}

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

    #[test]
    fn zero_zero_test() {
        assert_eq!(&Bit::Zero & Bit::Zero, Bit::Zero);
    }

    #[test]
    fn zero_one_test() {
        assert_eq!(&Bit::Zero & Bit::One, Bit::Zero);
    }

    #[test]
    fn one_zero_test() {
        assert_eq!(&Bit::One & Bit::Zero, Bit::Zero);
    }

    #[test]
    fn one_one_test() {
        assert_eq!(&Bit::One & Bit::One, Bit::One);
    }
}

impl<'a> BitAnd<&'a Bit> for Bit {
    type Output = <Bit as BitAnd<Bit>>::Output;

    fn bitand(self, rhs: &'a Bit) -> <Bit as BitAnd<Bit>>::Output {
        bitand_impl(&self, rhs)
    }
}

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

    #[test]
    fn zero_zero_test() {
        assert_eq!(Bit::Zero & &Bit::Zero, Bit::Zero);
    }

    #[test]
    fn zero_one_test() {
        assert_eq!(Bit::Zero & &Bit::One, Bit::Zero);
    }

    #[test]
    fn one_zero_test() {
        assert_eq!(Bit::One & &Bit::Zero, Bit::Zero);
    }

    #[test]
    fn one_one_test() {
        assert_eq!(Bit::One & &Bit::One, Bit::One);
    }
}

impl<'a, 'b> BitAnd<&'a Bit> for &'b Bit {
    type Output = <Bit as BitAnd<Bit>>::Output;

    fn bitand(self, rhs: &'a Bit) -> <Bit as BitAnd<Bit>>::Output {
        bitand_impl(self, rhs)
    }
}

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

    #[test]
    fn zero_zero_test() {
        assert_eq!(&Bit::Zero & &Bit::Zero, Bit::Zero);
    }

    #[test]
    fn zero_one_test() {
        assert_eq!(&Bit::Zero & &Bit::One, Bit::Zero);
    }

    #[test]
    fn one_zero_test() {
        assert_eq!(&Bit::One & &Bit::Zero, Bit::Zero);
    }

    #[test]
    fn one_one_test() {
        assert_eq!(&Bit::One & &Bit::One, Bit::One);
    }
}

impl BitOr for Bit {
    type Output = Bit;

    fn bitor(self, rhs: Bit) -> Bit {
        bitor_impl(&self, &rhs)
    }
}

fn bitor_impl(x: &Bit, y: &Bit) -> Bit
{
    match (x, y) {
        (&Bit::Zero, &Bit::Zero) => Bit::Zero,
        (&Bit::Zero, &Bit::One) => Bit::One,
        (&Bit::One, &Bit::Zero) => Bit::One,
        (&Bit::One, &Bit::One) => Bit::One
    }
}

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

    #[test]
    fn zero_zero_test() {
        assert_eq!(Bit::Zero | Bit::Zero, Bit::Zero);
    }

    #[test]
    fn zero_one_test() {
        assert_eq!(Bit::Zero | Bit::One, Bit::One);
    }

    #[test]
    fn one_zero_test() {
        assert_eq!(Bit::One | Bit::Zero, Bit::One);
    }

    #[test]
    fn one_one_test() {
        assert_eq!(Bit::One | Bit::One, Bit::One);
    }
}

impl<'a> BitOr<Bit> for &'a Bit {
    type Output = <Bit as BitOr<Bit>>::Output;

    fn bitor(self, rhs: Bit) -> <Bit as BitOr<Bit>>::Output {
        bitor_impl(self, &rhs)
    }
}

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

    #[test]
    fn zero_zero_test() {
        assert_eq!(&Bit::Zero | Bit::Zero, Bit::Zero);
    }

    #[test]
    fn zero_one_test() {
        assert_eq!(&Bit::Zero | Bit::One, Bit::One);
    }

    #[test]
    fn one_zero_test() {
        assert_eq!(&Bit::One | Bit::Zero, Bit::One);
    }

    #[test]
    fn one_one_test() {
        assert_eq!(&Bit::One | Bit::One, Bit::One);
    }
}

impl<'a> BitOr<&'a Bit> for Bit {
    type Output = <Bit as BitOr<Bit>>::Output;

    fn bitor(self, rhs: &'a Bit) -> <Bit as BitOr<Bit>>::Output {
        bitor_impl(&self, rhs)
    }
}

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

    #[test]
    fn zero_zero_test() {
        assert_eq!(Bit::Zero | &Bit::Zero, Bit::Zero);
    }

    #[test]
    fn zero_one_test() {
        assert_eq!(Bit::Zero | &Bit::One, Bit::One);
    }

    #[test]
    fn one_zero_test() {
        assert_eq!(Bit::One | &Bit::Zero, Bit::One);
    }

    #[test]
    fn one_one_test() {
        assert_eq!(Bit::One | &Bit::One, Bit::One);
    }
}

impl<'a, 'b> BitOr<&'a Bit> for &'b Bit {
    type Output = <Bit as BitOr<Bit>>::Output;

    fn bitor(self, rhs: &'a Bit) -> <Bit as BitOr<Bit>>::Output {
        bitor_impl(self, rhs)
    }
}

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

    #[test]
    fn zero_zero_test() {
        assert_eq!(&Bit::Zero | &Bit::Zero, Bit::Zero);
    }

    #[test]
    fn zero_one_test() {
        assert_eq!(&Bit::Zero | &Bit::One, Bit::One);
    }

    #[test]
    fn one_zero_test() {
        assert_eq!(&Bit::One | &Bit::Zero, Bit::One);
    }

    #[test]
    fn one_one_test() {
        assert_eq!(&Bit::One | &Bit::One, Bit::One);
    }
}
<commit_msg>apparently you can split up impl declarations; yes please :D<commit_after>use std::ops::Not;
use std::ops::BitAnd;
use std::ops::BitOr;

#[derive(PartialEq, Debug)]
pub enum Bit { Zero, One }

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

    #[test]
    fn eq_zero_zero_test() {
        assert!(Bit::Zero == Bit::Zero);
    }

    #[test]
    #[should_panic]
    fn eq_zero_one_test() {
        assert!(Bit::Zero == Bit::One);
    }

    #[test]
    #[should_panic]
    fn eq_one_zero_test() {
        assert!(Bit::One == Bit::Zero);
    }

    #[test]
    fn eq_one_one_test() {
        assert!(Bit::One == Bit::One);
    }

    #[test]
    #[should_panic]
    fn neq_zero_zero_test() {
        assert!(Bit::Zero != Bit::Zero);
    }

    #[test]
    fn neq_zero_one_test() {
        assert!(Bit::Zero != Bit::One);
    }

    #[test]
    fn neq_one_zero_test() {
        assert!(Bit::One != Bit::Zero);
    }

    #[test]
    #[should_panic]
    fn neq_one_one_test() {
        assert!(Bit::One != Bit::One);
    }
}

impl Bit {
    pub fn to_i32(&self) -> i32 {
        match *self {
            Bit::Zero => 0,
            Bit::One => 1
        }
    }
}

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

    #[test]
    fn zero_test() {
        assert_eq!(Bit::Zero.to_i32(), 0);
    }

    #[test]
    fn one_test() {
        assert_eq!(Bit::One.to_i32(), 1);
    }
}

impl Bit {
    pub fn to_u32(&self) -> u32 {
        match *self {
            Bit::Zero => 0u32,
            Bit::One => 1u32
        }
    }
}

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

    #[test]
    fn zero_test() {
        assert_eq!(Bit::Zero.to_u32(), 0);
    }

    #[test]
    fn one_test() {
        assert_eq!(Bit::One.to_u32(), 1);
    }
}

impl Not for Bit {
    type Output = Bit;

    fn not(self) -> Bit {
        not_impl(&self)
    }
}

fn not_impl(x: &Bit) -> Bit
{
    match *x {
        Bit::Zero => Bit::One,
        Bit::One => Bit::Zero
    }
}

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

    #[test]
    fn zero_test() {
        assert_eq!(!Bit::Zero, Bit::One);
    }

    #[test]
    fn one_test() {
        assert_eq!(!Bit::One, Bit::Zero);
    }
}

impl<'a> Not for &'a Bit {
    type Output = <Bit as Not>::Output;

    fn not(self) -> <Bit as Not>::Output {
        not_impl(self)
    }
}

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

    #[test]
    fn zero_test() {
        assert_eq!(!&Bit::Zero, Bit::One);
    }

    #[test]
    fn one_test() {
        assert_eq!(!&Bit::One, Bit::Zero);
    }
}

impl BitAnd<Bit> for Bit {
    type Output = Bit;

    fn bitand(self, rhs: Bit) -> Bit {
        bitand_impl(&self, &rhs)
    }
}

fn bitand_impl(x: &Bit, y: &Bit) -> Bit {
    match (x, y) {
        (&Bit::Zero, &Bit::Zero) => Bit::Zero,
        (&Bit::Zero, &Bit::One) => Bit::Zero,
        (&Bit::One, &Bit::Zero) => Bit::Zero,
        (&Bit::One, &Bit::One) => Bit::One
    }
}

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

    #[test]
    fn zero_zero_test() {
        assert_eq!(Bit::Zero & Bit::Zero, Bit::Zero);
    }

    #[test]
    fn zero_one_test() {
        assert_eq!(Bit::Zero & Bit::One, Bit::Zero);
    }

    #[test]
    fn one_zero_test() {
        assert_eq!(Bit::One & Bit::Zero, Bit::Zero);
    }

    #[test]
    fn one_one_test() {
        assert_eq!(Bit::One & Bit::One, Bit::One);
    }
}

impl<'a> BitAnd<Bit> for &'a Bit {
    type Output = <Bit as BitAnd<Bit>>::Output;

    fn bitand(self, rhs: Bit) -> <Bit as BitAnd<Bit>>::Output {
        bitand_impl(self, &rhs)
    }
}

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

    #[test]
    fn zero_zero_test() {
        assert_eq!(&Bit::Zero & Bit::Zero, Bit::Zero);
    }

    #[test]
    fn zero_one_test() {
        assert_eq!(&Bit::Zero & Bit::One, Bit::Zero);
    }

    #[test]
    fn one_zero_test() {
        assert_eq!(&Bit::One & Bit::Zero, Bit::Zero);
    }

    #[test]
    fn one_one_test() {
        assert_eq!(&Bit::One & Bit::One, Bit::One);
    }
}

impl<'a> BitAnd<&'a Bit> for Bit {
    type Output = <Bit as BitAnd<Bit>>::Output;

    fn bitand(self, rhs: &'a Bit) -> <Bit as BitAnd<Bit>>::Output {
        bitand_impl(&self, rhs)
    }
}

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

    #[test]
    fn zero_zero_test() {
        assert_eq!(Bit::Zero & &Bit::Zero, Bit::Zero);
    }

    #[test]
    fn zero_one_test() {
        assert_eq!(Bit::Zero & &Bit::One, Bit::Zero);
    }

    #[test]
    fn one_zero_test() {
        assert_eq!(Bit::One & &Bit::Zero, Bit::Zero);
    }

    #[test]
    fn one_one_test() {
        assert_eq!(Bit::One & &Bit::One, Bit::One);
    }
}

impl<'a, 'b> BitAnd<&'a Bit> for &'b Bit {
    type Output = <Bit as BitAnd<Bit>>::Output;

    fn bitand(self, rhs: &'a Bit) -> <Bit as BitAnd<Bit>>::Output {
        bitand_impl(self, rhs)
    }
}

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

    #[test]
    fn zero_zero_test() {
        assert_eq!(&Bit::Zero & &Bit::Zero, Bit::Zero);
    }

    #[test]
    fn zero_one_test() {
        assert_eq!(&Bit::Zero & &Bit::One, Bit::Zero);
    }

    #[test]
    fn one_zero_test() {
        assert_eq!(&Bit::One & &Bit::Zero, Bit::Zero);
    }

    #[test]
    fn one_one_test() {
        assert_eq!(&Bit::One & &Bit::One, Bit::One);
    }
}

impl BitOr for Bit {
    type Output = Bit;

    fn bitor(self, rhs: Bit) -> Bit {
        bitor_impl(&self, &rhs)
    }
}

fn bitor_impl(x: &Bit, y: &Bit) -> Bit
{
    match (x, y) {
        (&Bit::Zero, &Bit::Zero) => Bit::Zero,
        (&Bit::Zero, &Bit::One) => Bit::One,
        (&Bit::One, &Bit::Zero) => Bit::One,
        (&Bit::One, &Bit::One) => Bit::One
    }
}

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

    #[test]
    fn zero_zero_test() {
        assert_eq!(Bit::Zero | Bit::Zero, Bit::Zero);
    }

    #[test]
    fn zero_one_test() {
        assert_eq!(Bit::Zero | Bit::One, Bit::One);
    }

    #[test]
    fn one_zero_test() {
        assert_eq!(Bit::One | Bit::Zero, Bit::One);
    }

    #[test]
    fn one_one_test() {
        assert_eq!(Bit::One | Bit::One, Bit::One);
    }
}

impl<'a> BitOr<Bit> for &'a Bit {
    type Output = <Bit as BitOr<Bit>>::Output;

    fn bitor(self, rhs: Bit) -> <Bit as BitOr<Bit>>::Output {
        bitor_impl(self, &rhs)
    }
}

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

    #[test]
    fn zero_zero_test() {
        assert_eq!(&Bit::Zero | Bit::Zero, Bit::Zero);
    }

    #[test]
    fn zero_one_test() {
        assert_eq!(&Bit::Zero | Bit::One, Bit::One);
    }

    #[test]
    fn one_zero_test() {
        assert_eq!(&Bit::One | Bit::Zero, Bit::One);
    }

    #[test]
    fn one_one_test() {
        assert_eq!(&Bit::One | Bit::One, Bit::One);
    }
}

impl<'a> BitOr<&'a Bit> for Bit {
    type Output = <Bit as BitOr<Bit>>::Output;

    fn bitor(self, rhs: &'a Bit) -> <Bit as BitOr<Bit>>::Output {
        bitor_impl(&self, rhs)
    }
}

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

    #[test]
    fn zero_zero_test() {
        assert_eq!(Bit::Zero | &Bit::Zero, Bit::Zero);
    }

    #[test]
    fn zero_one_test() {
        assert_eq!(Bit::Zero | &Bit::One, Bit::One);
    }

    #[test]
    fn one_zero_test() {
        assert_eq!(Bit::One | &Bit::Zero, Bit::One);
    }

    #[test]
    fn one_one_test() {
        assert_eq!(Bit::One | &Bit::One, Bit::One);
    }
}

impl<'a, 'b> BitOr<&'a Bit> for &'b Bit {
    type Output = <Bit as BitOr<Bit>>::Output;

    fn bitor(self, rhs: &'a Bit) -> <Bit as BitOr<Bit>>::Output {
        bitor_impl(self, rhs)
    }
}

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

    #[test]
    fn zero_zero_test() {
        assert_eq!(&Bit::Zero | &Bit::Zero, Bit::Zero);
    }

    #[test]
    fn zero_one_test() {
        assert_eq!(&Bit::Zero | &Bit::One, Bit::One);
    }

    #[test]
    fn one_zero_test() {
        assert_eq!(&Bit::One | &Bit::Zero, Bit::One);
    }

    #[test]
    fn one_one_test() {
        assert_eq!(&Bit::One | &Bit::One, Bit::One);
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::cell::{RefCell, RefMut};

use reqwest::{Response};

use errors::*;
use client::MatrixClient;
use matrix_types::Event;

#[derive(Clone)]
pub struct RoomEvent<'a> {
    pub room_id: &'a str,
    pub raw_event: &'a Event,
}

pub struct Bot <'a, 'b> {
    client: RefCell<&'b mut MatrixClient>,
    root_services: Vec<&'a str>,
    all_services: HashMap<&'a str, RefCell<Box<Node<'a>>>>,

    rooms: RefCell<Vec<String>>,
}

impl<'a, 'b> Bot<'a, 'b> {
    pub fn new(client: &'b mut MatrixClient) -> Self{
        Bot {
            client: RefCell::new(client),
            root_services: Vec::new(),
            all_services: HashMap::new(),
            rooms: RefCell::new(Vec::new()),
        }
    }

    pub fn join(&self, room_id: &str) -> Result<Response, RustixError>{
        self.rooms.borrow_mut().push(room_id.clone().to_string());

        self.client.borrow().join(room_id)
    }

    pub fn say(&self, room_id: &str, message: &str) -> Result<Response, RustixError> {
        self.client.borrow_mut().send_msg(room_id, message)
    }

    pub fn reply(&self, event: &RoomEvent, message: &str) -> Result<Response, RustixError> {
        self.say(event.room_id, message)
    }

    /*
    pub fn action(&self, room_id: &str, action: &str) {
    }

    pub fn set_name(&self, name: &str) {
    }
    */

    pub fn register_service(&mut self,
                            name: &'a str,
                            parent: Option<&'a str>,
                            mut service: Box<Node<'a>>) -> Option<&'a str> {
        match parent {
            Some(p) => {
                self.all_services.get_mut(p).expect("Invalid parent node")
                    .borrow_mut().register_child(name)
            },
            None => self.root_services.push(name),
        };

        service.on_load();

        self.all_services.insert(name, RefCell::new(service));

        Some(name)
    }

    pub fn get_service(&self, name: &str) -> RefMut<Box<Node<'a>>> {
        self.all_services.get(name).unwrap().borrow_mut()
    }

    pub fn propagate_event(&self, event: &RoomEvent) {
        for service in &self.root_services {
            self.all_services.get(service).unwrap()
                .borrow_mut().handle(self, event.clone());
        }
    }

    pub fn run(&mut self) {
        let initial_rooms = vec!["test", "test2", "#geeks"];
        for room in initial_rooms {
            if let Some(rid) = self.client.borrow().get_public_room_id(room) {
                println!("Joining {} id: {}", &room, &rid);
                self.join(&rid);
            }
        }

        let mut next_batch: String = self.client.borrow().sync(None).unwrap().next_batch;

        loop {
            let sync_data = self.client.borrow().sync(Some(&next_batch)).unwrap();

            for room_id in self.rooms.borrow().iter() {
                if let Some(room) = sync_data.rooms.join.get(room_id) {
                    for raw_event in &room.timeline.events {
                        self.propagate_event(
                            &RoomEvent{room_id, raw_event}
                        );
                    }
                }
            }

            next_batch = sync_data.next_batch;
        }
    }
}

pub trait Node<'a> {
    fn children(&self) -> Option<&Vec<&'a str>> {
        None
    }

    fn register_child(&mut self, name: &'a str) {
    }

    fn propagate_event(&self, bot: &Bot, event: RoomEvent) {
        if let Some(children) = self.children() {
            for child in children {
                bot.get_service(child).handle(bot, event.clone());
            }
        }
    }

    fn handle(&mut self, bot: &Bot, event: RoomEvent) {
        self.propagate_event(bot, event);
    }

    fn on_load(&mut self) { }

    fn on_exit(&self) { }
}

/*
if let Ok(x) = serde_json::to_string_pretty(&res.rooms.join) {
    println!("{}", x);
} */
<commit_msg>Just removing an extra newline.<commit_after>use std::collections::HashMap;
use std::cell::{RefCell, RefMut};

use reqwest::{Response};

use errors::*;
use client::MatrixClient;
use matrix_types::Event;

#[derive(Clone)]
pub struct RoomEvent<'a> {
    pub room_id: &'a str,
    pub raw_event: &'a Event,
}

pub struct Bot <'a, 'b> {
    client: RefCell<&'b mut MatrixClient>,
    root_services: Vec<&'a str>,
    all_services: HashMap<&'a str, RefCell<Box<Node<'a>>>>,

    rooms: RefCell<Vec<String>>,
}

impl<'a, 'b> Bot<'a, 'b> {
    pub fn new(client: &'b mut MatrixClient) -> Self{
        Bot {
            client: RefCell::new(client),
            root_services: Vec::new(),
            all_services: HashMap::new(),
            rooms: RefCell::new(Vec::new()),
        }
    }

    pub fn join(&self, room_id: &str) -> Result<Response, RustixError>{
        self.rooms.borrow_mut().push(room_id.clone().to_string());

        self.client.borrow().join(room_id)
    }

    pub fn say(&self, room_id: &str, message: &str) -> Result<Response, RustixError> {
        self.client.borrow_mut().send_msg(room_id, message)
    }

    pub fn reply(&self, event: &RoomEvent, message: &str) -> Result<Response, RustixError> {
        self.say(event.room_id, message)
    }

    /*
    pub fn action(&self, room_id: &str, action: &str) {
    }

    pub fn set_name(&self, name: &str) {
    }
    */

    pub fn register_service(&mut self,
                            name: &'a str,
                            parent: Option<&'a str>,
                            mut service: Box<Node<'a>>) -> Option<&'a str> {
        match parent {
            Some(p) => {
                self.all_services.get_mut(p).expect("Invalid parent node")
                    .borrow_mut().register_child(name)
            },
            None => self.root_services.push(name),
        };

        service.on_load();

        self.all_services.insert(name, RefCell::new(service));

        Some(name)
    }

    pub fn get_service(&self, name: &str) -> RefMut<Box<Node<'a>>> {
        self.all_services.get(name).unwrap().borrow_mut()
    }

    pub fn propagate_event(&self, event: &RoomEvent) {
        for service in &self.root_services {
            self.all_services.get(service).unwrap()
                .borrow_mut().handle(self, event.clone());
        }
    }

    pub fn run(&mut self) {
        let initial_rooms = vec!["test", "test2", "#geeks"];
        for room in initial_rooms {
            if let Some(rid) = self.client.borrow().get_public_room_id(room) {
                println!("Joining {} id: {}", &room, &rid);
                self.join(&rid);
            }
        }

        let mut next_batch: String = self.client.borrow().sync(None).unwrap().next_batch;

        loop {
            let sync_data = self.client.borrow().sync(Some(&next_batch)).unwrap();

            for room_id in self.rooms.borrow().iter() {
                if let Some(room) = sync_data.rooms.join.get(room_id) {
                    for raw_event in &room.timeline.events {
                        self.propagate_event(
                            &RoomEvent{room_id, raw_event}
                        );
                    }
                }
            }

            next_batch = sync_data.next_batch;
        }
    }
}

pub trait Node<'a> {
    fn children(&self) -> Option<&Vec<&'a str>> {
        None
    }

    fn register_child(&mut self, name: &'a str) {
    }

    fn propagate_event(&self, bot: &Bot, event: RoomEvent) {
        if let Some(children) = self.children() {
            for child in children {
                bot.get_service(child).handle(bot, event.clone());
            }
        }
    }

    fn handle(&mut self, bot: &Bot, event: RoomEvent) {
        self.propagate_event(bot, event);
    }

    fn on_load(&mut self) { }

    fn on_exit(&self) { }
}

/*
if let Ok(x) = serde_json::to_string_pretty(&res.rooms.join) {
    println!("{}", x);
} */
<|endoftext|>


<commit_before>extern crate rand;

use std;

// A struct to contain info we need to print with every character
pub struct Control {
    pub seed: f64,
    pub spread: f64,
    pub frequency: f64,
    pub background_mode: bool,
    pub dialup_mode: bool,
}

// A wrapper around colored_print
pub fn print_with_lolcat(s: String, c: &mut Control) {
    let original_seed = c.seed;
    let mut skipping = false;

    for character in s.chars() {
        // Strip out any color chars
        if character == '\x1b' {
            skipping = true;
            continue;
        }
        if skipping && character == 'm' {
            skipping = false;
            continue;
        }
        if skipping {
            continue;
        }

        c.seed += 1.0;

        if c.background_mode {
            let bg = get_color_tuple(c);
            let fg = calc_fg_color(bg);
            colored_print(fg, bg, character);
        } else {
            let fg = get_color_tuple(c);
            let black = (0u8, 0u8, 0u8);
            colored_print(fg, black, character);
        }
    }

    print!("\n"); // A newline, because lines() gave us a single line without it
    c.seed = original_seed + 1.0; // Reset the seed, but bump it a bit
}

fn calc_fg_color(bg: (u8, u8, u8)) -> (u8, u8, u8) {
    // Currently, it only computes the forground clolor based on some threshold
    // on grayscale value.
    // TODO: Add a better algorithm for computing forground color
    if conv_grayscale(bg) > 0xA0_u8 {
        (0u8, 0u8, 0u8)
    } else {
        (0xffu8, 0xffu8, 0xffu8)
    }
}

fn linear_to_srgb(intensity: f64) -> f64 {
    if intensity <= 0.0031308 {
        (12.92 * intensity)
    } else {
        (1.055 * intensity.powf(1.0 / 2.4) - 0.055)
    }
}

fn srgb_to_linear(intensity: f64) -> f64 {
    if intensity < 0.04045 {
        (intensity / 12.92)
    } else {
        ((intensity + 0.055) / 1.055).powf(2.4)
    }
}

fn conv_grayscale(color: (u8, u8, u8)) -> u8 {
    // See https://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
    const SCALE: f64 = 256.0;

    // Changing SRGB to Linear for gamma correction
    let red = srgb_to_linear((color.0 as f64) / SCALE);
    let green = srgb_to_linear((color.1 as f64) / SCALE);
    let blue = srgb_to_linear((color.2 as f64) / SCALE);

    // Converting to grayscale
    let gray_linear = red * 0.299 + green * 0.587 + blue * 0.114;

    // Gamma correction
    let gray_srgb = linear_to_srgb(gray_linear);

    (gray_srgb * SCALE) as u8
}

fn colored_print(fg: (u8, u8, u8), bg: (u8, u8, u8), c: char) {
    print!(
        "\x1b[38;2;{};{};{};48;2;{};{};{}m{}\x1b[0m",
        fg.0, fg.1, fg.2, bg.0, bg.1, bg.2, c
    );
}

fn get_color_tuple(c: &Control) -> (u8, u8, u8) {
    let i = c.frequency * c.seed / c.spread;
    let red = i.sin() * 127.00 + 128.00;
    let green = (i + (std::f64::consts::PI * 2.00 / 3.00)).sin() * 127.00 + 128.00;
    let blue = (i + (std::f64::consts::PI * 4.00 / 3.00)).sin() * 127.00 + 128.00;

    (red as u8, green as u8, blue as u8)
}
<commit_msg>Removed rainbow from /^\s+/<commit_after>extern crate rand;

use std;

// A struct to contain info we need to print with every character
pub struct Control {
    pub seed: f64,
    pub spread: f64,
    pub frequency: f64,
    pub background_mode: bool,
    pub dialup_mode: bool,
}

// A wrapper around colored_print
pub fn print_with_lolcat(s: String, c: &mut Control) {
    let original_seed = c.seed;
    let mut skipping = false;
    let mut whitespace_after_newline = true;

    for character in s.chars() {
        // Strip out any color chars
        if character == '\x1b' {
            skipping = true;
            continue;
        }
        if skipping && character == 'm' {
            skipping = false;
            continue;
        }
        if skipping {
            continue;
        }

        if !character.is_whitespace() {
            whitespace_after_newline = false;
        }

        if whitespace_after_newline {
            print!("{}", character);
            continue;
        }

        c.seed += 1.0;

        if c.background_mode {
            let bg = get_color_tuple(c);
            let fg = calc_fg_color(bg);
            colored_print(fg, bg, character);
        } else {
            let fg = get_color_tuple(c);
            let black = (0u8, 0u8, 0u8);
            colored_print(fg, black, character);
        }
    }

    print!("\n"); // A newline, because lines() gave us a single line without it
    c.seed = original_seed + 1.0; // Reset the seed, but bump it a bit
}

fn calc_fg_color(bg: (u8, u8, u8)) -> (u8, u8, u8) {
    // Currently, it only computes the forground clolor based on some threshold
    // on grayscale value.
    // TODO: Add a better algorithm for computing forground color
    if conv_grayscale(bg) > 0xA0_u8 {
        (0u8, 0u8, 0u8)
    } else {
        (0xffu8, 0xffu8, 0xffu8)
    }
}

fn linear_to_srgb(intensity: f64) -> f64 {
    if intensity <= 0.0031308 {
        (12.92 * intensity)
    } else {
        (1.055 * intensity.powf(1.0 / 2.4) - 0.055)
    }
}

fn srgb_to_linear(intensity: f64) -> f64 {
    if intensity < 0.04045 {
        (intensity / 12.92)
    } else {
        ((intensity + 0.055) / 1.055).powf(2.4)
    }
}

fn conv_grayscale(color: (u8, u8, u8)) -> u8 {
    // See https://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
    const SCALE: f64 = 256.0;

    // Changing SRGB to Linear for gamma correction
    let red = srgb_to_linear((color.0 as f64) / SCALE);
    let green = srgb_to_linear((color.1 as f64) / SCALE);
    let blue = srgb_to_linear((color.2 as f64) / SCALE);

    // Converting to grayscale
    let gray_linear = red * 0.299 + green * 0.587 + blue * 0.114;

    // Gamma correction
    let gray_srgb = linear_to_srgb(gray_linear);

    (gray_srgb * SCALE) as u8
}

fn colored_print(fg: (u8, u8, u8), bg: (u8, u8, u8), c: char) {
    print!(
        "\x1b[38;2;{};{};{};48;2;{};{};{}m{}\x1b[0m",
        fg.0, fg.1, fg.2, bg.0, bg.1, bg.2, c
    );
}

fn get_color_tuple(c: &Control) -> (u8, u8, u8) {
    let i = c.frequency * c.seed / c.spread;
    let red = i.sin() * 127.00 + 128.00;
    let green = (i + (std::f64::consts::PI * 2.00 / 3.00)).sin() * 127.00 + 128.00;
    let blue = (i + (std::f64::consts::PI * 4.00 / 3.00)).sin() * 127.00 + 128.00;

    (red as u8, green as u8, blue as u8)
}
<|endoftext|>


<commit_before>extern crate futures;
extern crate hyper;
extern crate tokio_core;
extern crate tokio_process;

use self::futures::future::Future;
use self::futures::Stream;
use self::hyper::header::ContentEncoding;
use self::hyper::header::ContentLength;
use self::hyper::header::ContentType;
use self::hyper::server::{Request, Response};
use cgi::tokio_process::CommandExt;
use std::io;
use std::io::BufRead;
use std::io::Read;
use std::io::Write;
use std::process::Command;
use std::process::Stdio;
use std::str::FromStr;

pub fn do_cgi(
    req: Request,
    cmd: Command,
    handle: tokio_core::reactor::Handle,
) -> Box<Future<Item = Response, Error = hyper::Error>> {
    trace_scoped!("do_cgi");
    let mut cmd = cmd;
    cmd.stdout(Stdio::piped());
    cmd.stderr(Stdio::inherit());
    cmd.stdin(Stdio::piped());
    println!("REQUEST_METHOD {:?}", req.method());
    cmd.env("SERVER_SOFTWARE", "hyper")
        .env("SERVER_NAME", "localhost") // TODO
        .env("GATEWAY_INTERFACE", "CGI/1.1")
        .env("SERVER_PROTOCOL", "HTTP/1.1") // TODO
        .env("SERVER_PORT", "80") // TODO
        .env("REQUEST_METHOD", format!("{}", req.method()))
        .env("SCRIPT_NAME", "") // TODO
        .env("QUERY_STRING", req.query().unwrap_or(""))
        .env("REMOTE_ADDR", "") // TODO
        .env("AUTH_TYPE", "") // TODO
        .env("REMOTE_USER", "") // TODO
        .env(
            "CONTENT_TYPE",
            &format!(
                "{}",
                req.headers().get().unwrap_or(&ContentType::plaintext())
            ),
        )
        .env(
            "HTTP_CONTENT_ENCODING",
            &format!(
                "{}",
                req.headers().get().unwrap_or(&ContentEncoding(vec![]))
            ),
        )
        .env(
            "CONTENT_LENGTH",
            &format!("{}", req.headers().get().unwrap_or(&ContentLength(0))),
        );

    let mut child = cmd
        .spawn_async_with_handle(&handle.new_tokio_handle())
        .expect("can't spawn CGI command");

    Box::new(req.body().concat2().and_then(move |body| {
        if !child.stdin().take().unwrap().write_all(&body).is_ok() {
            debug!("write_all(body) failed");
        }

        child
            .wait_with_output()
            .map(build_response)
            .map_err(|e| e.into())
    }))
}

fn build_response(command_result: std::process::Output) -> Response {
    trace_begin!("build_response");
    let mut stdout = io::BufReader::new(command_result.stdout.as_slice());
    let mut stderr = io::BufReader::new(command_result.stderr.as_slice());

    let mut response = Response::new();

    let mut headers = vec![];
    for line in stdout.by_ref().lines() {
        println!("STDOUT line: {:?}", line);
        if line.as_ref().unwrap().is_empty() {
            break;
        }
        let l: Vec<&str> = line.as_ref().unwrap().as_str().splitn(2, ": ").collect();
        for x in &l {
            headers.push(x.to_string());
        }
        if l[0] == "Status" {
            response.set_status(hyper::StatusCode::Unregistered(
                u16::from_str(l[1].split(" ").next().unwrap()).unwrap(),
            ));
        } else {
            response
                .headers_mut()
                .set_raw(l[0].to_string(), l[1].to_string());
        }
    }

    let mut data = vec![];
    stdout
        .read_to_end(&mut data)
        .expect("can't read command output");

    let mut stderrdata = vec![];
    stderr
        .read_to_end(&mut stderrdata)
        .expect("can't read command output");

    trace_end!(
        "build_response",
        "stdout": &data,
        "stderr": &stderrdata,
        "headers": headers
    );
    response.set_body(hyper::Chunk::from(data));

    response
}
<commit_msg>log as string<commit_after>extern crate futures;
extern crate hyper;
extern crate tokio_core;
extern crate tokio_process;

use self::futures::future::Future;
use self::futures::Stream;
use self::hyper::header::ContentEncoding;
use self::hyper::header::ContentLength;
use self::hyper::header::ContentType;
use self::hyper::server::{Request, Response};
use cgi::tokio_process::CommandExt;
use std::io;
use std::io::BufRead;
use std::io::Read;
use std::io::Write;
use std::process::Command;
use std::process::Stdio;
use std::str::FromStr;

pub fn do_cgi(
    req: Request,
    cmd: Command,
    handle: tokio_core::reactor::Handle,
) -> Box<Future<Item = Response, Error = hyper::Error>> {
    trace_scoped!("do_cgi");
    let mut cmd = cmd;
    cmd.stdout(Stdio::piped());
    cmd.stderr(Stdio::inherit());
    cmd.stdin(Stdio::piped());
    println!("REQUEST_METHOD {:?}", req.method());
    cmd.env("SERVER_SOFTWARE", "hyper")
        .env("SERVER_NAME", "localhost") // TODO
        .env("GATEWAY_INTERFACE", "CGI/1.1")
        .env("SERVER_PROTOCOL", "HTTP/1.1") // TODO
        .env("SERVER_PORT", "80") // TODO
        .env("REQUEST_METHOD", format!("{}", req.method()))
        .env("SCRIPT_NAME", "") // TODO
        .env("QUERY_STRING", req.query().unwrap_or(""))
        .env("REMOTE_ADDR", "") // TODO
        .env("AUTH_TYPE", "") // TODO
        .env("REMOTE_USER", "") // TODO
        .env(
            "CONTENT_TYPE",
            &format!(
                "{}",
                req.headers().get().unwrap_or(&ContentType::plaintext())
            ),
        )
        .env(
            "HTTP_CONTENT_ENCODING",
            &format!(
                "{}",
                req.headers().get().unwrap_or(&ContentEncoding(vec![]))
            ),
        )
        .env(
            "CONTENT_LENGTH",
            &format!("{}", req.headers().get().unwrap_or(&ContentLength(0))),
        );

    let mut child = cmd
        .spawn_async_with_handle(&handle.new_tokio_handle())
        .expect("can't spawn CGI command");

    Box::new(req.body().concat2().and_then(move |body| {
        if !child.stdin().take().unwrap().write_all(&body).is_ok() {
            debug!("write_all(body) failed");
        }

        child
            .wait_with_output()
            .map(build_response)
            .map_err(|e| e.into())
    }))
}

fn build_response(command_result: std::process::Output) -> Response {
    trace_begin!("build_response");
    let mut stdout = io::BufReader::new(command_result.stdout.as_slice());
    let mut stderr = io::BufReader::new(command_result.stderr.as_slice());

    let mut response = Response::new();

    let mut headers = vec![];
    for line in stdout.by_ref().lines() {
        println!("STDOUT line: {:?}", line);
        if line.as_ref().unwrap().is_empty() {
            break;
        }
        let l: Vec<&str> = line.as_ref().unwrap().as_str().splitn(2, ": ").collect();
        for x in &l {
            headers.push(x.to_string());
        }
        if l[0] == "Status" {
            response.set_status(hyper::StatusCode::Unregistered(
                u16::from_str(l[1].split(" ").next().unwrap()).unwrap(),
            ));
        } else {
            response
                .headers_mut()
                .set_raw(l[0].to_string(), l[1].to_string());
        }
    }

    let mut data = vec![];
    stdout
        .read_to_end(&mut data)
        .expect("can't read command output");

    let mut stderrdata = vec![];
    stderr
        .read_to_end(&mut stderrdata)
        .expect("can't read command output");

    let out = String::from_utf8_lossy(&data).to_string();
    let err = String::from_utf8_lossy(&stderrdata);

    println!("build_response out {:?}", &out);
    println!("build_response err {:?}", &err);

    trace_end!(
        "build_response",
        "stdout": out,
        "stderr": err,
        "headers": headers
    );
    response.set_body(hyper::Chunk::from(data));

    response
}
<|endoftext|>


<commit_before>//! A simple parser for a tiny subset of CSS.
//!
//! To support more CSS syntax, it would probably be easiest to replace this
//! hand-rolled parser with one based on a library or parser generator.

use std::from_str::FromStr;
use std::ascii::OwnedStrAsciiExt;

// Data structures:

#[deriving(Show)]
pub struct Stylesheet {
    pub rules: Vec<Rule>,
}

#[deriving(Show)]
pub struct Rule {
    pub selectors: Vec<Selector>,
    pub declarations: Vec<Declaration>,
}

#[deriving(Show)]
pub enum Selector {
    Simple(SimpleSelector),
}

#[deriving(Show)]
pub enum SimpleSelector {
    TypeSelector(String),
}

#[deriving(Show)]
pub struct Declaration {
    pub name: String,
    pub value: Value,
}

#[deriving(Show)]
pub enum Value {
    Keyword(String),
    Length(f32, Unit),
}

#[deriving(Show)]
pub enum Unit {
    Px,
    // TODO: Everything else.
}

// Parsing:

pub fn parse(source: String) -> Stylesheet {
    let mut parser = Parser {
        pos: 0u,
        len: source.len(),
        input: source,
    };
    parser.parse_stylesheet()
}

pub struct Parser {
    pos: uint,
    len: uint,
    input: String,
}

impl Parser {
    fn parse_stylesheet(&mut self) -> Stylesheet {
        let mut rules = Vec::new();
        loop {
            self.consume_whitespace();
            if self.eof() {
                break;
            }
            rules.push(self.parse_rule());
        }
        Stylesheet { rules: rules }
    }

    fn parse_rule(&mut self) -> Rule {
        Rule {
            selectors: self.parse_selectors(),
            declarations: self.parse_declarations(),
        }
    }

    fn parse_selectors(&mut self) -> Vec<Selector> {
        let mut selectors = Vec::new();
        selectors.push(self.parse_type_selector());
        selectors
    }

    fn parse_type_selector(&mut self) -> Selector {
        Simple(TypeSelector(self.parse_identifier()))
    }

    fn parse_declarations(&mut self) -> Vec<Declaration> {
        self.consume_whitespace();
        assert!(self.consume_char() == '{');
        let mut declarations = Vec::new();
        loop {
            self.consume_whitespace();
            if self.curr_char() == Some('}') {
                self.consume_char();
                break;
            }
            declarations.push(self.parse_declaration());
        }
        declarations
    }

    fn parse_declaration(&mut self) -> Declaration {
        let property_name = self.parse_identifier();
        self.consume_whitespace();
        assert!(self.consume_char() == ':')
        self.consume_whitespace();
        let value = self.parse_value();
        self.consume_whitespace();
        assert!(self.consume_char() == ';')

        Declaration {
            name: property_name,
            value: value,
        }
    }

    fn parse_value(&mut self) -> Value {
        match self.curr_char().unwrap() {
            '0'..'9' => self.parse_length(),
            _ => Keyword(self.parse_identifier())
        }
    }

    fn parse_length(&mut self) -> Value {
        Length(self.parse_float(), self.parse_unit())
    }

    fn parse_identifier(&mut self) -> String {
        let mut name = String::new();
        // TODO: Identifiers must not start with a digit or "--" or "-" and a digit.
        loop {
            let c = self.curr_char();
            if c.is_none() {
                break;
            }
            match c.unwrap() {
                // TODO: Include U+00A0 and higher.
                'a'..'z' |
                'A'..'Z' |
                '0'..'9' |
                '-' | '_' => name.push_char(self.consume_char()),
                _ => break,
            }
        }
        name
    }

    fn parse_float(&mut self) -> f32 {
        let mut s = String::new();
        loop {
            match self.curr_char().unwrap() {
                '0'..'9' | '.' => s.push_char(self.consume_char()),
                _ => break
            }
        }
        let f: Option<f32> = FromStr::from_str(s.as_slice());
        f.unwrap()
    }

    fn parse_unit(&mut self) -> Unit {
        match self.parse_identifier().into_ascii_lower().as_slice() {
            "px" => Px,
            _ => fail!("unrecognized unit")
        }
    }

    /// Consume and discard zero or more whitespace characters.
    pub fn consume_whitespace(&mut self) {
        loop {
            match self.curr_char() {
                Some(c) if c.is_whitespace() => self.consume_char(),
                _ => break,
            };
        }
    }

    /// Return the current character, and advance self.pos to the next character.
    pub fn consume_char(&mut self) -> char {
        let range = self.input.as_slice().char_range_at(self.pos);
        self.pos = range.next;
        range.ch
    }

    /// Read a character without consuming it.
    pub fn char_at(&self, i: uint) -> Option<char> {
        if i < self.len {
            Some(self.input.as_slice().char_at(i))
        } else {
            None
        }
    }

    // Convenience functions for reading ahead 0 or 1 characters.
    pub fn curr_char(&self) -> Option<char> { self.char_at(self.pos)     }

    /// Return true if all input is consumed.
    pub fn eof(&self) -> bool {
        self.pos >= self.len
    }
}
<commit_msg>Code cleanup<commit_after>//! A simple parser for a tiny subset of CSS.
//!
//! To support more CSS syntax, it would probably be easiest to replace this
//! hand-rolled parser with one based on a library or parser generator.

use std::from_str::FromStr;
use std::ascii::OwnedStrAsciiExt;

// Data structures:

#[deriving(Show)]
pub struct Stylesheet {
    pub rules: Vec<Rule>,
}

#[deriving(Show)]
pub struct Rule {
    pub selectors: Vec<Selector>,
    pub declarations: Vec<Declaration>,
}

#[deriving(Show)]
pub enum Selector {
    Simple(SimpleSelector),
}

#[deriving(Show)]
pub enum SimpleSelector {
    TypeSelector(String),
}

#[deriving(Show)]
pub struct Declaration {
    pub name: String,
    pub value: Value,
}

#[deriving(Show)]
pub enum Value {
    Keyword(String),
    Length(f32, Unit),
}

#[deriving(Show)]
pub enum Unit {
    Px,
}

// Parsing:

pub fn parse(source: String) -> Stylesheet {
    let mut parser = Parser {
        pos: 0u,
        len: source.len(),
        input: source,
    };
    parser.parse_stylesheet()
}

struct Parser {
    pos: uint,
    len: uint,
    input: String,
}

impl Parser {
    fn parse_stylesheet(&mut self) -> Stylesheet {
        let mut rules = Vec::new();
        loop {
            self.consume_whitespace();
            if self.eof() {
                break;
            }
            rules.push(self.parse_rule());
        }
        Stylesheet { rules: rules }
    }

    fn parse_rule(&mut self) -> Rule {
        Rule {
            selectors: self.parse_selectors(),
            declarations: self.parse_declarations(),
        }
    }

    fn parse_selectors(&mut self) -> Vec<Selector> {
        let mut selectors = Vec::new();
        selectors.push(self.parse_type_selector());
        selectors
    }

    fn parse_type_selector(&mut self) -> Selector {
        Simple(TypeSelector(self.parse_identifier()))
    }

    fn parse_declarations(&mut self) -> Vec<Declaration> {
        self.consume_whitespace();
        assert!(self.consume_char() == '{');
        let mut declarations = Vec::new();
        loop {
            self.consume_whitespace();
            if self.curr_char() == Some('}') {
                self.consume_char();
                break;
            }
            declarations.push(self.parse_declaration());
        }
        declarations
    }

    fn parse_declaration(&mut self) -> Declaration {
        let property_name = self.parse_identifier();
        self.consume_whitespace();
        assert!(self.consume_char() == ':')
        self.consume_whitespace();
        let value = self.parse_value();
        self.consume_whitespace();
        assert!(self.consume_char() == ';')

        Declaration {
            name: property_name,
            value: value,
        }
    }

    fn parse_value(&mut self) -> Value {
        match self.curr_char().unwrap() {
            '0'..'9' => self.parse_length(),
            _ => Keyword(self.parse_identifier())
        }
    }

    fn parse_length(&mut self) -> Value {
        Length(self.parse_float(), self.parse_unit())
    }

    fn parse_identifier(&mut self) -> String {
        let mut name = String::new();
        // TODO: Identifiers must not start with a digit or "--" or "-" and a digit.
        loop {
            let c = self.curr_char();
            if c.is_none() {
                break;
            }
            match c.unwrap() {
                // TODO: Include U+00A0 and higher.
                'a'..'z' |
                'A'..'Z' |
                '0'..'9' |
                '-' | '_' => name.push_char(self.consume_char()),
                _ => break,
            }
        }
        name
    }

    fn parse_float(&mut self) -> f32 {
        let mut s = String::new();
        loop {
            match self.curr_char().unwrap() {
                '0'..'9' | '.' => s.push_char(self.consume_char()),
                _ => break
            }
        }
        let f: Option<f32> = FromStr::from_str(s.as_slice());
        f.unwrap()
    }

    fn parse_unit(&mut self) -> Unit {
        match self.parse_identifier().into_ascii_lower().as_slice() {
            "px" => Px,
            _ => fail!("unrecognized unit")
        }
    }

    /// Consume and discard zero or more whitespace characters.
    fn consume_whitespace(&mut self) {
        loop {
            match self.curr_char() {
                Some(c) if c.is_whitespace() => self.consume_char(),
                _ => break,
            };
        }
    }

    /// Return the current character, and advance self.pos to the next character.
    fn consume_char(&mut self) -> char {
        let range = self.input.as_slice().char_range_at(self.pos);
        self.pos = range.next;
        range.ch
    }

    /// Read a character without consuming it.
    fn char_at(&self, i: uint) -> Option<char> {
        if i < self.len {
            Some(self.input.as_slice().char_at(i))
        } else {
            None
        }
    }

    fn curr_char(&self) -> Option<char> { self.char_at(self.pos)     }

    /// Return true if all input is consumed.
    fn eof(&self) -> bool {
        self.pos >= self.len
    }
}
<|endoftext|>


<commit_before>/// Creates Rust structure for new Ruby class
///
/// # Examples
///
/// ```no_run
/// #[macro_use]
/// extern crate ruru;
///
/// use ruru::{AnyObject, Class, RString, VM};
/// use ruru::types::{Argc, Value};
/// use ruru::traits::Object;
///
/// class!(Greeter);
///
/// methods!(
///     Greeter,
///     itself,
///
///     anonymous_greeting() -> RString {
///         RString::new("Hello stranger!")
///     }
///
///     friendly_greeting(name: RString) -> RString {
///         let greeting = format!("Hello dear {}!", name.to_string());
///
///         RString::new(&greeting)
///     }
/// );
///
/// fn main() {
///     # VM::init();
///     Class::new("Greeter").define(|itself| {
///         itself.def("anonymous_greeting", anonymous_greeting);
///         itself.def("friendly_greeting", friendly_greeting);
///     });
/// }
/// ```
///
/// Ruby:
///
/// ```ruby
/// class Greeter
///   def anonymous_greeting
///     'Hello stranger!'
///   end
///
///   def friendly_greeting(name)
///     "Hello dear #{name}"
///   end
/// end
/// ```
#[macro_export]
macro_rules! class {
    ($class: ident) => {
        pub struct $class {
            value: Value,
        }

        impl From<Value> for $class {
            fn from(value: Value) -> Self {
                $class { value: value }
            }
        }

        impl Object for $class {
            fn value(&self) -> Value {
                self.value
            }
        }
    }
}

/// Creates callbacks for Ruby methods
///
/// # Examples
///
/// ```no_run
/// #[macro_use]
/// extern crate ruru;
///
/// use ruru::{AnyObject, Boolean, Class, Fixnum, RString, VM};
/// use ruru::types::Argc;
/// use ruru::traits::Object;
///
/// // Creates `string_is_blank` and `string_length_equals` functions
/// methods!(
///     RString, // type of `self` object
///     itself, // name of `self` object which will be used in methods
///
///     string_is_blank() -> Boolean {
///         Boolean::new(itself.to_string().chars().all(|c| c.is_whitespace()))
///     }
///
///     string_length_equals(expected_length: Fixnum) -> Boolean {
///         let real_length = itself.to_string().len() as i64;
///
///         Boolean::new(expected_length.to_i64() == real_length)
///     }
/// );
///
/// fn main() {
///     # VM::init();
///     Class::from_existing("String").define(|itself| {
///         itself.def("blank?", string_is_blank);
///         itself.def("length_equals?", string_length_equals);
///     });
/// }
/// ```
///
/// Ruby:
///
/// ```ruby
/// class String
///   def blank?
///     # ...
///   end
///
///   def length_equals?(expected_length)
///     # ...
///   end
/// end
/// ```
#[macro_export]
macro_rules! methods {
    (
        $itself_class: ty,
        $itself_name: ident,
        $(
            $method_name: ident
            ($($arg_name: ident: $arg_type: ty),*) -> $return_type: ident $body: block
        )*
    ) => {
        $(
            #[no_mangle]
            pub extern fn $method_name(argc: Argc,
                                       argv: *const AnyObject,
                                       mut $itself_name: $itself_class) -> $return_type {
                let arguments = VM::parse_arguments(argc, argv);
                let mut i = 0;

                $(
                    let $arg_name = arguments[i].to::<$arg_type>();
                    i += 1;
                )*

                $body
            }
        )*
    }
}
<commit_msg>Change methods! macro<commit_after>/// Creates Rust structure for new Ruby class
///
/// # Examples
///
/// ```no_run
/// #[macro_use]
/// extern crate ruru;
///
/// use ruru::{AnyObject, Class, RString, VM};
/// use ruru::types::{Argc, Value};
/// use ruru::traits::Object;
///
/// class!(Greeter);
///
/// methods!(
///     Greeter,
///     itself,
///
///     fn anonymous_greeting() -> RString {
///         RString::new("Hello stranger!")
///     }
///
///     fn friendly_greeting(name: RString) -> RString {
///         let greeting = format!("Hello dear {}!", name.to_string());
///
///         RString::new(&greeting)
///     }
/// );
///
/// fn main() {
///     # VM::init();
///     Class::new("Greeter").define(|itself| {
///         itself.def("anonymous_greeting", anonymous_greeting);
///         itself.def("friendly_greeting", friendly_greeting);
///     });
/// }
/// ```
///
/// Ruby:
///
/// ```ruby
/// class Greeter
///   def anonymous_greeting
///     'Hello stranger!'
///   end
///
///   def friendly_greeting(name)
///     "Hello dear #{name}"
///   end
/// end
/// ```
#[macro_export]
macro_rules! class {
    ($class: ident) => {
        pub struct $class {
            value: Value,
        }

        impl From<Value> for $class {
            fn from(value: Value) -> Self {
                $class { value: value }
            }
        }

        impl Object for $class {
            fn value(&self) -> Value {
                self.value
            }
        }
    }
}

/// Creates callbacks for Ruby methods
///
/// # Examples
///
/// ```no_run
/// #[macro_use]
/// extern crate ruru;
///
/// use ruru::{AnyObject, Boolean, Class, Fixnum, RString, VM};
/// use ruru::types::Argc;
/// use ruru::traits::Object;
///
/// // Creates `string_is_blank` and `string_length_equals` functions
/// methods!(
///     RString, // type of `self` object
///     itself, // name of `self` object which will be used in methods
///
///     fn string_is_blank() -> Boolean {
///         Boolean::new(itself.to_string().chars().all(|c| c.is_whitespace()))
///     }
///
///     fn string_length_equals(expected_length: Fixnum) -> Boolean {
///         let real_length = itself.to_string().len() as i64;
///
///         Boolean::new(expected_length.to_i64() == real_length)
///     }
/// );
///
/// fn main() {
///     # VM::init();
///     Class::from_existing("String").define(|itself| {
///         itself.def("blank?", string_is_blank);
///         itself.def("length_equals?", string_length_equals);
///     });
/// }
/// ```
///
/// Ruby:
///
/// ```ruby
/// class String
///   def blank?
///     # ...
///   end
///
///   def length_equals?(expected_length)
///     # ...
///   end
/// end
/// ```
#[macro_export]
macro_rules! methods {
    (
        $itself_class: ty,
        $itself_name: ident,
        $(
            fn $method_name: ident
            ($($arg_name: ident: $arg_type: ty),*) -> $return_type: ident $body: block
        )*
    ) => {
        $(
            #[no_mangle]
            pub extern fn $method_name(argc: Argc,
                                       argv: *const AnyObject,
                                       mut $itself_name: $itself_class) -> $return_type {
                let arguments = VM::parse_arguments(argc, argv);
                let mut i = 0;

                $(
                    let $arg_name = arguments[i].to::<$arg_type>();
                    i += 1;
                )*

                $body
            }
        )*
    }
}
<|endoftext|>


<commit_before>#![warn(trivial_casts, trivial_numeric_casts)]
#![warn(unused_qualifications)]
#![warn(unused_results)]

extern crate ansi_term;
extern crate datetime;
extern crate getopts;
extern crate libc;
extern crate locale;
extern crate natord;
extern crate num_cpus;
extern crate number_prefix;
extern crate scoped_threadpool;
extern crate term_grid;
extern crate unicode_width;
extern crate users;
extern crate zoneinfo_compiled;

#[cfg(feature="git")] extern crate git2;
#[macro_use] extern crate lazy_static;

use std::ffi::OsStr;
use std::io::{Write, Result as IOResult};
use std::path::{Component, Path};

use fs::{Dir, File};
use options::{Options, View};
pub use options::Misfire;

mod fs;
mod info;
mod options;
mod output;
mod term;

/// The main program wrapper.
pub struct Exa<'w, W: Write + 'w> {

    /// List of command-line options, having been successfully parsed.
    pub options: Options,

    /// The output handle that we write to. When running the program normally,
    /// this will be `std::io::Stdout`, but it can accept any struct that’s
    /// `Write` so we can write into, say, a vector for testing.
    pub writer: &'w mut W,

    /// List of the free command-line arguments that should correspond to file
    /// names (anything that isn’t an option).
    pub args: Vec<String>,
}

impl<'w, W: Write + 'w> Exa<'w, W> {
    pub fn new<S>(args: &[S], writer: &'w mut W) -> Result<Exa<'w, W>, Misfire>
    where S: AsRef<OsStr> {
        Options::getopts(args).map(move |(opts, args)| Exa {
            options: opts,
            writer:  writer,
            args:    args,
        })
    }

    pub fn run(&mut self) -> IOResult<()> {
        let mut files = Vec::new();
        let mut dirs = Vec::new();

        // List the current directory by default, like ls.
        if self.args.is_empty() {
            self.args.push(".".to_owned());
        }

        for file_name in self.args.iter() {
            match File::from_path(Path::new(&file_name), None) {
                Err(e) => {
                    try!(writeln!(self.writer, "{}: {}", file_name, e));
                },
                Ok(f) => {
                    if f.is_directory() && !self.options.dir_action.treat_dirs_as_files() {
                        match f.to_dir(self.options.should_scan_for_git()) {
                            Ok(d) => dirs.push(d),
                            Err(e) => try!(writeln!(self.writer, "{}: {}", file_name, e)),
                        }
                    }
                    else {
                        files.push(f);
                    }
                },
            }
        }

        // We want to print a directory’s name before we list it, *except* in
        // the case where it’s the only directory, *except* if there are any
        // files to print as well. (It’s a double negative)

        let no_files = files.is_empty();
        let is_only_dir = dirs.len() == 1 && no_files;

        if !no_files {
            try!(self.print_files(None, files));
        }

        self.print_dirs(dirs, no_files, is_only_dir)
    }

    fn print_dirs(&mut self, dir_files: Vec<Dir>, mut first: bool, is_only_dir: bool) -> IOResult<()> {
        for dir in dir_files {

            // Put a gap between directories, or between the list of files and
            // the first directory.
            if first {
                first = false;
            }
            else {
                try!(write!(self.writer, "\n"));
            }

            if !is_only_dir {
                try!(writeln!(self.writer, "{}:", dir.path.display()));
            }

            let mut children = Vec::new();
            for file in dir.files() {
                match file {
                    Ok(file)       => children.push(file),
                    Err((path, e)) => try!(writeln!(self.writer, "[{}: {}]", path.display(), e)),
                }
            };

            self.options.filter.filter_files(&mut children);
            self.options.filter.sort_files(&mut children);

            if let Some(recurse_opts) = self.options.dir_action.recurse_options() {
                let depth = dir.path.components().filter(|&c| c != Component::CurDir).count() + 1;
                if !recurse_opts.tree && !recurse_opts.is_too_deep(depth) {

                    let mut child_dirs = Vec::new();
                    for child_dir in children.iter().filter(|f| f.is_directory()) {
                        match child_dir.to_dir(false) {
                            Ok(d)  => child_dirs.push(d),
                            Err(e) => try!(writeln!(self.writer, "{}: {}", child_dir.path.display(), e)),
                        }
                    }

                    try!(self.print_files(Some(&dir), children));

                    if !child_dirs.is_empty() {
                        try!(self.print_dirs(child_dirs, false, false));
                    }

                    continue;
                }
            }

            try!(self.print_files(Some(&dir), children));
        }

        Ok(())
    }

    /// Prints the list of files using whichever view is selected.
    /// For various annoying logistical reasons, each one handles
    /// printing differently...
    fn print_files(&mut self, dir: Option<&Dir>, files: Vec<File>) -> IOResult<()> {
        match self.options.view {
            View::Grid(g)         => g.view(&files, self.writer),
            View::Details(d)      => d.view(dir, files, self.writer),
            View::GridDetails(gd) => gd.view(dir, files, self.writer),
            View::Lines(l)        => l.view(files, self.writer),
        }
    }
}
<commit_msg>Change to put error messages into stderr<commit_after>#![warn(trivial_casts, trivial_numeric_casts)]
#![warn(unused_qualifications)]
#![warn(unused_results)]

extern crate ansi_term;
extern crate datetime;
extern crate getopts;
extern crate libc;
extern crate locale;
extern crate natord;
extern crate num_cpus;
extern crate number_prefix;
extern crate scoped_threadpool;
extern crate term_grid;
extern crate unicode_width;
extern crate users;
extern crate zoneinfo_compiled;

#[cfg(feature="git")] extern crate git2;
#[macro_use] extern crate lazy_static;

use std::ffi::OsStr;
use std::io::{stderr, Write, Result as IOResult};
use std::path::{Component, Path};

use fs::{Dir, File};
use options::{Options, View};
pub use options::Misfire;

mod fs;
mod info;
mod options;
mod output;
mod term;

/// The main program wrapper.
pub struct Exa<'w, W: Write + 'w> {

    /// List of command-line options, having been successfully parsed.
    pub options: Options,

    /// The output handle that we write to. When running the program normally,
    /// this will be `std::io::Stdout`, but it can accept any struct that’s
    /// `Write` so we can write into, say, a vector for testing.
    pub writer: &'w mut W,

    /// List of the free command-line arguments that should correspond to file
    /// names (anything that isn’t an option).
    pub args: Vec<String>,
}

impl<'w, W: Write + 'w> Exa<'w, W> {
    pub fn new<S>(args: &[S], writer: &'w mut W) -> Result<Exa<'w, W>, Misfire>
    where S: AsRef<OsStr> {
        Options::getopts(args).map(move |(opts, args)| Exa {
            options: opts,
            writer:  writer,
            args:    args,
        })
    }

    pub fn run(&mut self) -> IOResult<()> {
        let mut files = Vec::new();
        let mut dirs = Vec::new();

        // List the current directory by default, like ls.
        if self.args.is_empty() {
            self.args.push(".".to_owned());
        }

        for file_name in self.args.iter() {
            match File::from_path(Path::new(&file_name), None) {
                Err(e) => {
                    try!(writeln!(stderr(), "{}: {}", file_name, e));
                },
                Ok(f) => {
                    if f.is_directory() && !self.options.dir_action.treat_dirs_as_files() {
                        match f.to_dir(self.options.should_scan_for_git()) {
                            Ok(d) => dirs.push(d),
                            Err(e) => try!(writeln!(stderr(), "{}: {}", file_name, e)),
                        }
                    }
                    else {
                        files.push(f);
                    }
                },
            }
        }

        // We want to print a directory’s name before we list it, *except* in
        // the case where it’s the only directory, *except* if there are any
        // files to print as well. (It’s a double negative)

        let no_files = files.is_empty();
        let is_only_dir = dirs.len() == 1 && no_files;

        if !no_files {
            try!(self.print_files(None, files));
        }

        self.print_dirs(dirs, no_files, is_only_dir)
    }

    fn print_dirs(&mut self, dir_files: Vec<Dir>, mut first: bool, is_only_dir: bool) -> IOResult<()> {
        for dir in dir_files {

            // Put a gap between directories, or between the list of files and
            // the first directory.
            if first {
                first = false;
            }
            else {
                try!(write!(self.writer, "\n"));
            }

            if !is_only_dir {
                try!(writeln!(self.writer, "{}:", dir.path.display()));
            }

            let mut children = Vec::new();
            for file in dir.files() {
                match file {
                    Ok(file)       => children.push(file),
                    Err((path, e)) => try!(writeln!(stderr(), "[{}: {}]", path.display(), e)),
                }
            };

            self.options.filter.filter_files(&mut children);
            self.options.filter.sort_files(&mut children);

            if let Some(recurse_opts) = self.options.dir_action.recurse_options() {
                let depth = dir.path.components().filter(|&c| c != Component::CurDir).count() + 1;
                if !recurse_opts.tree && !recurse_opts.is_too_deep(depth) {

                    let mut child_dirs = Vec::new();
                    for child_dir in children.iter().filter(|f| f.is_directory()) {
                        match child_dir.to_dir(false) {
                            Ok(d)  => child_dirs.push(d),
                            Err(e) => try!(writeln!(stderr(), "{}: {}", child_dir.path.display(), e)),
                        }
                    }

                    try!(self.print_files(Some(&dir), children));

                    if !child_dirs.is_empty() {
                        try!(self.print_dirs(child_dirs, false, false));
                    }

                    continue;
                }
            }

            try!(self.print_files(Some(&dir), children));
        }

        Ok(())
    }

    /// Prints the list of files using whichever view is selected.
    /// For various annoying logistical reasons, each one handles
    /// printing differently...
    fn print_files(&mut self, dir: Option<&Dir>, files: Vec<File>) -> IOResult<()> {
        match self.options.view {
            View::Grid(g)         => g.view(&files, self.writer),
            View::Details(d)      => d.view(dir, files, self.writer),
            View::GridDetails(gd) => gd.view(dir, files, self.writer),
            View::Lines(l)        => l.view(files, self.writer),
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use rustc::ty::layout::{Size, Align};
use rustc_mir::interpret::{Pointer, Memory};
use crate::stacked_borrows::Tag;
use crate::*;

#[derive(Default)]
pub struct EnvVars {
    map: HashMap<Vec<u8>, Pointer<Tag>>,
}

impl EnvVars {
    pub(crate) fn init<'mir, 'tcx>(
        ecx: &mut InterpCx<'mir, 'tcx, Evaluator<'tcx>>,
    ) {
        if ecx.machine.communicate {
            for (name, value) in std::env::vars() {
                let var_ptr = alloc_env_var(name.as_bytes(), value.as_bytes(), ecx.memory_mut());
                ecx.machine.env_vars.map.insert(name.into_bytes(), var_ptr);
            }
        }
    }
}

fn alloc_env_var<'mir, 'tcx>(
    name: &[u8],
    value: &[u8],
    memory: &mut Memory<'mir, 'tcx, Evaluator<'tcx>>,
) -> Pointer<Tag> {
    let bytes = [name, b"=", value].concat();
    let tcx = {memory.tcx.tcx};
    let length = bytes.len() as u64;
    // `+1` for the null terminator.
    let ptr = memory.allocate(
        Size::from_bytes(length + 1),
        Align::from_bytes(1).unwrap(),
        MiriMemoryKind::Env.into(),
    );
    // We just allocated these, so the write cannot fail.
    let alloc = memory.get_mut(ptr.alloc_id).unwrap();
    alloc.write_bytes(&tcx, ptr, &bytes).unwrap();
    let trailing_zero_ptr = ptr.offset(
        Size::from_bytes(length),
        &tcx,
    ).unwrap();
    alloc.write_bytes(&tcx, trailing_zero_ptr, &[0]).unwrap();
    ptr
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn getenv(
        &mut self,
        name_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, Scalar<Tag>> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let name = this.memory().read_c_str(name_ptr)?;
        Ok(match this.machine.env_vars.map.get(name) {
            Some(var_ptr) => Scalar::Ptr(var_ptr.offset(Size::from_bytes(name.len() as u64 + 1), this)?),
            None => Scalar::ptr_null(&*this.tcx),
        })
    }

    fn setenv(
        &mut self,
        name_op: OpTy<'tcx, Tag>,
        value_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let value_ptr = this.read_scalar(value_op)?.not_undef()?;
        let value = this.memory().read_c_str(value_ptr)?;
        let mut new = None;
        if !this.is_null(name_ptr)? {
            let name = this.memory().read_c_str(name_ptr)?;
            if !name.is_empty() && !name.contains(&b'=') {
                new = Some((name.to_owned(), value.to_owned()));
            }
        }
        if let Some((name, value)) = new {
            let var_ptr = alloc_env_var(&name, &value, this.memory_mut());
            if let Some(var) = this.machine.env_vars.map.insert(name.to_owned(), var_ptr) {
                this.memory_mut().deallocate(var, None, MiriMemoryKind::Env.into())?;
            }
            Ok(0)
        } else {
            Ok(-1)
        }
    }

    fn unsetenv(
        &mut self,
        name_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let mut success = None;
        if !this.is_null(name_ptr)? {
            let name = this.memory().read_c_str(name_ptr)?.to_owned();
            if !name.is_empty() && !name.contains(&b'=') {
                success = Some(this.machine.env_vars.map.remove(&name));
            }
        }
        if let Some(old) = success {
            if let Some(var) = old {
                this.memory_mut().deallocate(var, None, MiriMemoryKind::Env.into())?;
            }
            Ok(0)
        } else {
            Ok(-1)
        }
    }
}
<commit_msg>Add docs<commit_after>use std::collections::HashMap;

use rustc::ty::layout::{Size, Align};
use rustc_mir::interpret::{Pointer, Memory};
use crate::stacked_borrows::Tag;
use crate::*;

#[derive(Default)]
pub struct EnvVars {
    /// Stores pointers to the environment variables. These variables must be stored as
    /// null-terminated C strings with the `"{name}={value}"` format.
    map: HashMap<Vec<u8>, Pointer<Tag>>,
}

impl EnvVars {
    pub(crate) fn init<'mir, 'tcx>(
        ecx: &mut InterpCx<'mir, 'tcx, Evaluator<'tcx>>,
    ) {
        if ecx.machine.communicate {
            for (name, value) in std::env::vars() {
                let var_ptr = alloc_env_var(name.as_bytes(), value.as_bytes(), ecx.memory_mut());
                ecx.machine.env_vars.map.insert(name.into_bytes(), var_ptr);
            }
        }
    }
}

fn alloc_env_var<'mir, 'tcx>(
    name: &[u8],
    value: &[u8],
    memory: &mut Memory<'mir, 'tcx, Evaluator<'tcx>>,
) -> Pointer<Tag> {
    let bytes = [name, b"=", value].concat();
    let tcx = {memory.tcx.tcx};
    let length = bytes.len() as u64;
    // `+1` for the null terminator.
    let ptr = memory.allocate(
        Size::from_bytes(length + 1),
        Align::from_bytes(1).unwrap(),
        MiriMemoryKind::Env.into(),
    );
    // We just allocated these, so the write cannot fail.
    let alloc = memory.get_mut(ptr.alloc_id).unwrap();
    alloc.write_bytes(&tcx, ptr, &bytes).unwrap();
    let trailing_zero_ptr = ptr.offset(
        Size::from_bytes(length),
        &tcx,
    ).unwrap();
    alloc.write_bytes(&tcx, trailing_zero_ptr, &[0]).unwrap();
    ptr
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn getenv(
        &mut self,
        name_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, Scalar<Tag>> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let name = this.memory().read_c_str(name_ptr)?;
        Ok(match this.machine.env_vars.map.get(name) {
            // The offset is used to strip the "{name}=" part of the string.
            Some(var_ptr) => Scalar::Ptr(var_ptr.offset(Size::from_bytes(name.len() as u64 + 1), this)?),
            None => Scalar::ptr_null(&*this.tcx),
        })
    }

    fn setenv(
        &mut self,
        name_op: OpTy<'tcx, Tag>,
        value_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let value_ptr = this.read_scalar(value_op)?.not_undef()?;
        let value = this.memory().read_c_str(value_ptr)?;
        let mut new = None;
        if !this.is_null(name_ptr)? {
            let name = this.memory().read_c_str(name_ptr)?;
            if !name.is_empty() && !name.contains(&b'=') {
                new = Some((name.to_owned(), value.to_owned()));
            }
        }
        if let Some((name, value)) = new {
            let var_ptr = alloc_env_var(&name, &value, this.memory_mut());
            if let Some(var) = this.machine.env_vars.map.insert(name.to_owned(), var_ptr) {
                this.memory_mut().deallocate(var, None, MiriMemoryKind::Env.into())?;
            }
            Ok(0)
        } else {
            Ok(-1)
        }
    }

    fn unsetenv(
        &mut self,
        name_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let mut success = None;
        if !this.is_null(name_ptr)? {
            let name = this.memory().read_c_str(name_ptr)?.to_owned();
            if !name.is_empty() && !name.contains(&b'=') {
                success = Some(this.machine.env_vars.map.remove(&name));
            }
        }
        if let Some(old) = success {
            if let Some(var) = old {
                this.memory_mut().deallocate(var, None, MiriMemoryKind::Env.into())?;
            }
            Ok(0)
        } else {
            Ok(-1)
        }
    }
}
<|endoftext|>


<commit_before>/*
 *           _           _            _             _          _
 *          /\ \        /\ \         /\ \     _    /\ \       /\ \
 *         /  \ \      /  \ \       /  \ \   /\_\ /  \ \      \_\ \
 *        / /\ \ \    / /\ \ \     / /\ \ \_/ / // /\ \ \     /\__ \
 *       / / /\ \_\  / / /\ \_\   / / /\ \___/ // / /\ \_\   / /_ \ \
 *      / / /_/ / / / /_/_ \/_/  / / /  \/____// /_/_ \/_/  / / /\ \ \
 *     / / /__\/ / / /____/\    / / /    / / // /____/\    / / /  \/_/
 *    / / /_____/ / /\____\/   / / /    / / // /\____\/   / / /
 *   / / /\ \ \  / / /______  / / /    / / // / /______  / / /
 *  / / /  \ \ \/ / /_______\/ / /    / / // / /_______\/_/ /
 *  \/_/    \_\/\/__________/\/_/     \/_/ \/__________/\_\/
 *
 *
 * This file is released under terms described in the LICENSE file at
 * the top directory of this repository.
 *
 * Please contact Mark McDermott <mark.elias.mcdermott@gmail.com> or
 * the current maintainer of this software if you do not have a copy of
 * the license file.
 *
 * -------------------------------------------------------------------
 *  REnet is a rust language wrapper for the ENet networking library
 *
 *  TODO List
 * -------------------------------------------------------------------
 */

extern crate libc;

pub const ENET_HOST_ANY: libc::c_uint = 0;

pub const ENET_EVENT_TYPE_CONNECT: libc::c_uint    = 1;
pub const ENET_EVENT_TYPE_DISCONNECT: libc::c_uint = 2;
pub const ENET_EVENT_TYPE_RECEIVE: libc::c_uint    = 3;

pub const ENET_PACKET_FLAG_RELIABLE: libc::c_uint = 1;
pub const ENET_PACKET_FLAG_UNSEQUENCED: libc::c_uint = 2;
pub const ENET_PACKET_FLAG_NO_ALLOCATE: libc::c_uint = 4;
pub const ENET_PACKET_UNRELIABLE_FRAGMENT: libc::c_uint = 8;
pub const ENET_PACKET_FLAG_SENT: libc::c_uint = 256;

#[repr(C)]
pub struct ENetAddress {
    pub host: libc::c_uint,
    pub port: libc::c_ushort,
}

#[repr(C)]
pub struct ENetEvent {
    pub etype: libc::c_uint,
    pub peer: *mut ENetPeer,
    pub channelID: libc::c_uchar,
    pub data: libc::c_uint,
    pub packet: *mut ENetPacket,
}

#[repr(C)]
pub struct ENetPacket {
    pub referenceCount: libc::size_t,
    pub flags: libc::c_uint,
    pub data: *mut libc::c_void,
    pub dataLength: libc::size_t,
    pub freeCallback: *mut libc::c_void,
    pub userData: *mut libc::c_void
}

#[repr(C)]
pub struct ENetListNode {
    pub next: *mut ENetListNode,
    pub previous: *mut ENetListNode
}

#[repr(C)]
pub struct ENetPeer {
    pub dispatchList: ENetListNode,
    pub host: *mut libc::c_void,
    pub outgoingPeerID: libc::c_ushort,
    pub incomingPeerID: libc::c_ushort,
    pub connectID: libc::c_uint,
    pub outgoingSessionID: libc::c_uchar,
    pub incomingSessionID: libc::c_uchar,
    pub address: ENetAddress,
    pub data: *mut libc::c_void,

    // The rest of the fields has been omitted for now
}

#[link(name = "enet")]
#[link(name = "winmm")]
extern {
    pub fn enet_initialize() -> libc::c_int;
    pub fn enet_deinitialize();
    pub fn enet_linked_version() -> libc::c_uint;
    pub fn enet_host_create(address           : *const ENetAddress,
                            peerCount         : libc::size_t,
                            channelCount      : libc::size_t,
                            incomingBandwidth : libc::c_uint,
                            outgoingBandwidth : libc::c_uint) -> *mut libc::c_void;
    pub fn enet_host_service(host : *mut libc::c_void, event : *mut libc::c_void, timeout : libc::c_uint) -> libc::c_int;
    pub fn enet_host_destroy(host : *mut libc::c_void);
    pub fn enet_host_connect(host: *mut libc::c_void, address: *const ENetAddress, channelCount: libc::size_t, data: libc::c_uint) -> *mut ENetPeer;

    pub fn enet_packet_create(data: *mut libc::c_void, dataLength: libc::size_t, flags: libc::c_uint) -> *mut ENetPacket;
    pub fn enet_packet_destroy(packet: *mut ENetPacket);
    pub fn enet_peer_send(peer: *mut ENetPeer, channelID: libc::c_uchar, packet: *mut ENetPacket);
    pub fn enet_host_flush(host: *mut libc::c_void);
    pub fn enet_address_set_host(address: *mut ENetAddress, hostName: *const libc::c_char);
}
<commit_msg>Link to winmm only on windows<commit_after>/*
 *           _           _            _             _          _
 *          /\ \        /\ \         /\ \     _    /\ \       /\ \
 *         /  \ \      /  \ \       /  \ \   /\_\ /  \ \      \_\ \
 *        / /\ \ \    / /\ \ \     / /\ \ \_/ / // /\ \ \     /\__ \
 *       / / /\ \_\  / / /\ \_\   / / /\ \___/ // / /\ \_\   / /_ \ \
 *      / / /_/ / / / /_/_ \/_/  / / /  \/____// /_/_ \/_/  / / /\ \ \
 *     / / /__\/ / / /____/\    / / /    / / // /____/\    / / /  \/_/
 *    / / /_____/ / /\____\/   / / /    / / // /\____\/   / / /
 *   / / /\ \ \  / / /______  / / /    / / // / /______  / / /
 *  / / /  \ \ \/ / /_______\/ / /    / / // / /_______\/_/ /
 *  \/_/    \_\/\/__________/\/_/     \/_/ \/__________/\_\/
 *
 *
 * This file is released under terms described in the LICENSE file at
 * the top directory of this repository.
 *
 * Please contact Mark McDermott <mark.elias.mcdermott@gmail.com> or
 * the current maintainer of this software if you do not have a copy of
 * the license file.
 *
 * -------------------------------------------------------------------
 *  REnet is a rust language wrapper for the ENet networking library
 *
 *  TODO List
 * -------------------------------------------------------------------
 */

extern crate libc;

pub const ENET_HOST_ANY: libc::c_uint = 0;

pub const ENET_EVENT_TYPE_CONNECT: libc::c_uint    = 1;
pub const ENET_EVENT_TYPE_DISCONNECT: libc::c_uint = 2;
pub const ENET_EVENT_TYPE_RECEIVE: libc::c_uint    = 3;

pub const ENET_PACKET_FLAG_RELIABLE: libc::c_uint = 1;
pub const ENET_PACKET_FLAG_UNSEQUENCED: libc::c_uint = 2;
pub const ENET_PACKET_FLAG_NO_ALLOCATE: libc::c_uint = 4;
pub const ENET_PACKET_UNRELIABLE_FRAGMENT: libc::c_uint = 8;
pub const ENET_PACKET_FLAG_SENT: libc::c_uint = 256;

#[repr(C)]
pub struct ENetAddress {
    pub host: libc::c_uint,
    pub port: libc::c_ushort,
}

#[repr(C)]
pub struct ENetEvent {
    pub etype: libc::c_uint,
    pub peer: *mut ENetPeer,
    pub channelID: libc::c_uchar,
    pub data: libc::c_uint,
    pub packet: *mut ENetPacket,
}

#[repr(C)]
pub struct ENetPacket {
    pub referenceCount: libc::size_t,
    pub flags: libc::c_uint,
    pub data: *mut libc::c_void,
    pub dataLength: libc::size_t,
    pub freeCallback: *mut libc::c_void,
    pub userData: *mut libc::c_void
}

#[repr(C)]
pub struct ENetListNode {
    pub next: *mut ENetListNode,
    pub previous: *mut ENetListNode
}

#[repr(C)]
pub struct ENetPeer {
    pub dispatchList: ENetListNode,
    pub host: *mut libc::c_void,
    pub outgoingPeerID: libc::c_ushort,
    pub incomingPeerID: libc::c_ushort,
    pub connectID: libc::c_uint,
    pub outgoingSessionID: libc::c_uchar,
    pub incomingSessionID: libc::c_uchar,
    pub address: ENetAddress,
    pub data: *mut libc::c_void,

    // The rest of the fields has been omitted for now
}

#[link(name = "enet")]
#[cfg_attr(target_os = "windows", link(name = "winmm"))]
extern {
    pub fn enet_initialize() -> libc::c_int;
    pub fn enet_deinitialize();
    pub fn enet_linked_version() -> libc::c_uint;
    pub fn enet_host_create(address           : *const ENetAddress,
                            peerCount         : libc::size_t,
                            channelCount      : libc::size_t,
                            incomingBandwidth : libc::c_uint,
                            outgoingBandwidth : libc::c_uint) -> *mut libc::c_void;
    pub fn enet_host_service(host : *mut libc::c_void, event : *mut libc::c_void, timeout : libc::c_uint) -> libc::c_int;
    pub fn enet_host_destroy(host : *mut libc::c_void);
    pub fn enet_host_connect(host: *mut libc::c_void, address: *const ENetAddress, channelCount: libc::size_t, data: libc::c_uint) -> *mut ENetPeer;

    pub fn enet_packet_create(data: *mut libc::c_void, dataLength: libc::size_t, flags: libc::c_uint) -> *mut ENetPacket;
    pub fn enet_packet_destroy(packet: *mut ENetPacket);
    pub fn enet_peer_send(peer: *mut ENetPeer, channelID: libc::c_uchar, packet: *mut ENetPacket);
    pub fn enet_host_flush(host: *mut libc::c_void);
    pub fn enet_address_set_host(address: *mut ENetAddress, hostName: *const libc::c_char);
}
<|endoftext|>