<commit_before>/// ///////////////////////////////////////////////////////////////////////////
///  File: neil/solver.rs
/// ///////////////////////////////////////////////////////////////////////////
///  Copyright 2016 Samuel Sleight
///
///  Licensed under the Apache License, Version 2.0 (the "License");
///  you may not use this file except in compliance with the License.
///  You may obtain a copy of the License at
///
///      http://www.apache.org/licenses/LICENSE-2.0
///
///  Unless required by applicable law or agreed to in writing, software
///  distributed under the License is distributed on an "AS IS" BASIS,
///  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
///  See the License for the specific language governing permissions and
///  limitations under the License.
/// ///////////////////////////////////////////////////////////////////////////

use time;
use CoolingSchedule;
use EnergyType;
use TerminationCriteria;
use rand::thread_rng;
use rand::distributions::{Range, IndependentSample};
use ansi_term::Colour::Green;
use super::Problem::Problem;
use super::Updater::{Updater,UpdateFile};
use super::Cooler::{Cooler, StepsCooler, TimeCooler};
use std::fs::{File,OpenOptions};

/**
 * A solver will take a problem and use simulated annealing
 * to try and find an optimal state.
 */
#[derive(Debug, Clone)]
pub struct Solver {
    /**
     * The termination criteria (maximum time or maximum number of steps)
     */
    pub termination_criteria: TerminationCriteria,

    /**
     * The minimum temperature of the process.
     */
    pub min_temperature: f64,

    /**
     * The maximum temperature of the process.
     */
    pub max_temperature: f64,

    /**
     * The Cooling Schedule procedure to select
     */
    pub cooling_schedule: CoolingSchedule,

    /**
     * The Energy metric to evaluate (Throughput or Latency)
     */
    pub energy_type: EnergyType,
}

impl Solver {
    /**
     * Construct the new default solver.
     */
    pub fn new() -> Solver {
        Default::default()
    }

    /**
     * Construct a new solver with a given builder function.
     */
    pub fn build_new<F>(builder: F) -> Solver
        where F: FnOnce(&mut Solver)
    {
        let mut solver = Solver::new();
        builder(&mut solver);
        solver
    }

    /**
     * Run the solver for a maximization problem
     */
    pub fn solve<P>(&self, problem: &mut P) -> P::State
        where P: Problem
    {
        let best_configuration = match self.termination_criteria {
            TerminationCriteria::Max_Steps(value) => {
                self.solve_step_based(problem,
                                      value,
                                      StepsCooler {
                                          max_steps: value,
                                          min_temp: self.min_temperature,
                                          max_temp: self.max_temperature,
                                      })
            }
            TerminationCriteria::Max_Time_Seconds(value) => {
                self.solve_time_based(problem,
                                      value,
                                      TimeCooler {
                                          max_time: value,
                                          min_temp: self.min_temperature,
                                          max_temp: self.max_temperature,
                                      })
            }
        };

        return best_configuration;
    }

    fn solve_step_based<P>(&self, problem: &mut P, max_steps: u64, cooler: StepsCooler) -> P::State
        where P: Problem
    {
    	//let mut updater=UpdateFile::new();

        let mut rng = thread_rng();
        let range = Range::new(0.0, 1.0);

        println!("{}",Green.paint("\n-------------------------------------------------------------------------------------------------------------------"));
        println!("{} Initialization Phase: Evaluation of Energy for Default Paramters",
                 Green.paint("[TUNER]"));
        println!("{}",Green.paint("-------------------------------------------------------------------------------------------------------------------"));

        let mut state = problem.initial_state();
        let mut energy = match problem.energy(&state, self.energy_type.clone()) {
            Some(nrg) => nrg,
            None => panic!("The initial configuration does not allow to calculate the energy"),
        };
        let mut temperature: f64 = self.max_temperature;

        let mut attempted = 0;
        let mut accepted = 0;
        let mut rejected = 0;
        let mut total_improves = 0;
        let mut subsequent_improves = 0;
        let mut elapsed_time = 0.0;

        let start_time = time::precise_time_ns();

        for elapsed_steps in 0..max_steps {

            elapsed_time = (time::precise_time_ns() - start_time) as f64 / 1000000000.0f64;

            println!("{}",Green.paint("-------------------------------------------------------------------------------------------------------------------"));
            println!("{} Completed Steps: {:.2} - Percentage of Completion: {:.2}% - Time Spent until Now: {:.2} \
                      s",
                     Green.paint("[TUNER]"), elapsed_steps,
                     (elapsed_steps as f64 / cooler.max_steps as f64) * 100.0,
                     elapsed_time);
            println!("{} Total Accepted Solutions: {:?} - Current Temperature: {:.2}",
                     Green.paint("[TUNER]"),
                     accepted,
                     temperature);
           /* println!("{} Accepted State: {:?}",
                     Green.paint("[TUNER]"),
                     state as HashMap);*/
            println!("{}",Green.paint("-------------------------------------------------------------------------------------------------------------------"));

            state = {
                let next_state = match problem.new_state(&state, max_steps, elapsed_steps) {
                    // There is a neighborhood available
                    Some(n_s) => n_s,
                    // No neighborhood available, all states have been visited
                    None => {
                        println!("{} Any Neighborhood Available - Terminate the Annealing",
                                 Green.paint("[TUNER]"));
                        break;
                    }
                };

                let accepted_state = match problem.energy(&next_state, self.clone().energy_type) {
                    Some(new_energy) => {
                        let de = new_energy - energy;
                        if de > 0.0 || range.ind_sample(&mut rng) <= (-de / temperature).exp() {
                            accepted += 1;
                            energy = new_energy;

                            if de > 0.0 {
                                total_improves = total_improves + 1;
                                subsequent_improves = subsequent_improves + 1;
                            }

                            //updater.send_update(new_energy, next_state, energy, next_state, elapsed_steps);
                            next_state

                        } else {
                            subsequent_improves = 0;
                            //updater.send_update(new_energy, next_state, energy, state, elapsed_steps);
                            state
                        }

                    }
                    None => {
                        println!("{} The current configuration parameters cannot be evaluated. \
                                  Skip!",
                                 Green.paint("[TUNER]"));
                        state
                    }
                };

                accepted_state
            };

            temperature = match self.cooling_schedule {
                CoolingSchedule::linear => cooler.linear_cooling(elapsed_steps),
                CoolingSchedule::exponential => cooler.exponential_cooling(elapsed_steps),
                CoolingSchedule::adaptive => cooler.adaptive_cooling(),
            };
        }

        state
    }

    fn solve_time_based<P>(&self, problem: &mut P, max_time: u64, cooler: TimeCooler) -> P::State
        where P: Problem
    {
        let mut rng = thread_rng();
        let range = Range::new(0.0, 1.0);

        let mut state = problem.initial_state();

        return state;
    }

    /**
     * Automatic Evaluation of Tmin and Tmax based on certain number
     * of algorithm executions
     */
    pub fn auto_param_evaluation(&self) {}
}

impl Default for Solver {
    fn default() -> Solver {
        Solver {
            termination_criteria: TerminationCriteria::Max_Steps(10000),
            min_temperature: 2.5,
            max_temperature: 1000.0,
            cooling_schedule: CoolingSchedule::exponential,
            energy_type: EnergyType::throughput,
        }
    }
}
<commit_msg>more info 2 print<commit_after>/// ///////////////////////////////////////////////////////////////////////////
///  File: neil/solver.rs
/// ///////////////////////////////////////////////////////////////////////////
///  Copyright 2016 Samuel Sleight
///
///  Licensed under the Apache License, Version 2.0 (the "License");
///  you may not use this file except in compliance with the License.
///  You may obtain a copy of the License at
///
///      http://www.apache.org/licenses/LICENSE-2.0
///
///  Unless required by applicable law or agreed to in writing, software
///  distributed under the License is distributed on an "AS IS" BASIS,
///  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
///  See the License for the specific language governing permissions and
///  limitations under the License.
/// ///////////////////////////////////////////////////////////////////////////

use time;
use CoolingSchedule;
use EnergyType;
use TerminationCriteria;
use rand::thread_rng;
use rand::distributions::{Range, IndependentSample};
use ansi_term::Colour::Green;
use super::Problem::Problem;
use super::Updater::{Updater,UpdateFile};
use super::Cooler::{Cooler, StepsCooler, TimeCooler};
use std::fs::{File,OpenOptions};

/**
 * A solver will take a problem and use simulated annealing
 * to try and find an optimal state.
 */
#[derive(Debug, Clone)]
pub struct Solver {
    /**
     * The termination criteria (maximum time or maximum number of steps)
     */
    pub termination_criteria: TerminationCriteria,

    /**
     * The minimum temperature of the process.
     */
    pub min_temperature: f64,

    /**
     * The maximum temperature of the process.
     */
    pub max_temperature: f64,

    /**
     * The Cooling Schedule procedure to select
     */
    pub cooling_schedule: CoolingSchedule,

    /**
     * The Energy metric to evaluate (Throughput or Latency)
     */
    pub energy_type: EnergyType,
}

impl Solver {
    /**
     * Construct the new default solver.
     */
    pub fn new() -> Solver {
        Default::default()
    }

    /**
     * Construct a new solver with a given builder function.
     */
    pub fn build_new<F>(builder: F) -> Solver
        where F: FnOnce(&mut Solver)
    {
        let mut solver = Solver::new();
        builder(&mut solver);
        solver
    }

    /**
     * Run the solver for a maximization problem
     */
    pub fn solve<P>(&self, problem: &mut P) -> P::State
        where P: Problem
    {
        let best_configuration = match self.termination_criteria {
            TerminationCriteria::Max_Steps(value) => {
                self.solve_step_based(problem,
                                      value,
                                      StepsCooler {
                                          max_steps: value,
                                          min_temp: self.min_temperature,
                                          max_temp: self.max_temperature,
                                      })
            }
            TerminationCriteria::Max_Time_Seconds(value) => {
                self.solve_time_based(problem,
                                      value,
                                      TimeCooler {
                                          max_time: value,
                                          min_temp: self.min_temperature,
                                          max_temp: self.max_temperature,
                                      })
            }
        };

        return best_configuration;
    }

