<commit_before>#![feature(phase)]
extern crate serialize;
#[phase(plugin)] extern crate docopt_macros;
extern crate docopt;
extern crate core;
extern crate collections;
extern crate regex;
#[phase(plugin)] extern crate regex_macros;

use docopt::FlagParser;
use std::io::BufferedReader;
use std::io::BufferedWriter;
use std::io::File;
use core::result::Result;
use collections::string::String;
use collections::vec::Vec;

// Interleaver takes N files (e.g., i_1.txt ... i_N.txt) and transforms them into N output files
// named o_1.txt ... o_N.txt.  The lines of the input files must be prefixed with time stamps.  The
// output files contain the same content as the input files but only one file is allowed to make
// progress on a given line.  The other files are empty.

docopt!(Args, "
Usage:
  interleaver <file>...

Options:
  -h, --help    Show this screen.
", )

type BrType = BufferedReader<core::result::Result<std::io::fs::File,std::io::IoError>>;
type BwType = BufferedWriter<core::result::Result<std::io::fs::File,std::io::IoError>>;

#[deriving(Show,PartialEq,PartialOrd,Eq,Ord)]
enum Month { Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec }

fn string_to_month (s : &str) -> Option<Month> {
  match s {
    "Jan" => Some (Jan),
    "Feb" => Some (Feb),
    "Mar" => Some (Mar),
    "Apr" => Some (Apr),
    "May" => Some (May),
    "Jun" => Some (Jun),
    "Jul" => Some (Jul),
    "Aug" => Some (Aug),
    "Sep" => Some (Sep),
    "Oct" => Some (Oct),
    "Nov" => Some (Nov),
    "Dec" => Some (Dec),
    _     => None
  }
}

#[deriving(Show,PartialEq,Eq)]
struct TimedLine {
  l       : String,
  month   : Month,
  day     : u8,
  hour    : u8,
  minute  : u8,
  second  : u8,
  usecond : u32,
  target  : uint
}

impl TimedLine {
  fn new (l : &String, target : uint) -> TimedLine {
    let re = regex! (r"^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) +(\d+) (\d+):(\d+):(\d+) (\d+):.*$");
    let caps = match re.captures (l.as_slice()) {
      None => fail! ("Could not analyze line: \"{}\"", l),
      Some (caps) => caps
    };
    let (month, day, hour, minute, second, usecond) =
      match (string_to_month (caps.at(1)), from_str::<u8>(caps.at(2)), from_str::<u8> (caps.at(3)), from_str::<u8> (caps.at(4)), from_str::<u8> (caps.at(5)), from_str::<u32> (caps.at(6))
      ) {
        (Some (month), Some (day), Some (hour), Some (minute), Some (second), Some (usecond)) => (month, day, hour, minute, second, usecond*100),
        _ => fail! ("Could not extract fields from line: \"{}\"", l)
      };

    TimedLine {
      l       : l.clone (),
      month   : month,
      day     : day,
      hour    : hour,
      minute  : minute,
      second  : second,
      usecond : usecond,
      target  : target
    }
  }
}

impl Ord for TimedLine {
  fn cmp(&self, other: &TimedLine) -> Ordering {
    let month_cmp = self.month.cmp (&other.month);
    if month_cmp == Equal {
      let day_cmp = self.day.cmp (&other.day);
      if day_cmp == Equal {
        let hour_cmp = self.hour.cmp (&other.hour);
        if hour_cmp == Equal {
          let minute_cmp = self.minute.cmp (&other.minute);
          if minute_cmp == Equal {
            let second_cmp = self.second.cmp (&other.second);
            if second_cmp == Equal {
              self.usecond.cmp (&other.usecond)
            }
            else { second_cmp }
          }
          else { minute_cmp }
        }
        else { hour_cmp }
      }
      else { day_cmp }
    }
    else { month_cmp }
  }
}

impl PartialOrd for TimedLine {
  fn partial_cmp(&self, other: &TimedLine) -> Option<Ordering> {
    Some (self.cmp (other))
  }
}

fn main() {
  let args: Args = FlagParser::parse().unwrap_or_else(|e| e.exit());

  let s = String::from_str ("Sep  2 14:25:02 8993: (main|info): --- NODE STARTED ---");
  let tl = TimedLine::new (&s, 5u);
  println!("TimedLine: {}", tl);

  println!("Starting {}", args);

  let file_names = args.arg_file;
  let file_count = file_names.len ();
  let paths_it = file_names.iter ().map (|n| Path::new(n.clone ()));
  let files_it = paths_it.map (|path| File::open(&path));
  let mut buffered_readers_it = files_it.map (|file| BufferedReader::new (file));
  let mut buffered_readers_vec : Vec<BrType> = buffered_readers_it.collect ();

  let paths_out_it = range (0u, file_names.len ()).map (|i| Path::new (i.to_string()));
  let files_out_it = paths_out_it.map (|path_out| {
    let res = File::create(&path_out);
    match res {
      Ok(_)  => println!("Successfully opened"),
      Err(e) => fail!("Could not open output file: {}", e)
    };
    res
  }
  );
  let mut buffered_writers_it = files_out_it.map (|file_out| BufferedWriter::new (file_out) );

  let mut buffered_writers_vec : Vec<BwType> = buffered_writers_it.collect ();

  let mut done;
  let mut i = 0;

  loop {
    done = true;
    for buffered_reader in buffered_readers_vec.mut_iter () {
      let mut lines = buffered_reader.lines ();
      match lines.next () {
        None => (),
        Some (line) => {
          let target = buffered_writers_vec.get_mut (i);
          let res = target.write_str (line.unwrap ().as_slice ());
          match res {
            Ok(_) => {
              i = (i + 1) % file_count;
              done = false;
            }
            Err(e) => {
              let ref file_name = file_names[i];
              fail! ("Could not write to {}: {}", file_name, e);
            }
          }
        }
      }
    }
    if done { break; }
  }

  // let line_readers_it = buffered_readers_vec.iter().map (|mut buffered_reader| { buffered_reader.read_to_string(); });

  // let line_iterators = readers.map (|mut reader| reader.lines ());

  // let c = args.arg_FILENAMES.len();

  // let mut candidates : Vec<Option<IoResult<String>>> = Vec::new ();

  // for line_iterator in line_iterators.iter () {
  //   // let line = line_iterator.next ();
  //   // candidates.push (line);
  // }

  // let path = Path::new("p054_poker.txt");

  // let mut file = BufferedReader::new(File::open(&path));
  // for line in file.lines() {
  //   let l = line.unwrap ();
  // }
}
<commit_msg>Created ordered queue of timed lines<commit_after>#![feature(phase)]
extern crate serialize;
#[phase(plugin)] extern crate docopt_macros;
extern crate docopt;
extern crate core;
extern crate collections;
extern crate regex;
#[phase(plugin)] extern crate regex_macros;

use docopt::FlagParser;
use std::io::BufferedReader;
use std::io::BufferedWriter;
use std::io::File;
use core::result::Result;
use collections::string::String;
use collections::vec::Vec;
use collections::PriorityQueue;

// Interleaver takes N files (e.g., i_1.txt ... i_N.txt) and transforms them into N output files
// named o_1.txt ... o_N.txt.  The lines of the input files must be prefixed with time stamps.  The
// output files contain the same content as the input files but only one file is allowed to make
// progress on a given line.  The other files are empty.

docopt!(Args, "
Usage:
  interleaver <file>...

Options:
  -h, --help    Show this screen.
", )

type BrType = BufferedReader<core::result::Result<std::io::fs::File,std::io::IoError>>;
type BwType = BufferedWriter<core::result::Result<std::io::fs::File,std::io::IoError>>;

#[deriving(Show,PartialEq,PartialOrd,Eq,Ord)]
enum Month { Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec }

fn string_to_month (s : &str) -> Option<Month> {
  match s {
    "Jan" => Some (Jan),
    "Feb" => Some (Feb),
    "Mar" => Some (Mar),
    "Apr" => Some (Apr),
    "May" => Some (May),
    "Jun" => Some (Jun),
    "Jul" => Some (Jul),
    "Aug" => Some (Aug),
    "Sep" => Some (Sep),
    "Oct" => Some (Oct),
    "Nov" => Some (Nov),
    "Dec" => Some (Dec),
    _     => None
  }
}

#[deriving(Show,PartialEq,Eq)]
struct TimedLine {
  l       : String,
  month   : Month,
  day     : u8,
  hour    : u8,
  minute  : u8,
  second  : u8,
  usecond : u32,
  target  : uint
}

impl TimedLine {
  fn new (l : &String, target : uint) -> TimedLine {
    let re = regex! (r"^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) +(\d+) (\d+):(\d+):(\d+) (\d+):.*$");
    let caps = match re.captures (l.as_slice()) {
      None => fail! ("Could not analyze line: \"{}\"", l),
      Some (caps) => caps
    };
    let (month, day, hour, minute, second, usecond) =
      match (string_to_month (caps.at(1)), from_str::<u8>(caps.at(2)), from_str::<u8> (caps.at(3)), from_str::<u8> (caps.at(4)), from_str::<u8> (caps.at(5)), from_str::<u32> (caps.at(6))
      ) {
        (Some (month), Some (day), Some (hour), Some (minute), Some (second), Some (usecond)) => (month, day, hour, minute, second, usecond*100),
        _ => fail! ("Could not extract fields from line: \"{}\"", l)
      };

    TimedLine {
      l       : l.clone (),
      month   : month,
      day     : day,
      hour    : hour,
      minute  : minute,
      second  : second,
      usecond : usecond,
      target  : target
    }
  }
}

impl Ord for TimedLine {
  fn cmp(&self, other: &TimedLine) -> Ordering {
    let month_cmp = self.month.cmp (&other.month);
    if month_cmp == Equal {
      let day_cmp = self.day.cmp (&other.day);
      if day_cmp == Equal {
        let hour_cmp = self.hour.cmp (&other.hour);
        if hour_cmp == Equal {
          let minute_cmp = self.minute.cmp (&other.minute);
          if minute_cmp == Equal {
            let second_cmp = self.second.cmp (&other.second);
            if second_cmp == Equal {
              self.usecond.cmp (&other.usecond)
            }
            else { second_cmp }
          }
          else { minute_cmp }
        }
        else { hour_cmp }
      }
      else { day_cmp }
    }
    else { month_cmp }
  }
}

impl PartialOrd for TimedLine {
  fn partial_cmp(&self, other: &TimedLine) -> Option<Ordering> {
    Some (self.cmp (other))
  }
}

struct TimedLineQueue<'a> {
  q : PriorityQueue<TimedLine>,
  readers : &'a mut Vec<BrType>
}

impl<'a> TimedLineQueue<'a> {
  fn fill_que (&mut self, target : uint) {
    let mut reader = self.readers.get_mut (target);
    let mut lines = reader.lines ();
    let line_opt = lines.next ();
    match line_opt {
      Some (line) => {
        let timed_line = TimedLine::new (&line.unwrap(), target);
        self.q.push (timed_line);
      }
      None => ()
    }
  }

  fn new (readers : & 'a mut Vec<BrType>) -> TimedLineQueue {
    let mut res = TimedLineQueue {
      q : PriorityQueue::new (),
      readers : readers
    };

    for (i, _) in res.readers.mut_iter().enumerate () {
      res.fill_que(i);
    }

    res
  }
}

impl<'a> Iterator<TimedLine> for TimedLineQueue<'a> {
  fn next (&mut self) -> Option<TimedLine> {
    let timed_line_opt = self.q.pop ();
    match timed_line_opt {
      None => (),
      Some (ref timed_line) => {
        self.fill_que(timed_line.target);
      }
    }

    timed_line_opt
  }
}

fn main() {
  let args: Args = FlagParser::parse().unwrap_or_else(|e| e.exit());

  let s = String::from_str ("Sep  2 14:25:02 8993: (main|info): --- NODE STARTED ---");
  let tl = TimedLine::new (&s, 5u);
  println!("TimedLine: {}", tl);

  println!("Starting {}", args);

  let file_names = args.arg_file;
  let file_count = file_names.len ();
  let paths_it = file_names.iter ().map (|n| Path::new(n.clone ()));
  let files_it = paths_it.map (|path| File::open(&path));
  let mut buffered_readers_it = files_it.map (|file| BufferedReader::new (file));
  let mut buffered_readers_vec : Vec<BrType> = buffered_readers_it.collect ();

  let paths_out_it = range (0u, file_names.len ()).map (|i| Path::new (i.to_string()));
  let files_out_it = paths_out_it.map (|path_out| {
    let res = File::create(&path_out);
    match res {
      Ok(_)  => println!("Successfully opened"),
      Err(e) => fail!("Could not open output file: {}", e)
    };
    res
  }
  );
  let mut buffered_writers_it = files_out_it.map (|file_out| BufferedWriter::new (file_out) );

  let mut buffered_writers_vec : Vec<BwType> = buffered_writers_it.collect ();

  let mut done;
  let mut i = 0;

  loop {
    done = true;
    for buffered_reader in buffered_readers_vec.mut_iter () {
      let mut lines = buffered_reader.lines ();
      match lines.next () {
        None => (),
        Some (line) => {
          let target = buffered_writers_vec.get_mut (i);
          let res = target.write_str (line.unwrap ().as_slice ());
          match res {
            Ok(_) => {
              i = (i + 1) % file_count;
              done = false;
            }
            Err(e) => {
              let ref file_name = file_names[i];
              fail! ("Could not write to {}: {}", file_name, e);
            }
          }
        }
      }
    }
    if done { break; }
  }

  let tlq = TimedLineQueue::new (& mut buffered_readers_vec);

  // let line_readers_it = buffered_readers_vec.iter().map (|mut buffered_reader| { buffered_reader.read_to_string(); });

  // let line_iterators = readers.map (|mut reader| reader.lines ());

  // let c = args.arg_FILENAMES.len();

  // let mut candidates : Vec<Option<IoResult<String>>> = Vec::new ();

  // for line_iterator in line_iterators.iter () {
  //   // let line = line_iterator.next ();
  //   // candidates.push (line);
  // }

  // let path = Path::new("p054_poker.txt");

  // let mut file = BufferedReader::new(File::open(&path));
  // for line in file.lines() {
  //   let l = line.unwrap ();
  // }
}
<|endoftext|>


<commit_before>extern crate izhikevich_neurons;
extern crate gnuplot;

use izhikevich_neurons::{Config, State, Num};
use gnuplot::{Figure, Caption, Color, AxesCommon};

type NeuronId = u32;
type SynapseId = u32;
type TimeStep = u32;
type Delay = u8;

const MAX_DELAY: u8 = 40;

const STDP_FIRE_RESET: Num = 0.1;
const STDP_DECAY: Num = 0.95;

struct Synapse {
    pre_neuron: NeuronId,
    post_neuron: NeuronId,
    delay: Delay,
    weight: Num,

    // efficiacy derivative used for STDP
    eff_d: Num,

    _last_spike: TimeStep,
    // ... learning parameters
}

struct Neuron {
    state: State,
    config: Config,
    i_ext: Num,
    i_inp: Num,

    // XXX: Have a list of `active` synapses, which are active
    // once a neuron fires on it. The `active` synapses track
    // themselves, once they become inactive. Use a similar
    // `decay` process as for STDP for the action potential,
    // so that the shape of the spike is less sharp. A high
    // decay rate can simulate the old behaviour.

    // Spike-Time Dependent Plasticity
    //
    // when a neuron fires, we set this value to STDP_FIRE_RESET
    // (0.1 for example), and during every time-step we decay
    // it by STDP_DECAY e.g. 0.95.
    stdp: Num,

    // XXX: Rename to Connection and incoming/outgoing?
    pre_synapses: Vec<SynapseId>,
    post_synapses: Vec<SynapseId>,
}

struct Network {
    neurons: Vec<Neuron>,
    synapses: Vec<Synapse>,
}

impl Network {
    fn new() -> Network {
        Network {
            neurons: Vec::new(),
            synapses: Vec::new()
        }
    }

    fn create_neuron(&mut self, config: Config) -> NeuronId {
        let neuron = Neuron {
            state: State::new(),
            config: config,
            stdp: 0.0,
            i_ext: 0.0,
            i_inp: 0.0,
            pre_synapses: Vec::new(),
            post_synapses: Vec::new(),
        };
        let neuron_id = self.neurons.len() as u32;
        self.neurons.push(neuron);
        return neuron_id;
    }

    fn connect(&mut self, pre_neuron: NeuronId, post_neuron: NeuronId, delay: Delay, weight: Num) -> SynapseId {
        assert!((pre_neuron as usize) < self.neurons.len());
        assert!((post_neuron as usize) < self.neurons.len());
        assert!(delay > 0);
        assert!(delay <= MAX_DELAY);

        let synapse = Synapse {
            pre_neuron: pre_neuron,
            post_neuron: post_neuron,
            delay: delay,
            weight: weight,
            eff_d: 0.0,
            _last_spike: 0, // XXX
        };
        let synapse_id = self.synapses.len() as u32;

        self.synapses.push(synapse);
        self.neurons[pre_neuron as usize].post_synapses.push(synapse_id);
        self.neurons[post_neuron as usize].pre_synapses.push(synapse_id);

        return synapse_id;
    }

    fn update_state(&mut self, time_step: TimeStep, future_spikes: &mut Vec<Vec<SynapseId>>) {
        //for (i, mut neuron) in network.neurons.iter_mut().enumerate() {
        for i in 0 .. self.neurons.len() {
            let syn_i = self.neurons[i].i_ext + self.neurons[i].i_inp;

            let (new_state, fired) = self.neurons[i].state.step_1ms(syn_i, &self.neurons[i].config);
            self.neurons[i].state = new_state;

            // decay STDP
            self.neurons[i].stdp *= STDP_DECAY;

            if fired {
                // Reset the neurons STDP to a high value.
                self.neurons[i].stdp = STDP_FIRE_RESET;

                println!("Neuron {} fired at {} ms", i, time_step);
                for &syn_id in self.neurons[i].post_synapses.iter() {
                    let future = time_step + self.synapses[syn_id as usize].delay as TimeStep;
                    future_spikes[future as usize % MAX_DELAY as usize].push(syn_id);
                }

                // Excite the synapses that might have led to the firing of the underlying neuron.
                // We do this by adding the synapses pre_neuron's STDP value to the synapses eff_d
                // (efficacy derivative) value.
                //
                // We do not update the synapses weight value immediatly, but only once very while
                // (TODO), so that STDP reflects more LTP (Long Term Potentiation).
                for &syn_id in self.neurons[i].pre_synapses.iter() {
                    let stdp = self.neurons[self.synapses[syn_id as usize].pre_neuron as usize].stdp;
                    self.synapses[syn_id as usize].eff_d += stdp;
                }
            }
        }
    }

}

fn main() {
    const PARAMS : &'static [(&'static str, &'static str)] = &[
        ("Neuron 1 [7 pA current 200..700ms]", "blue"),
        //("Neuron 2 [2.69 pA current 200..700ms]", 2.69, "red"),
        ("Neuron 2 [0.0 pA current 200..700ms]", "red"),
        //("Neuron 3 [2.7 pA current 200..700ms]", 2.7, "green")
    ];

    let mut network = Network::new();

    let n1 = network.create_neuron(Config::regular_spiking());
    let n2 = network.create_neuron(Config::regular_spiking());
    //let n3 = network.create_neuron(Config::regular_spiking());

    let external_inputs: &[(NeuronId, TimeStep, Num)] = &[
        (n1, 200, 7.0),
        (n1, 701, 0.0)
    ];

    // We use a cyclic buffer
    // We use (time_step % MAX_DELAY) as index into the futures_spike array
    let mut future_spikes: Vec<Vec<SynapseId>> = (0..MAX_DELAY as usize).map(|_| Vec::new()).collect();

    let _ = network.connect(n1, n2, 10, 7.0);
    let _ = network.connect(n1, n2, 5, 7.0);
    let _ = network.connect(n1, n2, 2, 7.0);
    let _ = network.connect(n1, n2, 2, 7.0);
    let _ = network.connect(n2, n2, 40, 17.0);
    let _ = network.connect(n2, n2, 40, 7.0);

    let mut states: Vec<_> = PARAMS.iter().map(|_| Vec::new()).collect();

    let mut time_step: TimeStep = 0;

    while time_step <= 1_000 {
        // record current state
        for (i, neuron) in network.neurons.iter().enumerate() {
            states[i].push(neuron.state);
        }
        time_step += 1;

        // Clear all input currents
        for neuron in network.neurons.iter_mut() {
            neuron.i_inp = 0.0;
        }

        // get all synapse input
        {
            let current_spikes = &mut future_spikes[(time_step % (MAX_DELAY as TimeStep)) as usize];
            for &syn_fired in current_spikes.iter() {
                println!("time: {}. input from synapse: {}", time_step, syn_fired);
                let (weight, post_neuron) = {
                    let syn = &network.synapses[syn_fired as usize];
                    (syn.weight, syn.post_neuron)
                };
                network.neurons[post_neuron as usize].i_inp += weight;
            }
            current_spikes.clear();
        }

        // set external inputs
        for &(n_id, at, current) in external_inputs {
            if time_step == at {
                network.neurons[n_id as usize].i_ext = current;
            }
        }

        network.update_state(time_step, &mut future_spikes);
    }

    {
        let mut fg = Figure::new();
        {
            let mut diag = fg.axes2d().
                set_x_label("time (ms)", &[]).
                set_y_label("membrane potential v (mV)", &[]);
            for (i, &p) in PARAMS.iter().enumerate() {
                diag.lines(states[i].iter().enumerate().map(|(i, _)| i as f32), states[i].iter().map(|s| s.potential()), &[Caption(p.0), Color(p.1)]);
            }
        }
        fg.show();
    }

    /*
    let mut fg = Figure::new();
    {
        let mut diag = fg.axes2d().
            set_x_label("membrane potential v (mV)", &[]).
            set_y_label("recovery variable u", &[]);
        for (i, &p) in PARAMS.iter().enumerate() {
            diag.lines(states[i].iter().map(|s| s.potential()), states[i].iter().map(|s| s.recovery()), &[Caption(p.0), Color(p.2)]);
        }
    }
    fg.show();
    */

}
<commit_msg>Implement STDP<commit_after>extern crate izhikevich_neurons;
extern crate gnuplot;

