<commit_before>use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};

/// A base target for AVR devices using the GNU toolchain.
///
/// Requires GNU avr-gcc and avr-binutils on the host system.
pub fn target(target_cpu: String) -> TargetResult {
    Ok(Target {
        arch: "avr".to_string(),
        data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".to_string(),
        llvm_target: "avr-unknown-unknown".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "16".to_string(),
        linker_flavor: LinkerFlavor::Gcc,
        target_os: "unknown".to_string(),
        target_env: "".to_string(),
        target_vendor: "unknown".to_string(),
        target_c_int_width: 16.to_string(),
        options: TargetOptions {
            cpu: target_cpu.clone(),
            exe_suffix: ".elf".to_string(),
            linker: Some("avr-gcc".to_owned()),
            pre_link_args: vec![(
                LinkerFlavor::Gcc,
                vec!["-Os".to_owned(), format!("-mmcu={}", target_cpu)],
            )]
            .into_iter()
            .collect(),
            late_link_args: vec![(LinkerFlavor::Gcc, vec!["-lc".to_owned(), "-lgcc".to_owned()])]
                .into_iter()
                .collect(),
            ..super::freestanding_base::opts()
        },
    })
}
<commit_msg>[AVR] Remove unnecessary arguments passed to the linker for GNU target<commit_after>use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};

/// A base target for AVR devices using the GNU toolchain.
///
/// Requires GNU avr-gcc and avr-binutils on the host system.
pub fn target(target_cpu: String) -> TargetResult {
    Ok(Target {
        arch: "avr".to_string(),
        data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".to_string(),
        llvm_target: "avr-unknown-unknown".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "16".to_string(),
        linker_flavor: LinkerFlavor::Gcc,
        target_os: "unknown".to_string(),
        target_env: "".to_string(),
        target_vendor: "unknown".to_string(),
        target_c_int_width: 16.to_string(),
        options: TargetOptions {
            cpu: target_cpu.clone(),
            exe_suffix: ".elf".to_string(),
            linker: Some("avr-gcc".to_owned()),
            pre_link_args: vec![(LinkerFlavor::Gcc,
                vec![format!("-mmcu={}", target_cpu)],
            )]
            .into_iter()
            .collect(),
            late_link_args: vec![(LinkerFlavor::Gcc, vec!["-lgcc".to_owned()])]
                .into_iter()
                .collect(),
            ..super::freestanding_base::opts()
        },
    })
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate abomonation_derive;
extern crate abomonation;

extern crate rand;
extern crate timely;
extern crate differential_dataflow;

use rand::{Rng, SeedableRng, StdRng};

use timely::dataflow::ProbeHandle;
// use timely::progress::timestamp::RootTimestamp;

use timely::dataflow::operators::unordered_input::UnorderedInput;

use differential_dataflow::AsCollection;
use differential_dataflow::operators::*;

use pair::Pair;

fn main() {

    let nodes: usize = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: usize = std::env::args().nth(2).unwrap().parse().unwrap();
    let batch: usize = std::env::args().nth(3).unwrap().parse().unwrap();
    let rounds: usize = std::env::args().nth(4).unwrap().parse().unwrap();

    timely::execute_from_args(std::env::args().skip(5), move |worker| {

        let index = worker.index();
        let peers = worker.peers();
        let mut probe = ProbeHandle::new();

        let (mut root_input, root_cap, mut edge_input, mut edge_cap) =
        worker.dataflow(|scope| {

            let ((root_input, root_cap), roots) = scope.new_unordered_input();
            let ((edge_input, edge_cap), edges) = scope.new_unordered_input();

            let roots = roots.as_collection();
            let edges = edges.as_collection()
                             // .inspect(|x| println!("edge: {:?}", x))
                             ;

            roots.iterate(|inner| {

                let edges = edges.enter(&inner.scope());
                let roots = roots.enter(&inner.scope());

                edges
                    .semijoin(&inner)
                    .map(|(_s,d)| d)
                    .concat(&roots)
                    .distinct()
            })
            .consolidate()
            // .inspect(|x| println!("edge: {:?}", x))
            .map(|_| ())
            .consolidate()
            .inspect(|x| println!("{:?}\tchanges: {:?}", x.1, x.2))
            .probe_with(&mut probe);

            (root_input, root_cap, edge_input, edge_cap)
        });

        let seed: &[_] = &[1, 2, 3, index];
        let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions
        let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for edge deletions

        let worker_edges = edges / peers + if index < edges % peers { 1 } else { 0 };
        let worker_batch = batch / peers + if index < batch % peers { 1 } else { 0 };

        // Times: (revision, event_time)

        // load initial root.
        root_input
            .session(root_cap)
            .give((0, Pair::new(0, 0), 1));

        // load initial edges
        edge_input
            .session(edge_cap.clone())
            .give_iterator((0 .. worker_edges).map(|_|
                ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)),
                    Pair::new(0, 0), 1)
            ));

        let edge_cap_next = edge_cap.delayed(&Pair::new(1, 0));

        // Caps = { (1,0) , (0,1) }

        edge_cap.downgrade(&Pair::new(0, 1));
        while probe.less_than(edge_cap.time()) {
            worker.step();
        }

        println!("Initial computation complete");

        for round in 1 .. rounds {

            edge_input
                .session(edge_cap.clone())
                .give_iterator((0 .. worker_batch).flat_map(|_| {
                    let insert = ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), Pair::new(0, round), 1);
                    let remove = ((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)), Pair::new(0, round),-1);
                    Some(insert).into_iter().chain(Some(remove).into_iter())
                }));

            edge_cap.downgrade(&Pair::new(0, round+1));
            while probe.less_than(edge_cap.time()) {
                worker.step();
            }

            // Caps = { (1,0), (0,round+1) }
            println!("Initial round {} complete", round);
        }

        // Caps = { (1,0) }
        let edge_cap0 = edge_cap;
        println!("{:?}", edge_cap0.time());
        edge_cap = edge_cap_next;

        edge_input
            .session(edge_cap.clone())
            .give_iterator((0 .. worker_batch).map(|_| {
                ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), Pair::new(1, 0), 1)
            }));

        // Caps = { (2,0) }
        edge_cap.downgrade(&Pair::new(2, 0));
        while probe.less_equal(&Pair::new(1, rounds-1)) {
            worker.step();
        }

        edge_input
            .session(edge_cap.clone())
            .give_iterator((0 .. worker_batch).map(|_| {
                ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), Pair::new(2, 3), 1)
            }));

        // Caps = { (3,0) }
        edge_cap.downgrade(&Pair::new(3, 0));
        while probe.less_equal(&Pair::new(2, rounds-1)) {
            worker.step();
        }

        edge_input
            .session(edge_cap.clone())
            .give_iterator((0 .. worker_batch).map(|_| {
                ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), Pair::new(3, 1), 1)
            }));

        // Caps = { (4,0) }
        edge_cap.downgrade(&Pair::new(4, 0));
        while probe.less_equal(&Pair::new(3, rounds-1)) {
            worker.step();
        }

        edge_input
            .session(edge_cap0)
            .give_iterator((0 .. worker_batch).map(|_| {
                ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), Pair::new(0, 10), 1)
            }));

    }).unwrap();
}

/// This module contains a definition of a new timestamp time, a "pair" or product.
///
/// This is a minimal self-contained implementation, in that it doesn't borrow anything
/// from the rest of the library other than the traits it needs to implement. With this
/// type and its implementations, you can use it as a timestamp type.
mod pair {

    /// A pair of timestamps, partially ordered by the product order.
    #[derive(Hash, Default, Clone, Eq, PartialEq, Ord, PartialOrd, Abomonation)]
    pub struct Pair<S, T> {
        pub first: S,
        pub second: T,
    }

    impl<S, T> Pair<S, T> {
        /// Create a new pair.
        pub fn new(first: S, second: T) -> Self {
            Pair { first, second }
        }
    }

    // Implement timely dataflow's `PartialOrder` trait.
    use timely::order::PartialOrder;
    impl<S: PartialOrder, T: PartialOrder> PartialOrder for Pair<S, T> {
        fn less_equal(&self, other: &Self) -> bool {
            self.first.less_equal(&other.first) && self.second.less_equal(&other.second)
        }
    }

    use timely::progress::timestamp::Refines;
    impl<S: Timestamp, T: Timestamp> Refines<()> for Pair<S, T> {
        fn to_inner(_outer: ()) -> Self { Default::default() }
        fn to_outer(self) -> () { () }
        fn summarize(_summary: <Self>::Summary) -> () { () }
    }

    // Implement timely dataflow's `PathSummary` trait.
    // This is preparation for the `Timestamp` implementation below.
    use timely::progress::PathSummary;

    impl<S: Timestamp, T: Timestamp> PathSummary<Pair<S,T>> for () {
        fn results_in(&self, timestamp: &Pair<S, T>) -> Option<Pair<S,T>> {
            Some(timestamp.clone())
        }
        fn followed_by(&self, other: &Self) -> Option<Self> {
            Some(other.clone())
        }
    }

    // Implement timely dataflow's `Timestamp` trait.
    use timely::progress::Timestamp;
    impl<S: Timestamp, T: Timestamp> Timestamp for Pair<S, T> {
        type Summary = ();
    }