    fn solve_step_based<P>(&self, problem: &mut P, max_steps: u64, cooler: StepsCooler) -> P::State
        where P: Problem
    {
    	//let mut updater=UpdateFile::new();

        let mut rng = thread_rng();
        let range = Range::new(0.0, 1.0);

        println!("{}",Green.paint("\n-------------------------------------------------------------------------------------------------------------------"));
        println!("{} Initialization Phase: Evaluation of Energy for Default Paramters",
                 Green.paint("[TUNER]"));
        println!("{}",Green.paint("-------------------------------------------------------------------------------------------------------------------"));

        let mut start_time = time::precise_time_ns();

        let mut state = problem.initial_state();
        let mut energy = match problem.energy(&state, self.energy_type.clone()) {
            Some(nrg) => nrg,
            None => panic!("The initial configuration does not allow to calculate the energy"),
        };

        let mut elapsed_time = (time::precise_time_ns() - start_time) as f64 / 1000000000.0f64;
        let estimated_time_2_complete=((elapsed_time as f64)*max_steps as f64)/3600.0;

        let mut temperature: f64 = self.max_temperature;
        let mut attempted = 0;
        let mut accepted = 0;
        let mut rejected = 0;
        let mut total_improves = 0;
        let mut subsequent_improves = 0;

        start_time = time::precise_time_ns();

        for elapsed_steps in 0..max_steps {

            elapsed_time = (time::precise_time_ns() - start_time) as f64 / 1000000000.0f64;

            println!("{}",Green.paint("-------------------------------------------------------------------------------------------------------------------"));
            println!("{} Completed Steps: {:.2} - Percentage of Completion: {:.2}% - Estimated time to Complete: {:.2} Hrs",
                     Green.paint("[TUNER]"), elapsed_steps,
                     (elapsed_steps as f64 / cooler.max_steps as f64) * 100.0,
                      estimated_time_2_complete as usize);
            println!("{} Total Accepted Solutions: {:?} - Current Temperature: {:.2} - Elapsed Time: {:.2} s",
                     Green.paint("[TUNER]"),
                     accepted,
                     temperature,
                     elapsed_time);
           /* println!("{} Accepted State: {:?}",
                     Green.paint("[TUNER]"),
                     state);*/
            println!("{} Accepted Energy: {:.4}",
                     Green.paint("[TUNER]"),
                     energy);
            println!("{}",Green.paint("-------------------------------------------------------------------------------------------------------------------"));

            state = {
                let next_state = match problem.new_state(&state, max_steps, elapsed_steps) {
                    // There is a neighborhood available
                    Some(n_s) => n_s,
                    // No neighborhood available, all states have been visited
                    None => {
                        println!("{} Any Neighborhood Available - Terminate the Annealing",
                                 Green.paint("[TUNER]"));
                        break;
                    }
                };

                let accepted_state = match problem.energy(&next_state, self.clone().energy_type) {
                    Some(new_energy) => {
                        let de = new_energy - energy;
                        if de > 0.0 || range.ind_sample(&mut rng) <= (-de / temperature).exp() {
                            accepted += 1;
                            energy = new_energy;

                            if de > 0.0 {
                                total_improves = total_improves + 1;
                                subsequent_improves = subsequent_improves + 1;
                            }

                            //updater.send_update(new_energy, next_state, energy, next_state, elapsed_steps);
                            next_state

                        } else {
                            subsequent_improves = 0;
                            //updater.send_update(new_energy, next_state, energy, state, elapsed_steps);
                            state
                        }

                    }
                    None => {
                        println!("{} The current configuration parameters cannot be evaluated. \
                                  Skip!",
                                 Green.paint("[TUNER]"));
                        state
                    }
                };

                accepted_state
            };

            temperature = match self.cooling_schedule {
                CoolingSchedule::linear => cooler.linear_cooling(elapsed_steps),
                CoolingSchedule::exponential => cooler.exponential_cooling(elapsed_steps),
                CoolingSchedule::adaptive => cooler.adaptive_cooling(),
            };
        }

        state
    }

    fn solve_time_based<P>(&self, problem: &mut P, max_time: u64, cooler: TimeCooler) -> P::State
        where P: Problem
    {
        let mut rng = thread_rng();
        let range = Range::new(0.0, 1.0);

        let mut state = problem.initial_state();

        return state;
    }

    /**
     * Automatic Evaluation of Tmin and Tmax based on certain number
     * of algorithm executions
     */
    pub fn auto_param_evaluation(&self) {}
}

impl Default for Solver {
    fn default() -> Solver {
        Solver {
            termination_criteria: TerminationCriteria::Max_Steps(10000),
            min_temperature: 2.5,
            max_temperature: 1000.0,
            cooling_schedule: CoolingSchedule::exponential,
            energy_type: EnergyType::throughput,
        }
    }
}
<|endoftext|>


<commit_before>//! Simple timely_communication logging

extern crate time;
#[macro_use] extern crate abomonation;
#[macro_use] extern crate abomonation_derive;

use abomonation::Abomonation;

use std::rc::Rc;
use std::cell::RefCell;

pub struct StructMapWriter;

static mut PRECISE_TIME_NS_DELTA: Option<i64> = None;

/// Returns the value of an high resolution performance counter, in nanoseconds, rebased to be
/// roughly comparable to an unix timestamp.
/// Useful for comparing and merging logs from different machines (precision is limited by the
/// precision of the wall clock base; clock skew effects should be taken into consideration).
#[inline(always)]
pub fn get_precise_time_ns() -> u64 {
    let delta = unsafe {
        *PRECISE_TIME_NS_DELTA.get_or_insert_with(|| {
            let wall_time = time::get_time();
            let wall_time_ns = wall_time.nsec as i64 + wall_time.sec * 1000000000;
            time::precise_time_ns() as i64 - wall_time_ns
        })
    };
    (time::precise_time_ns() as i64 - delta) as u64
}

/// Logging methods
pub trait Logger {
    /// The type of loggable record.
    type Record;
    /// Adds `record` to the log.
    fn log(&self, record: Self::Record);
}

#[derive(Debug, Clone)]
pub struct CommunicationEvent {
    /// true for send event, false for receive event
    pub is_send: bool,
    /// communication channel id
    pub comm_channel: usize,
    /// source worker id
    pub source: usize,
    /// target worker id
    pub target: usize,
    /// sequence number
    pub seqno: usize,
}

unsafe_abomonate!(CommunicationEvent : is_send, comm_channel, source, target, seqno);

#[derive(Debug, Clone)]
/// Serialization
pub struct SerializationEvent {
    pub seq_no: Option<usize>,
    pub is_start: bool,
}

unsafe_abomonate!(SerializationEvent : seq_no, is_start);

#[derive(Debug, Clone)]
/// The creation of an `Operate` implementor.
pub struct OperatesEvent {
    /// Worker-unique identifier for the operator.
    pub id: usize,
    /// Sequence of nested scope identifiers indicating the path from the root to this instance.
    pub addr: Vec<usize>,
    /// A helpful name.
    pub name: String,
}

unsafe_abomonate!(OperatesEvent : id, addr, name);

#[derive(Debug, Clone)]
/// The creation of a channel between operators.
pub struct ChannelsEvent {
    /// Worker-unique identifier for the channel
    pub id: usize,
    /// Sequence of nested scope identifiers indicating the path from the root to this instance.
    pub scope_addr: Vec<usize>,
    /// Source descriptor, indicating operator index and output port.
    pub source: (usize, usize),
    /// Target descriptor, indicating operator index and input port.
    pub target: (usize, usize),
}

unsafe_abomonate!(ChannelsEvent : id, scope_addr, source, target);

#[derive(Debug, Clone)]
/// Send or receive of progress information.
pub struct ProgressEvent {
    /// `true` if the event is a send, and `false` if it is a receive.
    pub is_send: bool,
    /// Source worker index.
    pub source: usize,
    /// Communication channel identifier
    pub comm_channel: Option<usize>,
    /// Message sequence number.
    pub seq_no: usize,
    /// Sequence of nested scope identifiers indicating the path from the root to this instance.
    pub addr: Vec<usize>,
    /// List of message updates, containing Target descriptor, timestamp as string, and delta.
    pub messages: Vec<(usize, usize, String, i64)>,
    /// List of capability updates, containing Source descriptor, timestamp as string, and delta.
    pub internal: Vec<(usize, usize, String, i64)>,
}

unsafe_abomonate!(ProgressEvent : is_send, source, comm_channel, seq_no, addr, messages, internal);

#[derive(Debug, Clone)]
/// External progress pushed onto an operator
pub struct PushProgressEvent {
    /// Worker-unique operator identifier
    pub op_id: usize,
}

unsafe_abomonate!(PushProgressEvent : op_id);

#[derive(Debug, Clone)]
/// Message send or receive event
pub struct MessagesEvent {
    /// `true` if send event, `false` if receive event.
    pub is_send: bool,
    /// Channel identifier
    pub channel: usize,
    /// Communication channel identifier
    pub comm_channel: Option<usize>,
    /// Source worker index.
    pub source: usize,
    /// Target worker index.
    pub target: usize,
    /// Message sequence number.
    pub seq_no: usize,
    /// Number of typed records in the message.
    pub length: usize,
}

unsafe_abomonate!(MessagesEvent : is_send, channel, comm_channel, source, target, seq_no, length);

/// Records the starting and stopping of an operator.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum StartStop {
    /// Operator starts.
    Start,
    /// Operator stops; did it have any activity?
    Stop {
        /// Did the operator perform non-trivial work.
        activity: bool
    },
}

unsafe_abomonate!(StartStop);

#[derive(Debug, Clone)]
/// Operator start or stop.
pub struct ScheduleEvent {
    /// Worker-unique identifier for the operator, linkable to the identifiers in `OperatesEvent`.
    pub id: usize,
    /// `Start` if the operator is starting, `Stop` if it is stopping.
    /// activiy is true if it looks like some useful work was performed during this call (data was
    /// read or written, notifications were requested / delivered)
    pub start_stop: StartStop,
}

unsafe_abomonate!(ScheduleEvent : id, start_stop);

#[derive(Debug, Clone)]
/// Application-defined code startor stop
pub struct ApplicationEvent {
    /// Unique event type identifier
    pub id: usize,
    /// True when activity begins, false when it stops
    pub is_start: bool,
}

unsafe_abomonate!(ApplicationEvent : id, is_start);

#[derive(Debug, Clone)]
/// Application-defined code startor stop
pub struct GuardedMessageEvent {
    /// True when activity begins, false when it stops
    pub is_start: bool,
}

unsafe_abomonate!(GuardedMessageEvent : is_start);

#[derive(Debug, Clone)]
/// Application-defined code startor stop
pub struct GuardedProgressEvent {
    /// True when activity begins, false when it stops
    pub is_start: bool,
}

unsafe_abomonate!(GuardedProgressEvent : is_start);

#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub struct EventsSetup {
    pub index: usize,
}

unsafe_abomonate!(EventsSetup : index);

#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub struct CommsSetup {
    pub sender: bool,
    pub process: usize,
    pub remote: Option<usize>,
}

unsafe_abomonate!(CommsSetup : sender, process, remote);

#[derive(Debug, Clone)]
pub enum CommChannelKind {
    Progress,
    Data,
}

unsafe_abomonate!(CommChannelKind);

#[derive(Debug, Clone)]
pub struct CommChannelsEvent {
    pub comm_channel: Option<usize>,
    pub comm_channel_kind: CommChannelKind,
}

unsafe_abomonate!(CommChannelsEvent : comm_channel, comm_channel_kind);

#[derive(Debug, Clone)]
pub struct InputEvent {
    pub start_stop: StartStop,
}

unsafe_abomonate!(InputEvent : start_stop);

#[derive(Debug, Clone, Abomonation)]
pub enum Event {
    /*  0 */ Operates(OperatesEvent),
    /*  1 */ Channels(ChannelsEvent),
    /*  2 */ Progress(ProgressEvent),
    /*  3 */ PushProgress(PushProgressEvent),
    /*  4 */ Messages(MessagesEvent),
    /*  5 */ Schedule(ScheduleEvent),
    /*  6 */ Application(ApplicationEvent),
    /*  7 */ GuardedMessage(GuardedMessageEvent),
    /*  8 */ GuardedProgress(GuardedProgressEvent),
    /*  9 */ CommChannels(CommChannelsEvent),
    /* 10 */ Input(InputEvent),
}

#[derive(Debug, Clone, Abomonation)]
pub enum CommsEvent {
    /*  0 */ Communication(CommunicationEvent),
    /*  1 */ Serialization(SerializationEvent),
}

impl From<CommunicationEvent> for CommsEvent {
    fn from(v: CommunicationEvent) -> CommsEvent { CommsEvent::Communication(v) }
}

impl From<SerializationEvent> for CommsEvent {
    fn from(v: SerializationEvent) -> CommsEvent { CommsEvent::Serialization(v) }
}

impl From<OperatesEvent> for Event {
    fn from(v: OperatesEvent) -> Event { Event::Operates(v) }
}

impl From<ChannelsEvent> for Event {
    fn from(v: ChannelsEvent) -> Event { Event::Channels(v) }
}

impl From<ProgressEvent> for Event {
    fn from(v: ProgressEvent) -> Event { Event::Progress(v) }
}