use izhikevich_neurons::{Config, State, Num};
use gnuplot::{Figure, Caption, Color, AxesCommon};

type NeuronId = u32;
type SynapseId = u32;
type TimeStep = u32;
type Delay = u8;

const MAX_DELAY: u8 = 40;

const STDP_FIRE_RESET: Num = 0.1;
const STDP_DECAY: Num = 0.95;

struct Synapse {
    pre_neuron: NeuronId,
    post_neuron: NeuronId,
    delay: Delay,
    weight: Num,

    // efficiacy derivative used for STDP
    eff_d: Num,

    _last_spike: TimeStep,
    // ... learning parameters
}

struct Neuron {
    state: State,
    config: Config,
    i_ext: Num,
    i_inp: Num,

    // XXX: Have a list of `active` synapses, which are active
    // once a neuron fires on it. The `active` synapses track
    // themselves, once they become inactive. Use a similar
    // `decay` process as for STDP for the action potential,
    // so that the shape of the spike is less sharp. A high
    // decay rate can simulate the old behaviour.

    // Spike-Time Dependent Plasticity
    //
    // when a neuron fires, we set this value to STDP_FIRE_RESET
    // (0.1 for example), and during every time-step we decay
    // it by STDP_DECAY e.g. 0.95.
    stdp: Num,