    // Implement differential dataflow's `Lattice` trait.
    // This extends the `PartialOrder` implementation with additional structure.
    use differential_dataflow::lattice::Lattice;
    impl<S: Lattice, T: Lattice> Lattice for Pair<S, T> {
        fn minimum() -> Self { Pair { first: S::minimum(), second: T::minimum() }}
        fn maximum() -> Self { Pair { first: S::maximum(), second: T::maximum() }}
        fn join(&self, other: &Self) -> Self {
            Pair {
                first: self.first.join(&other.first),
                second: self.second.join(&other.second),
            }
        }
        fn meet(&self, other: &Self) -> Self {
            Pair {
                first: self.first.meet(&other.first),
                second: self.second.meet(&other.second),
            }
        }
    }

    use std::fmt::{Formatter, Error, Debug};

    /// Debug implementation to avoid seeing fully qualified path names.
    impl<TOuter: Debug, TInner: Debug> Debug for Pair<TOuter, TInner> {
        fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
            f.write_str(&format!("({:?}, {:?})", self.first, self.second))
        }
    }

}<commit_msg>time vector<commit_after>#[macro_use]
extern crate abomonation_derive;
extern crate abomonation;

extern crate rand;
extern crate timely;
extern crate differential_dataflow;

use rand::{Rng, SeedableRng, StdRng};

use timely::dataflow::ProbeHandle;

use timely::dataflow::operators::unordered_input::UnorderedInput;

use differential_dataflow::AsCollection;
use differential_dataflow::operators::*;

use pair::Pair;

fn main() {

    let nodes: usize = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: usize = std::env::args().nth(2).unwrap().parse().unwrap();
    let batch: usize = std::env::args().nth(3).unwrap().parse().unwrap();
    let rounds: usize = std::env::args().nth(4).unwrap().parse().unwrap();

    timely::execute_from_args(std::env::args().skip(5), move |worker| {

        let index = worker.index();
        let peers = worker.peers();
        let mut probe = ProbeHandle::new();

        let (mut root_input, root_cap, mut edge_input, mut edge_cap) =
        worker.dataflow(|scope| {

            let ((root_input, root_cap), roots) = scope.new_unordered_input();
            let ((edge_input, edge_cap), edges) = scope.new_unordered_input();

            let roots = roots.as_collection();
            let edges = edges.as_collection()
                             // .inspect(|x| println!("edge: {:?}", x))
                             ;

            roots.iterate(|inner| {

                let edges = edges.enter(&inner.scope());
                let roots = roots.enter(&inner.scope());

                edges
                    .semijoin(&inner)
                    .map(|(_s,d)| d)
                    .concat(&roots)
                    .distinct()
            })
            .consolidate()
            // .inspect(|x| println!("edge: {:?}", x))
            .map(|_| ())
            .consolidate()
            .inspect(|x| println!("{:?}\tchanges: {:?}", x.1, x.2))
            .probe_with(&mut probe);

            (root_input, root_cap, edge_input, edge_cap)
        });

        let seed: &[_] = &[1, 2, 3, index];
        let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions
        let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for edge deletions

        let worker_edges = edges / peers + if index < edges % peers { 1 } else { 0 };
        let worker_batch = batch / peers + if index < batch % peers { 1 } else { 0 };

        // Times: (revision, event_time)

        // load initial root.
        root_input
            .session(root_cap)
            .give((0, Pair::new(0, 0), 1));

        // load initial edges
        edge_input
            .session(edge_cap.clone())
            .give_iterator((0 .. worker_edges).map(|_|
                ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)),
                    Pair::new(0, 0), 1)
            ));

        let edge_cap_next = edge_cap.delayed(&Pair::new(1, 0));

        // Caps = { (1,0) , (0,1) }

        edge_cap.downgrade(&Pair::new(0, 1));
        while probe.less_than(edge_cap.time()) {
            worker.step();
        }

        println!("Initial computation complete");

        for round in 1 .. rounds {

            edge_input
                .session(edge_cap.clone())
                .give_iterator((0 .. worker_batch).flat_map(|_| {
                    let insert = ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), Pair::new(0, round), 1);
                    let remove = ((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)), Pair::new(0, round),-1);
                    Some(insert).into_iter().chain(Some(remove).into_iter())
                }));

            edge_cap.downgrade(&Pair::new(0, round+1));
            while probe.less_than(edge_cap.time()) {
                worker.step();
            }

            // Caps = { (1,0), (0,round+1) }
            println!("Initial round {} complete", round);
        }

        // Caps = { (1,0) }
        let edge_cap0 = edge_cap;
        println!("{:?}", edge_cap0.time());
        edge_cap = edge_cap_next;

        edge_input
            .session(edge_cap.clone())
            .give_iterator((0 .. worker_batch).map(|_| {
                ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), Pair::new(1, 0), 1)
            }));

        // Caps = { (2,0) }
        edge_cap.downgrade(&Pair::new(2, 0));
        while probe.less_equal(&Pair::new(1, rounds-1)) {
            worker.step();
        }

        edge_input
            .session(edge_cap.clone())
            .give_iterator((0 .. worker_batch).map(|_| {
                ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), Pair::new(2, 3), 1)
            }));

        // Caps = { (3,0) }
        edge_cap.downgrade(&Pair::new(3, 0));
        while probe.less_equal(&Pair::new(2, rounds-1)) {
            worker.step();
        }

        edge_input
            .session(edge_cap.clone())
            .give_iterator((0 .. worker_batch).map(|_| {
                ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), Pair::new(3, 1), 1)
            }));

        // Caps = { (4,0) }
        edge_cap.downgrade(&Pair::new(4, 0));
        while probe.less_equal(&Pair::new(3, rounds-1)) {
            worker.step();
        }

        edge_input
            .session(edge_cap0)
            .give_iterator((0 .. worker_batch).map(|_| {
                ((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), Pair::new(0, 10), 1)
            }));

    }).unwrap();
}

/// This module contains a definition of a new timestamp time, a "pair" or product.
///
/// This is a minimal self-contained implementation, in that it doesn't borrow anything
/// from the rest of the library other than the traits it needs to implement. With this
/// type and its implementations, you can use it as a timestamp type.
mod pair {

    /// A pair of timestamps, partially ordered by the product order.
    #[derive(Hash, Default, Clone, Eq, PartialEq, Ord, PartialOrd, Abomonation)]
    pub struct Pair<S, T> {
        pub first: S,
        pub second: T,
    }

    impl<S, T> Pair<S, T> {
        /// Create a new pair.
        pub fn new(first: S, second: T) -> Self {
            Pair { first, second }
        }
    }

    // Implement timely dataflow's `PartialOrder` trait.
    use timely::order::PartialOrder;
    impl<S: PartialOrder, T: PartialOrder> PartialOrder for Pair<S, T> {
        fn less_equal(&self, other: &Self) -> bool {
            self.first.less_equal(&other.first) && self.second.less_equal(&other.second)
        }
    }

    use timely::progress::timestamp::Refines;
    impl<S: Timestamp, T: Timestamp> Refines<()> for Pair<S, T> {
        fn to_inner(_outer: ()) -> Self { Default::default() }
        fn to_outer(self) -> () { () }
        fn summarize(_summary: <Self>::Summary) -> () { () }
    }

    // Implement timely dataflow's `PathSummary` trait.
    // This is preparation for the `Timestamp` implementation below.
    use timely::progress::PathSummary;

    impl<S: Timestamp, T: Timestamp> PathSummary<Pair<S,T>> for () {
        fn results_in(&self, timestamp: &Pair<S, T>) -> Option<Pair<S,T>> {
            Some(timestamp.clone())
        }
        fn followed_by(&self, other: &Self) -> Option<Self> {
            Some(other.clone())
        }
    }

    // Implement timely dataflow's `Timestamp` trait.
    use timely::progress::Timestamp;
    impl<S: Timestamp, T: Timestamp> Timestamp for Pair<S, T> {
        type Summary = ();
    }

    // Implement differential dataflow's `Lattice` trait.
    // This extends the `PartialOrder` implementation with additional structure.
    use differential_dataflow::lattice::Lattice;
    impl<S: Lattice, T: Lattice> Lattice for Pair<S, T> {
        fn minimum() -> Self { Pair { first: S::minimum(), second: T::minimum() }}
        fn join(&self, other: &Self) -> Self {
            Pair {
                first: self.first.join(&other.first),
                second: self.second.join(&other.second),
            }
        }
        fn meet(&self, other: &Self) -> Self {
            Pair {
                first: self.first.meet(&other.first),
                second: self.second.meet(&other.second),
            }
        }
    }

    use std::fmt::{Formatter, Error, Debug};

    /// Debug implementation to avoid seeing fully qualified path names.
    impl<TOuter: Debug, TInner: Debug> Debug for Pair<TOuter, TInner> {
        fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
            f.write_str(&format!("({:?}, {:?})", self.first, self.second))
        }
    }

}

/// This module contains a definition of a new timestamp time, a "pair" or product.
///
/// This is a minimal self-contained implementation, in that it doesn't borrow anything
/// from the rest of the library other than the traits it needs to implement. With this
/// type and its implementations, you can use it as a timestamp type.
mod vector {