impl From<PushProgressEvent> for Event {
    fn from(v: PushProgressEvent) -> Event { Event::PushProgress(v) }
}

impl From<MessagesEvent> for Event {
    fn from(v: MessagesEvent) -> Event { Event::Messages(v) }
}

impl From<ScheduleEvent> for Event {
    fn from(v: ScheduleEvent) -> Event { Event::Schedule(v) }
}

impl From<ApplicationEvent> for Event {
    fn from(v: ApplicationEvent) -> Event { Event::Application(v) }
}

impl From<GuardedMessageEvent> for Event {
    fn from(v: GuardedMessageEvent) -> Event { Event::GuardedMessage(v) }
}

impl From<GuardedProgressEvent> for Event {
    fn from(v: GuardedProgressEvent) -> Event { Event::GuardedProgress(v) }
}

impl From<CommChannelsEvent> for Event {
    fn from(v: CommChannelsEvent) -> Event { Event::CommChannels(v) }
}

impl From<InputEvent> for Event {
    fn from(v: InputEvent) -> Event { Event::Input(v) }
}

const BUFFERING_LOGGER_CAPACITY: usize = 1024;

pub enum LoggerBatch<'a, S: Clone+'a, L: Clone+'a> {
    Logs(&'a Vec<(u64, S, L)>),
    End,
}

enum BufferingLoggerInternal<S: Clone, L: Clone> {
    Active {
        setup: S,
        buffer: RefCell<Vec<(u64, S, L)>>,
        pushers: RefCell<Box<Fn(LoggerBatch<S, L>)->()>>,
    },
    Inactive
}

pub struct BufferingLogger<S: Clone, L: Clone> {
    internal: BufferingLoggerInternal<S, L>,
}

impl<S: Clone, L: Clone> BufferingLogger<S, L> {
    pub fn new(setup: S, pushers: Box<Fn(LoggerBatch<S, L>)->()>) -> Self {
        BufferingLogger {
            internal: BufferingLoggerInternal::Active {
                setup: setup,
                buffer: RefCell::new(Vec::with_capacity(BUFFERING_LOGGER_CAPACITY)),
                pushers: RefCell::new(pushers),
            },
        }
    }

    pub fn new_inactive() -> Rc<BufferingLogger<EventsSetup, Event>> {
        Rc::new(BufferingLogger {
            internal: BufferingLoggerInternal::Inactive,
        })
    }

    pub fn log(&self, l: L) {
        match self.internal {
            BufferingLoggerInternal::Active { ref setup, ref buffer, ref pushers } => {
                let ts = get_precise_time_ns();
                let mut buf = buffer.borrow_mut();
                buf.push((ts, setup.clone(), l));
                if buf.len() >= BUFFERING_LOGGER_CAPACITY {
                    (*pushers.borrow_mut())(LoggerBatch::Logs(&buf));
                    buf.clear();
                }
            },
            BufferingLoggerInternal::Inactive => {},
        }
    }
}

impl<S: Clone, L: Clone> Drop for BufferingLogger<S, L> {
    fn drop(&mut self) {
        match self.internal {
            BufferingLoggerInternal::Active { ref buffer, ref pushers, .. } => {
                let mut buf = buffer.borrow_mut();
                if buf.len() > 0 {
                    (*pushers.borrow_mut())(LoggerBatch::Logs(&buf));
                }
                (*pushers.borrow_mut())(LoggerBatch::End);
            },
            BufferingLoggerInternal::Inactive => {},
        }
    }
}
<commit_msg>logging: Derive Abomonation<commit_after>//! Simple timely logging

extern crate time;
extern crate abomonation;
#[macro_use] extern crate abomonation_derive;

use std::rc::Rc;
use std::cell::RefCell;

static mut PRECISE_TIME_NS_DELTA: Option<i64> = None;

/// Returns the value of an high resolution performance counter, in nanoseconds, rebased to be
/// roughly comparable to an unix timestamp.
/// Useful for comparing and merging logs from different machines (precision is limited by the
/// precision of the wall clock base; clock skew effects should be taken into consideration).
#[inline(always)]
pub fn get_precise_time_ns() -> u64 {
    let delta = unsafe {
        *PRECISE_TIME_NS_DELTA.get_or_insert_with(|| {
            let wall_time = time::get_time();
            let wall_time_ns = wall_time.nsec as i64 + wall_time.sec * 1000000000;
            time::precise_time_ns() as i64 - wall_time_ns
        })
    };
    (time::precise_time_ns() as i64 - delta) as u64
}

/// Logging methods
pub trait Logger {
    /// The type of loggable record.
    type Record;
    /// Adds `record` to the log.
    fn log(&self, record: Self::Record);
}

#[derive(Abomonation, Debug, Clone)]
pub struct CommunicationEvent {
    /// true for send event, false for receive event
    pub is_send: bool,
    /// communication channel id
    pub comm_channel: usize,
    /// source worker id
    pub source: usize,
    /// target worker id
    pub target: usize,
    /// sequence number
    pub seqno: usize,
}

#[derive(Abomonation, Debug, Clone)]
/// Serialization
pub struct SerializationEvent {
    pub seq_no: Option<usize>,
    pub is_start: bool,
}

#[derive(Abomonation, Debug, Clone)]
/// The creation of an `Operate` implementor.
pub struct OperatesEvent {
    /// Worker-unique identifier for the operator.
    pub id: usize,
    /// Sequence of nested scope identifiers indicating the path from the root to this instance.
    pub addr: Vec<usize>,
    /// A helpful name.
    pub name: String,
}

#[derive(Abomonation, Debug, Clone)]
/// The creation of a channel between operators.
pub struct ChannelsEvent {
    /// Worker-unique identifier for the channel
    pub id: usize,
    /// Sequence of nested scope identifiers indicating the path from the root to this instance.
    pub scope_addr: Vec<usize>,
    /// Source descriptor, indicating operator index and output port.
    pub source: (usize, usize),
    /// Target descriptor, indicating operator index and input port.
    pub target: (usize, usize),
}

#[derive(Abomonation, Debug, Clone)]
/// Send or receive of progress information.
pub struct ProgressEvent {
    /// `true` if the event is a send, and `false` if it is a receive.
    pub is_send: bool,
    /// Source worker index.
    pub source: usize,
    /// Communication channel identifier
    pub comm_channel: Option<usize>,
    /// Message sequence number.
    pub seq_no: usize,
    /// Sequence of nested scope identifiers indicating the path from the root to this instance.
    pub addr: Vec<usize>,
    /// List of message updates, containing Target descriptor, timestamp as string, and delta.
    pub messages: Vec<(usize, usize, String, i64)>,
    /// List of capability updates, containing Source descriptor, timestamp as string, and delta.
    pub internal: Vec<(usize, usize, String, i64)>,
}

#[derive(Abomonation, Debug, Clone)]
/// External progress pushed onto an operator
pub struct PushProgressEvent {
    /// Worker-unique operator identifier
    pub op_id: usize,
}

#[derive(Abomonation, Debug, Clone)]
/// Message send or receive event
pub struct MessagesEvent {
    /// `true` if send event, `false` if receive event.
    pub is_send: bool,
    /// Channel identifier
    pub channel: usize,
    /// Communication channel identifier
    pub comm_channel: Option<usize>,
    /// Source worker index.
    pub source: usize,
    /// Target worker index.
    pub target: usize,
    /// Message sequence number.
    pub seq_no: usize,
    /// Number of typed records in the message.
    pub length: usize,
}

/// Records the starting and stopping of an operator.
#[derive(Abomonation, Debug, Clone, PartialEq, Eq)]
pub enum StartStop {
    /// Operator starts.
    Start,
    /// Operator stops; did it have any activity?
    Stop {
        /// Did the operator perform non-trivial work.
        activity: bool
    },
}

#[derive(Abomonation, Debug, Clone)]
/// Operator start or stop.
pub struct ScheduleEvent {
    /// Worker-unique identifier for the operator, linkable to the identifiers in `OperatesEvent`.
    pub id: usize,
    /// `Start` if the operator is starting, `Stop` if it is stopping.
    /// activity is true if it looks like some useful work was performed during this call (data was
    /// read or written, notifications were requested / delivered)
    pub start_stop: StartStop,
}

#[derive(Abomonation, Debug, Clone)]
/// Application-defined code startor stop
pub struct ApplicationEvent {
    /// Unique event type identifier
    pub id: usize,
    /// True when activity begins, false when it stops
    pub is_start: bool,
}

#[derive(Abomonation, Debug, Clone)]
/// Application-defined code start or stop
pub struct GuardedMessageEvent {
    /// True when activity begins, false when it stops
    pub is_start: bool,
}

#[derive(Abomonation, Debug, Clone)]
/// Application-defined code start or stop
pub struct GuardedProgressEvent {
    /// True when activity begins, false when it stops
    pub is_start: bool,
}

#[derive(Abomonation, Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub struct EventsSetup {
    pub index: usize,
}

#[derive(Abomonation, Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub struct CommsSetup {
    pub sender: bool,
    pub process: usize,
    pub remote: Option<usize>,
}

#[derive(Abomonation, Debug, Clone)]
pub enum CommChannelKind {
    Progress,
    Data,
}

#[derive(Abomonation, Debug, Clone)]
pub struct CommChannelsEvent {
    pub comm_channel: Option<usize>,
    pub comm_channel_kind: CommChannelKind,
}

#[derive(Abomonation, Debug, Clone)]
pub struct InputEvent {
    pub start_stop: StartStop,
}

#[derive(Debug, Clone, Abomonation)]
pub enum Event {
    /*  0 */ Operates(OperatesEvent),
    /*  1 */ Channels(ChannelsEvent),
    /*  2 */ Progress(ProgressEvent),
    /*  3 */ PushProgress(PushProgressEvent),
    /*  4 */ Messages(MessagesEvent),
    /*  5 */ Schedule(ScheduleEvent),
    /*  6 */ Application(ApplicationEvent),
    /*  7 */ GuardedMessage(GuardedMessageEvent),
    /*  8 */ GuardedProgress(GuardedProgressEvent),
    /*  9 */ CommChannels(CommChannelsEvent),
    /* 10 */ Input(InputEvent),
}

#[derive(Debug, Clone, Abomonation)]
pub enum CommsEvent {
    /*  0 */ Communication(CommunicationEvent),
    /*  1 */ Serialization(SerializationEvent),
}

impl From<CommunicationEvent> for CommsEvent {
    fn from(v: CommunicationEvent) -> CommsEvent { CommsEvent::Communication(v) }
}

impl From<SerializationEvent> for CommsEvent {
    fn from(v: SerializationEvent) -> CommsEvent { CommsEvent::Serialization(v) }
}

impl From<OperatesEvent> for Event {
    fn from(v: OperatesEvent) -> Event { Event::Operates(v) }
}

impl From<ChannelsEvent> for Event {
    fn from(v: ChannelsEvent) -> Event { Event::Channels(v) }
}

impl From<ProgressEvent> for Event {
    fn from(v: ProgressEvent) -> Event { Event::Progress(v) }
}

impl From<PushProgressEvent> for Event {
    fn from(v: PushProgressEvent) -> Event { Event::PushProgress(v) }
}

impl From<MessagesEvent> for Event {
    fn from(v: MessagesEvent) -> Event { Event::Messages(v) }
}

impl From<ScheduleEvent> for Event {
    fn from(v: ScheduleEvent) -> Event { Event::Schedule(v) }
}

impl From<ApplicationEvent> for Event {
    fn from(v: ApplicationEvent) -> Event { Event::Application(v) }
}

impl From<GuardedMessageEvent> for Event {
    fn from(v: GuardedMessageEvent) -> Event { Event::GuardedMessage(v) }
}

impl From<GuardedProgressEvent> for Event {
    fn from(v: GuardedProgressEvent) -> Event { Event::GuardedProgress(v) }
}