    // XXX: Rename to Connection and incoming/outgoing?
    pre_synapses: Vec<SynapseId>,
    post_synapses: Vec<SynapseId>,
}

struct Network {
    neurons: Vec<Neuron>,
    synapses: Vec<Synapse>,
}

impl Network {
    fn new() -> Network {
        Network {
            neurons: Vec::new(),
            synapses: Vec::new()
        }
    }

    fn create_neuron(&mut self, config: Config) -> NeuronId {
        let neuron = Neuron {
            state: State::new(),
            config: config,
            stdp: 0.0,
            i_ext: 0.0,
            i_inp: 0.0,
            pre_synapses: Vec::new(),
            post_synapses: Vec::new(),
        };
        let neuron_id = self.neurons.len() as u32;
        self.neurons.push(neuron);
        return neuron_id;
    }

    fn connect(&mut self, pre_neuron: NeuronId, post_neuron: NeuronId, delay: Delay, weight: Num) -> SynapseId {
        assert!((pre_neuron as usize) < self.neurons.len());
        assert!((post_neuron as usize) < self.neurons.len());
        assert!(delay > 0);
        assert!(delay <= MAX_DELAY);

        let synapse = Synapse {
            pre_neuron: pre_neuron,
            post_neuron: post_neuron,
            delay: delay,
            weight: weight,
            eff_d: 0.0,
            _last_spike: 0, // XXX
        };
        let synapse_id = self.synapses.len() as u32;

        self.synapses.push(synapse);
        self.neurons[pre_neuron as usize].post_synapses.push(synapse_id);
        self.neurons[post_neuron as usize].pre_synapses.push(synapse_id);

        return synapse_id;
    }

    fn update_state(&mut self, time_step: TimeStep, future_spikes: &mut Vec<Vec<SynapseId>>) {
        //for (i, mut neuron) in network.neurons.iter_mut().enumerate() {
        for i in 0 .. self.neurons.len() {
            let syn_i = self.neurons[i].i_ext + self.neurons[i].i_inp;

            let (new_state, fired) = self.neurons[i].state.step_1ms(syn_i, &self.neurons[i].config);
            self.neurons[i].state = new_state;

            // decay STDP
            self.neurons[i].stdp *= STDP_DECAY;

            if fired {
                // Reset the neurons STDP to a high value.
                self.neurons[i].stdp = STDP_FIRE_RESET;

                println!("Neuron {} fired at {} ms", i, time_step);
                for &syn_id in self.neurons[i].post_synapses.iter() {
                    let future = time_step + self.synapses[syn_id as usize].delay as TimeStep;
                    future_spikes[future as usize % MAX_DELAY as usize].push(syn_id);
                }

                // Excite the synapses that might have led to the firing of the underlying neuron.
                // We do this by adding the synapses pre_neuron's STDP value to the synapses eff_d
                // (efficacy derivative) value.
                //
                // We do not update the synapses weight value immediatly, but only once very while
                // (TODO), so that STDP reflects more LTP (Long Term Potentiation).
                for &syn_id in self.neurons[i].pre_synapses.iter() {
                    let stdp = self.neurons[self.synapses[syn_id as usize].pre_neuron as usize].stdp;
                    self.synapses[syn_id as usize].eff_d += stdp;
                }
            }
        }
    }

    fn update_synapse_weights(&mut self, min_syn_weight: Num, max_syn_weight: Num, eff_d_decay: Num) {
        for syn in self.synapses.iter_mut() {
            let mut new_weight = syn.weight + syn.eff_d;

            // Restrict synapse weight min_syn_weight .. max_syn_weight
            if new_weight < min_syn_weight {
                new_weight = min_syn_weight;
            }
            else if new_weight > max_syn_weight {
                new_weight = max_syn_weight;
            }
            syn.weight = new_weight;
            syn.eff_d *= eff_d_decay; // decay
        }
    }

}

fn main() {
    const PARAMS : &'static [(&'static str, &'static str)] = &[
        ("Neuron 1 [7 pA current 200..700ms]", "blue"),
        //("Neuron 2 [2.69 pA current 200..700ms]", 2.69, "red"),
        ("Neuron 2 [0.0 pA current 200..700ms]", "red"),
        //("Neuron 3 [2.7 pA current 200..700ms]", 2.7, "green")
    ];

    let mut network = Network::new();

    let n1 = network.create_neuron(Config::regular_spiking());
    let n2 = network.create_neuron(Config::regular_spiking());
    //let n3 = network.create_neuron(Config::regular_spiking());

    let external_inputs: &[(NeuronId, TimeStep, Num)] = &[
        (n1, 200, 7.0),
        (n1, 701, 0.0)
    ];

    // We use a cyclic buffer
    // We use (time_step % MAX_DELAY) as index into the futures_spike array
    let mut future_spikes: Vec<Vec<SynapseId>> = (0..MAX_DELAY as usize).map(|_| Vec::new()).collect();

    let _ = network.connect(n1, n2, 10, 7.0);
    let _ = network.connect(n1, n2, 5, 7.0);
    let _ = network.connect(n1, n2, 2, 7.0);
    let _ = network.connect(n1, n2, 2, 7.0);
    let _ = network.connect(n2, n2, 20, 7.0);
    let _ = network.connect(n2, n2, 20, 7.0);

    let mut states: Vec<_> = PARAMS.iter().map(|_| Vec::new()).collect();

    let mut time_step: TimeStep = 0;

    while time_step <= 1_000 {
        // record current state
        for (i, neuron) in network.neurons.iter().enumerate() {
            states[i].push(neuron.state);
        }
        time_step += 1;

        // Clear all input currents
        for neuron in network.neurons.iter_mut() {
            neuron.i_inp = 0.0;
        }

        // get all synapse input
        {
            let current_spikes = &mut future_spikes[(time_step % (MAX_DELAY as TimeStep)) as usize];
            for &syn_fired in current_spikes.iter() {
                println!("time: {}. input from synapse: {}", time_step, syn_fired);
                let (weight, pre_neuron, post_neuron) = {
                    let syn = &network.synapses[syn_fired as usize];
                    (syn.weight, syn.pre_neuron, syn.post_neuron)
                };
                network.neurons[post_neuron as usize].i_inp += weight;

                // whenever a spike arrives here at it's post_neuron, this means, that
                // the pre-neuron fired some time ago (delay time-steps). It can be the
                // case that the post_neuron has fired ealier, in which case we have to
                // depress the synapse according to the STDP rule.
                network.synapses[syn_fired as usize].eff_d += network.neurons[pre_neuron as usize].stdp - network.neurons[post_neuron as usize].stdp;
            }
            current_spikes.clear();
        }

        // set external inputs
        for &(n_id, at, current) in external_inputs {
            if time_step == at {
                network.neurons[n_id as usize].i_ext = current;
            }
        }

        network.update_state(time_step, &mut future_spikes);

        if time_step % 500 == 0 {
            // Update synapse weights every 10 ms
            network.update_synapse_weights(0.0, 10.0, 0.9);
        }
    }

    {
        let mut fg = Figure::new();
        {
            let mut diag = fg.axes2d().
                set_x_label("time (ms)", &[]).
                set_y_label("membrane potential v (mV)", &[]);
            for (i, &p) in PARAMS.iter().enumerate() {
                diag.lines(states[i].iter().enumerate().map(|(i, _)| i as f32), states[i].iter().map(|s| s.potential()), &[Caption(p.0), Color(p.1)]);
            }
        }
        fg.show();
    }

    /*
    let mut fg = Figure::new();
    {
        let mut diag = fg.axes2d().
            set_x_label("membrane potential v (mV)", &[]).
            set_y_label("recovery variable u", &[]);
        for (i, &p) in PARAMS.iter().enumerate() {
            diag.lines(states[i].iter().map(|s| s.potential()), states[i].iter().map(|s| s.recovery()), &[Caption(p.0), Color(p.2)]);
        }
    }
    fg.show();
    */

}
<|endoftext|>


<commit_before>extern crate sdl2;
extern crate assimp;
extern crate cgmath;

use assimp::Importer;
use sdl2::pixels::Color;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::rect::Point;
use sdl2::render::Renderer;
use std::cmp::Ordering;
use cgmath::InnerSpace;
use cgmath::Vector3;
use cgmath::Zero;

use assimp::Vector3D;

fn sort_points_by_y(points: &mut Vec<Point>) {
    for _ in 0..(points.len() - 1) {
        for j in 0..(points.len() - 1) {
            if points[j].y() > points[j + 1].y() {
                points.swap(j, j + 1);
            }
        }
    }
}

fn clamp<N>(a: N, min: N, max: N) -> N where N: PartialOrd {
    if a < min { return min }
    if a > max { return max }
    a
}

fn interpolate(min: f32, max: f32, gradient: f32) -> f32 {
    min + (max - min) * clamp(gradient, 0., 1.)
}

fn get_line_points(start: Point, end: Point) -> Vec<Point> {
    let mut x0 = start.x();
    let mut y0 = start.y();
    let mut x1 = end.x();
    let mut y1 = end.y();

    let steep = (y1 - y0).abs() > (x1 - x0).abs();

    if steep {
        std::mem::swap(&mut x0, &mut y0);
        std::mem::swap(&mut x1, &mut y1);
    }

    let reverse = x0 > x1;

    if reverse {
        std::mem::swap(&mut x0, &mut x1);
        std::mem::swap(&mut y0, &mut y1);
    }

    let dx = x1 - x0;
    let dy = (y1 - y0).abs();

    let mut err = dx / 2;
    let mut y = y0;
    let ystep = match y0.cmp(&y1) {
        Ordering::Less => 1,
        _ => -1
    };

    let mut points: Vec<Point> = vec![];

    for x in x0..x1 {
        if steep {
            points.push(Point::new(y, x));
        } else {
            points.push(Point::new(x, y));
        }

        err -= dy;

        if err < 0 {
            y += ystep;
            err += dx;
        }
    }

    points
}

trait TinyRenderer {
    fn pixel(&mut self, Point, Color);
    fn line(&mut self, Point, Point, Color);
    fn process_scan_ine(&mut self, i32, Point, Point, Point, Point, Color);
    fn triangle(&mut self, Point, Point, Point, Color);
}

impl<'a> TinyRenderer for Renderer<'a> {
    fn pixel(&mut self, p: Point, c: Color) {
        let current_color = self.draw_color();

        self.set_draw_color(c);
        self.draw_point(p).unwrap();
        self.set_draw_color(current_color);
    }

    fn line(&mut self, start: Point, end: Point, c: Color) {
        let current_color = self.draw_color();
        self.set_draw_color(c);

        let points = get_line_points(start, end);

        for p in 0..points.len() {
            self.draw_point(points[p]).unwrap();
        }

        self.set_draw_color(current_color);
    }

