<commit_before>use decoders::Image;
use imageops::fcol;
use imageops::OpBuffer;
use std::cmp;

pub fn demosaic_and_scale(img: &Image, minwidth: usize, minheight: usize) -> OpBuffer {
  let scale = if minwidth == 0 || minheight == 0 {
    0
  } else {
    cmp::min(img.width / minwidth, img.height / minheight)
  };

  if scale <= 1 {
    full(img)
  } else {
    scaled(img, cmp::min(scale, 16)) // Never go less than 1/16th demosaic
  }
}

pub fn full(img: &Image) -> OpBuffer {
  let mut out = OpBuffer::new(img.width, img.height, 4);

  // First we set the colors we already have
  let mut ipos = 0;
  let mut opos = 0;
  for row in 0..img.height {
    for col in 0..img.width {
      let color = fcol(img, row, col);
      out.data[opos+color] = img.data[ipos] as f32;
      ipos += 1;
      opos += 4;
    }
  }

  // Now we go around the image setting the unset colors to the average of the
  // surrounding pixels
  out.mutate_lines(&(|line: &mut [f32], row| {
    for col in 0..img.width {
      let mut sums: [f32; 4] = [0.0;4];
      let mut counts: [u32; 4] = [0; 4];
      let color = fcol(img, row, col);

      for y in (cmp::max(0,(row as isize)-1) as usize) .. cmp::min(img.height, row+2) {
        for x in (cmp::max(0,(col as isize)-1) as usize) .. cmp::min(img.width, col+2) {
          let c = fcol(img, y, x);
          if c != color {
            sums[c] += img.data[y*img.width+x] as f32;
            counts[c] += 1;
          }
        }
      }

      for c in 0..4 {
        if c != color && counts[c] > 0 {
          line[col*4+c] = sums[c] / (counts[c] as f32);
        }
      }
    }
  }));

  out
}

pub fn scaled(img: &Image, scale: usize) -> OpBuffer {
  let width = img.width/scale;
  let mut out = OpBuffer::new(width, img.height/scale, 4);

  // Go around the image averaging every block of pixels
  out.mutate_lines(&(|line: &mut [f32], row| {
    for col in 0..width {
      let mut sums: [f32; 4] = [0.0;4];
      let mut counts: [u32; 4] = [0; 4];

      for y in row*scale..(row+1)*scale {
        for x in col*scale..(col+1)*scale {
          let c = fcol(img, y, x);
          sums[c] += img.data[y*img.width+x] as f32;
          counts[c] += 1;
        }
      }

      for c in 0..4 {
        if counts[c] > 0 {
          line[col*4+c] = sums[c] / (counts[c] as f32);
        }
      }
    }
  }));

  out
}
<commit_msg>demosaic: do the initial fill-in with threads<commit_after>use decoders::Image;
use imageops::fcol;
use imageops::OpBuffer;
use std::cmp;

pub fn demosaic_and_scale(img: &Image, minwidth: usize, minheight: usize) -> OpBuffer {
  let scale = if minwidth == 0 || minheight == 0 {
    0
  } else {
    cmp::min(img.width / minwidth, img.height / minheight)
  };

  if scale <= 1 {
    full(img)
  } else {
    scaled(img, cmp::min(scale, 16)) // Never go less than 1/16th demosaic
  }
}

pub fn full(img: &Image) -> OpBuffer {
  let mut out = OpBuffer::new(img.width, img.height, 4);

  // First we set the colors we already have
  out.mutate_lines(&(|line: &mut [f32], row| {
    for (col, (pixin, pixout)) in img.data.chunks(1).zip(line.chunks_mut(4)).enumerate() {
      let color = fcol(img, row, col);
      pixout[color] = pixin[0] as f32;
    }
  }));

  // Now we go around the image setting the unset colors to the average of the
  // surrounding pixels
  out.mutate_lines(&(|line: &mut [f32], row| {
    for col in 0..img.width {
      let mut sums: [f32; 4] = [0.0;4];
      let mut counts: [u32; 4] = [0; 4];
      let color = fcol(img, row, col);

      for y in (cmp::max(0,(row as isize)-1) as usize) .. cmp::min(img.height, row+2) {
        for x in (cmp::max(0,(col as isize)-1) as usize) .. cmp::min(img.width, col+2) {
          let c = fcol(img, y, x);
          if c != color {
            sums[c] += img.data[y*img.width+x] as f32;
            counts[c] += 1;
          }
        }
      }

      for c in 0..4 {
        if c != color && counts[c] > 0 {
          line[col*4+c] = sums[c] / (counts[c] as f32);
        }
      }
    }
  }));

  out
}

pub fn scaled(img: &Image, scale: usize) -> OpBuffer {
  let width = img.width/scale;
  let mut out = OpBuffer::new(width, img.height/scale, 4);

  // Go around the image averaging every block of pixels
  out.mutate_lines(&(|line: &mut [f32], row| {
    for col in 0..width {
      let mut sums: [f32; 4] = [0.0;4];
      let mut counts: [u32; 4] = [0; 4];

      for y in row*scale..(row+1)*scale {
        for x in col*scale..(col+1)*scale {
          let c = fcol(img, y, x);
          sums[c] += img.data[y*img.width+x] as f32;
          counts[c] += 1;
        }
      }

      for c in 0..4 {
        if counts[c] > 0 {
          line[col*4+c] = sums[c] / (counts[c] as f32);
        }
      }
    }
  }));

  out
}
<|endoftext|>


<commit_before>extern crate polydraw;

use polydraw::{Application, Renderer, Frame};
use polydraw::geom::point::Point;
use polydraw::draw::RGB;

struct Poly {
   points: Vec<Point>,
   color: RGB,
}

impl Poly {
   fn left_right_points(&self) -> (Vec<Point>, Vec<Point>) {
      let (min_y_i, max_y_i) = self._min_max_y_index();

      let (left_count, right_count) = self._left_right_count(min_y_i, max_y_i);

      return (
         self._left_points(min_y_i, left_count),
         self._right_points(min_y_i, right_count)
      )
   }

   fn _left_points(&self, min_y_i: usize, left_count: usize) -> Vec<Point> {
      let mut left = Vec::with_capacity(left_count);

      let points_len = self.points.len();

      let mut index = min_y_i;

      for _ in 0..left_count {
         left.push(self.points[index]);

         if index == 0 {
            index = points_len - 1;
         } else {
            index -= 1;
         }
      }

      return left;
   }

   fn _right_points(&self, min_y_i: usize, right_count: usize) -> Vec<Point> {
      let mut right = Vec::with_capacity(right_count);

      let points_len = self.points.len();

      let mut index = min_y_i;

      for _ in 0..right_count {
         if index == points_len {
            index = 0;
         }

         right.push(self.points[index]);

         index += 1;
      }

      return right;
   }

   fn _left_right_count(&self, min_y_i: usize, max_y_i: usize) -> (usize, usize) {
      let points_len = self.points.len();

      let left_count = if max_y_i > min_y_i {
         max_y_i - min_y_i + 1
      } else {
         points_len - min_y_i + max_y_i + 1
      };

      let right_count = points_len - left_count + 2;

      return (left_count, right_count)
   }

   fn _min_max_y_index(&self) -> (usize, usize) {
      let (first, rest) = self.points.split_first().unwrap();

      let mut min_y = first.y;
      let mut max_y = min_y;
      let mut min_index: usize = 0;
      let mut max_index: usize = 0;

      for (index, point) in rest.iter().enumerate() {
         if point.y < min_y {
            min_index = index + 1;
            min_y = point.y;
         } else if point.y > max_y {
            max_index = index + 1;
            max_y = point.y;
         }
      }

      (min_index, max_index)
   }
}

struct Scene {
   polys: Vec<Poly>,
}

impl Scene {
   #[inline]
   fn new() -> Self {
      Scene {
         polys: Vec::new(),
      }
   }

   #[inline]
   pub fn push(&mut self, poly: Poly) {
      self.polys.push(poly);
   }
}

struct DevRenderer {
   scene: Scene,
}

impl DevRenderer {
   fn new(scene: Scene) -> Self {
      DevRenderer {
         scene: scene,
      }
   }

   fn _render_poly(&self, frame: &mut Frame, poly: &Poly) {
      let (left_points, right_points) = poly.left_right_points();

      println!("LEFT");

      for (index, point) in left_points.iter().enumerate() {
         println!("[{}] = {:?}", index, point);
      }

      println!("RIGHT");

      for (index, point) in right_points.iter().enumerate() {
         println!("[{}] = {:?}", index, point);
      }

      for point in poly.points.iter() {
         frame.put_pixel(point.x as i32, point.y as i32, &poly.color)
      }
   }
}

impl Renderer for DevRenderer {
   fn render(&mut self, frame: &mut Frame) {
      frame.clear();

      for poly in self.scene.polys.iter() {
         self._render_poly(frame, poly);
      }

      panic!("Bye!");
   }
}

fn main() {
   let mut scene = Scene::new();

   let poly_a = Poly {
      points: vec![
         Point::new(1100, 400),
         Point::new(500, 700),
         Point::new(200, 200),
      ],
      color: RGB::new(34, 78, 29),
   };

   let poly_b = Poly {
      points: vec![
         Point::new(100, 500),
         Point::new(700, 100),
         Point::new(900, 200),
         Point::new(900, 1000),
      ],
      color: RGB::new(128, 59, 89),
   };

   scene.push(poly_a);
   scene.push(poly_b);

   let mut renderer = DevRenderer::new(scene);

   Application::new()
      .renderer(&mut renderer)
      .title("Dev Rasterizer")
      .size(800, 450)
      .run();
}

<commit_msg>Converting points to edges<commit_after>extern crate polydraw;

use polydraw::{Application, Renderer, Frame};
use polydraw::geom::point::Point;
use polydraw::draw::RGB;

struct Poly {
   points: Vec<Point>,
   color: RGB,
}

impl Poly {
   fn left_right_edges(&self) -> (Vec<Edge>, Vec<Edge>) {
      let (min_y_i, max_y_i) = self._min_max_y_index();

      let (left_count, right_count) = self._left_right_count(min_y_i, max_y_i);

      let left_points = self._left_points(min_y_i, left_count);

      let left_edges = self._edges_from_points(&left_points);

      let right_points = self._right_points(min_y_i, right_count);

      let right_edges = self._edges_from_points(&right_points);

      (left_edges, right_edges)
   }

   fn _edges_from_points(&self, points: &Vec<Point>) -> Vec<Edge> {
      let mut edges: Vec<Edge> = Vec::with_capacity(points.len() - 1);

      for index in 0..points.len() - 1 {
         edges.push(
            Edge::new(points[index], points[index + 1])
         );
      }

      edges
   }