    /// A pair of timestamps, partially ordered by the product order.
    #[derive(Hash, Default, Clone, Eq, PartialEq, Ord, PartialOrd, Abomonation, Debug)]
    pub struct Vector<T> {
        pub vector: Vec<T>,
    }

    impl<T> Vector<T> {
        /// Create a new pair.
        pub fn new(vector: Vec<T>) -> Self {
            Vector { vector }
        }
    }

    // Implement timely dataflow's `PartialOrder` trait.
    use timely::order::PartialOrder;
    impl<T: PartialOrder+Default> PartialOrder for Vector<T> {
        fn less_equal(&self, other: &Self) -> bool {
            self.vector
                .iter()
                .enumerate()
                .all(|(index, time)| time.less_equal(other.vector.get(index).unwrap_or(&Default::default())))
        }
    }

    use timely::progress::timestamp::Refines;
    impl<T: Timestamp> Refines<()> for Vector<T> {
        fn to_inner(_outer: ()) -> Self { Default::default() }
        fn to_outer(self) -> () { () }
        fn summarize(_summary: <Self>::Summary) -> () { () }
    }

    // Implement timely dataflow's `PathSummary` trait.
    // This is preparation for the `Timestamp` implementation below.
    use timely::progress::PathSummary;

    impl<T: Timestamp> PathSummary<Vector<T>> for () {
        fn results_in(&self, timestamp: &Vector<T>) -> Option<Vector<T>> {
            Some(timestamp.clone())
        }
        fn followed_by(&self, other: &Self) -> Option<Self> {
            Some(other.clone())
        }
    }

    // Implement timely dataflow's `Timestamp` trait.
    use timely::progress::Timestamp;
    impl<T: Timestamp> Timestamp for Vector<T> {
        type Summary = ();
    }

    // Implement differential dataflow's `Lattice` trait.
    // This extends the `PartialOrder` implementation with additional structure.
    use differential_dataflow::lattice::Lattice;
    impl<T: Lattice+Default+Clone> Lattice for Vector<T> {
        fn minimum() -> Self { Self { vector: Vec::new() } }
        fn join(&self, other: &Self) -> Self {
            let min_len = ::std::cmp::min(self.vector.len(), other.vector.len());
            let max_len = ::std::cmp::max(self.vector.len(), other.vector.len());
            let mut vector = Vec::with_capacity(max_len);
            for index in 0 .. min_len {
                vector.push(self.vector[index].join(&other.vector[index]));
            }
            for time in &self.vector[min_len..] {
                vector.push(time.clone());
            }
            for time in &other.vector[min_len..] {
                vector.push(time.clone());
            }
            Self { vector }
        }
        fn meet(&self, other: &Self) -> Self {
            let min_len = ::std::cmp::min(self.vector.len(), other.vector.len());
            let mut vector = Vec::with_capacity(min_len);
            for index in 0 .. min_len {
                vector.push(self.vector[index].meet(&other.vector[index]));
            }
            Self { vector }
        }
    }
}<|endoftext|>


<commit_before>//! Future for mediating the processing of commands received from the
//! CtlGateway in the Supervisor.

use super::handler::CtlHandler;
use crate::{ctl_gateway::server::MgrReceiver,
            manager::{action::ActionSender,
                      ManagerState}};
use futures::{future::Future,
              sync::oneshot,
              Async,
              Poll,
              Stream};
use std::sync::Arc;

pub struct CtlAcceptor {
    /// Communication channel from the control gateway server. User
    /// interactions are received there and then sent here into the
    /// `CtlAcceptor` future for further processing.
    mgr_receiver: MgrReceiver,
    /// Reference to the Supervisor's main state. This is passed into
    /// handlers that need to access, e.g., what services are running,
    /// etc.
    state: Arc<ManagerState>,
    /// Signaling channel for the intention to shut down. A message
    /// received on this channel will cause the `CtlAcceptor` future
    /// stream to terminate.
    shutdown_trigger: oneshot::Receiver<()>,
    /// Communication channel back into the main Supervisor loop. This
    /// is passed into any generated command handlers as a way to
    /// send actions into the Supervisor.
    action_sender: ActionSender,
}

impl CtlAcceptor {
    pub fn new(state: Arc<ManagerState>,
               mgr_receiver: MgrReceiver,
               shutdown_trigger: oneshot::Receiver<()>,
               action_sender: ActionSender)
               -> Self {
        CtlAcceptor { state,
                      mgr_receiver,
                      shutdown_trigger,
                      action_sender }
    }
}

impl Stream for CtlAcceptor {
    type Error = ();
    type Item = CtlHandler;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        match self.shutdown_trigger.poll() {
            Ok(Async::Ready(())) => {
                info!("Signal received; stopping CtlAcceptor");
                Ok(Async::Ready(None))
            }
            Err(e) => {
                error!("Error polling CtlAcceptor shutdown trigger: {:?}", e);
                Ok(Async::Ready(None))
            }
            Ok(Async::NotReady) => {
                match self.mgr_receiver.poll() {
                    Ok(Async::Ready(Some(cmd))) => {
                        let task =
                            CtlHandler::new(cmd, self.state.clone(), self.action_sender.clone());
                        Ok(Async::Ready(Some(task)))
                    }
                    Ok(Async::Ready(None)) => Ok(Async::Ready(None)),
                    Ok(Async::NotReady) => Ok(Async::NotReady),
                    Err(e) => {
                        debug!("CtlAcceptor error, {:?}", e);
                        Err(())
                    }
                }
            }
        }
    }
}
<commit_msg>[PR Feedback] Use Display, not Debug, for user-facing communication<commit_after>//! Future for mediating the processing of commands received from the
//! CtlGateway in the Supervisor.

use super::handler::CtlHandler;
use crate::{ctl_gateway::server::MgrReceiver,
            manager::{action::ActionSender,
                      ManagerState}};
use futures::{future::Future,
              sync::oneshot,
              Async,
              Poll,
              Stream};
use std::sync::Arc;

pub struct CtlAcceptor {
    /// Communication channel from the control gateway server. User
    /// interactions are received there and then sent here into the
    /// `CtlAcceptor` future for further processing.
    mgr_receiver: MgrReceiver,
    /// Reference to the Supervisor's main state. This is passed into
    /// handlers that need to access, e.g., what services are running,
    /// etc.
    state: Arc<ManagerState>,
    /// Signaling channel for the intention to shut down. A message
    /// received on this channel will cause the `CtlAcceptor` future
    /// stream to terminate.
    shutdown_trigger: oneshot::Receiver<()>,
    /// Communication channel back into the main Supervisor loop. This
    /// is passed into any generated command handlers as a way to
    /// send actions into the Supervisor.
    action_sender: ActionSender,
}

impl CtlAcceptor {
    pub fn new(state: Arc<ManagerState>,
               mgr_receiver: MgrReceiver,
               shutdown_trigger: oneshot::Receiver<()>,
               action_sender: ActionSender)
               -> Self {
        CtlAcceptor { state,
                      mgr_receiver,
                      shutdown_trigger,
                      action_sender }
    }
}