    fn process_scan_ine(&mut self, y: i32, pa: Point, pb: Point, pc: Point, pd: Point, c: Color) {
        let current_color = self.draw_color();
        self.set_draw_color(c);

        let grad1 = match (&pa.y()).cmp(&pb.y()) {
            Ordering::Equal => 1.,
            _ => (y - pa.y()) as f32 / (pb.y()- pa.y()) as f32
        };

        let grad2 = match (&pc.y()).cmp(&pd.y()) {
            Ordering::Equal => 1.,
            _ => (y - pc.y()) as f32 / (pd.y() - pc.y()) as f32
        };

        let sx = interpolate(pa.x() as f32, pb.x() as f32, grad1) as i32;
        let ex = interpolate(pc.x() as f32, pd.x() as f32, grad2) as i32;

        for x in sx..ex {
            self.draw_point(Point::new(x, y)).unwrap();
        }

        self.set_draw_color(current_color);
    }

    fn triangle(&mut self, p0: Point, p1: Point, p2: Point, c: Color) {
        let mut points = vec![p0, p1, p2];
        sort_points_by_y(&mut points);

        let dp0p1 = match (points[1].y() - points[0].y()).cmp(&0) {
            Ordering::Greater => (points[1].x() - points[0].x()) as f32 / (points[1].y() - points[0].y()) as f32,
            _ => 0.
        };

        let dp0p2 = match (points[2].y() - points[0].y()).cmp(&0) {
            Ordering::Greater => (points[2].x() - points[0].x()) as f32 / (points[2].y() - points[0].y()) as f32,
            _ => 0.
        };

        for y in points[0].y()..points[2].y() {
            if y < points[1].y() {
                if dp0p1 > dp0p2 {
                    self.process_scan_ine(y, points[0], points[2], points[0], points[1], c);
                } else {
                    self.process_scan_ine(y, points[0], points[1], points[0], points[2], c);
                }
            } else {
                if dp0p1 > dp0p2 {
                    self.process_scan_ine(y, points[0], points[2], points[1], points[2], c);
                } else {
                    self.process_scan_ine(y, points[1], points[2], points[0], points[2], c);
                }
            }
        }
    }
}

fn main() {
    let (width, height) = (700, 700);
    let importer = Importer::new();
    let scene = importer.read_file("resources/model.obj").unwrap();

    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();

    let window = video_subsystem.window("tinyrenderer-rs", width, height)
        .position_centered()
        .opengl()
        .build()
        .unwrap();

    let mut renderer = window.renderer().build().unwrap();

    renderer.set_draw_color(Color::RGB(0, 0, 0));
    renderer.clear();

    let light_dir = Vector3::new(0., 0., -1.);

    for mesh in scene.mesh_iter() {
        for face in mesh.face_iter() {
            let mut screen_coords: [Point; 3] = [Point::new(0, 0); 3];
            let mut world_coords: [Vector3<f32>; 3] = [Vector3::zero(); 3];

            for j in 0..3 {
                let v = match mesh.get_vertex(face[j]) {
                    Some(x) => x,
                    None => Vector3D::new(0., 0., 0.)
                };

                let (p1, p2) = ((v.x + 1.) * width as f32 / 2., (v.y + 1.) * height as f32 / 2.);
                screen_coords[j as usize] = Point::new(p1 as i32, (height as f32 - p2) as i32);

                world_coords[j as usize] = v.into();
            }

            let n = (world_coords[2] - world_coords[0]).cross(world_coords[1] - world_coords[0]).normalize();
            let intensity = n.dot(light_dir);

            if intensity > 0.0 {
                renderer.triangle(
                    screen_coords[0],
                    screen_coords[1],
                    screen_coords[2],
                    Color::RGB(
                        (intensity * 255.) as u8,
                        (intensity * 255.) as u8,
                        (intensity * 255.) as u8
                    )
                );
            }
        }
    }

    renderer.present();

    let mut event_pump = sdl_context.event_pump().unwrap();

    'running: loop {
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                    break 'running
                },
                _ => {}
            }
        }
        //code here
    }
}
<commit_msg>Swap sx and ex to always go from left to right<commit_after>extern crate sdl2;
extern crate assimp;
extern crate cgmath;

use assimp::Importer;
use sdl2::pixels::Color;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::rect::Point;
use sdl2::render::Renderer;
use std::cmp::Ordering;
use cgmath::InnerSpace;
use cgmath::Vector3;
use cgmath::Zero;

use assimp::Vector3D;

fn sort_points_by_y(points: &mut Vec<Point>) {
    for _ in 0..(points.len() - 1) {
        for j in 0..(points.len() - 1) {
            if points[j].y() > points[j + 1].y() {
                points.swap(j, j + 1);
            }
        }
    }
}

fn clamp<N>(a: N, min: N, max: N) -> N where N: PartialOrd {
    if a < min { return min }
    if a > max { return max }
    a
}

fn interpolate(min: f32, max: f32, gradient: f32) -> f32 {
    min + (max - min) * clamp(gradient, 0., 1.)
}

fn get_line_points(start: Point, end: Point) -> Vec<Point> {
    let mut x0 = start.x();
    let mut y0 = start.y();
    let mut x1 = end.x();
    let mut y1 = end.y();

    let steep = (y1 - y0).abs() > (x1 - x0).abs();

    if steep {
        std::mem::swap(&mut x0, &mut y0);
        std::mem::swap(&mut x1, &mut y1);
    }

    let reverse = x0 > x1;

    if reverse {
        std::mem::swap(&mut x0, &mut x1);
        std::mem::swap(&mut y0, &mut y1);
    }

    let dx = x1 - x0;
    let dy = (y1 - y0).abs();

    let mut err = dx / 2;
    let mut y = y0;
    let ystep = match y0.cmp(&y1) {
        Ordering::Less => 1,
        _ => -1
    };

    let mut points: Vec<Point> = vec![];

    for x in x0..x1 {
        if steep {
            points.push(Point::new(y, x));
        } else {
            points.push(Point::new(x, y));
        }

        err -= dy;

        if err < 0 {
            y += ystep;
            err += dx;
        }
    }

    points
}

trait TinyRenderer {
    fn pixel(&mut self, Point, Color);
    fn line(&mut self, Point, Point, Color);
    fn process_scan_ine(&mut self, i32, Point, Point, Point, Point, Color);
    fn triangle(&mut self, Point, Point, Point, Color);
}

impl<'a> TinyRenderer for Renderer<'a> {
    fn pixel(&mut self, p: Point, c: Color) {
        let current_color = self.draw_color();

        self.set_draw_color(c);
        self.draw_point(p).unwrap();
        self.set_draw_color(current_color);
    }

    fn line(&mut self, start: Point, end: Point, c: Color) {
        let current_color = self.draw_color();
        self.set_draw_color(c);

        let points = get_line_points(start, end);

        for p in 0..points.len() {
            self.draw_point(points[p]).unwrap();
        }

        self.set_draw_color(current_color);
    }

    fn process_scan_ine(&mut self, y: i32, pa: Point, pb: Point, pc: Point, pd: Point, c: Color) {
        let current_color = self.draw_color();
        self.set_draw_color(c);

        let grad1 = match (&pa.y()).cmp(&pb.y()) {
            Ordering::Equal => 1.,
            _ => (y - pa.y()) as f32 / (pb.y()- pa.y()) as f32
        };

        let grad2 = match (&pc.y()).cmp(&pd.y()) {
            Ordering::Equal => 1.,
            _ => (y - pc.y()) as f32 / (pd.y() - pc.y()) as f32
        };

        let mut sx = interpolate(pa.x() as f32, pb.x() as f32, grad1) as i32;
        let mut ex = interpolate(pc.x() as f32, pd.x() as f32, grad2) as i32;

        if sx > ex {
            std::mem::swap(&mut sx, &mut ex);
        }

        for x in sx..ex {
            self.draw_point(Point::new(x, y)).unwrap();
        }

        self.set_draw_color(current_color);
    }

    fn triangle(&mut self, p0: Point, p1: Point, p2: Point, c: Color) {
        let mut points = vec![p0, p1, p2];
        sort_points_by_y(&mut points);

        let dp0p1 = match (points[1].y() - points[0].y()).cmp(&0) {
            Ordering::Greater => (points[1].x() - points[0].x()) as f32 / (points[1].y() - points[0].y()) as f32,
            _ => 0.
        };

        let dp0p2 = match (points[2].y() - points[0].y()).cmp(&0) {
            Ordering::Greater => (points[2].x() - points[0].x()) as f32 / (points[2].y() - points[0].y()) as f32,
            _ => 0.
        };

        for y in points[0].y()..points[2].y() {
            if y < points[1].y() {
                if dp0p1 > dp0p2 {
                    self.process_scan_ine(y, points[0], points[2], points[0], points[1], c);
                } else {
                    self.process_scan_ine(y, points[0], points[1], points[0], points[2], c);
                }
            } else {
                if dp0p1 > dp0p2 {
                    self.process_scan_ine(y, points[0], points[2], points[1], points[2], c);
                } else {
                    self.process_scan_ine(y, points[1], points[2], points[0], points[2], c);
                }
            }
        }
    }
}

fn main() {
    let (width, height) = (700, 700);
    let importer = Importer::new();
    let scene = importer.read_file("resources/model.obj").unwrap();

    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();

    let window = video_subsystem.window("tinyrenderer-rs", width, height)
        .position_centered()
        .opengl()
        .build()
        .unwrap();

    let mut renderer = window.renderer().build().unwrap();

    renderer.set_draw_color(Color::RGB(0, 0, 0));
    renderer.clear();

    let light_dir = Vector3::new(0., 0., -1.);

    for mesh in scene.mesh_iter() {
        for face in mesh.face_iter() {
            let mut screen_coords: [Point; 3] = [Point::new(0, 0); 3];
            let mut world_coords: [Vector3<f32>; 3] = [Vector3::zero(); 3];

            for j in 0..3 {
                let v = match mesh.get_vertex(face[j]) {
                    Some(x) => x,
                    None => Vector3D::new(0., 0., 0.)
                };

                let (p1, p2) = ((v.x + 1.) * width as f32 / 2., (v.y + 1.) * height as f32 / 2.);
                screen_coords[j as usize] = Point::new(p1 as i32, (height as f32 - p2) as i32);

                world_coords[j as usize] = v.into();
            }

            let n = (world_coords[2] - world_coords[0]).cross(world_coords[1] - world_coords[0]).normalize();
            let intensity = n.dot(light_dir);

            if intensity > 0.0 {
                renderer.triangle(
                    screen_coords[0],
                    screen_coords[1],
                    screen_coords[2],
                    Color::RGB(
                        (intensity * 255.) as u8,
                        (intensity * 255.) as u8,
                        (intensity * 255.) as u8
                    )
                );
            }
        }
    }

    renderer.present();

    let mut event_pump = sdl_context.event_pump().unwrap();

    'running: loop {
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                    break 'running
                },
                _ => {}
            }
        }
        //code here
    }
}
<|endoftext|>


<commit_before>// Copyright Istio Authors
//
// 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.

extern crate core;
#[cfg(feature = "gperftools")]
extern crate gperftools;

use ztunnel::*;

// #[global_allocator]
// static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;

// #[global_allocator]
// static GLOBAL: tcmalloc::TCMalloc = tcmalloc::TCMalloc;

fn main() -> anyhow::Result<()> {
    telemetry::setup_logging();
    let config: config::Config = Default::default();
    tokio::runtime::Builder::new_multi_thread()
        .worker_threads(config.num_worker_threads)
        .enable_all()
        .build()
        .unwrap()
        .block_on(async move { run(config).await })
}

async fn run(cfg: config::Config) -> anyhow::Result<()> {
    // For now we don't need a complex CLI, so rather than pull in dependencies just use basic argv[1]
    match std::env::args().nth(1).as_deref() {
        None | Some("proxy") => proxy(cfg).await,
        Some("version") => version().await,
        Some(unknown) => {
            eprintln!("unknown command: {unknown}");
            std::process::exit(1)
        }
    }
}