impl From<CommChannelsEvent> for Event {
    fn from(v: CommChannelsEvent) -> Event { Event::CommChannels(v) }
}

impl From<InputEvent> for Event {
    fn from(v: InputEvent) -> Event { Event::Input(v) }
}

const BUFFERING_LOGGER_CAPACITY: usize = 1024;

pub enum LoggerBatch<'a, S: Clone+'a, L: Clone+'a> {
    Logs(&'a Vec<(u64, S, L)>),
    End,
}

enum BufferingLoggerInternal<S: Clone, L: Clone> {
    Active {
        setup: S,
        buffer: RefCell<Vec<(u64, S, L)>>,
        pushers: RefCell<Box<Fn(LoggerBatch<S, L>)->()>>,
    },
    Inactive
}

pub struct BufferingLogger<S: Clone, L: Clone> {
    internal: BufferingLoggerInternal<S, L>,
}

impl<S: Clone, L: Clone> BufferingLogger<S, L> {
    pub fn new(setup: S, pushers: Box<Fn(LoggerBatch<S, L>)->()>) -> Self {
        BufferingLogger {
            internal: BufferingLoggerInternal::Active {
                setup: setup,
                buffer: RefCell::new(Vec::with_capacity(BUFFERING_LOGGER_CAPACITY)),
                pushers: RefCell::new(pushers),
            },
        }
    }

    pub fn new_inactive() -> Rc<BufferingLogger<EventsSetup, Event>> {
        Rc::new(BufferingLogger {
            internal: BufferingLoggerInternal::Inactive,
        })
    }

    pub fn log(&self, l: L) {
        match self.internal {
            BufferingLoggerInternal::Active { ref setup, ref buffer, ref pushers } => {
                let ts = get_precise_time_ns();
                let mut buf = buffer.borrow_mut();
                buf.push((ts, setup.clone(), l));
                if buf.len() >= BUFFERING_LOGGER_CAPACITY {
                    (*pushers.borrow_mut())(LoggerBatch::Logs(&buf));
                    buf.clear();
                }
            },
            BufferingLoggerInternal::Inactive => {},
        }
    }
}

impl<S: Clone, L: Clone> Drop for BufferingLogger<S, L> {
    fn drop(&mut self) {
        match self.internal {
            BufferingLoggerInternal::Active { ref buffer, ref pushers, .. } => {
                let mut buf = buffer.borrow_mut();
                if buf.len() > 0 {
                    (*pushers.borrow_mut())(LoggerBatch::Logs(&buf));
                }
                (*pushers.borrow_mut())(LoggerBatch::End);
            },
            BufferingLoggerInternal::Inactive => {},
        }
    }
}
<|endoftext|>


<commit_before>use cgmath::{Matrix2, Point2, Vector2};
use cgmath::Angle;
use cgmath::Deg;
use gfx;
use gfx::Resources;
use gfx::traits::FactoryExt;

use crate::graphics::texture::Texture;
use crate::shaders::VertexData;

const DEFAULT_INDEX_DATA: &[u16] = &[0, 1, 2, 2, 3, 0];

#[derive(Clone)]
pub struct PlainMesh<R> where R: Resources {
  pub slice: gfx::Slice<R>,
  pub vertex_buffer: gfx::handle::Buffer<R, VertexData>,
}

impl<R> PlainMesh<R> where R: gfx::Resources {
  pub fn new<F>(factory: &mut F, vertices: &[VertexData], indices: &[u16]) -> PlainMesh<R> where F: gfx::Factory<R> {
    let (vertex_buffer, slice) = factory.create_vertex_buffer_with_slice(vertices, indices);
    PlainMesh {
      slice,
      vertex_buffer,
    }
  }

  pub fn new_with_data<F>(factory: &mut F, size: Point2<f32>, rotation: Option<f32>) -> PlainMesh<R> where F: gfx::Factory<R> {
    let w = size.x;
    let h = size.y;
    let rot = rotation.unwrap_or(0.0);

    let vertex_data: Vec<VertexData> = vec![
      VertexData::new([-w, -h], [0.0, 1.0]),
      VertexData::new([w, -h], [1.0, 1.0]),
      VertexData::new([w, h], [1.0, 0.0]),
      VertexData::new([-w, h], [0.0, 0.0]),
    ].iter()
      .map(|el| {
        let cos = Angle::cos(Deg(rot));
        let sin = Angle::sin(Deg(rot));
        let rotated =
          Matrix2::<f32>::new(cos, -sin, sin, cos) * Vector2::<f32>::new(el.pos[0] as f32, el.pos[1] as f32);
        VertexData { pos: [rotated.x, rotated.y], uv: el.uv }
      })
      .collect();

    let (vertex_buffer, slice) = factory.create_vertex_buffer_with_slice(&vertex_data[..], DEFAULT_INDEX_DATA);
    PlainMesh {
      slice,
      vertex_buffer,
    }
  }
}

#[derive(Clone)]
pub struct Mesh<R> where R: Resources {
  pub slice: gfx::Slice<R>,
  pub vertex_buffer: gfx::handle::Buffer<R, VertexData>,
  pub texture: Texture<R>,
}

#[derive(Clone)]
pub struct RectangularMesh<R> where R: Resources {
  pub mesh: Mesh<R>,
  pub size: Point2<f32>,
}

impl<R> RectangularMesh<R> where R: gfx::Resources {
  pub fn new<F>(factory: &mut F, texture: Texture<R>, size: Point2<f32>) -> RectangularMesh<R> where F: gfx::Factory<R> {
    let w = size.x;
    let h = size.y;
    let vertex_data: &[VertexData; 4] = &[
      VertexData::new([-w, -h], [0.0, 1.0]),
      VertexData::new([w, -h], [1.0, 1.0]),
      VertexData::new([w, h], [1.0, 0.0]),
      VertexData::new([-w, h], [0.0, 0.0]),
    ];
    let mesh = Mesh::new(factory, vertex_data, &DEFAULT_INDEX_DATA, texture);
    RectangularMesh {
      mesh,
      size,
    }
  }
}

impl<R> Mesh<R> where R: gfx::Resources {
  pub fn new<F>(factory: &mut F, vertices: &[VertexData], indices: &[u16], texture: Texture<R>) -> Mesh<R> where F: gfx::Factory<R> {
    let mesh = PlainMesh::new(factory, vertices, indices);
    Mesh {
      slice: mesh.slice,
      vertex_buffer: mesh.vertex_buffer,
      texture,
    }
  }
}
<commit_msg>Extract rectangle mesh to new function<commit_after>use cgmath::{Matrix2, Point2, Vector2};
use cgmath::Angle;
use cgmath::Deg;
use gfx;
use gfx::Resources;
use gfx::traits::FactoryExt;

use crate::graphics::texture::Texture;
use crate::shaders::VertexData;

const DEFAULT_INDEX_DATA: &[u16] = &[0, 1, 2, 2, 3, 0];

fn rectangle_mesh(w: f32, h: f32) -> [VertexData; 4] {
  [
    VertexData::new([-w, -h], [0.0, 1.0]),
    VertexData::new([w, -h], [1.0, 1.0]),
    VertexData::new([w, h], [1.0, 0.0]),
    VertexData::new([-w, h], [0.0, 0.0]),
  ]
}

#[derive(Clone)]
pub struct PlainMesh<R> where R: Resources {
  pub slice: gfx::Slice<R>,
  pub vertex_buffer: gfx::handle::Buffer<R, VertexData>,
}

impl<R> PlainMesh<R> where R: gfx::Resources {
  pub fn new<F>(factory: &mut F, vertices: &[VertexData], indices: &[u16]) -> PlainMesh<R> where F: gfx::Factory<R> {
    let (vertex_buffer, slice) = factory.create_vertex_buffer_with_slice(vertices, indices);
    PlainMesh {
      slice,
      vertex_buffer,
    }
  }

  pub fn new_with_data<F>(factory: &mut F, size: Point2<f32>, rotation: Option<f32>) -> PlainMesh<R> where F: gfx::Factory<R> {
    let w = size.x;
    let h = size.y;
    let rot = rotation.unwrap_or(0.0);

    let vertex_data = rectangle_mesh(w, h).to_vec().iter()
      .map(|el| {
        let cos = Angle::cos(Deg(rot));
        let sin = Angle::sin(Deg(rot));
        let rotated =
          Matrix2::<f32>::new(cos, -sin, sin, cos) * Vector2::<f32>::new(el.pos[0] as f32, el.pos[1] as f32);
        VertexData { pos: [rotated.x, rotated.y], uv: el.uv }
      })
      .collect::<Vec<VertexData>>();

    let (vertex_buffer, slice) = factory.create_vertex_buffer_with_slice(&vertex_data[..], DEFAULT_INDEX_DATA);
    PlainMesh {
      slice,
      vertex_buffer,
    }
  }
}

#[derive(Clone)]
pub struct Mesh<R> where R: Resources {
  pub slice: gfx::Slice<R>,
  pub vertex_buffer: gfx::handle::Buffer<R, VertexData>,
  pub texture: Texture<R>,
}

#[derive(Clone)]
pub struct RectangularMesh<R> where R: Resources {
  pub mesh: Mesh<R>,
  pub size: Point2<f32>,
}

impl<R> RectangularMesh<R> where R: gfx::Resources {
  pub fn new<F>(factory: &mut F, texture: Texture<R>, size: Point2<f32>) -> RectangularMesh<R> where F: gfx::Factory<R> {
    let w = size.x;
    let h = size.y;

    let mesh = Mesh::new(factory, &rectangle_mesh(w, h), &DEFAULT_INDEX_DATA, texture);
    RectangularMesh {
      mesh,
      size,
    }
  }
}

impl<R> Mesh<R> where R: gfx::Resources {
  pub fn new<F>(factory: &mut F, vertices: &[VertexData], indices: &[u16], texture: Texture<R>) -> Mesh<R> where F: gfx::Factory<R> {
    let mesh = PlainMesh::new(factory, vertices, indices);
    Mesh {
      slice: mesh.slice,
      vertex_buffer: mesh.vertex_buffer,
      texture,
    }
  }
}
<|endoftext|>


<commit_before>// This file is part of the uutils coreutils package.
//
// (c) Jordi Boggiano <j.boggiano@seld.be>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

/* last synced with: env (GNU coreutils) 8.13 */

// spell-checker:ignore (ToDO) chdir execvp progname subcommand subcommands unsets setenv putenv

#[macro_use]
extern crate clap;

#[macro_use]
extern crate uucore;

use clap::{App, AppSettings, Arg};
use ini::Ini;
use std::borrow::Cow;
use std::env;
use std::io::{self, Write};
use std::iter::Iterator;
use std::process::Command;
use uucore::display::Quotable;
use uucore::error::{UResult, USimpleError};

const USAGE: &str = "env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]";
const AFTER_HELP: &str = "\
A mere - implies -i. If no COMMAND, print the resulting environment.
";

struct Options<'a> {
    ignore_env: bool,
    null: bool,
    running_directory: Option<&'a str>,
    files: Vec<&'a str>,
    unsets: Vec<&'a str>,
    sets: Vec<(&'a str, &'a str)>,
    program: Vec<&'a str>,
}

// print name=value env pairs on screen
// if null is true, separate pairs with a \0, \n otherwise
fn print_env(null: bool) {
    let stdout_raw = io::stdout();
    let mut stdout = stdout_raw.lock();
    for (n, v) in env::vars() {
        write!(stdout, "{}={}{}", n, v, if null { '\0' } else { '\n' }).unwrap();
    }
}