   fn _left_points(&self, min_y_i: usize, left_count: usize) -> Vec<Point> {
      let mut left = Vec::with_capacity(left_count);

      let points_len = self.points.len();

      let mut index = min_y_i;

      for _ in 0..left_count {
         left.push(self.points[index]);

         if index == 0 {
            index = points_len - 1;
         } else {
            index -= 1;
         }
      }

      return left;
   }

   fn _right_points(&self, min_y_i: usize, right_count: usize) -> Vec<Point> {
      let mut right = Vec::with_capacity(right_count);

      let points_len = self.points.len();

      let mut index = min_y_i;

      for _ in 0..right_count {
         if index == points_len {
            index = 0;
         }

         right.push(self.points[index]);

         index += 1;
      }

      return right;
   }

   fn _left_right_count(&self, min_y_i: usize, max_y_i: usize) -> (usize, usize) {
      let points_len = self.points.len();

      let left_count = if max_y_i > min_y_i {
         max_y_i - min_y_i + 1
      } else {
         points_len - min_y_i + max_y_i + 1
      };

      let right_count = points_len - left_count + 2;

      return (left_count, right_count)
   }

   fn _min_max_y_index(&self) -> (usize, usize) {
      let (first, rest) = self.points.split_first().unwrap();

      let mut min_y = first.y;
      let mut max_y = min_y;
      let mut min_index: usize = 0;
      let mut max_index: usize = 0;

      for (index, point) in rest.iter().enumerate() {
         if point.y < min_y {
            min_index = index + 1;
            min_y = point.y;
         } else if point.y > max_y {
            max_index = index + 1;
            max_y = point.y;
         }
      }

      (min_index, max_index)
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct Edge {
   p1: Point,
   p2: Point,
}

impl Edge {
   #[inline]
   fn new(p1: Point, p2: Point) -> Self {
      Edge {
         p1: p1,
         p2: p2,
      }
   }
}

struct Scene {
   polys: Vec<Poly>,
}

impl Scene {
   #[inline]
   fn new() -> Self {
      Scene {
         polys: Vec::new(),
      }
   }

   #[inline]
   pub fn push(&mut self, poly: Poly) {
      self.polys.push(poly);
   }
}

struct DevRenderer {
   scene: Scene,
}

impl DevRenderer {
   fn new(scene: Scene) -> Self {
      DevRenderer {
         scene: scene,
      }
   }

   fn _render_poly(&self, frame: &mut Frame, poly: &Poly) {
      let (left_edges, right_edges) = poly.left_right_edges();

      println!("LEFT");

      for (index, edge) in left_edges.iter().enumerate() {
         println!("[{}] = {:?}", index, edge);
      }

      println!("RIGHT");

      for (index, edge) in right_edges.iter().enumerate() {
         println!("[{}] = {:?}", index, edge);
      }

      for point in poly.points.iter() {
         frame.put_pixel(point.x as i32, point.y as i32, &poly.color)
      }
   }
}

impl Renderer for DevRenderer {
   fn render(&mut self, frame: &mut Frame) {
      frame.clear();

      for poly in self.scene.polys.iter() {
         self._render_poly(frame, poly);
      }

      panic!("Bye!");
   }
}

fn main() {
   let mut scene = Scene::new();

   let poly_a = Poly {
      points: vec![
         Point::new(1100, 400),
         Point::new(500, 700),
         Point::new(200, 200),
      ],
      color: RGB::new(34, 78, 29),
   };

   let poly_b = Poly {
      points: vec![
         Point::new(100, 500),
         Point::new(700, 100),
         Point::new(900, 200),
         Point::new(900, 1000),
      ],
      color: RGB::new(128, 59, 89),
   };

   scene.push(poly_a);
   scene.push(poly_b);

   let mut renderer = DevRenderer::new(scene);

   Application::new()
      .renderer(&mut renderer)
      .title("Dev Rasterizer")
      .size(800, 450)
      .run();
}

<|endoftext|>


<commit_before>//! Sine wave generator with frequency configuration exposed through standard
//! input.

use crossbeam_channel::bounded;
use std::io;
use std::str::FromStr;

fn main() {
    // 1. open a client
    let (client, _status) =
        jack::Client::new("rust_jack_sine", jack::ClientOptions::NO_START_SERVER).unwrap();

    // 2. register port
    let mut out_port = client
        .register_port("sine_out", jack::AudioOut::default())
        .unwrap();

    // 3. define process callback handler
    let mut frequency = 220.0;
    let sample_rate = client.sample_rate();
    let frame_t = 1.0 / sample_rate as f64;
    let mut time = 0.0;
    let (tx, rx) = bounded(1_000_000);
    let process = jack::ClosureProcessHandler::new(
        move |_: &jack::Client, ps: &jack::ProcessScope| -> jack::Control {
            // Get output buffer
            let out = out_port.as_mut_slice(ps);

            // Check frequency requests
            while let Ok(f) = rx.try_recv() {
                time = 0.0;
                frequency = f;
            }

            // Write output
            for v in out.iter_mut() {
                let x = frequency * time * 2.0 * std::f64::consts::PI;
                let y = x.sin();
                *v = y as f32;
                time += frame_t;
            }

            // Continue as normal
            jack::Control::Continue
        },
    );

    // 4. activate the client
    let active_client = client.activate_async((), process).unwrap();
    // processing starts here

    // 5. wait or do some processing while your handler is running in real time.
    println!("Enter an integer value to change the frequency of the sine wave.");
    while let Some(f) = read_freq() {
        tx.send(f).unwrap();
    }

    // 6. Optional deactivate. Not required since active_client will deactivate on
    // drop, though explicit deactivate may help you identify errors in
    // deactivate.
    active_client.deactivate().unwrap();
}

/// Attempt to read a frequency from standard in. Will block until there is
/// user input. `None` is returned if there was an error reading from standard
/// in, or the retrieved string wasn't a compatible u16 integer.
fn read_freq() -> Option<f64> {
    let mut user_input = String::new();
    match io::stdin().read_line(&mut user_input) {
        Ok(_) => u16::from_str(user_input.trim()).ok().map(|n| n as f64),
        Err(_) => None,
    }
}
<commit_msg>Automatically hook up output to system. (#153)<commit_after>//! Sine wave generator with frequency configuration exposed through standard
//! input.

use crossbeam_channel::bounded;
use std::io;
use std::str::FromStr;

fn main() {
    // 1. open a client
    let (client, _status) =
        jack::Client::new("rust_jack_sine", jack::ClientOptions::NO_START_SERVER).unwrap();

    // 2. register port
    let mut out_port = client
        .register_port("sine_out", jack::AudioOut::default())
        .unwrap();

    // 3. define process callback handler
    let mut frequency = 220.0;
    let sample_rate = client.sample_rate();
    let frame_t = 1.0 / sample_rate as f64;
    let mut time = 0.0;
    let (tx, rx) = bounded(1_000_000);
    let process = jack::ClosureProcessHandler::new(
        move |_: &jack::Client, ps: &jack::ProcessScope| -> jack::Control {
            // Get output buffer
            let out = out_port.as_mut_slice(ps);

            // Check frequency requests
            while let Ok(f) = rx.try_recv() {
                time = 0.0;
                frequency = f;
            }

            // Write output
            for v in out.iter_mut() {
                let x = frequency * time * 2.0 * std::f64::consts::PI;
                let y = x.sin();
                *v = y as f32;
                time += frame_t;
            }

            // Continue as normal
            jack::Control::Continue
        },
    );

    // 4. Activate the client. Also connect the ports to the system audio.
    let active_client = client.activate_async((), process).unwrap();
    active_client
        .as_client()
        .connect_ports_by_name("rust_jack_sine:sine_out", "system:playback_1")
        .unwrap();
    active_client
        .as_client()
        .connect_ports_by_name("rust_jack_sine:sine_out", "system:playback_2")
        .unwrap();
    // processing starts here

    // 5. wait or do some processing while your handler is running in real time.
    println!("Enter an integer value to change the frequency of the sine wave.");
    while let Some(f) = read_freq() {
        tx.send(f).unwrap();
    }

    // 6. Optional deactivate. Not required since active_client will deactivate on
    // drop, though explicit deactivate may help you identify errors in
    // deactivate.
    active_client.deactivate().unwrap();
}

/// Attempt to read a frequency from standard in. Will block until there is
/// user input. `None` is returned if there was an error reading from standard
/// in, or the retrieved string wasn't a compatible u16 integer.
fn read_freq() -> Option<f64> {
    let mut user_input = String::new();
    match io::stdin().read_line(&mut user_input) {
        Ok(_) => u16::from_str(user_input.trim()).ok().map(|n| n as f64),
        Err(_) => None,
    }
}
<|endoftext|>


<commit_before>use super::Mode;
use super::KeyMap;
use super::Key;
use super::Command;
use super::View;
use super::KeyMapState;
use super::EventStatus;
use super::Direction;
use super::WordEdgeMatch;
use super::Response;
use super::utils;
use super::{Overlay, OverlayType, OverlayEvent};

pub struct NormalMode {
    keymap: KeyMap,
}

impl NormalMode {

    pub fn new() -> NormalMode {
        NormalMode {
            keymap: NormalMode::key_defaults(),
        }
    }

    fn key_defaults() -> KeyMap {
        let mut keymap = KeyMap::new();

        // movement
        keymap.bind_key(Key::Up, Command::MoveCursor(Direction::Up(1)));
        keymap.bind_key(Key::Down, Command::MoveCursor(Direction::Down(1)));
        keymap.bind_key(Key::Left, Command::MoveCursor(Direction::Left(1)));
        keymap.bind_key(Key::Right, Command::MoveCursor(Direction::Right(1)));
        keymap.bind_key(Key::Char('h'), Command::MoveCursor(Direction::Left(1)));
        keymap.bind_key(Key::Char('j'), Command::MoveCursor(Direction::Down(1)));
        keymap.bind_key(Key::Char('k'), Command::MoveCursor(Direction::Up(1)));
        keymap.bind_key(Key::Char('l'), Command::MoveCursor(Direction::Right(1)));
        keymap.bind_key(Key::Char('W'), Command::MoveCursor(Direction::RightWord(1, WordEdgeMatch::Whitespace)));
        keymap.bind_key(Key::Char('B'), Command::MoveCursor(Direction::LeftWord(1, WordEdgeMatch::Whitespace)));
        keymap.bind_key(Key::Char('w'), Command::MoveCursor(Direction::RightWord(1, WordEdgeMatch::Alphabet)));
        keymap.bind_key(Key::Char('b'), Command::MoveCursor(Direction::LeftWord(1, WordEdgeMatch::Alphabet)));
        keymap.bind_key(Key::Char('^'), Command::LineStart);
        keymap.bind_key(Key::Char('$'), Command::LineEnd);

        // editing
        keymap.bind_keys(&[Key::Char('d'), Key::Char('W')], Command::Delete(Direction::RightWord(1, WordEdgeMatch::Whitespace)));
        keymap.bind_keys(&[Key::Char('d'), Key::Char('B')], Command::Delete(Direction::LeftWord(1, WordEdgeMatch::Whitespace)));
        keymap.bind_keys(&[Key::Char('d'), Key::Char('w')], Command::Delete(Direction::RightWord(1, WordEdgeMatch::Alphabet)));
        keymap.bind_keys(&[Key::Char('d'), Key::Char('b')], Command::Delete(Direction::LeftWord(1, WordEdgeMatch::Alphabet)));
        keymap.bind_key(Key::Char('x'), Command::Delete(Direction::Right(1)));
        keymap.bind_key(Key::Char('X'), Command::Delete(Direction::Left(1)));
        keymap.bind_key(Key::Char('u'), Command::Undo);
        keymap.bind_key(Key::Ctrl('r'), Command::Redo);

        // open a prompt to the user
        keymap.bind_key(Key::Char(':'), Command::SetOverlay(OverlayType::Prompt));

        keymap
    }

    fn handle_command(&mut self, c: Command, view: &mut View) -> Response {
        match c {
            // Editor Commands
            Command::ExitEditor      => return Response::Quit,
            Command::SaveBuffer      => utils::save_buffer(&view.buffer),

            // Navigation
            Command::MoveCursor(dir) => view.move_cursor(dir),
            Command::LineEnd         => view.move_cursor_to_line_end(),
            Command::LineStart       => view.move_cursor_to_line_start(),

            // Editing
            Command::Delete(dir)     => view.delete_chars(dir),
            Command::Redo            => view.redo(),
            Command::Undo            => view.undo(),

            // Prompt
            Command::SetOverlay(o)   => view.set_overlay(o),
            _                        => {}
        }
        Response::Continue
    }
}

impl Mode for NormalMode {
    fn handle_key_event(&mut self, key: Option<Key>, view: &mut View) -> EventStatus {
        let key = match key {
            Some(k) => k,
            None => return EventStatus::NotHandled
        };

        // if there is an overlay on the view, send the key there
        // and don't allow the mode to handle it.
        match view.overlay {
            Overlay::None => {},
            _             => {
                let event = view.overlay.handle_key_event(key);
                if let OverlayEvent::Finished(response) = event {
                    view.overlay = Overlay::None;
                    if let Some(data) = response {
                        return EventStatus::Handled(self.interpret_command_input(data, view))
                    }
                }
                return EventStatus::NotHandled
            }
        }

        // send key to the keymap
        match self.keymap.check_key(key) {
            KeyMapState::Match(command) => {
                EventStatus::Handled(self.handle_command(command, view))
            },
            KeyMapState::Continue => {
                // keep going and wait for more keypresses
                EventStatus::Handled(Response::Continue)
            },
            KeyMapState::None => { EventStatus::NotHandled }
        }

    }

    fn interpret_command_input(&mut self, input: String, view: &mut View) -> Response {
        let command = Command::from_str(&*input);
        self.handle_command(command, view)
    }
}
<commit_msg>Bind '0' to start of line in normal mode - #75<commit_after>use super::Mode;
use super::KeyMap;
use super::Key;
use super::Command;
use super::View;
use super::KeyMapState;
use super::EventStatus;
use super::Direction;
use super::WordEdgeMatch;
use super::Response;
use super::utils;
use super::{Overlay, OverlayType, OverlayEvent};

pub struct NormalMode {
    keymap: KeyMap,
}

impl NormalMode {

    pub fn new() -> NormalMode {
        NormalMode {
            keymap: NormalMode::key_defaults(),
        }
    }

    fn key_defaults() -> KeyMap {
        let mut keymap = KeyMap::new();

        // movement
        keymap.bind_key(Key::Up, Command::MoveCursor(Direction::Up(1)));
        keymap.bind_key(Key::Down, Command::MoveCursor(Direction::Down(1)));
        keymap.bind_key(Key::Left, Command::MoveCursor(Direction::Left(1)));
        keymap.bind_key(Key::Right, Command::MoveCursor(Direction::Right(1)));
        keymap.bind_key(Key::Char('h'), Command::MoveCursor(Direction::Left(1)));
        keymap.bind_key(Key::Char('j'), Command::MoveCursor(Direction::Down(1)));
        keymap.bind_key(Key::Char('k'), Command::MoveCursor(Direction::Up(1)));
        keymap.bind_key(Key::Char('l'), Command::MoveCursor(Direction::Right(1)));
        keymap.bind_key(Key::Char('W'), Command::MoveCursor(Direction::RightWord(1, WordEdgeMatch::Whitespace)));
        keymap.bind_key(Key::Char('B'), Command::MoveCursor(Direction::LeftWord(1, WordEdgeMatch::Whitespace)));
        keymap.bind_key(Key::Char('w'), Command::MoveCursor(Direction::RightWord(1, WordEdgeMatch::Alphabet)));
        keymap.bind_key(Key::Char('b'), Command::MoveCursor(Direction::LeftWord(1, WordEdgeMatch::Alphabet)));
        keymap.bind_key(Key::Char('0'), Command::LineStart);
        keymap.bind_key(Key::Char('$'), Command::LineEnd);

        // editing
        keymap.bind_keys(&[Key::Char('d'), Key::Char('W')], Command::Delete(Direction::RightWord(1, WordEdgeMatch::Whitespace)));
        keymap.bind_keys(&[Key::Char('d'), Key::Char('B')], Command::Delete(Direction::LeftWord(1, WordEdgeMatch::Whitespace)));
        keymap.bind_keys(&[Key::Char('d'), Key::Char('w')], Command::Delete(Direction::RightWord(1, WordEdgeMatch::Alphabet)));
        keymap.bind_keys(&[Key::Char('d'), Key::Char('b')], Command::Delete(Direction::LeftWord(1, WordEdgeMatch::Alphabet)));
        keymap.bind_key(Key::Char('x'), Command::Delete(Direction::Right(1)));
        keymap.bind_key(Key::Char('X'), Command::Delete(Direction::Left(1)));
        keymap.bind_key(Key::Char('u'), Command::Undo);
        keymap.bind_key(Key::Ctrl('r'), Command::Redo);

        // open a prompt to the user
        keymap.bind_key(Key::Char(':'), Command::SetOverlay(OverlayType::Prompt));

        keymap
    }

    fn handle_command(&mut self, c: Command, view: &mut View) -> Response {
        match c {
            // Editor Commands
            Command::ExitEditor      => return Response::Quit,
            Command::SaveBuffer      => utils::save_buffer(&view.buffer),

            // Navigation
            Command::MoveCursor(dir) => view.move_cursor(dir),
            Command::LineEnd         => view.move_cursor_to_line_end(),
            Command::LineStart       => view.move_cursor_to_line_start(),

            // Editing
            Command::Delete(dir)     => view.delete_chars(dir),
            Command::Redo            => view.redo(),
            Command::Undo            => view.undo(),

            // Prompt
            Command::SetOverlay(o)   => view.set_overlay(o),
            _                        => {}
        }
        Response::Continue
    }
}

impl Mode for NormalMode {
    fn handle_key_event(&mut self, key: Option<Key>, view: &mut View) -> EventStatus {
        let key = match key {
            Some(k) => k,
            None => return EventStatus::NotHandled
        };

        // if there is an overlay on the view, send the key there
        // and don't allow the mode to handle it.
        match view.overlay {
            Overlay::None => {},
            _             => {
                let event = view.overlay.handle_key_event(key);
                if let OverlayEvent::Finished(response) = event {
                    view.overlay = Overlay::None;
                    if let Some(data) = response {
                        return EventStatus::Handled(self.interpret_command_input(data, view))
                    }
                }
                return EventStatus::NotHandled
            }
        }

        // send key to the keymap
        match self.keymap.check_key(key) {
            KeyMapState::Match(command) => {
                EventStatus::Handled(self.handle_command(command, view))
            },
            KeyMapState::Continue => {
                // keep going and wait for more keypresses
                EventStatus::Handled(Response::Continue)
            },
            KeyMapState::None => { EventStatus::NotHandled }
        }

    }

    fn interpret_command_input(&mut self, input: String, view: &mut View) -> Response {
        let command = Command::from_str(&*input);
        self.handle_command(command, view)
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

use std::io::Write as _;

use byteorder::{BigEndian, WriteBytesExt as _};

/// Size of a gzchunked block.
const BLOCK_SIZE: usize = 10 << 20;

/// A wrapper type for gzip compression level.
pub struct Compression(flate2::Compression);

/// A type for defining gzip compression level for gzchunked.
impl Compression {

    pub fn new(level: u32) -> Compression {
        Compression(flate2::Compression::new(level))
    }
}

impl Default for Compression {

    fn default() -> Compression {
        Compression(flate2::Compression::new(5))
    }
}

/// A gzchunked streaming encoder.
pub struct Encoder {
    encoder: flate2::write::GzEncoder<Vec<u8>>,
    compression: Compression,
}

impl Encoder {

    /// Creates a new encoder with specified gzip compression level.
    pub fn new(compression: Compression) -> Encoder {
        Encoder {
            encoder: flate2::write::GzEncoder::new(Vec::new(), compression.0),
            compression,
        }
    }

    /// Writes next data chunk into the stream.
    pub fn write(&mut self, buf: &[u8]) -> std::io::Result<()> {
        self.encoder.write_u64::<BigEndian>(buf.len() as u64)?;
        self.encoder.write_all(buf)?;
        Ok(())
    }

    /// Attempts to retrieve next gzipped block.
    /// Returns `Ok(None)` if there's not enough data for a whole block.
    pub fn try_next_chunk(&mut self) -> std::io::Result<Option<Vec<u8>>> {
        self.encoder.flush()?;
        if self.encoder.get_ref().len() < BLOCK_SIZE {
            return Ok(None)
        }

        Ok(Some(self.next_chunk()?))
    }

    /// Retrieves next gzipped block without checking its size.
    pub fn next_chunk(&mut self) -> std::io::Result<Vec<u8>> {
        self.encoder.flush()?;
        let new_encoder = flate2::write::GzEncoder::new(Vec::new(), self.compression.0);
        let old_encoder = std::mem::replace(&mut self.encoder, new_encoder);
        let encoded_data = old_encoder.finish()?;

        Ok(encoded_data)
    }
}

pub struct EncodeOpts {
    pub compression: Compression,
    pub part_size: u64,
}

impl Default for EncodeOpts {

    fn default() -> EncodeOpts {
        EncodeOpts {
            compression: Compression::default(),
            part_size: 1 * 1024 * 1024, // 1 MiB.
        }
    }
}

pub struct Encode<I> {
    chunked: crate::chunked::Encode<I>,
    opts: EncodeOpts,
}

impl<'a, I> Encode<I>
where
    I: Iterator<Item = &'a [u8]>,
{
    pub fn with_default_opts(iter: I) -> Encode<I> {
        Encode::with_opts(iter, EncodeOpts::default())
    }

    pub fn with_opts(iter: I, opts: EncodeOpts) -> Encode<I> {
        Encode {
            chunked: crate::chunked::encode(iter),
            opts: opts,
        }
    }

    fn pull(&mut self) -> std::io::Result<Option<Vec<u8>>> {
        let compression = self.opts.compression.0;
        let part_size = self.opts.part_size;

        let mut encoder = flate2::write::GzEncoder::new(vec!(), compression);
        crate::io::copy_until(&mut self.chunked, &mut encoder, |_, encoder| {
            encoder.get_ref().len() as u64 >= part_size
        })?;

        let chunk = encoder.finish()?;
        if chunk.is_empty() {
            Ok(None)
        } else {
            Ok(Some(chunk))
        }
    }
}

impl<'a, I> Iterator for Encode<I>
where
    I: Iterator<Item = &'a [u8]>,
{
    type Item = std::io::Result<Vec<u8>>;

    fn next(&mut self) -> Option<std::io::Result<Vec<u8>>> {
        self.pull().transpose()
    }
}
<commit_msg>Add wrappers for encoding gzchunked streams.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

use std::io::Write as _;

use byteorder::{BigEndian, WriteBytesExt as _};

/// Size of a gzchunked block.
const BLOCK_SIZE: usize = 10 << 20;

/// A wrapper type for gzip compression level.
pub struct Compression(flate2::Compression);

/// A type for defining gzip compression level for gzchunked.
impl Compression {

    pub fn new(level: u32) -> Compression {
        Compression(flate2::Compression::new(level))
    }
}

impl Default for Compression {

    fn default() -> Compression {
        Compression(flate2::Compression::new(5))
    }
}

/// A gzchunked streaming encoder.
pub struct Encoder {
    encoder: flate2::write::GzEncoder<Vec<u8>>,
    compression: Compression,
}

impl Encoder {

    /// Creates a new encoder with specified gzip compression level.
    pub fn new(compression: Compression) -> Encoder {
        Encoder {
            encoder: flate2::write::GzEncoder::new(Vec::new(), compression.0),
            compression,
        }
    }

    /// Writes next data chunk into the stream.
    pub fn write(&mut self, buf: &[u8]) -> std::io::Result<()> {
        self.encoder.write_u64::<BigEndian>(buf.len() as u64)?;
        self.encoder.write_all(buf)?;
        Ok(())
    }

    /// Attempts to retrieve next gzipped block.
    /// Returns `Ok(None)` if there's not enough data for a whole block.
    pub fn try_next_chunk(&mut self) -> std::io::Result<Option<Vec<u8>>> {
        self.encoder.flush()?;
        if self.encoder.get_ref().len() < BLOCK_SIZE {
            return Ok(None)
        }

        Ok(Some(self.next_chunk()?))
    }

    /// Retrieves next gzipped block without checking its size.
    pub fn next_chunk(&mut self) -> std::io::Result<Vec<u8>> {
        self.encoder.flush()?;
        let new_encoder = flate2::write::GzEncoder::new(Vec::new(), self.compression.0);
        let old_encoder = std::mem::replace(&mut self.encoder, new_encoder);
        let encoded_data = old_encoder.finish()?;

        Ok(encoded_data)
    }
}

pub fn encode<'a, I>(iter: I) -> Encode<I>
where
    I: Iterator<Item=&'a [u8]>,
{
    encode_with_opts(iter, EncodeOpts::default())
}

pub fn encode_with_opts<'a, I>(iter: I, opts: EncodeOpts) -> Encode<I>
where
    I: Iterator<Item=&'a [u8]>,
{
    Encode::with_opts(iter, opts)
}

pub struct EncodeOpts {
    pub compression: Compression,
    pub part_size: u64,
}

impl Default for EncodeOpts {

    fn default() -> EncodeOpts {
        EncodeOpts {
            compression: Compression::default(),
            part_size: 1 * 1024 * 1024, // 1 MiB.
        }
    }
}

pub struct Encode<I> {
    chunked: crate::chunked::Encode<I>,
    opts: EncodeOpts,
}

impl<'a, I> Encode<I>
where
    I: Iterator<Item = &'a [u8]>,
{
    fn with_opts(iter: I, opts: EncodeOpts) -> Encode<I> {
        Encode {
            chunked: crate::chunked::encode(iter),
            opts: opts,
        }
    }

    fn pull(&mut self) -> std::io::Result<Option<Vec<u8>>> {
        let compression = self.opts.compression.0;
        let part_size = self.opts.part_size;

        let mut encoder = flate2::write::GzEncoder::new(vec!(), compression);
        crate::io::copy_until(&mut self.chunked, &mut encoder, |_, encoder| {
            encoder.get_ref().len() as u64 >= part_size
        })?;

        let chunk = encoder.finish()?;
        if chunk.is_empty() {
            Ok(None)
        } else {
            Ok(Some(chunk))
        }
    }
}

impl<'a, I> Iterator for Encode<I>
where
    I: Iterator<Item = &'a [u8]>,
{
    type Item = std::io::Result<Vec<u8>>;

    fn next(&mut self) -> Option<std::io::Result<Vec<u8>>> {
        self.pull().transpose()
    }
}
<|endoftext|>


<commit_before>//! Automatically generates bindings for the Vulkan API. In order to use, first create a
//! [`VkRegistry`] struct with a valid Vulkan XML file, and then call either one of the two
//! generation functions ([`gen_global()`] or [`gen_struct()`]) or a custom one. Further
//! documentation can be found in [`VkRegistry`] and [`GenConfig`], and looking over the provided
//! [examples](https://github.com/Osspial/vk-rs/tree/master/vk_generator/examples) is encouraged.

extern crate xml;
extern crate boolinator;

use std::mem;

#[cfg(feature = "unstable_generator_api")]
pub mod registry;
#[cfg(feature = "unstable_generator_api")]
pub mod generator;

#[cfg(not(feature = "unstable_generator_api"))]
mod registry;
#[cfg(not(feature = "unstable_generator_api"))]
mod generator;

pub use registry::{VkRegistry, VkVersion};
pub use generator::GenConfig;

#[inline]
fn to_option<'u>(s: *const str) -> Option<&'u str> {
    unsafe{ mem::transmute(s) }
}<commit_msg>Fixed a few documentation links.<commit_after>//! Automatically generates bindings for the Vulkan API. In order to use, first create a
//! [`VkRegistry`] struct with a valid Vulkan XML file, and then call either one of the two
//! generation functions ([`gen_global()`] or [`gen_struct()`]) or a custom one. Further
//! documentation can be found in [`VkRegistry`] and [`GenConfig`], and looking over the provided
//! [examples](https://github.com/Osspial/vk-rs/tree/master/vk_generator/examples) is encouraged.
//!
//! [`VkRegistry`]: ./struct.VkRegistry.html
//! [`GenConfig`]: ./struct.GenConfig.html
//! [`gen_global()`]: ./struct.VkRegistry.html#method.gen_global
//! [`gen_struct()`]: ./struct.VkRegistry.html#method.gen_struct

extern crate xml;
extern crate boolinator;

use std::mem;

#[cfg(feature = "unstable_generator_api")]
pub mod registry;
#[cfg(feature = "unstable_generator_api")]
pub mod generator;

#[cfg(not(feature = "unstable_generator_api"))]
mod registry;
#[cfg(not(feature = "unstable_generator_api"))]
mod generator;

pub use registry::{VkRegistry, VkVersion};
pub use generator::GenConfig;

#[inline]
fn to_option<'u>(s: *const str) -> Option<&'u str> {
    unsafe{ mem::transmute(s) }
}<|endoftext|>


<commit_before>use rustc_serialize::json;
use hyper;
use hyper::Client;
use url::form_urlencoded;
use crossbeam;

use std::io::Read;

use text_view::view_as_text;
use text_view::insert_annotation;
use token::Token;
use token::Data;
use error::{Error, Result, Source};

/// Represents a grammar error from language tool
///
/// Note: lots of fields are missing
#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct GrammarError {
    pub message: String,
    pub offset: usize,
    pub length: usize,
    pub short_message: Option<String>,
    pub issue_type: Option<String>,
}

/// Contains a list of matches to errors
///
/// Corresponds to the JSON that LanguageTool-server sends back
///
/// Note: lots of fields are missing
#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct GrammarCheck {
    pub matches: Vec<GrammarError>,
}

/// GrammarChecker
pub struct GrammarChecker {
    lang: String,
    port: usize,
}

impl GrammarChecker {
    /// Initialize the grammarchecker
    pub fn new<S: Into<String>>(port: usize, lang: S) -> Result<GrammarChecker> {
        let checker = GrammarChecker {
            lang: lang.into(),
            port: port,
        };

        let res = Client::new()
            .get(&format!("http://localhost:{}/v2/languages", port))
            .send()
            .map_err(|e| {
                Error::grammar_check(Source::empty(),
                                     lformat!("could not connect to language tool server: {error}",
                                              error = e))
            })?;
        if res.status != hyper::Ok {
            return Err(Error::grammar_check(Source::empty(),
                                            lformat!("server didn't respond with a OK status \
                                                      code")));
        }
        Ok(checker)
    }

    /// Send a query to LanguageTools server and get back a list of errors
    pub fn check(&self, text: &str) -> Result<GrammarCheck> {
        let query: String = form_urlencoded::Serializer::new(String::new())
            .append_pair("language", &self.lang)
            .append_pair("text", text)
            .finish();

        let client = Client::new();

        let mut res = client.post(&format!("http://localhost:{}/v2/check", self.port))
            .body(&query)
            .send()
            .map_err(|e| {
                Error::grammar_check(Source::empty(),
                                     lformat!("could not send request to server: {error}",
                                              error = e))
            })?;

        if res.status != hyper::Ok {
            return Err(Error::grammar_check(Source::empty(),
                                            lformat!("server didn't respond with a OK status \
                                                      code")));
        }

        let mut s = String::new();
        res.read_to_string(&mut s)
            .map_err(|e| {
                Error::grammar_check(Source::empty(),
                                     lformat!("could not read response: {error}", error = e))
            })?;
        let reponse: GrammarCheck = json::decode(&s)
            .map_err(|e| {
                Error::default(Source::empty(),
                               lformat!("could not decode JSON: {error}", error = e))
            })?;
        Ok(reponse)
    }
}

impl GrammarChecker {
    /// Check the grammar in a vector of tokens.
    ///
    /// This modifies the AST
    pub fn check_chapter(&self, tokens: &mut Vec<Token>) -> Result<()> {
        let n_threads = 4; // seems to give best results but quite random
        let len = tokens.len();
        let subvecs = tokens.chunks_mut(len / n_threads);

        let mut result = Ok(());
        crossbeam::scope(|scope| {
            let mut handles = vec![];
            for subvec in subvecs {
                for mut token in subvec.iter_mut() {
                    match *token {
                        Token::Paragraph(ref mut v) |
                        Token::Header(_, ref mut v) |
                        Token::BlockQuote(ref mut v) |
                        Token::List(ref mut v) |
                        Token::OrderedList(_, ref mut v) => {
                            handles.push(scope.spawn(move || {
                                let check = self.check(&view_as_text(v))?;
                                for error in check.matches {
                                    insert_annotation(v,
                                                      &Data::GrammarError(error.message.clone()),
                                                      error.offset,
                                                      error.length);
                                }
                                Ok(())
                            }))
                        }
                        _ => (),
                    }
                }
            }
            for handle in handles.into_iter() {
                if let Err(err) = handle.join() {
                    result = Err(err);
                    break;
                }
            }
        });
        result

        // crossbeam::scope(|scope| {
        //     for subvec in subvecs {
        //         scope.spawn(|| Self::check_grammar(lang, subvec)
        //     }
        // });

        //        Ok(())
    }
}
<commit_msg>Add license information to grammar_check.rs<commit_after>// Copyright (C) 2016 Élisabeth HENRY.
//
// This file is part of Crowbook.
//
// Crowbook is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Crowbook is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Crowbook.  If not, see <http://www.gnu.org/licenses/>.

use rustc_serialize::json;
use hyper;
use hyper::Client;
use url::form_urlencoded;
use crossbeam;

use std::io::Read;

use text_view::view_as_text;
use text_view::insert_annotation;
use token::Token;
use token::Data;
use error::{Error, Result, Source};

/// Represents a grammar error from language tool
///
/// Note: lots of fields are missing
#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct GrammarError {
    pub message: String,
    pub offset: usize,
    pub length: usize,
    pub short_message: Option<String>,
    pub issue_type: Option<String>,
}

/// Contains a list of matches to errors
///
/// Corresponds to the JSON that LanguageTool-server sends back
///
/// Note: lots of fields are missing
#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct GrammarCheck {
    pub matches: Vec<GrammarError>,
}

/// GrammarChecker
pub struct GrammarChecker {
    lang: String,
    port: usize,
}

impl GrammarChecker {
    /// Initialize the grammarchecker
    pub fn new<S: Into<String>>(port: usize, lang: S) -> Result<GrammarChecker> {
        let checker = GrammarChecker {
            lang: lang.into(),
            port: port,
        };

        let res = Client::new()
            .get(&format!("http://localhost:{}/v2/languages", port))
            .send()
            .map_err(|e| {
                Error::grammar_check(Source::empty(),
                                     lformat!("could not connect to language tool server: {error}",
                                              error = e))
            })?;
        if res.status != hyper::Ok {
            return Err(Error::grammar_check(Source::empty(),
                                            lformat!("server didn't respond with a OK status \
                                                      code")));
        }
        Ok(checker)
    }