async fn version() -> anyhow::Result<()> {
    println!("{}", version::BuildInfo::new());
    Ok(())
}

async fn proxy(cfg: config::Config) -> anyhow::Result<()> {
    app::build(cfg).await?.spawn().await
}
<commit_msg>Change the worker thread name for tracing easily (#178)<commit_after>// Copyright Istio Authors
//
// 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.

extern crate core;
#[cfg(feature = "gperftools")]
extern crate gperftools;

use std::sync::atomic::{AtomicUsize, Ordering};
use ztunnel::*;

// #[global_allocator]
// static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;

// #[global_allocator]
// static GLOBAL: tcmalloc::TCMalloc = tcmalloc::TCMalloc;

fn main() -> anyhow::Result<()> {
    telemetry::setup_logging();
    let config: config::Config = Default::default();
    tokio::runtime::Builder::new_multi_thread()
        .worker_threads(config.num_worker_threads)
        .thread_name_fn(|| {
            static ATOMIC_ID: AtomicUsize = AtomicUsize::new(0);
            let id = ATOMIC_ID.fetch_add(1, Ordering::SeqCst);
            format!("proxy-{}", id)
        })
        .enable_all()
        .build()
        .unwrap()
        .block_on(async move { run(config).await })
}

async fn run(cfg: config::Config) -> anyhow::Result<()> {
    // For now we don't need a complex CLI, so rather than pull in dependencies just use basic argv[1]
    match std::env::args().nth(1).as_deref() {
        None | Some("proxy") => proxy(cfg).await,
        Some("version") => version().await,
        Some(unknown) => {
            eprintln!("unknown command: {unknown}");
            std::process::exit(1)
        }
    }
}

async fn version() -> anyhow::Result<()> {
    println!("{}", version::BuildInfo::new());
    Ok(())
}

async fn proxy(cfg: config::Config) -> anyhow::Result<()> {
    app::build(cfg).await?.spawn().await
}
<|endoftext|>


<commit_before>extern crate docopt;
extern crate rustc_serialize;
extern crate kafka;

use docopt::Docopt;
use kafka::client::KafkaClient;
use std::io;
use std::io::prelude::*;

// usage string
static USAGE: &'static str = "
ktee - tee for Kafka.

Usage:
    ktee -b BROKER -t TOPIC
    ktee (-h | --help)

Options:
    -h, --help                  Show this message.
    -b BROKER, --broker=BROKER  Kafka broker [default: localhost:9092].
    -t TOPIC, --topic=TOPIC     Kafka topic.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_broker: String,
    flag_topic: String,
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());

    let mut client = KafkaClient::new(vec!(args.flag_broker));
    let meta_res = client.load_metadata_all();
    if meta_res.is_err() {
        match meta_res.err() {
            Some(err) => println!("Error: {}", err),
            None => println!("Non-specific error")
        }
        return;
    }

    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let res = client.send_message(
            1,                           // Required Acks
            0,                           // Timeout
            args.flag_topic.to_string(), // Topic
            line.unwrap().into_bytes()   // Message
        );
        if res.is_err() {
            match res.err() {
                Some(err) => println!("{}", err),
                None => println!("Non-specific error")
            }
        }
    }
}
<commit_msg>Made broker command-line parameter optional since it has a default<commit_after>extern crate docopt;
extern crate rustc_serialize;
extern crate kafka;

use docopt::Docopt;
use kafka::client::KafkaClient;
use std::io;
use std::io::prelude::*;

// usage string
static USAGE: &'static str = "
ktee - tee for Kafka.

Usage:
    ktee [-b BROKER] -t TOPIC
    ktee (-h | --help)

Options:
    -h, --help                  Show this message.
    -b BROKER, --broker=BROKER  Kafka broker [default: localhost:9092].
    -t TOPIC, --topic=TOPIC     Kafka topic.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_broker: String,
    flag_topic: String,
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());

    let mut client = KafkaClient::new(vec!(args.flag_broker));
    let meta_res = client.load_metadata_all();
    if meta_res.is_err() {
        match meta_res.err() {
            Some(err) => println!("Error: {}", err),
            None => println!("Non-specific error")
        }
        return;
    }

    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let res = client.send_message(
            1,                           // Required Acks
            0,                           // Timeout
            args.flag_topic.to_string(), // Topic
            line.unwrap().into_bytes()   // Message
        );
        if res.is_err() {
            match res.err() {
                Some(err) => println!("{}", err),
                None => println!("Non-specific error")
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate rand;
extern crate libshft;

use clap::{Arg, App};
use rand::SeedableRng;
use rand::isaac;
use std::io;
use std::io::{Read, Write};
use std::fs::File;
use std::path::Path;
use libshft::grammar::Grammar;
use libshft::parse::{ParsedFile, slurp};
use libshft::fuzz::fuzz_one;

#[cfg(test)]
mod test {
    use libshft::grammar::{Grammar, GrammarDef};
    use libshft::parse::slurp;
    use libshft::fuzz::FuzzFile;

    fn roundtrip(grammar: &Grammar, buf: &[u8]) -> bool {
        let parsed_file = slurp(grammar, buf);
        println!("parsed = {:?}", parsed_file.dump());
        let ff = FuzzFile::new(&parsed_file);
        let serialized = ff.serialize();
        println!("serialized = {:#?}", serialized);
        serialized == buf
    }

    #[test]
    fn test_whitespace() {
        let grammar = Grammar::new(vec![], vec![b" ".to_vec()]);
        let buf = b"1 2 3";
        assert!(roundtrip(&grammar, buf))
    }

    #[test]
    fn test_two_whitespaces() {
        let grammar = Grammar::new(vec![], vec![b" ".to_vec(), b"\r\n".to_vec()]);
        let buf = b"1 2\r\n3 \r\n4";
        assert!(roundtrip(&grammar, buf))
    }

    #[test]
    fn test_delim() {
        let grammar = Grammar::new(vec![
            GrammarDef::Delim(vec![b'<', b'<'], vec![b'>', b'>']),
        ], vec![]);
        assert!(roundtrip(&grammar, b"1<<2<<3>>4>>5"));
        assert!(roundtrip(&grammar, b"1<<2<<3>>4"));
        assert!(roundtrip(&grammar, b"1<<2>>3>>4"));
        assert!(roundtrip(&grammar, b"1<<2"));
        assert!(roundtrip(&grammar, b"1>>2"));
    }
}

fn read_file<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
    let mut f = File::open(path)?;
    let mut buffer = Vec::new();

    match f.read_to_end(&mut buffer) {
        Ok(_) => Ok(buffer),
        Err(err) => Err(err),
    }
}

fn do_fuzz<'buf>(parsed_file: &ParsedFile<'buf>) {
    let mut rng = isaac::Isaac64Rng::from_seed(&[1, 2, 3, 4]);
    for i in 0..50000 {
        let fuzzed = fuzz_one(parsed_file, &mut rng, 5);

        let out_filename = format!("out/{}.pdf", i);
        let mut file = File::create(out_filename).expect("oops");
        file.write_all(&fuzzed[..]).expect("oops")
    }
}

fn main() {
    let matches = App::new("super-happy-fuzz-time")
        .arg(Arg::with_name("INPUT")
            .help("File to fuzz")
            .required(true)
            .index(1))
        .arg(Arg::with_name("CONFIG")
            .help("Config file")
            .long("config")
            .number_of_values(1)
            .required(true))
        .arg(Arg::with_name("dump")
            .help("Dump input file")
            .long("dump"))
        .get_matches();

    let input_filename = matches.value_of("INPUT").unwrap();
    let config_filename = matches.value_of("CONFIG").unwrap();

    if let Ok(buf) = read_file(input_filename) {
        let grammar = Grammar::from_path(config_filename);
        let parsed_file = slurp(&grammar, &buf);

        if matches.occurrences_of("dump") != 0 {
            println!("{}", parsed_file.dump());
        } else {
            do_fuzz(&parsed_file);
        }
    }
}
<commit_msg>Add separate dump and fuzz commands.<commit_after>extern crate clap;
extern crate rand;
extern crate libshft;

use clap::{Arg, App, SubCommand};
use rand::SeedableRng;
use rand::isaac;
use std::io;
use std::io::{Read, Write};
use std::fs::File;
use std::path::Path;
use libshft::grammar::Grammar;
use libshft::parse::{ParsedFile, slurp};
use libshft::fuzz::fuzz_one;

#[cfg(test)]
mod test {
    use libshft::grammar::{Grammar, GrammarDef};
    use libshft::parse::slurp;
    use libshft::fuzz::FuzzFile;

    fn roundtrip(grammar: &Grammar, buf: &[u8]) -> bool {
        let parsed_file = slurp(grammar, buf);
        println!("parsed = {:?}", parsed_file.dump());
        let ff = FuzzFile::new(&parsed_file);
        let serialized = ff.serialize();
        println!("serialized = {:#?}", serialized);
        serialized == buf
    }

    #[test]
    fn test_whitespace() {
        let grammar = Grammar::new(vec![], vec![b" ".to_vec()]);
        let buf = b"1 2 3";
        assert!(roundtrip(&grammar, buf))
    }

    #[test]
    fn test_two_whitespaces() {
        let grammar = Grammar::new(vec![], vec![b" ".to_vec(), b"\r\n".to_vec()]);
        let buf = b"1 2\r\n3 \r\n4";
        assert!(roundtrip(&grammar, buf))
    }

    #[test]
    fn test_delim() {
        let grammar = Grammar::new(vec![
            GrammarDef::Delim(vec![b'<', b'<'], vec![b'>', b'>']),
        ], vec![]);
        assert!(roundtrip(&grammar, b"1<<2<<3>>4>>5"));
        assert!(roundtrip(&grammar, b"1<<2<<3>>4"));
        assert!(roundtrip(&grammar, b"1<<2>>3>>4"));
        assert!(roundtrip(&grammar, b"1<<2"));
        assert!(roundtrip(&grammar, b"1>>2"));
    }
}

fn read_file<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
    let mut f = File::open(path)?;
    let mut buffer = Vec::new();

    match f.read_to_end(&mut buffer) {
        Ok(_) => Ok(buffer),
        Err(err) => Err(err),
    }
}

fn do_fuzz<'buf>(parsed_file: &ParsedFile<'buf>, iterations: usize) {
    let mut rng = isaac::Isaac64Rng::from_seed(&[1, 2, 3, 4]);
    for i in 0..iterations {
        let fuzzed = fuzz_one(parsed_file, &mut rng, 5);

        let out_filename = format!("out/{}.pdf", i);
        let mut file = File::create(out_filename).expect("oops");
        file.write_all(&fuzzed[..]).expect("oops")
    }
}

fn parse_input_file<'buf>(config_filename: &str, buf: &'buf [u8]) -> ParsedFile<'buf> {
    let grammar = Grammar::from_path(config_filename);
    slurp(&grammar, buf)
}

fn main() {
    let app = App::new("super-happy-fuzz-time")
        .arg(Arg::with_name("INPUT")
            .help("File to fuzz")
            .long("input")
            .short("i")
            .number_of_values(1)
            .required(true))
        .arg(Arg::with_name("CONFIG")
            .help("Config file")
            .long("config")
            .short("c")
            .number_of_values(1)
            .required(true))
        .subcommand(
            SubCommand::with_name("dump")
                .help("Parse and dump input file"))
        .subcommand(
            SubCommand::with_name("fuzz")
                .help("Fuzz input file"));
    let matches = app.clone().get_matches();

    let config_filename = matches.value_of("CONFIG").expect("impossible");
    let input_filename = matches.value_of("INPUT").expect("impossible");

    match matches.subcommand() {
        ("dump", _) => {
            let buf = read_file(input_filename).expect("read_file");
            let parsed_file = parse_input_file(config_filename, &buf[..]);
            println!("{}", parsed_file.dump());
        },
        ("fuzz", _) => {
            let buf = read_file(input_filename).expect("read_file");
            let parsed_file = parse_input_file(config_filename, &buf[..]);
            do_fuzz(&parsed_file, 10);
        },
        _ => {
                let mut out = io::stdout();
                app.write_help(&mut out).expect("app.write_help");
                write!(out, "\n\nMust provide 'dump' or 'fuzz'\n").expect("write newline");
        },
    }
}
<|endoftext|>