fn parse_name_value_opt<'a>(opts: &mut Options<'a>, opt: &'a str) -> Result<bool, i32> {
    // is it a NAME=VALUE like opt ?
    if let Some(idx) = opt.find('=') {
        // yes, so push name, value pair
        let (name, value) = opt.split_at(idx);
        opts.sets.push((name, &value['='.len_utf8()..]));

        Ok(false)
    } else {
        // no, it's a program-like opt
        parse_program_opt(opts, opt).map(|_| true)
    }
}

fn parse_program_opt<'a>(opts: &mut Options<'a>, opt: &'a str) -> Result<(), i32> {
    if opts.null {
        eprintln!(
            "{}: cannot specify --null (-0) with command",
            uucore::util_name()
        );
        eprintln!(
            "Type \"{} --help\" for detailed information",
            uucore::execution_phrase()
        );
        Err(1)
    } else {
        opts.program.push(opt);
        Ok(())
    }
}

fn load_config_file(opts: &mut Options) -> UResult<()> {
    // NOTE: config files are parsed using an INI parser b/c it's available and compatible with ".env"-style files
    //   ... * but support for actual INI files, although working, is not intended, nor claimed
    for &file in &opts.files {
        let conf = if file == "-" {
            let stdin = io::stdin();
            let mut stdin_locked = stdin.lock();
            Ini::read_from(&mut stdin_locked)
        } else {
            Ini::load_from_file(file)
        };

        let conf = conf.map_err(|error| {
            show_error!("{}: {}", file.maybe_quote(), error);
            1
        })?;

        for (_, prop) in &conf {
            // ignore all INI section lines (treat them as comments)
            for (key, value) in prop.iter() {
                env::set_var(key, value);
            }
        }
    }

    Ok(())
}

#[cfg(not(windows))]
fn build_command<'a, 'b>(args: &'a mut Vec<&'b str>) -> (Cow<'b, str>, &'a [&'b str]) {
    let progname = Cow::from(args[0]);
    (progname, &args[1..])
}

#[cfg(windows)]
fn build_command<'a, 'b>(args: &'a mut Vec<&'b str>) -> (Cow<'b, str>, &'a [&'b str]) {
    args.insert(0, "/d/c");
    let progname = env::var("ComSpec")
        .map(Cow::from)
        .unwrap_or_else(|_| Cow::from("cmd"));

    (progname, &args[..])
}

pub fn uu_app() -> App<'static, 'static> {
    App::new(crate_name!())
        .version(crate_version!())
        .author(crate_authors!())
        .about(crate_description!())
        .usage(USAGE)
        .after_help(AFTER_HELP)
        .setting(AppSettings::AllowExternalSubcommands)
        .arg(Arg::with_name("ignore-environment")
            .short("i")
            .long("ignore-environment")
            .help("start with an empty environment"))
        .arg(Arg::with_name("chdir")
            .short("c")
            .long("chdir")
            .takes_value(true)
            .number_of_values(1)
            .value_name("DIR")
            .help("change working directory to DIR"))
        .arg(Arg::with_name("null")
            .short("0")
            .long("null")
            .help("end each output line with a 0 byte rather than a newline (only valid when \
                    printing the environment)"))
        .arg(Arg::with_name("file")
            .short("f")
            .long("file")
            .takes_value(true)
            .number_of_values(1)
            .value_name("PATH")
            .multiple(true)
            .help("read and set variables from a \".env\"-style configuration file (prior to any \
                    unset and/or set)"))
        .arg(Arg::with_name("unset")
            .short("u")
            .long("unset")
            .takes_value(true)
            .number_of_values(1)
            .value_name("NAME")
            .multiple(true)
            .help("remove variable from the environment"))
}

fn run_env(args: impl uucore::Args) -> UResult<()> {
    let app = uu_app();
    let matches = app.get_matches_from(args);

    let ignore_env = matches.is_present("ignore-environment");
    let null = matches.is_present("null");
    let running_directory = matches.value_of("chdir");
    let files = matches
        .values_of("file")
        .map(Iterator::collect)
        .unwrap_or_else(|| Vec::with_capacity(0));
    let unsets = matches
        .values_of("unset")
        .map(Iterator::collect)
        .unwrap_or_else(|| Vec::with_capacity(0));

    let mut opts = Options {
        ignore_env,
        null,
        running_directory,
        files,
        unsets,
        sets: vec![],
        program: vec![],
    };

    // change directory
    if let Some(d) = opts.running_directory {
        match env::set_current_dir(d) {
            Ok(()) => d,
            Err(error) => {
                return Err(USimpleError::new(
                    125,
                    format!("cannot change directory to \"{}\": {}", d, error),
                ));
            }
        };
    }

    // we handle the name, value pairs and the program to be executed by treating them as external
    // subcommands in clap
    if let (external, Some(matches)) = matches.subcommand() {
        let mut begin_prog_opts = false;

        if external == "-" {
            // "-" implies -i and stop parsing opts
            opts.ignore_env = true;
        } else {
            begin_prog_opts = parse_name_value_opt(&mut opts, external)?;
        }

        if let Some(mut iter) = matches.values_of("") {
            // read NAME=VALUE arguments (and up to a single program argument)
            while !begin_prog_opts {
                if let Some(opt) = iter.next() {
                    begin_prog_opts = parse_name_value_opt(&mut opts, opt)?;
                } else {
                    break;
                }
            }

            // read any leftover program arguments
            for opt in iter {
                parse_program_opt(&mut opts, opt)?;
            }
        }
    }

    // NOTE: we manually set and unset the env vars below rather than using Command::env() to more
    //       easily handle the case where no command is given

    // remove all env vars if told to ignore presets
    if opts.ignore_env {
        for (ref name, _) in env::vars() {
            env::remove_var(name);
        }
    }

    // load .env-style config file prior to those given on the command-line
    load_config_file(&mut opts)?;

    // unset specified env vars
    for name in &opts.unsets {
        env::remove_var(name);
    }

    // set specified env vars
    for &(name, val) in &opts.sets {
        /*
         * set_var panics if name is an empty string
         * set_var internally calls setenv (on unix at least), while GNU env calls putenv instead.
         *
         * putenv returns successfully if provided with something like "=a" and modifies the environ
         * variable to contain "=a" inside it, effectively modifying the process' current environment
         * to contain a malformed string in it. Using GNU's implementation, the command `env =a`
         * prints out the malformed string and even invokes the child process with that environment.
         * This can be seen by using `env -i =a env` or `env -i =a cat /proc/self/environ`
         *
         * POSIX.1-2017 doesn't seem to mention what to do if the string is malformed (at least
         * not in "Chapter 8, Environment Variables" or in the definition for environ and various
         * exec*'s or in the description of env in the "Shell & Utilities" volume).
         *
         * It also doesn't specify any checks for putenv before modifying the environ variable, which
         * is likely why glibc doesn't do so. However, setenv's first argument cannot point to
         * an empty string or a string containing '='.
         *
         * There is no benefit in replicating GNU's env behavior, since it will only modify the
         * environment in weird ways
         */

        if name.is_empty() {
            show_warning!("no name specified for value {}", val.quote());
            continue;
        }
        env::set_var(name, val);
    }

    if !opts.program.is_empty() {
        // we need to execute a command
        let (prog, args) = build_command(&mut opts.program);

        // FIXME: this should just use execvp() (no fork()) on Unix-like systems
        match Command::new(&*prog).args(args).status() {
            Ok(exit) if !exit.success() => return Err(exit.code().unwrap().into()),
            Err(ref err) if err.kind() == io::ErrorKind::NotFound => return Err(127.into()),
            Err(_) => return Err(126.into()),
            Ok(_) => (),
        }
    } else {
        // no program provided, so just dump all env vars to stdout
        print_env(opts.null);
    }

    Ok(())
}

#[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
    run_env(args)
}
<commit_msg>env: change comment<commit_after>// This file is part of the uutils coreutils package.
//
// (c) Jordi Boggiano <j.boggiano@seld.be>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

/* last synced with: env (GNU coreutils) 8.13 */

// spell-checker:ignore (ToDO) chdir execvp progname subcommand subcommands unsets setenv putenv posix_spawnp

#[macro_use]
extern crate clap;

#[macro_use]
extern crate uucore;

use clap::{App, AppSettings, Arg};
use ini::Ini;
use std::borrow::Cow;
use std::env;
use std::io::{self, Write};
use std::iter::Iterator;
use std::process::Command;
use uucore::display::Quotable;
use uucore::error::{UResult, USimpleError};

const USAGE: &str = "env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]";
const AFTER_HELP: &str = "\
A mere - implies -i. If no COMMAND, print the resulting environment.
";

struct Options<'a> {
    ignore_env: bool,
    null: bool,
    running_directory: Option<&'a str>,
    files: Vec<&'a str>,
    unsets: Vec<&'a str>,
    sets: Vec<(&'a str, &'a str)>,
    program: Vec<&'a str>,
}

// print name=value env pairs on screen
// if null is true, separate pairs with a \0, \n otherwise
fn print_env(null: bool) {
    let stdout_raw = io::stdout();
    let mut stdout = stdout_raw.lock();
    for (n, v) in env::vars() {
        write!(stdout, "{}={}{}", n, v, if null { '\0' } else { '\n' }).unwrap();
    }
}

fn parse_name_value_opt<'a>(opts: &mut Options<'a>, opt: &'a str) -> Result<bool, i32> {
    // is it a NAME=VALUE like opt ?
    if let Some(idx) = opt.find('=') {
        // yes, so push name, value pair
        let (name, value) = opt.split_at(idx);
        opts.sets.push((name, &value['='.len_utf8()..]));

        Ok(false)
    } else {
        // no, it's a program-like opt
        parse_program_opt(opts, opt).map(|_| true)
    }
}

fn parse_program_opt<'a>(opts: &mut Options<'a>, opt: &'a str) -> Result<(), i32> {
    if opts.null {
        eprintln!(
            "{}: cannot specify --null (-0) with command",
            uucore::util_name()
        );
        eprintln!(
            "Type \"{} --help\" for detailed information",
            uucore::execution_phrase()
        );
        Err(1)
    } else {
        opts.program.push(opt);
        Ok(())
    }
}

fn load_config_file(opts: &mut Options) -> UResult<()> {
    // NOTE: config files are parsed using an INI parser b/c it's available and compatible with ".env"-style files
    //   ... * but support for actual INI files, although working, is not intended, nor claimed
    for &file in &opts.files {
        let conf = if file == "-" {
            let stdin = io::stdin();
            let mut stdin_locked = stdin.lock();
            Ini::read_from(&mut stdin_locked)
        } else {
            Ini::load_from_file(file)
        };

        let conf = conf.map_err(|error| {
            show_error!("{}: {}", file.maybe_quote(), error);
            1
        })?;

        for (_, prop) in &conf {
            // ignore all INI section lines (treat them as comments)
            for (key, value) in prop.iter() {
                env::set_var(key, value);
            }
        }
    }

    Ok(())
}