impl Stream for CtlAcceptor {
    type Error = ();
    type Item = CtlHandler;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        match self.shutdown_trigger.poll() {
            Ok(Async::Ready(())) => {
                info!("Signal received; stopping CtlAcceptor");
                Ok(Async::Ready(None))
            }
            Err(e) => {
                error!("Error polling CtlAcceptor shutdown trigger: {}", e);
                Ok(Async::Ready(None))
            }
            Ok(Async::NotReady) => {
                match self.mgr_receiver.poll() {
                    Ok(Async::Ready(Some(cmd))) => {
                        let task =
                            CtlHandler::new(cmd, self.state.clone(), self.action_sender.clone());
                        Ok(Async::Ready(Some(task)))
                    }
                    Ok(Async::Ready(None)) => Ok(Async::Ready(None)),
                    Ok(Async::NotReady) => Ok(Async::NotReady),
                    Err(e) => {
                        debug!("CtlAcceptor error, {:?}", e);
                        Err(())
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::error::Error;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use std::process::Command;

struct Ignore;

impl<E> From<E> for Ignore where E: Error
{
    fn from(_: E) -> Ignore { Ignore }
}

fn main() -> Result<(), std::io::Error> {
    let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    File::create(out_dir.join("commit-info.txt"))?.write_all(commit_info().as_bytes())?;
    let log_level = env::var("LOG_LEVEL").unwrap_or_else(|_| "OFF".to_string());
    File::create(out_dir.join("log-level.txt"))?.write_all(log_level.as_bytes())?;
    Ok(println!("cargo:rerun-if-changed=build.rs"))
}

fn commit_info() -> String {
    match (commit_date(), commit_hash()) {
        (Ok(date), Ok(hash)) => format!(" {} {}", date.trim_end(), hash.trim_end(),),
        _ => String::new(),
    }
}

fn commit_hash() -> Result<String, Ignore> {
    Ok(String::from_utf8(Command::new("git").args(&["rev-parse",
                                                    "--short=10",
                                                    "HEAD"])
                                            .output()?
                                            .stdout)?)
}

fn commit_date() -> Result<String, Ignore> {
    Ok(String::from_utf8(Command::new("git").args(&["log",
                                                    "-1",
                                                    "--date=short",
                                                    "--pretty=format:%cd"])
                                            .output()?
                                            .stdout)?)
}
<commit_msg>Refactor to simplify<commit_after>use std::env;
use std::error::Error;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use std::process::Command;

struct Ignore;

impl<E> From<E> for Ignore where E: Error
{
    fn from(_: E) -> Ignore { Ignore }
}

fn main() -> Result<(), std::io::Error> {
    let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    File::create(out_dir.join("commit-info.txt"))?.write_all(commit_info().as_bytes())?;
    let log_level = env::var("LOG_LEVEL").unwrap_or_else(|_| "OFF".to_string());
    File::create(out_dir.join("log-level.txt"))?.write_all(log_level.as_bytes())?;
    Ok(println!("cargo:rerun-if-changed=build.rs"))
}

fn commit_info() -> String {
    match (commit_date(), commit_hash()) {
        (Ok(date), Ok(hash)) => format!(" {} {}", date.trim_end(), hash.trim_end(),),
        _ => String::new(),
    }
}

fn commit_hash() -> Result<String, Ignore> {
    let args = &["rev-parse", "--short=10", "HEAD"];
    Ok(String::from_utf8(Command::new("git").args(args).output()?.stdout)?)
}

fn commit_date() -> Result<String, Ignore> {
    let args = &["log", "-1", "--date=short", "--pretty=format:%cd"];
    Ok(String::from_utf8(Command::new("git").args(args).output()?.stdout)?)
}
<|endoftext|>


<commit_before>use std::env;
use std::fs;
use std::io::{Error, Write};
use std::path::Path;
use std::collections::HashMap;

// View loc folder with subfolders, get listings
// Returns touple (folder_map, file_list)
// folder_map keys are folders, and values are lists of direct childs
// file_list is a vector of all detected files with full path
fn scan_folder(loc: &Path) -> (HashMap<String, Vec<String>>, Vec<String>) {
    let mut folders: HashMap<String, Vec<String>> = HashMap::new();
    let mut files: Vec<String> = Vec::new();
    let mut current = Vec::new();

    if loc.is_dir() {
        for entry in fs::read_dir(loc).unwrap() {
            let entry = entry.unwrap();
            let path = entry.path();
            let path_str = String::from(path.to_str().unwrap()).replace("\\", "/");

            current.push(path_str.clone());

            // if folder then scan recursively
            if path.is_dir() {
                let (d, mut f) = scan_folder(&path);
                for (key, value) in d.into_iter() {
                    folders.insert(key, value);
                }

                files.append(&mut f);
            } else {
                files.push(path_str);
            }
        }

        current.sort();
        folders.entry(String::from(loc.to_str().unwrap()).replace("\\", "/")).or_insert(current);
    } else {
        panic!("{:?} is not a folder!", loc);
    }

    (folders, files)
}

// Write folder/file information to output file
fn fill_from_location(f: &mut fs::File, loc: &Path ) -> Result<(), (Error)> {
    let (folders, mut files) = scan_folder(loc);
    let mut folder_it:Vec<_> = folders.keys().collect();

    let loc_str = loc.to_str().unwrap();
    let mut idx = loc_str.len();

    if !loc_str.ends_with("/") {
        idx += 1;
    }

    folder_it.sort();
    files.sort();
    for dir in folder_it.iter() {
        let strip: String = dir.chars().skip(idx).collect();
        write!(f, "        files.insert(b\"{}\", (b\"", strip)?;

        // Write child elements separated with \n
        let sub = folders.get(*dir).unwrap();
        let mut first = true;
        for child in sub.iter() {
            let idx = child.rfind('/').unwrap() + 1;
            let (_, c) = child.split_at(idx);
            if first {
                write!(f, "{}", c)?;
                first = false;
            } else {
                write!(f, "\\n{}", c)?;
            }
        }
        write!(f, "\", true));\n")?;
    }

    for name in files.iter() {
        let (_, strip) = name.split_at(idx);
        write!(f, "        files.insert(b\"{}\", (include_bytes!(\"{}\"), false));\n", strip, name)?;
    }

    Ok(())
}

fn main() {
    println!("cargo:rustc-env=TARGET={}", env::var("TARGET").unwrap());

    let out_dir = env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("gen.rs");
    let mut f = fs::File::create(&dest_path).unwrap();
    let src = env::var("INITFS_FOLDER");

    // Write header
    f.write_all(b"
mod gen {
    use collections::BTreeMap;
    pub fn gen() -> BTreeMap<&'static [u8], (&'static [u8], bool)> {
        let mut files: BTreeMap<&'static [u8], (&'static [u8], bool)> = BTreeMap::new();
").unwrap();

    match src {
        Ok(v) => fill_from_location(&mut f, Path::new(&v)).unwrap(),
        Err(e) => {
            f.write_all(
b"        files.clear();" // Silence mutability warning
).unwrap();
            println!("cargo:warning=location not found: {}, please set proper INITFS_FOLDER.", e);
        }
    }

    f.write_all(b"        files
    }
}
    ").unwrap();
}
<commit_msg>Fix output of build script<commit_after>use std::env;
use std::fs;
use std::io::{Error, Write};
use std::path::Path;
use std::collections::HashMap;

// View loc folder with subfolders, get listings
// Returns touple (folder_map, file_list)
// folder_map keys are folders, and values are lists of direct childs
// file_list is a vector of all detected files with full path
fn scan_folder(loc: &Path) -> (HashMap<String, Vec<String>>, Vec<String>) {
    let mut folders: HashMap<String, Vec<String>> = HashMap::new();
    let mut files: Vec<String> = Vec::new();
    let mut current = Vec::new();

    if loc.is_dir() {
        for entry in fs::read_dir(loc).unwrap() {
            let entry = entry.unwrap();
            let path = entry.path();
            let path_str = String::from(path.to_str().unwrap()).replace("\\", "/");

            current.push(path_str.clone());

            // if folder then scan recursively
            if path.is_dir() {
                let (d, mut f) = scan_folder(&path);
                for (key, value) in d.into_iter() {
                    folders.insert(key, value);
                }

                files.append(&mut f);
            } else {
                files.push(path_str);
            }
        }

        current.sort();
        folders.entry(String::from(loc.to_str().unwrap()).replace("\\", "/")).or_insert(current);
    } else {
        panic!("{:?} is not a folder!", loc);
    }

    (folders, files)
}

// Write folder/file information to output file
fn fill_from_location(f: &mut fs::File, loc: &Path ) -> Result<(), (Error)> {
    let (folders, mut files) = scan_folder(loc);
    let mut folder_it:Vec<_> = folders.keys().collect();

    let loc_str = loc.to_str().unwrap();
    let mut idx = loc_str.len();

    if !loc_str.ends_with("/") {
        idx += 1;
    }

    folder_it.sort();
    files.sort();
    for dir in folder_it.iter() {
        let strip: String = dir.chars().skip(idx).collect();
        write!(f, "        files.insert(b\"{}\", (b\"", strip)?;

        // Write child elements separated with \n
        let sub = folders.get(*dir).unwrap();
        let mut first = true;
        for child in sub.iter() {
            let idx = child.rfind('/').unwrap() + 1;
            let (_, c) = child.split_at(idx);
            if first {
                write!(f, "{}", c)?;
                first = false;
            } else {
                write!(f, "\\n{}", c)?;
            }
        }
        write!(f, "\", true));\n")?;
    }

    for name in files.iter() {
        let (_, strip) = name.split_at(idx);
        write!(f, "        files.insert(b\"{}\", (include_bytes!(\"{}\"), false));\n", strip, name)?;
    }

    Ok(())
}

fn main() {
    println!("cargo:rustc-env=TARGET={}", env::var("TARGET").unwrap());

    let out_dir = env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("gen.rs");
    let mut f = fs::File::create(&dest_path).unwrap();
    let src = env::var("INITFS_FOLDER");

    // Write header
    f.write_all(b"
mod gen {
    use collections::BTreeMap;
    pub fn gen() -> BTreeMap<&'static [u8], (&'static [u8], bool)> {
        let mut files: BTreeMap<&'static [u8], (&'static [u8], bool)> = BTreeMap::new();
").unwrap();

    match src {
        Ok(v) => fill_from_location(&mut f, Path::new(&v)).unwrap(),
        Err(e) => {
            f.write_all(
                b"        files.clear();" // Silence mutability warning
            ).unwrap();
            println!("cargo:warning=location not found: {}, please set proper INITFS_FOLDER.", e);
        }
    }

    f.write_all(b"
        files
    }
}
").unwrap();
}
<|endoftext|>


<commit_before>extern crate rustc_version;
extern crate xdg;

use std::ffi::OsStr;
use std::path::Path;
use std::process::Command;

static AFL_SRC_PATH: &str = "afl-2.52b";

#[path = "src/common.rs"]
mod common;

fn main() {
    build_afl(&common::afl_dir());
    build_afl_llvm_runtime();
}

fn build_afl(out_dir: &Path) {
    let status = Command::new("make")
        .current_dir(AFL_SRC_PATH)
        .args(&["clean", "all", "install"])
        // Rely on LLVM’s built-in execution tracing feature instead of AFL’s
        // LLVM passi instrumentation.
        .env("AFL_TRACE_PC", "1")
        .env("DESTDIR", out_dir)
        .env("PREFIX", "")
        .status()
        .expect("could not run 'make'");
    assert!(status.success());
}

fn build_afl_llvm_runtime() {
    let status = Command::new("cc")
        .current_dir(AFL_SRC_PATH)
        .arg("-c")
        .arg("-O1")
        .arg("-fPIC")
        .arg("-fno-omit-frame-pointer")
        .arg("llvm_mode/afl-llvm-rt.o.c")
        .arg("-fpermissive")
        .args(&[OsStr::new("-o"), common::object_file_path().as_os_str()])
        .status()
        .expect("could not run 'gcc'");
    assert!(status.success());

    let status = Command::new("ar")
        .arg("r")
        .arg(common::archive_file_path())
        .arg(common::object_file_path())
        .status()
        .expect("could not run 'ar'");
    assert!(status.success());
}
<commit_msg>Build support for AFL on ARM (#157)<commit_after>extern crate rustc_version;
extern crate xdg;

use std::ffi::OsStr;
use std::path::Path;
use std::process::Command;

static AFL_SRC_PATH: &str = "afl-2.52b";

#[path = "src/common.rs"]
mod common;

fn main() {
    build_afl(&common::afl_dir());
    build_afl_llvm_runtime();
}

#[cfg(not(target_arch = "arm"))]
fn build_afl(out_dir: &Path) {
    let status = Command::new("make")
        .current_dir(AFL_SRC_PATH)
        .args(&["clean", "all", "install"])
        // Rely on LLVM’s built-in execution tracing feature instead of AFL’s
        // LLVM passi instrumentation.
        .env("AFL_TRACE_PC", "1")
        .env("DESTDIR", out_dir)
        .env("PREFIX", "")
        .status()
        .expect("could not run 'make'");
    assert!(status.success());
}

#[cfg(target_arch = "arm")]
fn build_afl(out_dir: &Path) {
    let status = Command::new("make")
        .current_dir(AFL_SRC_PATH)
        .args(&["clean", "all", "install"])
        // Rely on LLVM’s built-in execution tracing feature instead of AFL’s
        // LLVM passi instrumentation.
        .env("AFL_TRACE_PC", "1")
        .env("DESTDIR", out_dir)
        .env("PREFIX", "")
        // sets AFL_NO_X86 to compile for ARM arch
        .env("AFL_NO_X86", "1")
        .status()
        .expect("could not run 'make'");
    assert!(status.success());
}

fn build_afl_llvm_runtime() {
    let status = Command::new("cc")
        .current_dir(AFL_SRC_PATH)
        .arg("-c")
        .arg("-O1")
        .arg("-fPIC")
        .arg("-fno-omit-frame-pointer")
        .arg("llvm_mode/afl-llvm-rt.o.c")
        .arg("-fpermissive")
        .args(&[OsStr::new("-o"), common::object_file_path().as_os_str()])
        .status()
        .expect("could not run 'gcc'");
    assert!(status.success());

    let status = Command::new("ar")
        .arg("r")
        .arg(common::archive_file_path())
        .arg(common::object_file_path())
        .status()
        .expect("could not run 'ar'");
    assert!(status.success());
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017  Sebastian Wiesner <swiesner@lunaryorn.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

extern crate reqwest;
extern crate sha2;

use sha2::{Sha256, Digest};
use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

static URL: &'static str = "https://www.eff.org/files/2016/07/18/eff_large_wordlist.txt";
static WORDLIST_SHA256: &'static str = {
    "addd35536511597a02fa0a9ff1e5284677b8883b83e986e43f15a3db996b903e"
};

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let eff_wordlist = Path::new(&out_dir).join("eff_wordlist.txt");

    let client = reqwest::Client::new().unwrap();

    let mut response = client.get(URL)
        .header(reqwest::header::Connection::close())
        .send()
        .unwrap();
    let mut wordlist_buffer = Vec::with_capacity(40000);
    response.read_to_end(&mut wordlist_buffer).unwrap();

    let mut hasher = Sha256::new();
    hasher.input(&wordlist_buffer);
    let hash = hasher.result().map(|b| format!("{:02x}", b)).join("");
    if hash != WORDLIST_SHA256 {
        panic!("SHA256 mismatch for EFF wordlist! Report issue to \
                https://github.com/lunaryorn/xkpwgen.rs");
    }

    File::create(&eff_wordlist).unwrap().write_all(&wordlist_buffer).unwrap();
    println!("Wrote EFF wordlist to {}", eff_wordlist.to_string_lossy());
}
<commit_msg>Verify hash bytewise<commit_after>/*
 * Copyright (C) 2017  Sebastian Wiesner <swiesner@lunaryorn.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

extern crate reqwest;
extern crate sha2;

use sha2::{Sha256, Digest};
use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

// We use the diceware list of the EFF, which contains 7776 common English words between three and
// nine characters.  I'm unsure about the licensing situation concerning this list so I'm not
// shipping it with the sources but instead download it during the build and use its hash to verify
// its authenticity.
static URL: &'static str = "https://www.eff.org/files/2016/07/18/eff_large_wordlist.txt";
static WORDLIST_SHA256: &'static [u8] = &[0xad, 0xdd, 0x35, 0x53, 0x65, 0x11, 0x59, 0x7a, 0x02,
                                          0xfa, 0x0a, 0x9f, 0xf1, 0xe5, 0x28, 0x46, 0x77, 0xb8,
                                          0x88, 0x3b, 0x83, 0xe9, 0x86, 0xe4, 0x3f, 0x15, 0xa3,
                                          0xdb, 0x99, 0x6b, 0x90, 0x3e];

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let eff_wordlist = Path::new(&out_dir).join("eff_wordlist.txt");

    let client = reqwest::Client::new().unwrap();

    let mut response = client.get(URL)
        .header(reqwest::header::Connection::close())
        .send()
        .unwrap();
    let mut wordlist_buffer = Vec::with_capacity(40000);
    response.read_to_end(&mut wordlist_buffer).unwrap();

    let mut hasher = Sha256::new();
    hasher.input(&wordlist_buffer);
    let hash = hasher.result();
    if *hash != *WORDLIST_SHA256 {
        panic!("SHA256 mismatch for EFF wordlist! Report issue to \
                https://github.com/lunaryorn/xkpwgen.rs");
    }

    File::create(&eff_wordlist).unwrap().write_all(&wordlist_buffer).unwrap();
    println!("Wrote EFF wordlist to {}", eff_wordlist.to_string_lossy());
}
<|endoftext|>


<commit_before>use std::env;
use std::error::Error;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use std::process::Command;

struct Ignore;

impl<E> From<E> for Ignore where E: Error
{
    fn from(_: E) -> Ignore { Ignore }
}

fn main() {
    let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    File::create(out_dir.join("commit-info.txt")).unwrap()
                                                 .write_all(commit_info().as_bytes())
                                                 .unwrap();
    let log_level = env::var("LOG_LEVEL").unwrap_or(String::from("OFF"));
    File::create(out_dir.join("log-level.txt")).unwrap()
                                               .write_all(log_level.as_bytes())
                                               .unwrap();
    println!("cargo:rerun-if-changed=build.rs");
}

fn commit_info() -> String {
    match (commit_date(), commit_hash()) {
        (Ok(date), Ok(hash)) => format!(" {} {}", date.trim_end(), hash.trim_end(),),
        _ => String::new(),
    }
}

fn commit_hash() -> Result<String, Ignore> {
    Ok(String::from_utf8(Command::new("git").args(&["rev-parse",
                                                    "--short=10",
                                                    "HEAD"])
                                            .output()?
                                            .stdout)?)
}

fn commit_date() -> Result<String, Ignore> {
    Ok(String::from_utf8(Command::new("git").args(&["log",
                                                    "-1",
                                                    "--date=short",
                                                    "--pretty=format:%cd"])
                                            .output()?
                                            .stdout)?)
}
<commit_msg>Change build main to return result<commit_after>use std::env;
use std::error::Error;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use std::process::Command;

struct Ignore;

impl<E> From<E> for Ignore where E: Error
{
    fn from(_: E) -> Ignore { Ignore }
}

fn main() -> Result<(), std::io::Error> {
    let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    File::create(out_dir.join("commit-info.txt"))?.write_all(commit_info().as_bytes())?;
    let log_level = env::var("LOG_LEVEL").unwrap_or_else(|_| "OFF".to_string());
    File::create(out_dir.join("log-level.txt"))?.write_all(log_level.as_bytes())?;
    Ok(println!("cargo:rerun-if-changed=build.rs"))
}

fn commit_info() -> String {
    match (commit_date(), commit_hash()) {
        (Ok(date), Ok(hash)) => format!(" {} {}", date.trim_end(), hash.trim_end(),),
        _ => String::new(),
    }
}

fn commit_hash() -> Result<String, Ignore> {
    Ok(String::from_utf8(Command::new("git").args(&["rev-parse",
                                                    "--short=10",
                                                    "HEAD"])
                                            .output()?
                                            .stdout)?)
}

fn commit_date() -> Result<String, Ignore> {
    Ok(String::from_utf8(Command::new("git").args(&["log",
                                                    "-1",
                                                    "--date=short",
                                                    "--pretty=format:%cd"])
                                            .output()?
                                            .stdout)?)
}
<|endoftext|>


<commit_before>extern crate gl_generator;
extern crate khronos_api;

use std::env;
use std::fs::File;
use std::path::PathBuf;

fn main() {
    let target = env::var("TARGET").unwrap();
    let dest = PathBuf::new(&env::var("OUT_DIR").unwrap());

    if target.contains("windows") {
        let mut file = File::create(&dest.join("wgl_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StaticGenerator,
                                        gl_generator::registry::Ns::Wgl,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::WGL_XML, vec![],
                                        "1.0", "core", &mut file).unwrap();

        let mut file = File::create(&dest.join("wgl_extra_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StructGenerator,
                                        gl_generator::registry::Ns::Wgl,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::WGL_XML,
                                        vec![
                                            "WGL_ARB_create_context".to_string(),
                                            "WGL_EXT_swap_control".to_string()
                                        ],
                                        "1.0", "core", &mut file).unwrap();
    }

    if target.contains("linux") {
        let mut file = File::create(&dest.join("glx_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StaticGenerator,
                                        gl_generator::registry::Ns::Glx,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::GLX_XML, vec![],
                                        "1.4", "core", &mut file).unwrap();

        let mut file = File::create(&dest.join("glx_extra_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StructGenerator,
                                        gl_generator::registry::Ns::Glx,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::GLX_XML,
                                        vec![
                                            "GLX_ARB_create_context".to_string(),
                                            "GLX_EXT_swap_control".to_string(),
                                            "GLX_SGI_swap_control".to_string()
                                        ],
                                        "1.4", "core", &mut file).unwrap();
    }

    if target.contains("android") {
        let mut file = File::create(&dest.join("egl_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StaticGenerator,
                                        gl_generator::registry::Ns::Egl,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::EGL_XML, vec![],
                                        "1.5", "core", &mut file).unwrap();
    }

    if target.contains("darwin") {
        let mut file = File::create(&dest.join("gl_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::GlobalGenerator,
                                        gl_generator::registry::Ns::Gl,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::GL_XML,
                                        vec!["GL_EXT_framebuffer_object".to_string()],
                                        "3.2", "core", &mut file).unwrap();
    } else if target.contains("android") {
        let mut file = File::create(&dest.join("gles2_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StructGenerator,
                                        gl_generator::registry::Ns::Gles2,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::GL_XML, vec![],
                                        "3.1", "core", &mut file).unwrap();
    } else {
        let mut file = File::create(&dest.join("gl_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StructGenerator,
                                        gl_generator::registry::Ns::Gl,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::GL_XML, vec![],
                                        "4.1", "core", &mut file).unwrap();
    }
}
<commit_msg>Fix for rust changes: PathBuf::new() -> PathBuf::from().<commit_after>extern crate gl_generator;
extern crate khronos_api;

use std::env;
use std::fs::File;
use std::path::PathBuf;

fn main() {
    let target = env::var("TARGET").unwrap();
    let dest = PathBuf::from(&env::var("OUT_DIR").unwrap());

    if target.contains("windows") {
        let mut file = File::create(&dest.join("wgl_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StaticGenerator,
                                        gl_generator::registry::Ns::Wgl,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::WGL_XML, vec![],
                                        "1.0", "core", &mut file).unwrap();

        let mut file = File::create(&dest.join("wgl_extra_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StructGenerator,
                                        gl_generator::registry::Ns::Wgl,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::WGL_XML,
                                        vec![
                                            "WGL_ARB_create_context".to_string(),
                                            "WGL_EXT_swap_control".to_string()
                                        ],
                                        "1.0", "core", &mut file).unwrap();
    }

    if target.contains("linux") {
        let mut file = File::create(&dest.join("glx_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StaticGenerator,
                                        gl_generator::registry::Ns::Glx,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::GLX_XML, vec![],
                                        "1.4", "core", &mut file).unwrap();

        let mut file = File::create(&dest.join("glx_extra_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StructGenerator,
                                        gl_generator::registry::Ns::Glx,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::GLX_XML,
                                        vec![
                                            "GLX_ARB_create_context".to_string(),
                                            "GLX_EXT_swap_control".to_string(),
                                            "GLX_SGI_swap_control".to_string()
                                        ],
                                        "1.4", "core", &mut file).unwrap();
    }

    if target.contains("android") {
        let mut file = File::create(&dest.join("egl_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StaticGenerator,
                                        gl_generator::registry::Ns::Egl,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::EGL_XML, vec![],
                                        "1.5", "core", &mut file).unwrap();
    }

    if target.contains("darwin") {
        let mut file = File::create(&dest.join("gl_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::GlobalGenerator,
                                        gl_generator::registry::Ns::Gl,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::GL_XML,
                                        vec!["GL_EXT_framebuffer_object".to_string()],
                                        "3.2", "core", &mut file).unwrap();
    } else if target.contains("android") {
        let mut file = File::create(&dest.join("gles2_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StructGenerator,
                                        gl_generator::registry::Ns::Gles2,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::GL_XML, vec![],
                                        "3.1", "core", &mut file).unwrap();
    } else {
        let mut file = File::create(&dest.join("gl_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StructGenerator,
                                        gl_generator::registry::Ns::Gl,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::GL_XML, vec![],
                                        "4.1", "core", &mut file).unwrap();
    }
}
<|endoftext|>


<commit_before>extern crate puzrs;
extern crate rand;
extern crate getopts;

use getopts::Options;
use getopts::Matches;
use std::env;

use puzrs::*;
use std::io;
use std::time::Instant;
use rand::Rng;

use std::thread;
use std::sync::Mutex;
use std::io::Write;

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

#[derive(Clone, Copy, Debug)]
struct GeneratorOption {
    height: i32,
    width: i32,
    jobs: i32,
    no_adjacent_clues: bool,
    symmetry_clue: bool,
    minimum_path_length: i32,
    empty_width: i32,
    corner: Option<(i32, i32)>,
}

fn run_generator(opts: GeneratorOption) {
    let height = opts.height;
    let width = opts.width;
    let mut ths = vec![];
    let gen_probs = std::sync::Arc::new(Mutex::new(0i64));

    for _ in 0..opts.jobs {
        let gen_probs = gen_probs.clone();
        let opts = opts;

        ths.push(thread::spawn(move || {
            let start = Instant::now();

            let mut generator = numberlink::PlacementGenerator::new(height, width);

            let mut rng = rand::thread_rng();
            loop {
                let mut end = Grid::new(height, width, numberlink::Endpoint::Any);

                let trans = move |x: i32, y: i32, d: i32| {
                    let mut x = x;
                    let mut y = y;
                    if d == 1 || d == 3 {
                        x = width - 1 - x;
                    }
                    if d == 2 || d == 3 {
                        y = height - 1 - y;
                    }
                    (Y(y), X(x))
                };
                let fr = opts.empty_width;
                for y in 0..height {
                    for x in 0..width {
                        if y < fr || y >= height - fr || x < fr || x >= width - fr {
                            end[(Y(y), X(x))] = numberlink::Endpoint::Prohibited;
                        }
                    }
                }
                if let Some((lo, hi)) = opts.corner {
                    for d in 0..4 {
                        let i = rng.gen_range(lo, hi + 1);
                        end[trans(i, i, d)] = numberlink::Endpoint::Forced;
                        end[trans(i, i + 1, d)] = numberlink::Endpoint::Prohibited;
                        end[trans(i + 1, i, d)] = numberlink::Endpoint::Prohibited;
                        for j in 0..i {
                            end[trans(j, j, d)] = numberlink::Endpoint::Prohibited;
                        }
                    }
                }
                let opt = numberlink::GeneratorOption {
                    chain_threshold: opts.minimum_path_length,
                    endpoint_constraint: Some(&end),
                    forbid_adjacent_clue: opts.no_adjacent_clues,
                    symmetry_clue: opts.symmetry_clue,
                };

                let problem = generator.generate(&opt, &mut rng);
                if let Some(problem) = problem {
                    let ans = numberlink::solve2(&problem, Some(2), false, true);

                    if ans.len() == 1 && !ans.found_not_fully_filled {
                        let mut num_clues = 0;
                        for y in 0..height {
                            for x in 0..width {
                                if problem[(Y(y), X(x))] != numberlink::Clue(0) {
                                    num_clues += 1;
                                }
                            }
                        }
                        num_clues /= 2;

                        let mut trans = vec![];
                        for i in 0..num_clues {
                            trans.push(i + 1);
                        }
                        rng.shuffle(&mut trans);
                        let stdin = io::stdout();
                        let handle = &mut stdin.lock();

                        let end = start.elapsed();
                        let cost_time = (end.as_secs() as f64 + end.subsec_nanos() as f64 / 1e9f64) / 60f64;
                        let mut cnt = gen_probs.lock().unwrap();
                        *cnt += 1;
                        eprintln!("{} problem(s) in {:.3}[min] ({:.3} [prob/min])", *cnt, cost_time, (*cnt) as f64 / cost_time);

                        writeln!(handle, "{} {}", height, width).unwrap();
                        for y in 0..height {
                            for x in 0..width {
                                let numberlink::Clue(c) = problem[(Y(y), X(x))];
                                if c >= 1 {
                                    write!(handle, "{}{}", trans[(c - 1) as usize], if x == width - 1 { '\n' } else { ' ' }).unwrap();
                                } else {
                                    write!(handle, ".{}", if x == width - 1 { '\n' } else { ' ' }).unwrap();
                                }
                            }
                        }
                        writeln!(handle).unwrap();
                    }
                }
            }
        }));
    }
    for th in ths {
        th.join().unwrap();
    }
}

fn parse_options(matches: Matches) -> Result<GeneratorOption, &'static str> {
    let height = try!(
        matches.opt_str("h")
            .ok_or("'height' must be specified")
            .and_then(|arg| arg.parse::<i32>().map_err(|_| "Could not parse value for 'height'"))
            .and_then(|arg| if arg > 0 { Ok(arg) } else { Err("'height' must be a positive integer") }));
    let width = try!(
        matches.opt_str("w")
            .ok_or("'width' must be specified")
            .and_then(|arg| arg.parse::<i32>().map_err(|_| "Could not parse value for 'width'"))
            .and_then(|arg| if arg > 0 { Ok(arg) } else { Err("'width' must be a positive integer") }));
    let jobs = try!(
        matches.opt_str("j").map(|s|
            s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'jobs'")
                .and_then(|arg| if arg > 0 { Ok(arg) } else { Err("'jobs' must be a positive integer") })
        ).unwrap_or(Ok(1)));
    let no_adjacent_clues = matches.opt_present("no-adjacent-clues");
    let symmetry_clue = matches.opt_present("symmetry");
    let minimum_path_length = try!(
        matches.opt_str("minimum-path-length").map(|s|
            s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'minimum-path-length'")
                .and_then(|arg| if arg > 0 { Ok(arg) } else { Err("'minimum-path-length' must be a positive integer") })
        ).unwrap_or(Ok(1)));
    let empty_width = try!(
        matches.opt_str("empty-width").map(|s|
            s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'empty-width'")
                .and_then(|arg| if arg > 0 { Ok(arg) } else { Err("'empty-width' must be a positive integer") })
        ).unwrap_or(Ok(1)));
    let corner = match matches.opt_str("corner") {
        Some(s) => {
            let split = s.split(",").collect::<Vec<&str>>();
            if split.len() != 2 {
                return Err("Could not parse value for 'corner'");
            }
            let lo = try!(split[0].parse::<i32>().map_err(|_| "Could not parse value for 'corner'"));
            let hi = try!(split[1].parse::<i32>().map_err(|_| "Could not parse value for 'corner'"));
            if !(1 <= lo && lo <= hi) {
                return Err("'corner' must be a valid range on positive integers");
            }
            Some((lo, hi))
        },
        None => None,
    };
    Ok(GeneratorOption {
        height,
        width,
        jobs,
        no_adjacent_clues,
        symmetry_clue,
        minimum_path_length,
        empty_width,
        corner
    })
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut options = Options::new();
    options.optflag("", "help", "Show this help menu");
    options.optopt("h", "height", "Height of desired problems", "10");
    options.optopt("w", "width", "Width of desired problems", "10");
    options.optopt("j", "jobs", "Number of workers (threads)", "2");
    options.optflag("a", "no-adjacent-clues", "Disallow adjacent clues");
    options.optflag("s", "symmetry", "Force symmetry");
    options.optopt("m", "minimum-path-length", "Minimum length of paths in the answer", "12");
    options.optopt("e", "empty-width", "Disallow clues on n cell(s) from the outer border", "1");
    options.optopt("c", "corner", "Put one clue within specified range from each corner", "1,3");

    let matches = match options.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            eprintln!("error: {}", f);
            return;
        },
    };

    if matches.opt_present("help") {
        print_usage(&program, options);
        return;
    }

    let opt = match parse_options(matches) {
        Ok(opt) => opt,
        Err(f) => {
            eprintln!("error: {}", f);
            return;
        },
    };
    run_generator(opt);
}
<commit_msg>Numberlink: improve initial constraint generation in nl_generator<commit_after>extern crate puzrs;
extern crate rand;
extern crate getopts;

use getopts::Options;
use getopts::Matches;
use std::env;

use puzrs::*;
use std::io;
use std::time::Instant;
use rand::Rng;

use std::thread;
use std::sync::Mutex;
use std::io::Write;

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

#[derive(Clone, Copy, Debug)]
struct GeneratorOption {
    height: i32,
    width: i32,
    jobs: i32,
    no_adjacent_clues: bool,
    symmetry_clue: bool,
    minimum_path_length: i32,
    empty_width: i32,
    corner: Option<(i32, i32)>,
}

fn run_generator(opts: GeneratorOption) {
    let height = opts.height;
    let width = opts.width;
    let mut ths = vec![];
    let gen_probs = std::sync::Arc::new(Mutex::new(0i64));

    for _ in 0..opts.jobs {
        let gen_probs = gen_probs.clone();
        let opts = opts;

        ths.push(thread::spawn(move || {
            let start = Instant::now();

            let mut generator = numberlink::PlacementGenerator::new(height, width);

            let mut rng = rand::thread_rng();
            loop {
                let mut end = Grid::new(height, width, numberlink::Endpoint::Any);

                let trans = move |x: i32, y: i32, d: i32| {
                    let mut x = x;
                    let mut y = y;
                    if d == 1 || d == 3 {
                        x = width - 1 - x;
                    }
                    if d == 2 || d == 3 {
                        y = height - 1 - y;
                    }
                    (Y(y), X(x))
                };
                let fr = opts.empty_width;
                for y in 0..height {
                    for x in 0..width {
                        if y < fr || y >= height - fr || x < fr || x >= width - fr {
                            end[(Y(y), X(x))] = numberlink::Endpoint::Prohibited;
                        }
                    }
                }
                if let Some((lo, hi)) = opts.corner {
                    if opts.symmetry_clue {
                        for d in 0..2 {
                            let i = rng.gen_range(lo, hi + 1);
                            let (d0, d1) = if d == 0 { (0, 3) } else { (1, 2) };

                            end[trans(i, i, d0)] = numberlink::Endpoint::Forced;
                            end[trans(i, i + 1, d0)] = numberlink::Endpoint::Prohibited;
                            end[trans(i + 1, i, d0)] = numberlink::Endpoint::Prohibited;
                            for j in 0..i {
                                end[trans(j, j, d0)] = numberlink::Endpoint::Prohibited;
                            }
                            end[trans(i, i, d1)] = numberlink::Endpoint::Forced;
                            end[trans(i, i + 1, d1)] = numberlink::Endpoint::Prohibited;
                            end[trans(i + 1, i, d1)] = numberlink::Endpoint::Prohibited;
                            for j in 0..i {
                                end[trans(j, j, d1)] = numberlink::Endpoint::Prohibited;
                            }
                        }
                    } else {
                        for d in 0..4 {
                            let i = rng.gen_range(lo, hi + 1);
                            end[trans(i, i, d)] = numberlink::Endpoint::Forced;
                            end[trans(i, i + 1, d)] = numberlink::Endpoint::Prohibited;
                            end[trans(i + 1, i, d)] = numberlink::Endpoint::Prohibited;
                            for j in 0..i {
                                end[trans(j, j, d)] = numberlink::Endpoint::Prohibited;
                            }
                        }
                    }
                }
                let opt = numberlink::GeneratorOption {
                    chain_threshold: opts.minimum_path_length,
                    endpoint_constraint: Some(&end),
                    forbid_adjacent_clue: opts.no_adjacent_clues,
                    symmetry_clue: opts.symmetry_clue,
                };

                let problem = generator.generate(&opt, &mut rng);
                if let Some(problem) = problem {
                    let ans = numberlink::solve2(&problem, Some(2), false, true);

                    if ans.len() == 1 && !ans.found_not_fully_filled {
                        let mut num_clues = 0;
                        for y in 0..height {
                            for x in 0..width {
                                if problem[(Y(y), X(x))] != numberlink::Clue(0) {
                                    num_clues += 1;
                                }
                            }
                        }
                        num_clues /= 2;

                        let mut trans = vec![];
                        for i in 0..num_clues {
                            trans.push(i + 1);
                        }
                        rng.shuffle(&mut trans);
                        let stdin = io::stdout();
                        let handle = &mut stdin.lock();

                        let end = start.elapsed();
                        let cost_time = (end.as_secs() as f64 + end.subsec_nanos() as f64 / 1e9f64) / 60f64;
                        let mut cnt = gen_probs.lock().unwrap();
                        *cnt += 1;
                        eprintln!("{} problem(s) in {:.3}[min] ({:.3} [prob/min])", *cnt, cost_time, (*cnt) as f64 / cost_time);

                        writeln!(handle, "{} {}", height, width).unwrap();
                        for y in 0..height {
                            for x in 0..width {
                                let numberlink::Clue(c) = problem[(Y(y), X(x))];
                                if c >= 1 {
                                    write!(handle, "{}{}", trans[(c - 1) as usize], if x == width - 1 { '\n' } else { ' ' }).unwrap();
                                } else {
                                    write!(handle, ".{}", if x == width - 1 { '\n' } else { ' ' }).unwrap();
                                }
                            }
                        }
                        writeln!(handle).unwrap();
                    }
                }
            }
        }));
    }
    for th in ths {
        th.join().unwrap();
    }
}

fn parse_options(matches: Matches) -> Result<GeneratorOption, &'static str> {
    let height = try!(
        matches.opt_str("h")
            .ok_or("'height' must be specified")
            .and_then(|arg| arg.parse::<i32>().map_err(|_| "Could not parse value for 'height'"))
            .and_then(|arg| if arg > 0 { Ok(arg) } else { Err("'height' must be a positive integer") }));
    let width = try!(
        matches.opt_str("w")
            .ok_or("'width' must be specified")
            .and_then(|arg| arg.parse::<i32>().map_err(|_| "Could not parse value for 'width'"))
            .and_then(|arg| if arg > 0 { Ok(arg) } else { Err("'width' must be a positive integer") }));
    let jobs = try!(
        matches.opt_str("j").map(|s|
            s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'jobs'")
                .and_then(|arg| if arg > 0 { Ok(arg) } else { Err("'jobs' must be a positive integer") })
        ).unwrap_or(Ok(1)));
    let no_adjacent_clues = matches.opt_present("no-adjacent-clues");
    let symmetry_clue = matches.opt_present("symmetry");
    let minimum_path_length = try!(
        matches.opt_str("minimum-path-length").map(|s|
            s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'minimum-path-length'")
                .and_then(|arg| if arg > 0 { Ok(arg) } else { Err("'minimum-path-length' must be a positive integer") })
        ).unwrap_or(Ok(1)));
    let empty_width = try!(
        matches.opt_str("empty-width").map(|s|
            s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'empty-width'")
                .and_then(|arg| if arg > 0 { Ok(arg) } else { Err("'empty-width' must be a positive integer") })
        ).unwrap_or(Ok(1)));
    let corner = match matches.opt_str("corner") {
        Some(s) => {
            let split = s.split(",").collect::<Vec<&str>>();
            if split.len() != 2 {
                return Err("Could not parse value for 'corner'");
            }
            let lo = try!(split[0].parse::<i32>().map_err(|_| "Could not parse value for 'corner'"));
            let hi = try!(split[1].parse::<i32>().map_err(|_| "Could not parse value for 'corner'"));
            if !(1 <= lo && lo <= hi) {
                return Err("'corner' must be a valid range on positive integers");
            }
            Some((lo, hi))
        },
        None => None,
    };
    Ok(GeneratorOption {
        height,
        width,
        jobs,
        no_adjacent_clues,
        symmetry_clue,
        minimum_path_length,
        empty_width,
        corner
    })
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut options = Options::new();
    options.optflag("", "help", "Show this help menu");
    options.optopt("h", "height", "Height of desired problems", "10");
    options.optopt("w", "width", "Width of desired problems", "10");
    options.optopt("j", "jobs", "Number of workers (threads)", "2");
    options.optflag("a", "no-adjacent-clues", "Disallow adjacent clues");
    options.optflag("s", "symmetry", "Force symmetry");
    options.optopt("m", "minimum-path-length", "Minimum length of paths in the answer", "12");
    options.optopt("e", "empty-width", "Disallow clues on n cell(s) from the outer border", "1");
    options.optopt("c", "corner", "Put one clue within specified range from each corner", "1,3");

    let matches = match options.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            eprintln!("error: {}", f);
            return;
        },
    };

    if matches.opt_present("help") {
        print_usage(&program, options);
        return;
    }

    let opt = match parse_options(matches) {
        Ok(opt) => opt,
        Err(f) => {
            eprintln!("error: {}", f);
            return;
        },
    };
    run_generator(opt);
}
<|endoftext|>


<commit_before>use std::iter;

/// LSD radix sort
pub fn lsd_sort_string(a: &mut [&str]) {
    let w = a[0].as_bytes().len();
    let n = a.len();
    let r = 256;

    let mut aux = iter::repeat("").take(n).collect::<Vec<&str>>();

    for d in (0 .. w).rev() {
        // sort by key-indexed counting on dth character

        // frequency counts
        let mut count = iter::repeat(0).take(r+1).collect::<Vec<usize>>();
        for i in 0 .. n {
            count[a[i].as_bytes()[d] as usize + 1] += 1;
        }

        // cumulates
        for r in 0 .. r {
            count[r+1] += count[r];
        }

        // move data
        for i in 0 .. n {
            aux[count[a[i].as_bytes()[d] as usize]] = a[i];
            count[a[i].as_bytes()[d] as usize] += 1;
        }

        // copy back
        for i in 0 .. n {
            a[i] = aux[i];
        }
    }
}

#[cfg(test)]
fn is_sorted<T: PartialOrd>(a: &[T]) -> bool {
    for i in 1 .. a.len() {
        if a[i] < a[i-1] {
            return false;
        }
    }
    true
}

#[test]
fn test_lsd_sort_string() {
    let mut to_be_sorted = vec![
        "dab", "add", "cab", "fad", "fee", "bad",
        "bee", "fed", "bed", "ebb", "ace", "dad"];
    assert!(!is_sorted(&to_be_sorted));
    lsd_sort_string(&mut to_be_sorted);
    assert!(is_sorted(&to_be_sorted));
}
<commit_msg>radix_sorts: add LSD sort trait, lsd int sorting tests<commit_after>use std::iter;

/// LSD radix sort
pub fn lsd_string_sort(a: &mut [&str]) {
    let w = a[0].as_bytes().len();
    let n = a.len();
    let r = 256;

    let mut aux = iter::repeat("").take(n).collect::<Vec<&str>>();

    for d in (0 .. w).rev() {
        // sort by key-indexed counting on dth character

        // frequency counts
        let mut count = iter::repeat(0).take(r+1).collect::<Vec<usize>>();
        for i in 0 .. n {
            count[a[i].as_bytes()[d] as usize + 1] += 1;
        }

        // cumulates
        for r in 0 .. r {
            count[r+1] += count[r];
        }

        // move data
        for i in 0 .. n {
            aux[count[a[i].as_bytes()[d] as usize]] = a[i];
            count[a[i].as_bytes()[d] as usize] += 1;
        }

        // copy back
        for i in 0 .. n {
            a[i] = aux[i];
        }
    }
}

pub trait LSD: Clone + Default {
    fn r() -> usize;
    fn width(&self) -> usize;
    fn item_at(&self, n: usize) -> usize;

    fn sort(a: &mut [Self]) {
        let w = a[0].width();
        // assume all width equals
        let n = a.len();
        let r = Self::r();

        let mut aux = iter::repeat(Default::default()).take(n).collect::<Vec<Self>>();

        // NOTE: no .rev() here
        for d in 0 .. w {
            // sort by ey-indexed counting on dth character

            // frequency counts
            let mut count = iter::repeat(0).take(r+1).collect::<Vec<usize>>();
            for i in 0 .. n {
                count[a[i].item_at(d) + 1] += 1;
            }

            // cumulates
            for r in 0 .. r {
                count[r+1] += count[r];
            }

            // move data
            for i in 0 .. n {
                aux[count[a[i].item_at(d)]] = a[i].clone();
                count[a[i].item_at(d)] += 1;
            }

            // copy back
            for i in 0 .. n {
                a[i] = aux[i].clone();
            }
        }
    }
}

impl LSD for u32 {
    fn r() -> usize { 256 }
    fn width(&self) -> usize { 4 }
    fn item_at(&self, n: usize) -> usize {
        // 0:   lowest byte
        // n-1: highest byte
        ((self >> (8 * n)) & 0xFF) as usize
    }
}

impl LSD for i16 {
    fn r() -> usize { 256 }
    fn width(&self) -> usize { 2 }
    fn item_at(&self, n: usize) -> usize {
        // 0:   lowest byte
        // n-1: highest byte
        let mut ret = (self >> (8 * n)) & 0xFF;
        // handle highest byte negative
        if n == 1 {
            if *self < 0 {
                ret -= 128;
            } else {
                ret += 128;
            }
        }
        ret as usize
    }
}

#[cfg(test)]
fn is_sorted<T: PartialOrd>(a: &[T]) -> bool {
    for i in 1 .. a.len() {
        if a[i] < a[i-1] {
            return false;
        }
    }
    true
}

#[test]
fn test_lsd_string_sort() {
    let mut to_be_sorted = vec![
        "dab", "add", "cab", "fad", "fee", "bad",
        "bee", "fed", "bed", "ebb", "ace", "dad"];
    assert!(!is_sorted(&to_be_sorted));
    lsd_string_sort(&mut to_be_sorted);
    assert!(is_sorted(&to_be_sorted));
}

#[test]
fn test_lsd_ints_sort() {
    let mut to_be_sorted: Vec<u32> = vec![
        2830665856, 3165123597, 780293973, 3412877992, 3781910346,
        2837710927, 560466804, 2778567425, 265098057, 18593204];

    assert!(!is_sorted(&to_be_sorted));
    LSD::sort(&mut to_be_sorted);
    assert!(is_sorted(&to_be_sorted));

    let mut to_be_sorted: Vec<i16> = vec![
        19195, -5970, 2060, 2553, 26078, 15152,
        2318, 9647, -7906, -8452, -127, 128, 127];

    assert!(!is_sorted(&to_be_sorted));
    LSD::sort(&mut to_be_sorted);
    assert!(is_sorted(&to_be_sorted));

}
<|endoftext|>