    /// Send a query to LanguageTools server and get back a list of errors
    pub fn check(&self, text: &str) -> Result<GrammarCheck> {
        let query: String = form_urlencoded::Serializer::new(String::new())
            .append_pair("language", &self.lang)
            .append_pair("text", text)
            .finish();

        let client = Client::new();

        let mut res = client.post(&format!("http://localhost:{}/v2/check", self.port))
            .body(&query)
            .send()
            .map_err(|e| {
                Error::grammar_check(Source::empty(),
                                     lformat!("could not send request to server: {error}",
                                              error = e))
            })?;

        if res.status != hyper::Ok {
            return Err(Error::grammar_check(Source::empty(),
                                            lformat!("server didn't respond with a OK status \
                                                      code")));
        }

        let mut s = String::new();
        res.read_to_string(&mut s)
            .map_err(|e| {
                Error::grammar_check(Source::empty(),
                                     lformat!("could not read response: {error}", error = e))
            })?;
        let reponse: GrammarCheck = json::decode(&s)
            .map_err(|e| {
                Error::default(Source::empty(),
                               lformat!("could not decode JSON: {error}", error = e))
            })?;
        Ok(reponse)
    }
}

impl GrammarChecker {
    /// Check the grammar in a vector of tokens.
    ///
    /// This modifies the AST
    pub fn check_chapter(&self, tokens: &mut Vec<Token>) -> Result<()> {
        let n_threads = 4; // seems to give best results but quite random
        let len = tokens.len();
        let subvecs = tokens.chunks_mut(len / n_threads);

        let mut result = Ok(());
        crossbeam::scope(|scope| {
            let mut handles = vec![];
            for subvec in subvecs {
                for mut token in subvec.iter_mut() {
                    match *token {
                        Token::Paragraph(ref mut v) |
                        Token::Header(_, ref mut v) |
                        Token::BlockQuote(ref mut v) |
                        Token::List(ref mut v) |
                        Token::OrderedList(_, ref mut v) => {
                            handles.push(scope.spawn(move || {
                                let check = self.check(&view_as_text(v))?;
                                for error in check.matches {
                                    insert_annotation(v,
                                                      &Data::GrammarError(error.message.clone()),
                                                      error.offset,
                                                      error.length);
                                }
                                Ok(())
                            }))
                        }
                        _ => (),
                    }
                }
            }
            for handle in handles.into_iter() {
                if let Err(err) = handle.join() {
                    result = Err(err);
                    break;
                }
            }
        });
        result

        // crossbeam::scope(|scope| {
        //     for subvec in subvecs {
        //         scope.spawn(|| Self::check_grammar(lang, subvec)
        //     }
        // });

        //        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::{iter::Peekable, str};

#[derive(Debug, PartialEq, Eq, Hash)]
enum Quotes {
    Single,
    Double,
    None,
}

#[derive(Debug)]
struct EofMatcher {
    eof:       Vec<u8>,
    complete:  bool,
    match_idx: usize,
}

impl EofMatcher {
    fn new() -> Self { EofMatcher { eof: Vec::with_capacity(10), complete: false, match_idx: 0 } }

    #[inline]
    fn next(&mut self, c: u8) -> bool {
        if self.complete && self.eof.get(self.match_idx) == Some(&c) {
            self.match_idx += 1;
        } else if self.complete {
            self.match_idx = 0;
        } else if c == b'\n' {
            self.complete = true;
        } else if !self.eof.is_empty() || !(c as char).is_whitespace() {
            self.eof.push(c);
        }
        self.complete && self.match_idx == self.eof.len()
    }
}

/// Serves as a buffer for storing a string until that string can be terminated.
///
/// # Examples
///
/// This example comes from the shell's REPL, which ensures that the user's input
/// will only be submitted for execution once a terminated command is supplied.
#[derive(Debug)]
pub struct Terminator<I: Iterator<Item = u8>> {
    inner:      RearPeekable<I>,
    eof:        Option<EofMatcher>,
    array:      usize,
    skip_next:  bool,
    quotes:     Quotes,
    terminated: bool,
    and_or:     bool,
    whitespace: bool,
    lt_count:   u8,
    empty:      bool,
    subshell:   usize,
}

impl<'a> From<&'a str> for Terminator<std::str::Bytes<'a>> {
    fn from(string: &'a str) -> Self { Terminator::new(string.bytes()) }
}

#[derive(Clone, Debug)]
pub struct RearPeekable<I: Iterator> {
    iter: Peekable<I>,
    now:  Option<I::Item>,
    last: Option<I::Item>,
}

impl<I> Iterator for RearPeekable<I>
where
    I: Iterator,
    I::Item: Copy,
{
    type Item = I::Item;

    #[inline]
    fn next(&mut self) -> Option<I::Item> {
        self.last = self.now;
        self.now = self.iter.next();
        self.now
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
}

impl<I: Iterator> RearPeekable<I> {
    #[inline]
    pub fn peek(&mut self) -> Option<&I::Item> { self.iter.peek() }

    #[inline]
    pub fn prev(&self) -> Option<&I::Item> { self.last.as_ref() }
}

impl<I: Iterator<Item = u8>> Iterator for Terminator<I> {
    type Item = u8;

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        if self.terminated {
            return None;
        }

        let prev_whitespace = self.whitespace;
        self.whitespace = false;

        let mut next = if prev_whitespace && self.array == 0 && !self.and_or && !self.empty {
            self.inner.find(|&c| c == b'\n' || !c.is_ascii_whitespace())
        } else if prev_whitespace {
            self.inner.find(|&c| !c.is_ascii_whitespace())
        } else {
            self.inner.next()
        };

        if self.skip_next {
            self.skip_next = false;
        } else if let Some(matcher) = self.eof.as_mut() {
            if let Some(character) = next {
                if matcher.next(character) {
                    self.eof = None;
                }
            }
        } else if self.quotes != Quotes::None && next != Some(b'\\') {
            match (next, &self.quotes) {
                (Some(b'\''), Quotes::Single) | (Some(b'"'), Quotes::Double) => {
                    self.quotes = Quotes::None;
                }
                _ => (),
            }
        } else if let Some(character) = next {
            next = self.handle_char(character, prev_whitespace);
            self.empty &= character.is_ascii_whitespace();
        } else if self.subshell == 0 && self.array == 0 && !self.and_or && !self.empty {
            self.terminated = true;
        }

        next
    }
}

impl<I: Iterator<Item = u8>> Terminator<I> {
    /// Consumes lines until a statement is formed or the iterator runs dry, and returns the
    /// underlying `String`.
    pub fn terminate(&mut self) -> Option<Result<String, ()>> {
        let stmt = self.collect::<Vec<_>>();
        let stmt = unsafe { String::from_utf8_unchecked(stmt) };

        if self.terminated {
            Some(Ok(stmt))
        } else if self.empty {
            None
        } else {
            Some(Err(()))
        }
    }

    fn handle_char(&mut self, character: u8, prev_whitespace: bool) -> Option<u8> {
        match character {
            b'\'' => {
                self.quotes = Quotes::Single;
                Some(b'\'')
            }
            b'"' => {
                self.quotes = Quotes::Double;
                Some(b'"')
            }
            b'(' if self.inner.prev() == Some(&b'$') || self.inner.prev() == Some(&b'@') => {
                self.subshell += 1;
                Some(b'(')
            }
            b')' if self.subshell > 0 => {
                self.subshell -= 1;
                Some(b')')
            }
            b'<' => {
                if let Some(&b'<') = self.inner.peek() {
                    self.lt_count += 1;
                } else if self.lt_count == 1 {
                    self.eof = Some(EofMatcher::new());
                    self.lt_count = 0;
                } else {
                    self.lt_count = 0;
                }
                Some(b'<')
            }
            b'[' => {
                self.array += 1;
                Some(b'[')
            }
            b']' if self.array > 0 => {
                self.array -= 1;
                Some(b']')
            }
            b'#' if prev_whitespace => {
                self.inner.find(|&c| c == b'\n');
                if self.array == 0 && self.subshell == 0 && !self.and_or && !self.empty {
                    self.terminated = true;
                    None
                } else {
                    self.whitespace = true;
                    Some(b' ')
                }
            }
            b'\\' => {
                if self.inner.peek() == Some(&b'\n') {
                    self.whitespace = true;
                    self.inner.next();
                    self.next()
                } else {
                    self.skip_next = true;
                    Some(character)
                }
            }
            b'&' | b'|' if self.inner.prev() == Some(&character) => {
                self.and_or = true;
                Some(character)
            }
            b'\n' if self.array == 0 && self.subshell == 0 && !self.and_or && !self.empty => {
                self.terminated = true;
                None
            }
            _ if character.is_ascii_whitespace() => {
                self.whitespace = true;
                Some(b' ')
            }
            _ => {
                self.and_or = false;
                Some(character)
            }
        }
    }

    pub fn new(inner: I) -> Terminator<I> {
        Terminator {
            inner:      RearPeekable { iter: inner.peekable(), now: None, last: None },
            eof:        None,
            array:      0,
            skip_next:  false,
            quotes:     Quotes::None,
            terminated: false,
            and_or:     false,
            whitespace: true,
            lt_count:   0,
            empty:      true,
            subshell:   0,
        }
    }
}
<commit_msg>Don't trim starting space<commit_after>use std::{iter::Peekable, str};

#[derive(Debug, PartialEq, Eq, Hash)]
enum Quotes {
    Single,
    Double,
    None,
}

#[derive(Debug)]
struct EofMatcher {
    eof:       Vec<u8>,
    complete:  bool,
    match_idx: usize,
}

impl EofMatcher {
    fn new() -> Self { EofMatcher { eof: Vec::with_capacity(10), complete: false, match_idx: 0 } }

    #[inline]
    fn next(&mut self, c: u8) -> bool {
        if self.complete && self.eof.get(self.match_idx) == Some(&c) {
            self.match_idx += 1;
        } else if self.complete {
            self.match_idx = 0;
        } else if c == b'\n' {
            self.complete = true;
        } else if !self.eof.is_empty() || !(c as char).is_whitespace() {
            self.eof.push(c);
        }
        self.complete && self.match_idx == self.eof.len()
    }
}

/// Serves as a buffer for storing a string until that string can be terminated.
///
/// # Examples
///
/// This example comes from the shell's REPL, which ensures that the user's input
/// will only be submitted for execution once a terminated command is supplied.
#[derive(Debug)]
pub struct Terminator<I: Iterator<Item = u8>> {
    inner:      RearPeekable<I>,
    eof:        Option<EofMatcher>,
    array:      usize,
    skip_next:  bool,
    quotes:     Quotes,
    terminated: bool,
    and_or:     bool,
    whitespace: bool,
    lt_count:   u8,
    empty:      bool,
    subshell:   usize,
}

impl<'a> From<&'a str> for Terminator<std::str::Bytes<'a>> {
    fn from(string: &'a str) -> Self { Terminator::new(string.bytes()) }
}

#[derive(Clone, Debug)]
pub struct RearPeekable<I: Iterator> {
    iter: Peekable<I>,
    now:  Option<I::Item>,
    last: Option<I::Item>,
}

impl<I> Iterator for RearPeekable<I>
where
    I: Iterator,
    I::Item: Copy,
{
    type Item = I::Item;

    #[inline]
    fn next(&mut self) -> Option<I::Item> {
        self.last = self.now;
        self.now = self.iter.next();
        self.now
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
}

impl<I: Iterator> RearPeekable<I> {
    #[inline]
    pub fn peek(&mut self) -> Option<&I::Item> { self.iter.peek() }

    #[inline]
    pub fn prev(&self) -> Option<&I::Item> { self.last.as_ref() }
}

impl<I: Iterator<Item = u8>> Iterator for Terminator<I> {
    type Item = u8;

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        if self.terminated {
            return None;
        }

        let prev_whitespace = self.whitespace;
        self.whitespace = false;

        let mut next = if prev_whitespace && self.array == 0 && !self.and_or && !self.empty {
            self.inner.find(|&c| c == b'\n' || !c.is_ascii_whitespace())
        } else if prev_whitespace {
            self.inner.find(|&c| !c.is_ascii_whitespace())
        } else {
            self.inner.next()
        };

        if self.skip_next {
            self.skip_next = false;
        } else if let Some(matcher) = self.eof.as_mut() {
            if let Some(character) = next {
                if matcher.next(character) {
                    self.eof = None;
                }
            }
        } else if self.quotes != Quotes::None && next != Some(b'\\') {
            match (next, &self.quotes) {
                (Some(b'\''), Quotes::Single) | (Some(b'"'), Quotes::Double) => {
                    self.quotes = Quotes::None;
                }
                _ => (),
            }
        } else if let Some(character) = next {
            next = self.handle_char(character, prev_whitespace);
            self.empty &= character.is_ascii_whitespace();
        } else if self.subshell == 0 && self.array == 0 && !self.and_or && !self.empty {
            self.terminated = true;
        }

        next
    }
}

impl<I: Iterator<Item = u8>> Terminator<I> {
    /// Consumes lines until a statement is formed or the iterator runs dry, and returns the
    /// underlying `String`.
    pub fn terminate(&mut self) -> Option<Result<String, ()>> {
        let stmt = self.collect::<Vec<_>>();
        let stmt = unsafe { String::from_utf8_unchecked(stmt) };

        if self.terminated {
            Some(Ok(stmt))
        } else if self.empty {
            None
        } else {
            Some(Err(()))
        }
    }

    fn handle_char(&mut self, character: u8, prev_whitespace: bool) -> Option<u8> {
        match character {
            b'\'' => {
                self.quotes = Quotes::Single;
                Some(b'\'')
            }
            b'"' => {
                self.quotes = Quotes::Double;
                Some(b'"')
            }
            b'(' if self.inner.prev() == Some(&b'$') || self.inner.prev() == Some(&b'@') => {
                self.subshell += 1;
                Some(b'(')
            }
            b')' if self.subshell > 0 => {
                self.subshell -= 1;
                Some(b')')
            }
            b'<' => {
                if let Some(&b'<') = self.inner.peek() {
                    self.lt_count += 1;
                } else if self.lt_count == 1 {
                    self.eof = Some(EofMatcher::new());
                    self.lt_count = 0;
                } else {
                    self.lt_count = 0;
                }
                Some(b'<')
            }
            b'[' => {
                self.array += 1;
                Some(b'[')
            }
            b']' if self.array > 0 => {
                self.array -= 1;
                Some(b']')
            }
            b'#' if prev_whitespace => {
                self.inner.find(|&c| c == b'\n');
                if self.array == 0 && self.subshell == 0 && !self.and_or && !self.empty {
                    self.terminated = true;
                    None
                } else {
                    self.whitespace = true;
                    Some(b' ')
                }
            }
            b'\\' => {
                if self.inner.peek() == Some(&b'\n') {
                    self.whitespace = true;
                    self.inner.next();
                    self.next()
                } else {
                    self.skip_next = true;
                    Some(character)
                }
            }
            b'&' | b'|' if self.inner.prev() == Some(&character) => {
                self.and_or = true;
                Some(character)
            }
            b'\n' if self.array == 0 && self.subshell == 0 && !self.and_or && !self.empty => {
                self.terminated = true;
                None
            }
            _ if character.is_ascii_whitespace() => {
                self.whitespace = true;
                Some(b' ')
            }
            _ => {
                self.and_or = false;
                Some(character)
            }
        }
    }

    pub fn new(inner: I) -> Terminator<I> {
        Terminator {
            inner:      RearPeekable { iter: inner.peekable(), now: None, last: None },
            eof:        None,
            array:      0,
            skip_next:  false,
            quotes:     Quotes::None,
            terminated: false,
            and_or:     false,
            whitespace: false,
            lt_count:   0,
            empty:      true,
            subshell:   0,
        }
    }
}
<|endoftext|>


<commit_before>use super::branchify::generate_branchified_method;
use super::get_writer;
use std::io::IoResult;

pub fn generate(output_dir: &Path) -> IoResult<()> {
    let mut writer = get_writer(output_dir, "read_method.rs");
    try!(writer.write(bytes!("\
// This automatically generated file is included in request.rs.
{
    use method::{Connect, Delete, Get, Head, Options, Patch, Post, Put, Trace, ExtensionMethod};
    use server::request::MAX_METHOD_LEN;
    use rfc2616::{SP, is_token_item};

")));

    try!(generate_branchified_method(
        writer,
        branchify!(case sensitive,
            "CONNECT" => Connect,
            "DELETE"  => Delete,
            "GET"     => Get,
            "HEAD"    => Head,
            "OPTIONS" => Options,
            "PATCH"   => Patch,
            "POST"    => Post,
            "PUT"     => Put,
            "TRACE"   => Trace
        ),
        1,
        "self.stream.read_byte()",
        "SP",
        "MAX_METHOD_LEN",
        "is_token_item(b)",
        "ExtensionMethod({})"));
    writer.write(bytes!("}\n"))
}
<commit_msg>Replaced bytes! with byte literals.<commit_after>use super::branchify::generate_branchified_method;
use super::get_writer;
use std::io::IoResult;

pub fn generate(output_dir: &Path) -> IoResult<()> {
    let mut writer = get_writer(output_dir, "read_method.rs");
    try!(writer.write(b"\
// This automatically generated file is included in request.rs.
{
    use method::{Connect, Delete, Get, Head, Options, Patch, Post, Put, Trace, ExtensionMethod};
    use server::request::MAX_METHOD_LEN;
    use rfc2616::{SP, is_token_item};

"));

    try!(generate_branchified_method(
        writer,
        branchify!(case sensitive,
            "CONNECT" => Connect,
            "DELETE"  => Delete,
            "GET"     => Get,
            "HEAD"    => Head,
            "OPTIONS" => Options,
            "PATCH"   => Patch,
            "POST"    => Post,
            "PUT"     => Put,
            "TRACE"   => Trace
        ),
        1,
        "self.stream.read_byte()",
        "SP",
        "MAX_METHOD_LEN",
        "is_token_item(b)",
        "ExtensionMethod({})"));
    writer.write(b"}\n")
}
<|endoftext|>


<commit_before>import front.ast;
import driver.session;
import util.common.span;

type env = ();

fn resolve_name(&env e, &span sp, ast.name_ n) -> ast.name {
    auto s = "resolving name: ";
    s += n.ident;
    log s;
    ret fold.respan[ast.name_](sp, n);
}

fn resolve_crate(session.session sess, @ast.crate crate) -> @ast.crate {
    let fold.ast_fold[env] fld = fold.new_identity_fold[env]();
    fld = @rec( fold_name = bind resolve_name(_,_,_)
                with *fld );
    ret fold.fold_crate[env]((), fld, crate);
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Begin sketching name lookup in rustc.<commit_after>import front.ast;
import driver.session;
import util.common.span;
import std.map.hashmap;
import std.list.list;
import std.list.nil;
import std.list.cons;
import std.util.option;
import std.util.some;
import std.util.none;
import std._str;

tag scope {
    scope_crate(@ast.crate);
    scope_item(@ast.item);
    scope_block(ast.block);
}

type env = list[scope];

fn resolve_name(&env e, &span sp, ast.name_ n) -> ast.name {

    log "resolving name " + n.ident;

    fn in_scope(ast.ident i, &scope s) -> option[scope] {
        alt (s) {
            case (scope_crate(?c)) {
                if (c.node.module.contains_key(i)) {
                    ret some[scope](s);
                }
            }
            case (scope_item(?it)) {
                alt (it.node) {
                    case (ast.item_fn(?f, _)) {
                        for (ast.input inp in f.inputs) {
                            if (_str.eq(inp.ident, i)) {
                                ret some[scope](s);
                            }
                        }
                    }
                    case (ast.item_mod(?m)) {
                        if (m.contains_key(i)) {
                            ret some[scope](s);
                        }
                    }
                }
            }
        }
        ret none[scope];
    }

    alt (std.list.find[scope](e, bind in_scope(n.ident, _))) {
        case (some[scope](?s)) {
            log "resolved name " + n.ident;
        }
        case (none[scope]) {
            log "unresolved name " + n.ident;
        }
    }

    ret fold.respan[ast.name_](sp, n);
}

fn update_env_for_crate(&env e, @ast.crate c) -> env {
    log "updating env with crate";
    ret cons[scope](scope_crate(c), @e);
}

fn update_env_for_item(&env e, @ast.item i) -> env {
    log "updating env with item";
    ret cons[scope](scope_item(i), @e);
}

fn update_env_for_block(&env e, ast.block b) -> env {
    log "updating env with block";
    ret cons[scope](scope_block(b), @e);
}

fn resolve_crate(session.session sess, @ast.crate crate) -> @ast.crate {
    let fold.ast_fold[env] fld = fold.new_identity_fold[env]();
    fld = @rec( fold_name = bind resolve_name(_,_,_),
                update_env_for_crate = bind update_env_for_crate(_,_),
                update_env_for_item = bind update_env_for_item(_,_),
                update_env_for_block = bind update_env_for_block(_,_)
                with *fld );
    ret fold.fold_crate[env](nil[scope], fld, crate);
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>
extern crate ndarray;
#[macro_use]
extern crate ndarray_linalg;

use ndarray::*;
use ndarray_linalg::*;

#[test]
fn diag_1d() {
    let d = arr1(&[1.0, 2.0]);
    let v = arr1(&[1.0, 1.0]);
    let dv = d.into_diagonal().op(v);
    assert_close_l2!(&dv, &arr1(&[1.0, 2.0]), 1e-7);
}

#[test]
fn diag_2d() {
    let d = arr1(&[1.0, 2.0]);
    let m = arr2(&[[1.0, 1.0], [1.0, 1.0]]);
    let dm = d.into_diagonal().op(m);
    println!("dm = {:?}", dm);
    assert_close_l2!(&dm, &arr2(&[[1.0, 1.0], [2.0, 2.0]]), 1e-7);
}
<commit_msg>Fix test<commit_after>
extern crate ndarray;
#[macro_use]
extern crate ndarray_linalg;

use ndarray::*;
use ndarray_linalg::*;

#[test]
fn diag_1d() {
    let d = arr1(&[1.0, 2.0]);
    let v = arr1(&[1.0, 1.0]);
    let dv = d.into_diagonal().op(&v);
    assert_close_l2!(&dv, &arr1(&[1.0, 2.0]), 1e-7);
}

#[test]
fn diag_2d() {
    let d = arr1(&[1.0, 2.0]);
    let m = arr2(&[[1.0, 1.0], [1.0, 1.0]]);
    let dm = d.into_diagonal().op(&m);
    println!("dm = {:?}", dm);
    assert_close_l2!(&dm, &arr2(&[[1.0, 1.0], [2.0, 2.0]]), 1e-7);
}
<|endoftext|>


<commit_before>// Copyright 2018 Chao Lin & William Sergeant (Sorbonne University)

// 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.

#![macro_use]
use middle::analysis::ast::*;
use ast::Expression::*;
use std::cmp;
use syntax::codemap::BytePos;
pub use rust::NO_EXPANSION;

enum Predicate {
    And(usize),
    Not(usize),
    Oom(usize),
    Zom(usize),
    Nothing
}

enum VecType {
    And,
    OneOrMore,
    Nothing
}

pub struct UselessChaining<'a: 'c, 'b: 'a, 'c>
{
  grammar: &'c AGrammar<'a, 'b>,
  pred: Predicate,
  vec_pred : Vec<Predicate>,
  vec_type : VecType
}

impl <'a, 'b, 'c> UselessChaining<'a, 'b, 'c>
{
  pub fn analyse(grammar: AGrammar<'a, 'b>) -> Partial<AGrammar<'a, 'b>> {
    UselessChaining::check_chaining(&grammar);
    Partial::Value(grammar)
  }

  fn check_chaining(grammar: &'c AGrammar<'a, 'b>){
    let mut analyser = UselessChaining{
      grammar: grammar,
      pred: Predicate::Nothing,
      vec_pred: vec![],
      vec_type: VecType::Nothing
    };
    for rule in &grammar.rules {
      analyser.visit_expr(rule.expr_idx)
    }
  }

  fn span_end_point(&self, sp: Span) -> Span{
      let lo = cmp::max(sp.hi().0 - 1, sp.lo().0);
      sp.with_lo(BytePos(lo))
  }

  fn get_th(&self, n: usize) -> &'static str {
      match n {
          1 => "st",
          2 => "nd",
          3 => "rd",
          _ => "th"
      }
  }

  fn warn_useless_chaining(&self, pred: (&'static str, &'static str, &'static str, &'static str), span2: Span, span1: Span){
      let (detected,help,first,second) = pred;
      self.grammar.span_warn(
          span1,
          format!(
              "Detected useless chaining: {}
              \nHelp: {}
              \n1{} predicate {}"
          ,detected,help,self.get_th(1),first)
      );
      self.grammar.span_note(
          span2,
          format!("2{} predicate {}",self.get_th(2),second)
      )
  }

  fn warn_vec_useless_chaining(&self, pred: (&'static str, &'static str, &'static str), i: usize, span: Span){
      let (warn,note,span_note) = pred;
      if i==0 {
          self.grammar.span_warn(
              span,
              format!(
                  "Detected useless chaining: multiple {}
                  \nHelp: {}
                  \n1{} occurence of {}"
              ,warn,note,self.get_th(1),warn)
          )
      }
      else{
          self.grammar.span_note(
              span,
              format!("{}{} occurence of {}",i+1,self.get_th(i+1),span_note)
          )
      }

  }

  fn warn_verify_multiple(&self) {
      for (i, x) in self.vec_pred.iter().enumerate() {
          match x {
              &Predicate::And(this) => {
                  let lo = self.grammar[this].span().lo();
                  let span = Span::new(lo,lo,NO_EXPANSION);
                  self.warn_vec_useless_chaining(("&","&(&e) -> &e","and"),i,span);
              }
              &Predicate::Oom(this) => {
                  let sp = self.grammar[this].span();
                  let span = self.span_end_point(sp);
                  self.warn_vec_useless_chaining(("+","(e+)+ -> e+","one or more"),i,span);
              }
              _ => unreachable!()
          }
      }
  }

  fn verify_multiple(&mut self){
      if self.vec_pred.len()>=2 {
          self.warn_verify_multiple()
      }
      self.vec_pred.clear();
      self.vec_type=VecType::Nothing;
  }

  fn warning(&mut self, current: Predicate){
      match (&self.pred, current) {
          (&Predicate::Zom(t),Predicate::Oom(this)) => {
              self.warn_useless_chaining(
                  ("(e+)*","(e+)* -> e+","One or more","Zero or more"),
                  self.span_end_point(self.grammar[this].span()),
                  self.span_end_point(self.grammar[t].span())
              );
          }
          (&Predicate::Not(t),Predicate::Not(this)) => {
              let f_lo = self.grammar[this].span().lo();
              let s_lo = self.grammar[t].span().lo();
              self.warn_useless_chaining(
                  ("!(!e)","!(!e) -> &e","not","not"),
                  Span::new(f_lo, f_lo, NO_EXPANSION),
                  Span::new(s_lo, s_lo, NO_EXPANSION)
              );
          }
          (&Predicate::And(t),Predicate::Not(this)) => {
              let f_lo = self.grammar[this].span().lo();
              let s_lo = self.grammar[t].span().lo();
              self.warn_useless_chaining(
                  ("&(!e)","&(!e) -> !e","not","and"),
                  Span::new(f_lo, f_lo, NO_EXPANSION),
                  Span::new(s_lo, s_lo, NO_EXPANSION)
              );
          }
          (&Predicate::Not(t),Predicate::And(this)) => {
              let f_lo = self.grammar[this].span().lo();
              let s_lo = self.grammar[t].span().lo();
              self.warn_useless_chaining(
                  ("!(&e)","!(&e) -> !e","and","not"),
                  Span::new(f_lo, f_lo, NO_EXPANSION),
                  Span::new(s_lo, s_lo, NO_EXPANSION)
              );
          }
          _ => {}
      }
  }

 }

impl<'a, 'b, 'c> ExprByIndex for UselessChaining<'a, 'b, 'c>
{
  fn expr_by_index(&self, index: usize) -> Expression {
    self.grammar.expr_by_index(index).clone()
  }
}

impl<'a, 'b, 'c> Visitor<()> for UselessChaining<'a, 'b, 'c>
{

  fn visit_str_literal(&mut self, _this: usize, _lit: String){
      self.pred=Predicate::Nothing;
      self.verify_multiple();
  }

  fn visit_atom(&mut self, _this: usize){
      self.pred=Predicate::Nothing;
      self.verify_multiple();
  }

  fn visit_non_terminal_symbol(&mut self, _this: usize, rule: Ident){
      let predicate = self.grammar.find_rule_by_ident(rule).expr_idx;
      match self.expr_by_index(predicate){
          ZeroOrMore(_child) => {
            self.warning(Predicate::Zom(predicate));
          }
          OneOrMore(_child) => {
            self.warning(Predicate::Oom(predicate));
            match self.vec_type {
                VecType::OneOrMore => {
                    self.vec_pred.push(Predicate::Oom(predicate));
                }
                _ => ()
            }
          }
          NotPredicate(_child) => {
            self.warning(Predicate::Not(predicate));
          }
          AndPredicate(_child) => {
            self.warning(Predicate::And(predicate));
            match self.vec_type {
                VecType::And => {
                    self.vec_pred.push(Predicate::And(predicate));
                }
                _ => ()
            }
          }
          _ => {}
      }
      self.pred=Predicate::Nothing;
      self.verify_multiple();
  }

  fn visit_one_or_more(&mut self, this: usize, child: usize){
    // println!("one_or_more");
    self.warning(Predicate::Oom(this));
    match self.vec_type {
        VecType::And => {
            self.verify_multiple()
        }
        VecType::Nothing => {
            self.vec_type=VecType::OneOrMore
        }
        _ => ()
    }
    self.vec_pred.push(Predicate::Oom(this));
    self.visit_expr(child)
  }

  fn visit_zero_or_more(&mut self, this: usize, child: usize){
    // println!("zero_or_more");
    self.pred = Predicate::Zom(this);
    self.verify_multiple();
    self.visit_expr(child)
  }

  fn visit_not_predicate(&mut self, this: usize, child: usize){
    // println!("not_predicate");
    self.warning(Predicate::Not(this));
    self.pred=Predicate::Not(this);
    self.verify_multiple();
    self.visit_expr(child)
  }

  fn visit_and_predicate(&mut self, this: usize, child: usize){
    // println!("and_predicate");
    self.warning(Predicate::And(this));
    self.pred=Predicate::And(this);

    match self.vec_type {
        VecType::OneOrMore => {
            self.verify_multiple()
        }
        VecType::Nothing => {
            self.vec_type=VecType::And;
        }
        _ => ()
    }
    self.vec_pred.push(Predicate::And(this));
    self.visit_expr(child)
  }

  fn visit_sequence(&mut self, _: usize, children: Vec<usize>){
    for child in children {
        self.verify_multiple();
        self.visit_expr(child);
    }
  }

  fn visit_choice(&mut self, _: usize, children: Vec<usize>){
      for child in children {
          self.verify_multiple();
          self.visit_expr(child);
      }
  }
}
<commit_msg>[analysis] In UselessChaining, clear contents of variable pred in visit_choice and visit_sequence<commit_after>// Copyright 2018 Chao Lin & William Sergeant (Sorbonne University)

// 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.

#![macro_use]
use middle::analysis::ast::*;
use ast::Expression::*;
use std::cmp;
use syntax::codemap::BytePos;
pub use rust::NO_EXPANSION;

enum Predicate {
    And(usize),
    Not(usize),
    Oom(usize),
    Zom(usize),
    Nothing
}

enum VecType {
    And,
    OneOrMore,
    Nothing
}

pub struct UselessChaining<'a: 'c, 'b: 'a, 'c>
{
  grammar: &'c AGrammar<'a, 'b>,
  pred: Predicate,
  vec_pred : Vec<Predicate>,
  vec_type : VecType
}

impl <'a, 'b, 'c> UselessChaining<'a, 'b, 'c>
{
  pub fn analyse(grammar: AGrammar<'a, 'b>) -> Partial<AGrammar<'a, 'b>> {
    UselessChaining::check_chaining(&grammar);
    Partial::Value(grammar)
  }

  fn check_chaining(grammar: &'c AGrammar<'a, 'b>){
    let mut analyser = UselessChaining{
      grammar: grammar,
      pred: Predicate::Nothing,
      vec_pred: vec![],
      vec_type: VecType::Nothing
    };
    for rule in &grammar.rules {
      analyser.visit_expr(rule.expr_idx)
    }
  }

  fn span_end_point(&self, sp: Span) -> Span{
      let lo = cmp::max(sp.hi().0 - 1, sp.lo().0);
      sp.with_lo(BytePos(lo))
  }

  fn get_th(&self, n: usize) -> &'static str {
      match n {
          1 => "st",
          2 => "nd",
          3 => "rd",
          _ => "th"
      }
  }

  fn warn_useless_chaining(&self, pred: (&'static str, &'static str, &'static str, &'static str), span2: Span, span1: Span){
      let (detected,help,first,second) = pred;
      self.grammar.span_warn(
          span1,
          format!(
              "Detected useless chaining: {}
              \nHelp: {}
              \n1{} predicate {}"
          ,detected,help,self.get_th(1),first)
      );
      self.grammar.span_note(
          span2,
          format!("2{} predicate {}",self.get_th(2),second)
      )
  }

  fn warn_vec_useless_chaining(&self, pred: (&'static str, &'static str, &'static str), i: usize, span: Span){
      let (warn,note,span_note) = pred;
      if i==0 {
          self.grammar.span_warn(
              span,
              format!(
                  "Detected useless chaining: multiple {}
                  \nHelp: {}
                  \n1{} occurence of {}"
              ,warn,note,self.get_th(1),warn)
          )
      }
      else{
          self.grammar.span_note(
              span,
              format!("{}{} occurence of {}",i+1,self.get_th(i+1),span_note)
          )
      }

  }

  fn warn_verify_multiple(&self) {
      for (i, x) in self.vec_pred.iter().enumerate() {
          match x {
              &Predicate::And(this) => {
                  let lo = self.grammar[this].span().lo();
                  let span = Span::new(lo,lo,NO_EXPANSION);
                  self.warn_vec_useless_chaining(("&","&(&e) -> &e","and"),i,span);
              }
              &Predicate::Oom(this) => {
                  let sp = self.grammar[this].span();
                  let span = self.span_end_point(sp);
                  self.warn_vec_useless_chaining(("+","(e+)+ -> e+","one or more"),i,span);
              }
              _ => unreachable!()
          }
      }
  }

  fn verify_multiple(&mut self){
      if self.vec_pred.len()>=2 {
          self.warn_verify_multiple()
      }
      self.vec_pred.clear();
      self.vec_type=VecType::Nothing;
  }

  fn warning(&mut self, current: Predicate){
      match (&self.pred, current) {
          (&Predicate::Zom(t),Predicate::Oom(this)) => {
              self.warn_useless_chaining(
                  ("(e+)*","(e+)* -> e+","One or more","Zero or more"),
                  self.span_end_point(self.grammar[this].span()),
                  self.span_end_point(self.grammar[t].span())
              );
          }
          (&Predicate::Not(t),Predicate::Not(this)) => {
              let f_lo = self.grammar[this].span().lo();
              let s_lo = self.grammar[t].span().lo();
              self.warn_useless_chaining(
                  ("!(!e)","!(!e) -> &e","not","not"),
                  Span::new(f_lo, f_lo, NO_EXPANSION),
                  Span::new(s_lo, s_lo, NO_EXPANSION)
              );
          }
          (&Predicate::And(t),Predicate::Not(this)) => {
              let f_lo = self.grammar[this].span().lo();
              let s_lo = self.grammar[t].span().lo();
              self.warn_useless_chaining(
                  ("&(!e)","&(!e) -> !e","not","and"),
                  Span::new(f_lo, f_lo, NO_EXPANSION),
                  Span::new(s_lo, s_lo, NO_EXPANSION)
              );
          }
          (&Predicate::Not(t),Predicate::And(this)) => {
              let f_lo = self.grammar[this].span().lo();
              let s_lo = self.grammar[t].span().lo();
              self.warn_useless_chaining(
                  ("!(&e)","!(&e) -> !e","and","not"),
                  Span::new(f_lo, f_lo, NO_EXPANSION),
                  Span::new(s_lo, s_lo, NO_EXPANSION)
              );
          }
          _ => {}
      }
  }

 }

impl<'a, 'b, 'c> ExprByIndex for UselessChaining<'a, 'b, 'c>
{
  fn expr_by_index(&self, index: usize) -> Expression {
    self.grammar.expr_by_index(index).clone()
  }
}

impl<'a, 'b, 'c> Visitor<()> for UselessChaining<'a, 'b, 'c>
{

  fn visit_str_literal(&mut self, _this: usize, _lit: String){
      self.pred=Predicate::Nothing;
      self.verify_multiple();
  }

  fn visit_atom(&mut self, _this: usize){
      self.pred=Predicate::Nothing;
      self.verify_multiple();
  }

  fn visit_non_terminal_symbol(&mut self, _this: usize, rule: Ident){
      let predicate = self.grammar.find_rule_by_ident(rule).expr_idx;
      match self.expr_by_index(predicate){
          ZeroOrMore(_child) => {
            self.warning(Predicate::Zom(predicate));
          }
          OneOrMore(_child) => {
            self.warning(Predicate::Oom(predicate));
            match self.vec_type {
                VecType::OneOrMore => {
                    self.vec_pred.push(Predicate::Oom(predicate));
                }
                _ => ()
            }
          }
          NotPredicate(_child) => {
            self.warning(Predicate::Not(predicate));
          }
          AndPredicate(_child) => {
            self.warning(Predicate::And(predicate));
            match self.vec_type {
                VecType::And => {
                    self.vec_pred.push(Predicate::And(predicate));
                }
                _ => ()
            }
          }
          _ => {}
      }
      self.pred=Predicate::Nothing;
      self.verify_multiple();
  }

  fn visit_one_or_more(&mut self, this: usize, child: usize){
    // println!("one_or_more");
    self.warning(Predicate::Oom(this));
    match self.vec_type {
        VecType::And => {
            self.verify_multiple()
        }
        VecType::Nothing => {
            self.vec_type=VecType::OneOrMore
        }
        _ => ()
    }
    self.vec_pred.push(Predicate::Oom(this));
    self.visit_expr(child)
  }

  fn visit_zero_or_more(&mut self, this: usize, child: usize){
    // println!("zero_or_more");
    self.pred = Predicate::Zom(this);
    self.verify_multiple();
    self.visit_expr(child)
  }

  fn visit_not_predicate(&mut self, this: usize, child: usize){
    // println!("not_predicate");
    self.warning(Predicate::Not(this));
    self.pred=Predicate::Not(this);
    self.verify_multiple();
    self.visit_expr(child)
  }

  fn visit_and_predicate(&mut self, this: usize, child: usize){
    // println!("and_predicate");
    self.warning(Predicate::And(this));
    self.pred=Predicate::And(this);

    match self.vec_type {
        VecType::OneOrMore => {
            self.verify_multiple()
        }
        VecType::Nothing => {
            self.vec_type=VecType::And;
        }
        _ => ()
    }
    self.vec_pred.push(Predicate::And(this));
    self.visit_expr(child)
  }

  fn visit_sequence(&mut self, _: usize, children: Vec<usize>){
    for child in children {
        self.pred=Predicate::Nothing;
        self.verify_multiple();
        self.visit_expr(child);
    }
  }

  fn visit_choice(&mut self, _: usize, children: Vec<usize>){
      for child in children {
          self.pred=Predicate::Nothing;
          self.verify_multiple();
          self.visit_expr(child);
      }
  }
}
<|endoftext|>