#[cfg(not(windows))]
fn build_command<'a, 'b>(args: &'a mut Vec<&'b str>) -> (Cow<'b, str>, &'a [&'b str]) {
    let progname = Cow::from(args[0]);
    (progname, &args[1..])
}

#[cfg(windows)]
fn build_command<'a, 'b>(args: &'a mut Vec<&'b str>) -> (Cow<'b, str>, &'a [&'b str]) {
    args.insert(0, "/d/c");
    let progname = env::var("ComSpec")
        .map(Cow::from)
        .unwrap_or_else(|_| Cow::from("cmd"));

    (progname, &args[..])
}

pub fn uu_app() -> App<'static, 'static> {
    App::new(crate_name!())
        .version(crate_version!())
        .author(crate_authors!())
        .about(crate_description!())
        .usage(USAGE)
        .after_help(AFTER_HELP)
        .setting(AppSettings::AllowExternalSubcommands)
        .arg(Arg::with_name("ignore-environment")
            .short("i")
            .long("ignore-environment")
            .help("start with an empty environment"))
        .arg(Arg::with_name("chdir")
            .short("c")
            .long("chdir")
            .takes_value(true)
            .number_of_values(1)
            .value_name("DIR")
            .help("change working directory to DIR"))
        .arg(Arg::with_name("null")
            .short("0")
            .long("null")
            .help("end each output line with a 0 byte rather than a newline (only valid when \
                    printing the environment)"))
        .arg(Arg::with_name("file")
            .short("f")
            .long("file")
            .takes_value(true)
            .number_of_values(1)
            .value_name("PATH")
            .multiple(true)
            .help("read and set variables from a \".env\"-style configuration file (prior to any \
                    unset and/or set)"))
        .arg(Arg::with_name("unset")
            .short("u")
            .long("unset")
            .takes_value(true)
            .number_of_values(1)
            .value_name("NAME")
            .multiple(true)
            .help("remove variable from the environment"))
}

fn run_env(args: impl uucore::Args) -> UResult<()> {
    let app = uu_app();
    let matches = app.get_matches_from(args);

    let ignore_env = matches.is_present("ignore-environment");
    let null = matches.is_present("null");
    let running_directory = matches.value_of("chdir");
    let files = matches
        .values_of("file")
        .map(Iterator::collect)
        .unwrap_or_else(|| Vec::with_capacity(0));
    let unsets = matches
        .values_of("unset")
        .map(Iterator::collect)
        .unwrap_or_else(|| Vec::with_capacity(0));

    let mut opts = Options {
        ignore_env,
        null,
        running_directory,
        files,
        unsets,
        sets: vec![],
        program: vec![],
    };

    // change directory
    if let Some(d) = opts.running_directory {
        match env::set_current_dir(d) {
            Ok(()) => d,
            Err(error) => {
                return Err(USimpleError::new(
                    125,
                    format!("cannot change directory to \"{}\": {}", d, error),
                ));
            }
        };
    }

    // we handle the name, value pairs and the program to be executed by treating them as external
    // subcommands in clap
    if let (external, Some(matches)) = matches.subcommand() {
        let mut begin_prog_opts = false;

        if external == "-" {
            // "-" implies -i and stop parsing opts
            opts.ignore_env = true;
        } else {
            begin_prog_opts = parse_name_value_opt(&mut opts, external)?;
        }

        if let Some(mut iter) = matches.values_of("") {
            // read NAME=VALUE arguments (and up to a single program argument)
            while !begin_prog_opts {
                if let Some(opt) = iter.next() {
                    begin_prog_opts = parse_name_value_opt(&mut opts, opt)?;
                } else {
                    break;
                }
            }

            // read any leftover program arguments
            for opt in iter {
                parse_program_opt(&mut opts, opt)?;
            }
        }
    }

    // NOTE: we manually set and unset the env vars below rather than using Command::env() to more
    //       easily handle the case where no command is given

    // remove all env vars if told to ignore presets
    if opts.ignore_env {
        for (ref name, _) in env::vars() {
            env::remove_var(name);
        }
    }

    // load .env-style config file prior to those given on the command-line
    load_config_file(&mut opts)?;

    // unset specified env vars
    for name in &opts.unsets {
        env::remove_var(name);
    }

    // set specified env vars
    for &(name, val) in &opts.sets {
        /*
         * set_var panics if name is an empty string
         * set_var internally calls setenv (on unix at least), while GNU env calls putenv instead.
         *
         * putenv returns successfully if provided with something like "=a" and modifies the environ
         * variable to contain "=a" inside it, effectively modifying the process' current environment
         * to contain a malformed string in it. Using GNU's implementation, the command `env =a`
         * prints out the malformed string and even invokes the child process with that environment.
         * This can be seen by using `env -i =a env` or `env -i =a cat /proc/self/environ`
         *
         * POSIX.1-2017 doesn't seem to mention what to do if the string is malformed (at least
         * not in "Chapter 8, Environment Variables" or in the definition for environ and various
         * exec*'s or in the description of env in the "Shell & Utilities" volume).
         *
         * It also doesn't specify any checks for putenv before modifying the environ variable, which
         * is likely why glibc doesn't do so. However, setenv's first argument cannot point to
         * an empty string or a string containing '='.
         *
         * There is no benefit in replicating GNU's env behavior, since it will only modify the
         * environment in weird ways
         */

        if name.is_empty() {
            show_warning!("no name specified for value {}", val.quote());
            continue;
        }
        env::set_var(name, val);
    }

    if !opts.program.is_empty() {
        // we need to execute a command
        let (prog, args) = build_command(&mut opts.program);

        /*
         * On Unix-like systems Command::status either ends up calling either fork or posix_spawnp
         * (which ends up calling clone). Keep using the current process would be ideal, but the
         * standard library contains many checks and fail-safes to ensure the process ends up being
         * created. This is much simpler than dealing with the hassles of calling execvp directly.
         */
        match Command::new(&*prog).args(args).status() {
            Ok(exit) if !exit.success() => return Err(exit.code().unwrap().into()),
            Err(ref err) if err.kind() == io::ErrorKind::NotFound => return Err(127.into()),
            Err(_) => return Err(126.into()),
            Ok(_) => (),
        }
    } else {
        // no program provided, so just dump all env vars to stdout
        print_env(opts.null);
    }

    Ok(())
}

#[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
    run_env(args)
}
<|endoftext|>


<commit_before>//! Functions for computing [integral images](https://en.wikipedia.org/wiki/Summed_area_table)
//! and running sums of rows and columns.

extern crate image;

use image::{
    Luma,
    GenericImage,
    ImageBuffer
};

use definitions::{
    VecBuffer
};

/// Computes the integral image of an 8bpp grayscale image.
/// I is the integral image of an image F if I(x, y) is the
/// sum of F(x', y') for x' <= x, y' <= y. i.e. each pixel
/// in the integral image contains the sum of the pixel intensities
/// of all input pixels that are above it and to its left.
/// The integral image has the helpful property that it lets us
/// compute the sum of pixel intensities from any rectangular region
/// in the input image in constant time.
/// Specifically, given a rectangle in F with clockwise corners
/// A, B, C, D, with A at the upper left, the total pixel intensity
/// of this rectangle is I(C) - I(B) - I(D) + I(A).
// TODO: Support more formats.
// TODO: This is extremely slow. Fix that!
pub fn integral_image<I>(image: &I) -> VecBuffer<Luma<u32>>
    where I: GenericImage<Pixel=Luma<u8>> {
    padded_integral_image(image, 0, 0)
}

/// Computes the integral image of the result of padding image
/// with its boundary pixels for x_padding columns on either
/// side and y_padding rows at its top and bottom.
/// Returned image has width image.width() + 2 * x_padding
/// and height image.height() + 2 * y_padding.
pub fn padded_integral_image<I>(image: &I, x_padding: u32, y_padding: u32)
        -> VecBuffer<Luma<u32>>
    where I: GenericImage<Pixel=Luma<u8>> {

    let (in_width, in_height) = image.dimensions();
    let out_width = in_width + 2 * x_padding;
    let out_height = in_height + 2 * y_padding;

    let mut out: ImageBuffer<Luma<u32>, Vec<u32>>
        = ImageBuffer::new(out_width, out_height);

    for y in 0..out_height {
        for x in 0..out_width {

            let y_in: u32;
            if y < y_padding {
                y_in = 0;
            }
            else if y >= in_height + y_padding {
                y_in = in_height - 1;
            }
            else {
                y_in = y - y_padding;
            }
            let x_in: u32;
            if x < x_padding {
                x_in = 0;
            }
            else if x >= in_width + x_padding {
                x_in = in_width - 1;
            }
            else {
                x_in = x - x_padding;
            }

            unsafe {
                let p = image.unsafe_get_pixel(x_in, y_in);
                out.unsafe_put_pixel(x, y, Luma([p[0] as u32]));
            }
        }
    }

    for x in 1..out_width {
        (*out.get_pixel_mut(x, 0))[0] += unsafe { out.unsafe_get_pixel(x - 1, 0)[0] };
    }

    for y in 1..out_height {
        (*out.get_pixel_mut(0, y))[0] += unsafe { out.unsafe_get_pixel(0, y - 1)[0] };

        for x in 1..out_width {
            (*out.get_pixel_mut(x, y))[0] += unsafe { out.unsafe_get_pixel(x, y - 1)[0] };
            (*out.get_pixel_mut(x, y))[0] += unsafe { out.unsafe_get_pixel(x - 1, y)[0] };
            (*out.get_pixel_mut(x, y))[0] -= unsafe { out.unsafe_get_pixel(x - 1, y - 1)[0] };
        }
    }

    out
}

/// Computes the running sum of one row of image, padded
/// at the beginning and end. The padding is by continuity.
/// Takes a reference to buffer so that this can be reused
/// for all rows in an image.
// TODO: faster, more formats
pub fn row_running_sum<I>(image: &I, row: u32, buffer: &mut [u32], padding: u32)
    where I: GenericImage<Pixel=Luma<u8>> {

    let width = image.width();
    assert!(buffer.len() >= (width + 2 * padding) as usize,
        format!("Buffer length {} is less than 2 * {} + {}",
            buffer.len(), width, padding));
    assert!(row < image.height(), format!("row out of bound: {} >= {}",
                                          row, image.height()));

    for x in 0..padding {
        buffer[x as usize] = unsafe { image.unsafe_get_pixel(0, row)[0] as u32 };
    }

    for x in 0..width {
        let idx = (x + padding) as usize;
        buffer[idx] = unsafe { image.unsafe_get_pixel(x, row)[0] as u32 };
    }

    for x in 0..padding {
        let idx = (x + width + padding) as usize;
        buffer[idx] = unsafe { image.unsafe_get_pixel(width - 1, row)[0] as u32 };
    }

    for x in 1..width + 2 * padding {
        buffer[x as usize] += buffer[(x - 1) as usize] as u32;
    }
}

/// Computes the running sum of one column of image, padded
/// at the top and bottom. The padding is by continuity.
/// Takes a reference to buffer so that this can be reused
/// for all columns in an image.
// TODO: faster, more formats
pub fn column_running_sum<I>(image: &I, column: u32, buffer: &mut [u32], padding: u32)
    where I: GenericImage<Pixel=Luma<u8>> {

    let height = image.height();
    assert!(buffer.len() >= (height + 2 * padding) as usize,
        format!("Buffer length {} is less than 2 * {} + {}",
            buffer.len(), height, padding));
    assert!(column < image.width(), format!("column out of bound: {} >= {}",
                                             column, image.width()));

    for y in 0..padding {
        buffer[y as usize] = unsafe { image.unsafe_get_pixel(column, 0)[0] as u32 };
    }

    for y in 0..height {
        let idx = (y + padding) as usize;
        buffer[idx] = unsafe { image.unsafe_get_pixel(column, y)[0] as u32 };
    }

    for y in 0..padding {
        let idx = (y + height + padding) as usize;
        buffer[idx] = unsafe { image.unsafe_get_pixel(column, height - 1)[0] as u32 };
    }

    for y in 1..height + 2 * padding {
        buffer[y as usize] += buffer[(y - 1) as usize] as u32;
    }
}

#[cfg(test)]
mod test {

    use super::{
        column_running_sum,
        integral_image,
        padded_integral_image,
        row_running_sum
    };
    use utils::{
        gray_bench_image
    };
    use image::{
        GrayImage,
        ImageBuffer,
        Luma
    };
    use test;

    #[test]
    fn test_integral_image() {
        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            1, 2, 3,
            4, 5, 6]).unwrap();

        let expected: ImageBuffer<Luma<u32>, Vec<u32>>
            = ImageBuffer::from_raw(3, 2, vec![
            1,  3,  6,
            5, 12, 21]).unwrap();

        assert_pixels_eq!(integral_image(&image), expected);
    }

    #[bench]
    fn bench_integral_image(b: &mut test::Bencher) {
        let image = gray_bench_image(500, 500);
        b.iter(|| {
            let integral = integral_image(&image);
            test::black_box(integral);
            });
    }

    #[test]
    fn test_padded_integral_image() {
        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            1, 2, 3,
            4, 5, 6]).unwrap();

        let expected: ImageBuffer<Luma<u32>, Vec<u32>>
            = ImageBuffer::from_raw(5, 4, vec![
              1,  2,   4,   7,  10,
              2,  4,   8,  14,  20,
              6, 12,  21,  33,  45,
             10, 20,  34,  52,  70]).unwrap();

        assert_pixels_eq!(padded_integral_image(&image, 1, 1), expected);
    }

    #[test]
    fn test_row_running_sum() {
        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            1, 2, 3,
            4, 5, 6]).unwrap();

        let expected = [1, 2, 4, 7, 10];

        let mut buffer = [0; 5];
        row_running_sum(&image, 0, &mut buffer, 1);

        assert_eq!(buffer, expected);
    }

    #[bench]
    fn bench_row_running_sum(b: &mut test::Bencher) {
        let image = gray_bench_image(1000, 1);
        let mut buffer = [0; 1010];
        b.iter(|| {
            row_running_sum(&image, 0, &mut buffer, 5);
            });
    }

    #[test]
    fn test_column_running_sum() {
        let image: GrayImage = ImageBuffer::from_raw(2, 3, vec![
            1, 4,
            2, 5,
            3, 6]).unwrap();

        let expected = [1, 2, 4, 7, 10];

        let mut buffer = [0; 5];
        column_running_sum(&image, 0, &mut buffer, 1);

        assert_eq!(buffer, expected);
    }

    #[bench]
    fn bench_column_running_sum(b: &mut test::Bencher) {
        let image = gray_bench_image(100, 1000);
        let mut buffer = [0; 1010];
        b.iter(|| {
            column_running_sum(&image, 0, &mut buffer, 5);
            });
    }
}
<commit_msg>Fix error message<commit_after>//! Functions for computing [integral images](https://en.wikipedia.org/wiki/Summed_area_table)
//! and running sums of rows and columns.