<commit_before>#![cfg(feature = "full")]

#[macro_use]
extern crate quote;
extern crate syn;
extern crate synom;
extern crate syntex_pos;
extern crate syntex_syntax;
extern crate walkdir;

use syntex_pos::Span;
use syntex_syntax::ast;
use syntex_syntax::parse::{self, ParseSess, PResult};
use syntex_syntax::codemap::FilePathMapping;
use walkdir::{DirEntry, WalkDir, WalkDirIterator};

use std::fs::File;
use std::io::{self, Read, Write};
use std::panic;
use std::time::Instant;

macro_rules! errorf {
    ($($tt:tt)*) => {
        write!(io::stderr(), $($tt)*).unwrap();
    };
}

fn filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map(|e| e != "rs").unwrap_or(true) {
        return false;
    }
    let path_string = path.to_string_lossy();
    let path_string = if cfg!(windows) {
        path_string.replace('\\', "/").into()
    } else {
        path_string
    };
    // TODO assert that parsing fails on the parse-fail cases
    if path_string.starts_with("tests/rust/src/test/parse-fail") ||
       path_string.starts_with("tests/rust/src/test/compile-fail") {
        return false;
    }

    if path_string.starts_with("tests/rust/src/test/ui") {
        let stderr_path = path.with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    match path_string.as_ref() {
        // TODO better support for attributes
        "tests/rust/src/librustc_data_structures/blake2b.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/incremental/hashes/enum_defs.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/pretty/stmt_expr_attributes.rs" |
        // not actually a test case
        "tests/rust/src/test/run-pass/auxiliary/macro-include-items-expr.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/run-pass/cfg_stmt_expr.rs" |
        // TODO weird glob import
        "tests/rust/src/test/run-pass/import-glob-crate.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/run-pass/inner-attrs-on-impl.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/run-pass/item-attributes.rs" |
        // TODO precedence issue with binop vs poly trait ref
        "tests/rust/src/test/run-pass/try-macro.rs" => false,
        _ => true,
    }
}

/// Abort immediately after this many failures.
fn abort_after() -> u32 {
    if let Ok(s) = std::env::var("ABORT_AFTER_FAILURE") {
        if let Ok(n) = s.parse::<u32>() {
            return n;
        }
    }
    std::u32::MAX
}

#[test]
fn test_round_trip() {
    {
        let min_stack_value = std::env::var("RUST_MIN_STACK").expect("RUST_MIN_STACK env var should be set since some tests require it.");
        let min_stack_value: usize = min_stack_value.parse().expect("RUST_MIN_STACK env var should be set since some tests require it.");
        assert!(min_stack_value >= 16000000);
    }

    let abort_after = abort_after();
    if abort_after == 0 {
        panic!("Skipping all round_trip tests");
    }

    let mut failed = 0;

    let walk = WalkDir::new("tests/rust").sort_by(|a, b| a.cmp(b));
    for entry in walk.into_iter().filter_entry(filter) {
        let entry = entry.unwrap();

        let path = entry.path();
        if path.is_dir() {
            continue;
        }
        errorf!("=== {}: ", path.display());

        let mut file = File::open(path).unwrap();
        let mut content = String::new();
        file.read_to_string(&mut content).unwrap();

        let start = Instant::now();
        let (krate, elapsed) = match content.parse::<syn::Crate>() {
            Ok(krate) => (krate, start.elapsed()),
            Err(msg) => {
                errorf!("syn failed to parse\n{:?}\n", msg);
                failed += 1;
                if failed >= abort_after {
                    panic!("Aborting Immediately due to ABORT_AFTER_FAILURE");
                }
                continue;
            }
        };
        let back = quote!(#krate).to_string();

        let equal = panic::catch_unwind(|| {
            let sess = ParseSess::new(FilePathMapping::empty());
            let before = match syntex_parse(content, &sess) {
                Ok(before) => before,
                Err(mut diagnostic) => {
                    diagnostic.cancel();
                    if diagnostic.message().starts_with("file not found for module") {
                        errorf!("ignore\n");
                    } else {
                        errorf!("ignore - syntex failed to parse original content: {}\n", diagnostic.message());
                    }
                    return true;
                }
            };
            let after = match syntex_parse(back, &sess) {
                Ok(after) => after,
                Err(mut diagnostic) => {
                    errorf!("syntex failed to parse");
                    diagnostic.emit();
                    return false;
                }
            };

            if before == after {
                errorf!("pass in {}ms\n",
                        elapsed.as_secs() * 1000 + elapsed.subsec_nanos() as u64 / 1_000_000);
                true
            } else {
                errorf!("FAIL\nbefore: {}\nafter: {}\n",
                        format!("{:?}", before).replace("\n", ""),
                        format!("{:?}", after).replace("\n", ""));
                false
            }
        });
        match equal {
            Err(_) => errorf!("ignoring syntex panic\n"),
            Ok(true) => {}
            Ok(false) => {
                failed += 1;
                if failed >= abort_after {
                    panic!("Aborting Immediately due to ABORT_AFTER_FAILURE");
                }
            },
        }
    }

    if failed > 0 {
        panic!("{} failures", failed);
    }
}

fn syntex_parse(content: String, sess: &ParseSess) -> PResult<ast::Crate> {
    let name = "test_round_trip".to_string();
    parse::parse_crate_from_source_str(name, content, sess).map(respan_crate)
}

fn respan_crate(krate: ast::Crate) -> ast::Crate {
    use std::rc::Rc;
    use syntex_syntax::ast::{Attribute, Expr, ExprKind, Field, FnDecl, FunctionRetTy, ImplItem,
                             ImplItemKind, ItemKind, Mac, MetaItem, MetaItemKind, MethodSig,
                             NestedMetaItem, NestedMetaItemKind, TraitItem, TraitItemKind, TyParam,
                             Visibility};
    use syntex_syntax::codemap::{self, Spanned};
    use syntex_syntax::fold::{self, Folder};
    use syntex_syntax::parse::token::{Lit, Token};
    use syntex_syntax::ptr::P;
    use syntex_syntax::symbol::Symbol;
    use syntex_syntax::tokenstream::{Delimited, TokenTree};
    use syntex_syntax::util::move_map::MoveMap;
    use syntex_syntax::util::small_vector::SmallVector;

    struct Respanner;

    impl Respanner {
        fn fold_spanned<T>(&mut self, spanned: Spanned<T>) -> Spanned<T> {
            codemap::respan(self.new_span(spanned.span), spanned.node)
        }

        fn fold_lit(&mut self, l: Lit) -> Lit {
            // Give up on comparing literals inside of macros because there are
            // so many equivalent representations of the same literal; they are
            // tested elsewhere
            match l {
                Lit::Byte(_) => Lit::Byte(Symbol::intern("")),
                Lit::Char(_) => Lit::Char(Symbol::intern("")),
                Lit::Integer(_) => Lit::Integer(Symbol::intern("")),
                Lit::Float(_) => Lit::Float(Symbol::intern("")),
                Lit::Str_(_) => Lit::Str_(Symbol::intern("")),
                Lit::ByteStr(_) => Lit::ByteStr(Symbol::intern("")),
                _ => l,
            }
        }
    }

    impl Folder for Respanner {
        fn new_span(&mut self, _: Span) -> Span {
            syntex_pos::DUMMY_SP
        }

        fn fold_item_kind(&mut self, i: ItemKind) -> ItemKind {
            match i {
                ItemKind::Fn(decl, unsafety, constness, abi, generics, body) => {
                    let generics = self.fold_generics(generics);
                    let decl = self.fold_fn_decl(decl);
                    let body = self.fold_block(body);
                    // default fold_item_kind does not fold this span
                    let constness = self.fold_spanned(constness);
                    ItemKind::Fn(decl, unsafety, constness, abi, generics, body)
                }
                _ => fold::noop_fold_item_kind(i, self),
            }
        }

        fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
            e.map(|e| {
                let folded = fold::noop_fold_expr(e, self);
                Expr {
                    node: match folded.node {
                        ExprKind::Lit(l) => {
                            // default fold_expr does not fold lits
                            ExprKind::Lit(l.map(|l| self.fold_spanned(l)))
                        }
                        ExprKind::Binary(op, lhs, rhs) => {
                            // default fold_expr does not fold the op span
                            ExprKind::Binary(self.fold_spanned(op),
                                             self.fold_expr(lhs),
                                             self.fold_expr(rhs))
                        }
                        ExprKind::AssignOp(op, lhs, rhs) => {
                            // default fold_expr does not fold the op span
                            ExprKind::AssignOp(self.fold_spanned(op),
                                               self.fold_expr(lhs),
                                               self.fold_expr(rhs))
                        }
                        other => other,
                    },
                    ..folded
                }
            })
        }

        fn fold_ty_param(&mut self, tp: TyParam) -> TyParam {
            TyParam {
                // default fold_ty_param does not fold the span
                span: self.new_span(tp.span),
                ..fold::noop_fold_ty_param(tp, self)
            }
        }

        fn fold_fn_decl(&mut self, decl: P<FnDecl>) -> P<FnDecl> {
            decl.map(|FnDecl { inputs, output, variadic }| {
                FnDecl {
                    inputs: inputs.move_map(|x| self.fold_arg(x)),
                    output: match output {
                        FunctionRetTy::Ty(ty) => FunctionRetTy::Ty(self.fold_ty(ty)),
                        // default fold_fn_decl does not fold this span
                        FunctionRetTy::Default(span) => FunctionRetTy::Default(self.new_span(span)),
                    },
                    variadic: variadic,
                }
            })
        }

        fn fold_field(&mut self, field: Field) -> Field {
            Field {
                ident: codemap::respan(// default fold_field does not fold this span
                                       self.new_span(field.ident.span),
                                       self.fold_ident(field.ident.node)),
                expr: self.fold_expr(field.expr),
                span: self.new_span(field.span),
                is_shorthand: field.is_shorthand,
                attrs: ast::ThinVec::new(),
            }
        }

        fn fold_trait_item(&mut self, i: TraitItem) -> SmallVector<TraitItem> {
            let noop = fold::noop_fold_trait_item(i, self).expect_one("");
            SmallVector::one(TraitItem {
                                 node: match noop.node {
                                     TraitItemKind::Method(sig, body) => {
                        TraitItemKind::Method(MethodSig {
                                                  constness: self.fold_spanned(sig.constness),
                                                  ..sig
                                              },
                                              body)
                    }
                                     node => node,
                                 },
                                 ..noop
                             })
        }

        fn fold_impl_item(&mut self, i: ImplItem) -> SmallVector<ImplItem> {
            let noop = fold::noop_fold_impl_item(i, self).expect_one("");
            SmallVector::one(ImplItem {
                                 node: match noop.node {
                                     ImplItemKind::Method(sig, body) => {
                        ImplItemKind::Method(MethodSig {
                                                 constness: self.fold_spanned(sig.constness),
                                                 ..sig
                                             },
                                             body)
                    }
                                     node => node,
                                 },
                                 ..noop
                             })
        }

        fn fold_attribute(&mut self, mut at: Attribute) -> Option<Attribute> {
            at.id.0 = 0;
            fold::noop_fold_attribute(at, self)
        }

        fn fold_meta_item(&mut self, meta_item: MetaItem) -> MetaItem {
            let MetaItem { name, node, span } = meta_item;
            MetaItem {
                name: name,
                node: match node {
                    MetaItemKind::Word => MetaItemKind::Word,
                    MetaItemKind::List(nested) => {
                        MetaItemKind::List(nested.move_map(|e| self.fold_meta_list_item(e)))
                    }
                    // default fold_meta_item does not fold the value span
                    MetaItemKind::NameValue(lit) => MetaItemKind::NameValue(self.fold_spanned(lit)),
                },
                span: self.new_span(span),
            }
        }

        fn fold_meta_list_item(&mut self, list_item: NestedMetaItem) -> NestedMetaItem {
            Spanned {
                node: match list_item.node {
                    NestedMetaItemKind::MetaItem(mi) => {
                        NestedMetaItemKind::MetaItem(self.fold_meta_item(mi))
                    }
                    // default fold_meta_list_item does not fold the span
                    NestedMetaItemKind::Literal(lit) => {
                        NestedMetaItemKind::Literal(self.fold_spanned(lit))
                    }
                },
                span: self.new_span(list_item.span),
            }
        }

        fn fold_mac(&mut self, mac: Mac) -> Mac {
            fold::noop_fold_mac(mac, self)
        }

        fn fold_tt(&mut self, tt: TokenTree) -> TokenTree {
            match tt {
                TokenTree::Token(span, ref tok) => {
                    TokenTree::Token(self.new_span(span), self.fold_token(tok.clone()))
                }
                TokenTree::Delimited(span, ref delimed) => {
                    TokenTree::Delimited(self.new_span(span),
                                         Delimited {
                                             delim: delimed.delim,
                                             tts: self.fold_tts(delimed.tts.clone().into()).into(),
                                         })
                }
            }
        }

        fn fold_token(&mut self, t: Token) -> Token {
            match t {
                // default fold_token does not fold literals
                Token::Literal(lit, repr) => Token::Literal(self.fold_lit(lit), repr),
                Token::Ident(id) => Token::Ident(self.fold_ident(id)),
                Token::Lifetime(id) => Token::Lifetime(self.fold_ident(id)),
                Token::Interpolated(nt) => {
                    let nt = match Rc::try_unwrap(nt) {
                        Ok(nt) => nt,
                        Err(nt) => (*nt).clone(),
                    };
                    Token::Interpolated(Rc::new(self.fold_interpolated(nt)))
                }
                Token::SubstNt(ident) => Token::SubstNt(self.fold_ident(ident)),
                _ => t,
            }
        }

        fn fold_vis(&mut self, vis: Visibility) -> Visibility {
            match vis {
                Visibility::Crate(span) => Visibility::Crate(self.new_span(span)),
                _ => fold::noop_fold_vis(vis, self),
            }
        }
    }

    Respanner.fold_crate(krate)
}
<commit_msg>try-macro.rs now succeeds due to precedence changes<commit_after>#![cfg(feature = "full")]