extern crate image;

use image::{
    Luma,
    GenericImage,
    ImageBuffer
};

use definitions::{
    VecBuffer
};

/// Computes the integral image of an 8bpp grayscale image.
/// I is the integral image of an image F if I(x, y) is the
/// sum of F(x', y') for x' <= x, y' <= y. i.e. each pixel
/// in the integral image contains the sum of the pixel intensities
/// of all input pixels that are above it and to its left.
/// The integral image has the helpful property that it lets us
/// compute the sum of pixel intensities from any rectangular region
/// in the input image in constant time.
/// Specifically, given a rectangle in F with clockwise corners
/// A, B, C, D, with A at the upper left, the total pixel intensity
/// of this rectangle is I(C) - I(B) - I(D) + I(A).
// TODO: Support more formats.
// TODO: This is extremely slow. Fix that!
pub fn integral_image<I>(image: &I) -> VecBuffer<Luma<u32>>
    where I: GenericImage<Pixel=Luma<u8>> {
    padded_integral_image(image, 0, 0)
}

/// Computes the integral image of the result of padding image
/// with its boundary pixels for x_padding columns on either
/// side and y_padding rows at its top and bottom.
/// Returned image has width image.width() + 2 * x_padding
/// and height image.height() + 2 * y_padding.
pub fn padded_integral_image<I>(image: &I, x_padding: u32, y_padding: u32)
        -> VecBuffer<Luma<u32>>
    where I: GenericImage<Pixel=Luma<u8>> {

    let (in_width, in_height) = image.dimensions();
    let out_width = in_width + 2 * x_padding;
    let out_height = in_height + 2 * y_padding;

    let mut out: ImageBuffer<Luma<u32>, Vec<u32>>
        = ImageBuffer::new(out_width, out_height);

    for y in 0..out_height {
        for x in 0..out_width {

            let y_in: u32;
            if y < y_padding {
                y_in = 0;
            }
            else if y >= in_height + y_padding {
                y_in = in_height - 1;
            }
            else {
                y_in = y - y_padding;
            }
            let x_in: u32;
            if x < x_padding {
                x_in = 0;
            }
            else if x >= in_width + x_padding {
                x_in = in_width - 1;
            }
            else {
                x_in = x - x_padding;
            }

            unsafe {
                let p = image.unsafe_get_pixel(x_in, y_in);
                out.unsafe_put_pixel(x, y, Luma([p[0] as u32]));
            }
        }
    }

    for x in 1..out_width {
        (*out.get_pixel_mut(x, 0))[0] += unsafe { out.unsafe_get_pixel(x - 1, 0)[0] };
    }

    for y in 1..out_height {
        (*out.get_pixel_mut(0, y))[0] += unsafe { out.unsafe_get_pixel(0, y - 1)[0] };

        for x in 1..out_width {
            (*out.get_pixel_mut(x, y))[0] += unsafe { out.unsafe_get_pixel(x, y - 1)[0] };
            (*out.get_pixel_mut(x, y))[0] += unsafe { out.unsafe_get_pixel(x - 1, y)[0] };
            (*out.get_pixel_mut(x, y))[0] -= unsafe { out.unsafe_get_pixel(x - 1, y - 1)[0] };
        }
    }

    out
}

/// Computes the running sum of one row of image, padded
/// at the beginning and end. The padding is by continuity.
/// Takes a reference to buffer so that this can be reused
/// for all rows in an image.
// TODO: faster, more formats
pub fn row_running_sum<I>(image: &I, row: u32, buffer: &mut [u32], padding: u32)
    where I: GenericImage<Pixel=Luma<u8>> {

    let width = image.width();
    assert!(buffer.len() >= (width + 2 * padding) as usize,
        format!("Buffer length {} is less than 2 * {} + {}",
            buffer.len(), width, padding));
    assert!(row < image.height(), format!("row out of bound: {} >= {}",
                                          row, image.height()));

    for x in 0..padding {
        buffer[x as usize] = unsafe { image.unsafe_get_pixel(0, row)[0] as u32 };
    }

    for x in 0..width {
        let idx = (x + padding) as usize;
        buffer[idx] = unsafe { image.unsafe_get_pixel(x, row)[0] as u32 };
    }

    for x in 0..padding {
        let idx = (x + width + padding) as usize;
        buffer[idx] = unsafe { image.unsafe_get_pixel(width - 1, row)[0] as u32 };
    }

    for x in 1..width + 2 * padding {
        buffer[x as usize] += buffer[(x - 1) as usize] as u32;
    }
}

/// Computes the running sum of one column of image, padded
/// at the top and bottom. The padding is by continuity.
/// Takes a reference to buffer so that this can be reused
/// for all columns in an image.
// TODO: faster, more formats
pub fn column_running_sum<I>(image: &I, column: u32, buffer: &mut [u32], padding: u32)
    where I: GenericImage<Pixel=Luma<u8>> {

    let height = image.height();
    assert!(buffer.len() >= (height + 2 * padding) as usize,
        format!("Buffer length {} is less than {} + 2 * {}",
            buffer.len(), height, padding));
    assert!(column < image.width(), format!("column out of bound: {} >= {}",
                                             column, image.width()));

    for y in 0..padding {
        buffer[y as usize] = unsafe { image.unsafe_get_pixel(column, 0)[0] as u32 };
    }

    for y in 0..height {
        let idx = (y + padding) as usize;
        buffer[idx] = unsafe { image.unsafe_get_pixel(column, y)[0] as u32 };
    }

    for y in 0..padding {
        let idx = (y + height + padding) as usize;
        buffer[idx] = unsafe { image.unsafe_get_pixel(column, height - 1)[0] as u32 };
    }

    for y in 1..height + 2 * padding {
        buffer[y as usize] += buffer[(y - 1) as usize] as u32;
    }
}

#[cfg(test)]
mod test {

    use super::{
        column_running_sum,
        integral_image,
        padded_integral_image,
        row_running_sum
    };
    use utils::{
        gray_bench_image
    };
    use image::{
        GrayImage,
        ImageBuffer,
        Luma
    };
    use test;

    #[test]
    fn test_integral_image() {
        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            1, 2, 3,
            4, 5, 6]).unwrap();

        let expected: ImageBuffer<Luma<u32>, Vec<u32>>
            = ImageBuffer::from_raw(3, 2, vec![
            1,  3,  6,
            5, 12, 21]).unwrap();

        assert_pixels_eq!(integral_image(&image), expected);
    }

    #[bench]
    fn bench_integral_image(b: &mut test::Bencher) {
        let image = gray_bench_image(500, 500);
        b.iter(|| {
            let integral = integral_image(&image);
            test::black_box(integral);
            });
    }

    #[test]
    fn test_padded_integral_image() {
        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            1, 2, 3,
            4, 5, 6]).unwrap();

        let expected: ImageBuffer<Luma<u32>, Vec<u32>>
            = ImageBuffer::from_raw(5, 4, vec![
              1,  2,   4,   7,  10,
              2,  4,   8,  14,  20,
              6, 12,  21,  33,  45,
             10, 20,  34,  52,  70]).unwrap();

        assert_pixels_eq!(padded_integral_image(&image, 1, 1), expected);
    }

    #[test]
    fn test_row_running_sum() {
        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            1, 2, 3,
            4, 5, 6]).unwrap();

        let expected = [1, 2, 4, 7, 10];

        let mut buffer = [0; 5];
        row_running_sum(&image, 0, &mut buffer, 1);

        assert_eq!(buffer, expected);
    }

    #[bench]
    fn bench_row_running_sum(b: &mut test::Bencher) {
        let image = gray_bench_image(1000, 1);
        let mut buffer = [0; 1010];
        b.iter(|| {
            row_running_sum(&image, 0, &mut buffer, 5);
            });
    }

    #[test]
    fn test_column_running_sum() {
        let image: GrayImage = ImageBuffer::from_raw(2, 3, vec![
            1, 4,
            2, 5,
            3, 6]).unwrap();

        let expected = [1, 2, 4, 7, 10];

        let mut buffer = [0; 5];
        column_running_sum(&image, 0, &mut buffer, 1);

        assert_eq!(buffer, expected);
    }

    #[bench]
    fn bench_column_running_sum(b: &mut test::Bencher) {
        let image = gray_bench_image(100, 1000);
        let mut buffer = [0; 1010];
        b.iter(|| {
            column_running_sum(&image, 0, &mut buffer, 5);
            });
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate neon;
#[macro_use]
extern crate lazy_static;
extern crate fall_tree;
extern crate fall_gen;
extern crate lang_fall;

extern crate neon_serde;
#[macro_use]
extern crate serde_derive;
extern crate serde;

use serde::{Serialize, Deserialize};

use std::sync::{Arc, Mutex, MutexGuard};

use neon::vm::{Call, VmResult, JsResult};
use neon::scope::{Scope, RootScope};
use neon::mem::Handle;
use neon::js::{JsString, JsInteger, JsNull, JsValue, JsFunction};
use neon::task::Task;

use lang_fall::editor_api;
use fall_tree::{TextRange, TextUnit, File};
use fall_gen::TestRenderer;

lazy_static! {
    static ref FILE: Mutex<Option<Arc<File>>> = Mutex::new(None);
}

lazy_static! {
    static ref TEST_RENDERER: Mutex<TestRenderer> = Mutex::new(TestRenderer);
}

fn renderer() -> MutexGuard<'static, TestRenderer> {
    TEST_RENDERER.lock().unwrap()
}

macro_rules! get_file_or_return_null {
    ($guard:expr) => {
        match *$guard {
            None => return Ok(JsNull::new().upcast()),
            Some(ref f) => f,
        }
    }
}

fn file_create(call: Call) -> JsResult<JsNull> {
    let scope = call.scope;
    let text = call.arguments.require(scope, 0)?.check::<JsString>()?;
    let text = text.value();
    *FILE.lock().unwrap() = Some(Arc::new(editor_api::parse(text)));
    Ok(JsNull::new())
}

#[derive(Serialize)]
struct PerformanceCounters {
    lexing_time: u32,
    parsing_time: u32,
    reparsed_region: TextRange,
}

fn performance_counters(file: &File) -> PerformanceCounters {
    let stats = file.stats();
    PerformanceCounters {
        lexing_time: stats.lexing_time.subsec_nanos(),
        parsing_time: stats.parsing_time.subsec_nanos(),
        reparsed_region: stats.reparsed_region,
    }
}

fn parse_test(call: Call) -> JsResult<JsValue> {
    let scope = call.scope;
    let test = call.arguments.require(scope, 0)?.check::<JsInteger>()?.value() as usize;
    let callback = call.arguments.require(scope, 1)?.check::<JsFunction>()?;
    let file = FILE.lock().unwrap();
    let file = get_file_or_return_null!(file).clone();

    struct RenderTask(Arc<File>, usize);
    impl Task for RenderTask {
        type Output = String;
        type Error = ();
        type JsEvent = JsString;

        fn perform(&self) -> Result<String, ()> {
            let mut renderer = renderer();
            let tree = renderer.render_one(&self.0, self.1);
            Ok(tree)
        }

        fn complete<'a, T: Scope<'a>>(self, scope: &'a mut T, result: Result<String, ()>) -> JsResult<JsString> {
            Ok(JsString::new(scope, &result.unwrap()).unwrap())
        }
    }

    RenderTask(file, test).schedule(callback);
    Ok(JsNull::new().upcast())
}

fn file_fn<'a, S, F>(call: &mut Call<'a>, f: F) -> JsResult<'a, JsValue>
    where S: Serialize,
          F: Fn(&mut Call<'a>, &File) -> VmResult<S> {
    let file = FILE.lock().unwrap();
    let file = match *file {
        None => return Ok(JsNull::new().upcast()),
        Some(ref file) => file,
    };
    let result = f(call, file)?;
    Ok(to_value(&result, call.scope)?)
}

fn file_fn0<S: Serialize, F: Fn(&File) -> S>(mut call: Call, f: F) -> JsResult<JsValue> {
    file_fn(&mut call, |_, file| Ok(f(file)))
}

fn file_fn1<'c, S: Serialize, D: Deserialize<'c>>(
    mut call: Call<'c>,
    f: fn(&File, D) -> S
) -> JsResult<'c, JsValue> {
    file_fn(&mut call, |call, file| {
        let arg: D = from_handle(call.arguments.require(call.scope, 0)?, call.scope)?;
        Ok(f(file, arg))
    })
}

fn file_fn2<'c, S: Serialize, D1: Deserialize<'c>, D2: Deserialize<'c>>(
    mut call: Call<'c>,
    f: fn(&File, D1, D2) -> S
) -> JsResult<'c, JsValue> {
    file_fn(&mut call, |call, file| {
        let arg1: D1 = from_handle(call.arguments.require(call.scope, 0)?, call.scope)?;
        let arg2: D2 = from_handle(call.arguments.require(call.scope, 1)?, call.scope)?;
        Ok(f(file, arg1, arg2))
    })
}

register_module!(m, {
    m.export("tree_as_text", |call| file_fn0(call, editor_api::tree_as_text))?;
    m.export("performance_counters", |call| file_fn0(call, performance_counters))?;
    m.export("highlight", |call| file_fn0(call, editor_api::highlight))?;
    m.export("structure", |call| file_fn0(call, editor_api::structure))?;
    m.export("extend_selection", |call| file_fn1(call, editor_api::extend_selection))?;
    m.export("context_actions", |call| file_fn1(call, editor_api::context_actions))?;
    m.export("apply_context_action", |call| file_fn2(call, |file, offset: TextUnit, aid: String| {
        editor_api::apply_context_action(file, offset, &aid)
    }))?;
    m.export("resolve_reference", |call| file_fn1(call, editor_api::resolve_reference))?;
    m.export("find_usages", |call| file_fn1(call, editor_api::find_usages))?;
    m.export("diagnostics", |call| file_fn0(call, editor_api::diagnostics))?;
    m.export("reformat", |call| file_fn0(call, editor_api::reformat))?;
    m.export("test_at_offset", |call| file_fn1(call, editor_api::test_at_offset))?;
    m.export("parse_test", parse_test)?;
    m.export("file_create", file_create)?;
    Ok(())
});

fn from_handle<'a, T: serde::Deserialize<'a> + ? Sized>(
    input: Handle<'a, JsValue>,
    scope: &mut RootScope<'a>,
) -> neon_serde::errors::Result<T> {
    let scope: &'a mut RootScope<'a> = unsafe { ::std::mem::transmute(scope) };
    neon_serde::from_handle(input, scope)
}

fn to_value<'value, 'scope, V: Serialize + ?Sized>(
    value: &'value V,
    scope: &mut RootScope<'scope>,
) -> neon_serde::errors::Result<Handle<'scope, JsValue>> {
    let scope: &'scope mut RootScope<'scope> = unsafe { ::std::mem::transmute(scope) };
    neon_serde::to_value(value, scope)
}

<commit_msg>Simplify<commit_after>#[macro_use]
extern crate neon;
#[macro_use]
extern crate lazy_static;
extern crate fall_tree;
extern crate fall_gen;
extern crate lang_fall;

extern crate neon_serde;
#[macro_use]
extern crate serde_derive;
extern crate serde;

use serde::{Serialize, Deserialize};

use std::sync::{Arc, Mutex};

use neon::vm::{Call, VmResult, JsResult};
use neon::scope::{Scope, RootScope};
use neon::mem::Handle;
use neon::js::{JsString, JsInteger, JsNull, JsValue, JsFunction};
use neon::task::Task;

use lang_fall::editor_api;
use fall_tree::{TextRange, TextUnit, File};
use fall_gen::TestRenderer;

lazy_static! {
    static ref FILE: Mutex<Option<Arc<File>>> = Mutex::new(None);
}

fn file_create(call: Call) -> JsResult<JsNull> {
    let scope = call.scope;
    let text = call.arguments.require(scope, 0)?.check::<JsString>()?;
    let text = text.value();
    *FILE.lock().unwrap() = Some(Arc::new(editor_api::parse(text)));
    Ok(JsNull::new())
}

#[derive(Serialize)]
struct PerformanceCounters {
    lexing_time: u32,
    parsing_time: u32,
    reparsed_region: TextRange,
}

fn performance_counters(file: &File) -> PerformanceCounters {
    let stats = file.stats();
    PerformanceCounters {
        lexing_time: stats.lexing_time.subsec_nanos(),
        parsing_time: stats.parsing_time.subsec_nanos(),
        reparsed_region: stats.reparsed_region,
    }
}

struct RenderTask(Arc<File>, usize);
impl Task for RenderTask {
    type Output = String;
    type Error = ();
    type JsEvent = JsString;

    fn perform(&self) -> Result<String, ()> {
        lazy_static! {
            static ref TEST_RENDERER: Mutex<TestRenderer> = Mutex::new(TestRenderer);
        }

        let mut renderer = TEST_RENDERER.lock().unwrap();
        let tree = renderer.render_one(&self.0, self.1);
        Ok(tree)
    }

    fn complete<'a, T: Scope<'a>>(self, scope: &'a mut T, result: Result<String, ()>) -> JsResult<JsString> {
        Ok(JsString::new(scope, &result.unwrap()).unwrap())
    }
}

fn parse_test(call: Call) -> JsResult<JsValue> {
    let scope = call.scope;
    let test = call.arguments.require(scope, 0)?.check::<JsInteger>()?.value() as usize;
    let callback = call.arguments.require(scope, 1)?.check::<JsFunction>()?;
    let file = FILE.lock().unwrap();

    if let Some(ref file) = *file {
        RenderTask(file.clone(), test).schedule(callback);
    }
    Ok(JsNull::new().upcast())
}

fn file_fn<'a, S, F>(call: &mut Call<'a>, f: F) -> JsResult<'a, JsValue>
    where S: Serialize,
          F: Fn(&mut Call<'a>, &File) -> VmResult<S> {
    let file = FILE.lock().unwrap();
    let file = match *file {
        None => return Ok(JsNull::new().upcast()),
        Some(ref file) => file,
    };
    let result = f(call, file)?;
    Ok(to_value(&result, call.scope)?)
}

fn file_fn0<S: Serialize, F: Fn(&File) -> S>(mut call: Call, f: F) -> JsResult<JsValue> {
    file_fn(&mut call, |_, file| Ok(f(file)))
}

fn file_fn1<'c, S: Serialize, D: Deserialize<'c>>(
    mut call: Call<'c>,
    f: fn(&File, D) -> S
) -> JsResult<'c, JsValue> {
    file_fn(&mut call, |call, file| {
        let arg: D = from_handle(call.arguments.require(call.scope, 0)?, call.scope)?;
        Ok(f(file, arg))
    })
}

fn file_fn2<'c, S: Serialize, D1: Deserialize<'c>, D2: Deserialize<'c>>(
    mut call: Call<'c>,
    f: fn(&File, D1, D2) -> S
) -> JsResult<'c, JsValue> {
    file_fn(&mut call, |call, file| {
        let arg1: D1 = from_handle(call.arguments.require(call.scope, 0)?, call.scope)?;
        let arg2: D2 = from_handle(call.arguments.require(call.scope, 1)?, call.scope)?;
        Ok(f(file, arg1, arg2))
    })
}

register_module!(m, {
    m.export("tree_as_text", |call| file_fn0(call, editor_api::tree_as_text))?;
    m.export("performance_counters", |call| file_fn0(call, performance_counters))?;
    m.export("highlight", |call| file_fn0(call, editor_api::highlight))?;
    m.export("structure", |call| file_fn0(call, editor_api::structure))?;
    m.export("extend_selection", |call| file_fn1(call, editor_api::extend_selection))?;
    m.export("context_actions", |call| file_fn1(call, editor_api::context_actions))?;
    m.export("apply_context_action", |call| file_fn2(call, |file, offset: TextUnit, aid: String| {
        editor_api::apply_context_action(file, offset, &aid)
    }))?;
    m.export("resolve_reference", |call| file_fn1(call, editor_api::resolve_reference))?;
    m.export("find_usages", |call| file_fn1(call, editor_api::find_usages))?;
    m.export("diagnostics", |call| file_fn0(call, editor_api::diagnostics))?;
    m.export("reformat", |call| file_fn0(call, editor_api::reformat))?;
    m.export("test_at_offset", |call| file_fn1(call, editor_api::test_at_offset))?;
    m.export("parse_test", parse_test)?;
    m.export("file_create", file_create)?;
    Ok(())
});

fn from_handle<'a, T: serde::Deserialize<'a> + ? Sized>(
    input: Handle<'a, JsValue>,
    scope: &mut RootScope<'a>,
) -> neon_serde::errors::Result<T> {
    let scope: &'a mut RootScope<'a> = unsafe { ::std::mem::transmute(scope) };
    neon_serde::from_handle(input, scope)
}

fn to_value<'value, 'scope, V: Serialize + ?Sized>(
    value: &'value V,
    scope: &mut RootScope<'scope>,
) -> neon_serde::errors::Result<Handle<'scope, JsValue>> {
    let scope: &'scope mut RootScope<'scope> = unsafe { ::std::mem::transmute(scope) };
    neon_serde::to_value(value, scope)
}

<|endoftext|>