#[macro_use]
extern crate quote;
extern crate syn;
extern crate synom;
extern crate syntex_pos;
extern crate syntex_syntax;
extern crate walkdir;

use syntex_pos::Span;
use syntex_syntax::ast;
use syntex_syntax::parse::{self, ParseSess, PResult};
use syntex_syntax::codemap::FilePathMapping;
use walkdir::{DirEntry, WalkDir, WalkDirIterator};

use std::fs::File;
use std::io::{self, Read, Write};
use std::panic;
use std::time::Instant;

macro_rules! errorf {
    ($($tt:tt)*) => {
        write!(io::stderr(), $($tt)*).unwrap();
    };
}

fn filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map(|e| e != "rs").unwrap_or(true) {
        return false;
    }
    let path_string = path.to_string_lossy();
    let path_string = if cfg!(windows) {
        path_string.replace('\\', "/").into()
    } else {
        path_string
    };
    // TODO assert that parsing fails on the parse-fail cases
    if path_string.starts_with("tests/rust/src/test/parse-fail") ||
       path_string.starts_with("tests/rust/src/test/compile-fail") {
        return false;
    }

    if path_string.starts_with("tests/rust/src/test/ui") {
        let stderr_path = path.with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    match path_string.as_ref() {
        // TODO better support for attributes
        "tests/rust/src/librustc_data_structures/blake2b.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/incremental/hashes/enum_defs.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/pretty/stmt_expr_attributes.rs" |
        // not actually a test case
        "tests/rust/src/test/run-pass/auxiliary/macro-include-items-expr.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/run-pass/cfg_stmt_expr.rs" |
        // TODO weird glob import
        "tests/rust/src/test/run-pass/import-glob-crate.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/run-pass/inner-attrs-on-impl.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/run-pass/item-attributes.rs" => false,
        _ => true,
    }
}

/// Abort immediately after this many failures.
fn abort_after() -> u32 {
    if let Ok(s) = std::env::var("ABORT_AFTER_FAILURE") {
        if let Ok(n) = s.parse::<u32>() {
            return n;
        }
    }
    std::u32::MAX
}

#[test]
fn test_round_trip() {
    {
        let min_stack_value = std::env::var("RUST_MIN_STACK").expect("RUST_MIN_STACK env var should be set since some tests require it.");
        let min_stack_value: usize = min_stack_value.parse().expect("RUST_MIN_STACK env var should be set since some tests require it.");
        assert!(min_stack_value >= 16000000);
    }

    let abort_after = abort_after();
    if abort_after == 0 {
        panic!("Skipping all round_trip tests");
    }

    let mut failed = 0;

    let walk = WalkDir::new("tests/rust").sort_by(|a, b| a.cmp(b));
    for entry in walk.into_iter().filter_entry(filter) {
        let entry = entry.unwrap();

        let path = entry.path();
        if path.is_dir() {
            continue;
        }
        errorf!("=== {}: ", path.display());

        let mut file = File::open(path).unwrap();
        let mut content = String::new();
        file.read_to_string(&mut content).unwrap();

        let start = Instant::now();
        let (krate, elapsed) = match content.parse::<syn::Crate>() {
            Ok(krate) => (krate, start.elapsed()),
            Err(msg) => {
                errorf!("syn failed to parse\n{:?}\n", msg);
                failed += 1;
                if failed >= abort_after {
                    panic!("Aborting Immediately due to ABORT_AFTER_FAILURE");
                }
                continue;
            }
        };
        let back = quote!(#krate).to_string();

        let equal = panic::catch_unwind(|| {
            let sess = ParseSess::new(FilePathMapping::empty());
            let before = match syntex_parse(content, &sess) {
                Ok(before) => before,
                Err(mut diagnostic) => {
                    diagnostic.cancel();
                    if diagnostic.message().starts_with("file not found for module") {
                        errorf!("ignore\n");
                    } else {
                        errorf!("ignore - syntex failed to parse original content: {}\n", diagnostic.message());
                    }
                    return true;
                }
            };
            let after = match syntex_parse(back, &sess) {
                Ok(after) => after,
                Err(mut diagnostic) => {
                    errorf!("syntex failed to parse");
                    diagnostic.emit();
                    return false;
                }
            };

            if before == after {
                errorf!("pass in {}ms\n",
                        elapsed.as_secs() * 1000 + elapsed.subsec_nanos() as u64 / 1_000_000);
                true
            } else {
                errorf!("FAIL\nbefore: {}\nafter: {}\n",
                        format!("{:?}", before).replace("\n", ""),
                        format!("{:?}", after).replace("\n", ""));
                false
            }
        });
        match equal {
            Err(_) => errorf!("ignoring syntex panic\n"),
            Ok(true) => {}
            Ok(false) => {
                failed += 1;
                if failed >= abort_after {
                    panic!("Aborting Immediately due to ABORT_AFTER_FAILURE");
                }
            },
        }
    }

    if failed > 0 {
        panic!("{} failures", failed);
    }
}

fn syntex_parse(content: String, sess: &ParseSess) -> PResult<ast::Crate> {
    let name = "test_round_trip".to_string();
    parse::parse_crate_from_source_str(name, content, sess).map(respan_crate)
}

fn respan_crate(krate: ast::Crate) -> ast::Crate {
    use std::rc::Rc;
    use syntex_syntax::ast::{Attribute, Expr, ExprKind, Field, FnDecl, FunctionRetTy, ImplItem,
                             ImplItemKind, ItemKind, Mac, MetaItem, MetaItemKind, MethodSig,
                             NestedMetaItem, NestedMetaItemKind, TraitItem, TraitItemKind, TyParam,
                             Visibility};
    use syntex_syntax::codemap::{self, Spanned};
    use syntex_syntax::fold::{self, Folder};
    use syntex_syntax::parse::token::{Lit, Token};
    use syntex_syntax::ptr::P;
    use syntex_syntax::symbol::Symbol;
    use syntex_syntax::tokenstream::{Delimited, TokenTree};
    use syntex_syntax::util::move_map::MoveMap;
    use syntex_syntax::util::small_vector::SmallVector;

    struct Respanner;

    impl Respanner {
        fn fold_spanned<T>(&mut self, spanned: Spanned<T>) -> Spanned<T> {
            codemap::respan(self.new_span(spanned.span), spanned.node)
        }

        fn fold_lit(&mut self, l: Lit) -> Lit {
            // Give up on comparing literals inside of macros because there are
            // so many equivalent representations of the same literal; they are
            // tested elsewhere
            match l {
                Lit::Byte(_) => Lit::Byte(Symbol::intern("")),
                Lit::Char(_) => Lit::Char(Symbol::intern("")),
                Lit::Integer(_) => Lit::Integer(Symbol::intern("")),
                Lit::Float(_) => Lit::Float(Symbol::intern("")),
                Lit::Str_(_) => Lit::Str_(Symbol::intern("")),
                Lit::ByteStr(_) => Lit::ByteStr(Symbol::intern("")),
                _ => l,
            }
        }
    }

    impl Folder for Respanner {
        fn new_span(&mut self, _: Span) -> Span {
            syntex_pos::DUMMY_SP
        }

        fn fold_item_kind(&mut self, i: ItemKind) -> ItemKind {
            match i {
                ItemKind::Fn(decl, unsafety, constness, abi, generics, body) => {
                    let generics = self.fold_generics(generics);
                    let decl = self.fold_fn_decl(decl);
                    let body = self.fold_block(body);
                    // default fold_item_kind does not fold this span
                    let constness = self.fold_spanned(constness);
                    ItemKind::Fn(decl, unsafety, constness, abi, generics, body)
                }
                _ => fold::noop_fold_item_kind(i, self),
            }
        }

        fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
            e.map(|e| {
                let folded = fold::noop_fold_expr(e, self);
                Expr {
                    node: match folded.node {
                        ExprKind::Lit(l) => {
                            // default fold_expr does not fold lits
                            ExprKind::Lit(l.map(|l| self.fold_spanned(l)))
                        }
                        ExprKind::Binary(op, lhs, rhs) => {
                            // default fold_expr does not fold the op span
                            ExprKind::Binary(self.fold_spanned(op),
                                             self.fold_expr(lhs),
                                             self.fold_expr(rhs))
                        }
                        ExprKind::AssignOp(op, lhs, rhs) => {
                            // default fold_expr does not fold the op span
                            ExprKind::AssignOp(self.fold_spanned(op),
                                               self.fold_expr(lhs),
                                               self.fold_expr(rhs))
                        }
                        other => other,
                    },
                    ..folded
                }
            })
        }

        fn fold_ty_param(&mut self, tp: TyParam) -> TyParam {
            TyParam {
                // default fold_ty_param does not fold the span
                span: self.new_span(tp.span),
                ..fold::noop_fold_ty_param(tp, self)
            }
        }

        fn fold_fn_decl(&mut self, decl: P<FnDecl>) -> P<FnDecl> {
            decl.map(|FnDecl { inputs, output, variadic }| {
                FnDecl {
                    inputs: inputs.move_map(|x| self.fold_arg(x)),
                    output: match output {
                        FunctionRetTy::Ty(ty) => FunctionRetTy::Ty(self.fold_ty(ty)),
                        // default fold_fn_decl does not fold this span
                        FunctionRetTy::Default(span) => FunctionRetTy::Default(self.new_span(span)),
                    },
                    variadic: variadic,
                }
            })
        }

        fn fold_field(&mut self, field: Field) -> Field {
            Field {
                ident: codemap::respan(// default fold_field does not fold this span
                                       self.new_span(field.ident.span),
                                       self.fold_ident(field.ident.node)),
                expr: self.fold_expr(field.expr),
                span: self.new_span(field.span),
                is_shorthand: field.is_shorthand,
                attrs: ast::ThinVec::new(),
            }
        }

        fn fold_trait_item(&mut self, i: TraitItem) -> SmallVector<TraitItem> {
            let noop = fold::noop_fold_trait_item(i, self).expect_one("");
            SmallVector::one(TraitItem {
                                 node: match noop.node {
                                     TraitItemKind::Method(sig, body) => {
                        TraitItemKind::Method(MethodSig {
                                                  constness: self.fold_spanned(sig.constness),
                                                  ..sig
                                              },
                                              body)
                    }
                                     node => node,
                                 },
                                 ..noop
                             })
        }

        fn fold_impl_item(&mut self, i: ImplItem) -> SmallVector<ImplItem> {
            let noop = fold::noop_fold_impl_item(i, self).expect_one("");
            SmallVector::one(ImplItem {
                                 node: match noop.node {
                                     ImplItemKind::Method(sig, body) => {
                        ImplItemKind::Method(MethodSig {
                                                 constness: self.fold_spanned(sig.constness),
                                                 ..sig
                                             },
                                             body)
                    }
                                     node => node,
                                 },
                                 ..noop
                             })
        }

        fn fold_attribute(&mut self, mut at: Attribute) -> Option<Attribute> {
            at.id.0 = 0;
            fold::noop_fold_attribute(at, self)
        }

        fn fold_meta_item(&mut self, meta_item: MetaItem) -> MetaItem {
            let MetaItem { name, node, span } = meta_item;
            MetaItem {
                name: name,
                node: match node {
                    MetaItemKind::Word => MetaItemKind::Word,
                    MetaItemKind::List(nested) => {
                        MetaItemKind::List(nested.move_map(|e| self.fold_meta_list_item(e)))
                    }
                    // default fold_meta_item does not fold the value span
                    MetaItemKind::NameValue(lit) => MetaItemKind::NameValue(self.fold_spanned(lit)),
                },
                span: self.new_span(span),
            }
        }

        fn fold_meta_list_item(&mut self, list_item: NestedMetaItem) -> NestedMetaItem {
            Spanned {
                node: match list_item.node {
                    NestedMetaItemKind::MetaItem(mi) => {
                        NestedMetaItemKind::MetaItem(self.fold_meta_item(mi))
                    }
                    // default fold_meta_list_item does not fold the span
                    NestedMetaItemKind::Literal(lit) => {
                        NestedMetaItemKind::Literal(self.fold_spanned(lit))
                    }
                },
                span: self.new_span(list_item.span),
            }
        }

        fn fold_mac(&mut self, mac: Mac) -> Mac {
            fold::noop_fold_mac(mac, self)
        }

        fn fold_tt(&mut self, tt: TokenTree) -> TokenTree {
            match tt {
                TokenTree::Token(span, ref tok) => {
                    TokenTree::Token(self.new_span(span), self.fold_token(tok.clone()))
                }
                TokenTree::Delimited(span, ref delimed) => {
                    TokenTree::Delimited(self.new_span(span),
                                         Delimited {
                                             delim: delimed.delim,
                                             tts: self.fold_tts(delimed.tts.clone().into()).into(),
                                         })
                }
            }
        }

        fn fold_token(&mut self, t: Token) -> Token {
            match t {
                // default fold_token does not fold literals
                Token::Literal(lit, repr) => Token::Literal(self.fold_lit(lit), repr),
                Token::Ident(id) => Token::Ident(self.fold_ident(id)),
                Token::Lifetime(id) => Token::Lifetime(self.fold_ident(id)),
                Token::Interpolated(nt) => {
                    let nt = match Rc::try_unwrap(nt) {
                        Ok(nt) => nt,
                        Err(nt) => (*nt).clone(),
                    };
                    Token::Interpolated(Rc::new(self.fold_interpolated(nt)))
                }
                Token::SubstNt(ident) => Token::SubstNt(self.fold_ident(ident)),
                _ => t,
            }
        }

        fn fold_vis(&mut self, vis: Visibility) -> Visibility {
            match vis {
                Visibility::Crate(span) => Visibility::Crate(self.new_span(span)),
                _ => fold::noop_fold_vis(vis, self),
            }
        }
    }

    Respanner.fold_crate(krate)
}
<|endoftext|>


<commit_before>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![doc(html_root_url = "https://docs.rs/serde_test/0.9.13")]

#[macro_use]
extern crate serde;

mod ser;
mod de;
mod error;

mod token;
mod assert;

pub use token::Token;
pub use assert::{assert_tokens, assert_ser_tokens, assert_ser_tokens_error, assert_de_tokens,
                 assert_de_tokens_error};

// Not public API.
#[doc(hidden)]
pub use de::Deserializer;
<commit_msg>Crate-level documentation for serde_test<commit_after>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! This crate provides a convenient concise way to write unit tests for
//! implementations of [`Serialize`] and [`Deserialize`].
//!
//! [`Serialize`]: https://docs.serde.rs/serde/ser/trait.Serialize.html
//! [`Deserialize`]: https://docs.serde.rs/serde/de/trait.Deserialize.html
//!
//! The `Serialize` impl for a value can be characterized by the sequence of
//! [`Serializer`] calls that are made in the course of serializing the value,
//! so `serde_test` provides a [`Token`] abstraction which corresponds roughly
//! to `Serializer` method calls. There is an [`assert_ser_tokens`] function to
//! test that a value serializes to a particular sequence of method calls, an
//! [`assert_de_tokens`] function to test that a value can be deserialized from
//! a particular sequence of method calls, and an [`assert_tokens`] function to
//! test both directions. There are also functions to test expected failure
//! conditions.
//!
//! [`Serializer`]: https://docs.serde.rs/serde/ser/trait.Serializer.html
//! [`Token`]: https://docs.serde.rs/serde_test/enum.Token.html
//! [`assert_ser_tokens`]: https://docs.serde.rs/serde_test/fn.assert_ser_tokens.html
//! [`assert_de_tokens`]: https://docs.serde.rs/serde_test/fn.assert_de_tokens.html
//! [`assert_tokens`]: https://docs.serde.rs/serde_test/fn.assert_tokens.html
//!
//! Here is an example from the [`linked-hash-map`] crate.
//!
//! [`linked-hash-map`]: https://github.com/contain-rs/linked-hash-map
//!
//! ```rust
//! # extern crate serde;
//! #
//! # macro_rules! ignore {
//! #     ($($tt:tt)+) => {}
//! # }
//! #
//! # ignore! {
//! extern crate linked_hash_map;
//! use linked_hash_map::LinkedHashMap;
//! # }
//!
//! extern crate serde_test;
//! use serde_test::{Token, assert_tokens};
//!
//! # use std::fmt;
//! # use std::marker::PhantomData;
//! #
//! # use serde::ser::{Serialize, Serializer, SerializeMap};
//! # use serde::de::{Deserialize, Deserializer, Visitor, MapAccess};
//! #
//! # // Dumb immitation of LinkedHashMap.
//! # #[derive(PartialEq, Debug)]
//! # struct LinkedHashMap<K, V>(Vec<(K, V)>);
//! #
//! # impl<K, V> LinkedHashMap<K, V> {
//! #     fn new() -> Self {
//! #         LinkedHashMap(Vec::new())
//! #     }
//! #
//! #     fn insert(&mut self, k: K, v: V) {
//! #         self.0.push((k, v));
//! #     }
//! # }
//! #
//! # impl<K, V> Serialize for LinkedHashMap<K, V>
//! #     where K: Serialize,
//! #           V: Serialize
//! # {
//! #     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
//! #         where S: Serializer
//! #     {
//! #         let mut map = serializer.serialize_map(Some(self.0.len()))?;
//! #         for &(ref k, ref v) in &self.0 {
//! #             map.serialize_entry(k, v)?;
//! #         }
//! #         map.end()
//! #     }
//! # }
//! #
//! # struct LinkedHashMapVisitor<K, V>(PhantomData<(K, V)>);
//! #
//! # impl<'de, K, V> Visitor<'de> for LinkedHashMapVisitor<K, V>
//! #     where K: Deserialize<'de>,
//! #           V: Deserialize<'de>
//! # {
//! #     type Value = LinkedHashMap<K, V>;
//! #
//! #     fn expecting(&self, _: &mut fmt::Formatter) -> fmt::Result {
//! #         unimplemented!()
//! #     }
//! #
//! #     fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
//! #         where M: MapAccess<'de>
//! #     {
//! #         let mut map = LinkedHashMap::new();
//! #         while let Some((key, value)) = access.next_entry()? {
//! #             map.insert(key, value);
//! #         }
//! #         Ok(map)
//! #     }
//! # }
//! #
//! # impl<'de, K, V> Deserialize<'de> for LinkedHashMap<K, V>
//! #     where K: Deserialize<'de>,
//! #           V: Deserialize<'de>
//! # {
//! #     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
//! #         where D: Deserializer<'de>
//! #     {
//! #         deserializer.deserialize_map(LinkedHashMapVisitor(PhantomData))
//! #     }
//! # }
//! #
//! #[test]
//! # fn not_a_test_ser_de_empty() {}
//! fn test_ser_de_empty() {
//!     let map = LinkedHashMap::<char, u32>::new();
//!
//!     assert_tokens(&map, &[
//!         Token::Map { len: Some(0) },
//!         Token::MapEnd,
//!     ]);
//! }
//!
//! #[test]
//! # fn not_a_test_ser_de() {}
//! fn test_ser_de() {
//!     let mut map = LinkedHashMap::new();
//!     map.insert('b', 20);
//!     map.insert('a', 10);
//!     map.insert('c', 30);
//!
//!     assert_tokens(&map, &[
//!         Token::Map { len: Some(3) },
//!         Token::Char('b'),
//!         Token::I32(20),
//!
//!         Token::Char('a'),
//!         Token::I32(10),
//!
//!         Token::Char('c'),
//!         Token::I32(30),
//!         Token::MapEnd,
//!     ]);
//! }
//! #
//! # fn main() {
//! #     test_ser_de_empty();
//! #     test_ser_de();
//! # }
//! ```

#![doc(html_root_url = "https://docs.rs/serde_test/0.9.13")]

#[macro_use]
extern crate serde;

mod ser;
mod de;
mod error;

mod token;
mod assert;

pub use token::Token;
pub use assert::{assert_tokens, assert_ser_tokens, assert_ser_tokens_error, assert_de_tokens,
                 assert_de_tokens_error};

// Not public API.
#[doc(hidden)]
pub use de::Deserializer;
<|endoftext|>