<commit_before>#![feature(collections, io, slice_patterns)]
use std::fs;
use std::io;
use std::io::{Read, Write};
use std::path::Path;

#[derive(Debug)]
enum ParserResult {
    Something(Op),
    Nothing,
    EOF
}

use ParserResult::*;

#[derive(Debug)]
enum Op {
    Add(u8),
    Mov(isize),
    In,
    Out,
    Loop(OpStream),

    Clear
}

use Op::*;

#[derive(Debug)]
struct OpStream {
    ops: Vec<Op>
}

impl OpStream {
    fn add(&mut self, op: Op) {
        self.ops.push(op);
    }

    fn optimize(&mut self) {
        let mut i = 0;
        while i < self.ops.len() {
            match &self.ops[i..] {
                [Add(a), Add(b), ..] => {
                    self.ops[i] = Add(a.wrapping_add(b));
                    self.ops.remove(i + 1);
                }
                [Mov(a), Mov(b), ..] => {
                    self.ops[i] = Mov(a + b);
                    self.ops.remove(i + 1);
                }
                [Add(0), ..] | [Mov(0), ..] => {
                    self.ops.remove(i);
                }
                [Loop(_), ..] => {
                    let mut maybe_new_op: Option<Op> = None;

                    if let &mut Loop(ref mut stream) = &mut self.ops[i] {
                        stream.optimize();
                        match &mut stream.ops[..] {
                            [Add(x)] if x % 2 != 0 => {
                                maybe_new_op = Some(Clear);
                            }
                            _ => ()
                        }
                    }

                    if let Some(new_op) = maybe_new_op {
                        self.ops[i] = new_op;
                    } else {
                        i += 1
                    }
                }
                _ => i += 1
            }
        }
    }

    fn get(&self) -> &[Op] {
        &self.ops[..]
    }

    fn new() -> OpStream {
        OpStream { ops: Vec::new() }
    }
}

static ZERO: u8 = 0;

struct State {
    index: usize,
    memory: Vec<u8>
}

impl State {
    fn new() -> State {
        State { index: 0, memory: vec![] }
    }

    fn rel_index(&self, relative: isize) -> usize {
        (self.index as isize + relative) as usize
    }

    fn step(&mut self, op: &Op) -> bool {
        match op {
            &Add(i) => {
                self[0] = self[0].wrapping_add(i);
            }
            &Mov(n) => {
                self.index = self.rel_index(n);
            }
            &In => {
                let mut c = vec![0u8];
                if io::stdin().read(&mut c).unwrap() == 0 {
                    return false;
                }
                self[0] = c[0];
            }
            &Out => {
                io::stdout().write(&vec![self[0]]).unwrap();
            }
            &Loop(ref ops) => {
                while self[0] != 0 {
                    if !self.run(ops.get()) {
                        return false;
                    }
                }
            }
            &Clear => {
                self[0] = 0;
            }
        }
        return true;
    }

    fn run(&mut self, ops: &[Op]) -> bool {
        for op in ops {
            if !self.step(op) {
                return false;
            }
        }
        return true;
    }
}

impl std::ops::Index<isize> for State {
    type Output = u8;
    fn index(&self, _index: isize) -> &u8 {
        let idx = self.rel_index(_index);
        if idx >= self.memory.len() {
            &ZERO
        } else {
            &self.memory[idx]
        }
    }
}

impl std::ops::IndexMut<isize> for State {
    fn index_mut(&mut self, _index: isize) -> &mut u8 {
        let idx = self.rel_index(_index);
        if idx >= self.memory.len() {
            self.memory.resize(idx * 2 + 1, 0);
        }
        &mut self.memory[idx]
    }
}

fn main() {
    let filenames: Vec<String> = std::iter::FromIterator::from_iter(std::env::args());

    for filename in &filenames[1..] {
        match reader(&Path::new(filename)) {
            Ok(reader) => {
                let mut chars = reader.chars().peekable();

                let mut opstream = OpStream::new();
                loop {
                    match parse(&mut chars) {
                        Something(op) => opstream.add(op),
                        EOF => break,
                        _ => {}
                    }
                }

                opstream.optimize();

                State::new().run(opstream.get());
            }
            Err(e) => {
                writeln!(&mut io::stderr(), "Error while processing {}: {}", filename, e).unwrap();
            }
        }
    }
}

fn parse<T: io::Read>(mut chars: &mut std::iter::Peekable<io::Chars<T>>) -> ParserResult {
    match chars.next() {
        Some(Ok(c)) => match c {
            '+' => Something(Add(0x01)),
            '-' => Something(Add(0xff)),
            '<' => Something(Mov(-1)),
            '>' => Something(Mov(1)),
            ',' => Something(In),
            '.' => Something(Out),
            '[' => {
                let mut childstream = OpStream::new();
                while match chars.peek() {
                    Some(&Ok(c)) => c != ']',
                    _ => false
                } {
                    match parse(&mut chars) {
                        Something(op) => childstream.add(op),
                        Nothing => {},
                        EOF => panic!()
                    }
                }
                chars.next();
                Something(Loop(childstream))
            },
            _ => Nothing  // other characters
        },
        _ => EOF  // XXX: really?
    }
}

fn reader(path: &Path) -> Result<io::BufReader<fs::File>, io::Error> {
    Ok(io::BufReader::new(try!(fs::File::open(path))))
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::io::Read;
    use super::{parse, ParserResult, State, OpStream};
    use super::Op::*;

    macro_rules! assert_let(
        ($test:pat, $value:expr, $then:block) => (
            if let $test = $value {
                $then
            } else {
                panic!("{:?} doesn't match {}", $value, stringify!($test))
            }
        );
        ($test:pat, $value:expr) => (
            assert_let!($test, $value, {})
        );
    );

    #[test]
    fn test_state_index() {
        let mut state = State { index: 0, memory: vec![23, 0, 0, 0, 0, 42] };
        assert_eq!(23, state[0]);
        state.index = 5;
        assert_eq!(42, state[0]);
    }

    #[test]
    fn test_state_index_mut() {
        let mut state = State::new();
        state[0] = 23;
        assert_eq!(23, state.memory[state.index]);
        state.index = 5;
        state[0] = 42;
        assert_eq!(42, state.memory[state.index]);
    }

    #[test]
    fn test_state_step_add() {
        let mut state = State::new();
        state.step(&Add(23));
        assert_eq!(23, state[0]);
        state.step(&Add(42));
        assert_eq!(65, state[0]);
        state.step(&Add(190));
        assert_eq!(255, state[0]);
    }

    #[test]
    fn test_state_step_mov() {
        let mut state = State::new();
        state.step(&Mov(1));
        assert_eq!(1, state.index);
        state.step(&Mov(42));
        assert_eq!(43, state.index);
        state.step(&Mov(-1));
        assert_eq!(42, state.index);
    }

    #[test]
    fn test_state_step_loop() {
        let mut state = State::new();
        state[0] = 23;
        state.step(&Loop(OpStream { ops: vec![Add(1)] }));
        assert_eq!(0, state[0]);
    }

    #[test]
    fn test_opstream_new_empty() {
        let opstream = OpStream::new();
        assert_eq!(0, opstream.ops.len());
    }

    #[test]
    fn test_opstream_optimize() {
        let mut opstream = OpStream::new();
        opstream.add(Mov(1));
        opstream.add(Mov(1));
        opstream.add(Add(0x01));
        opstream.add(Add(0xff));
        opstream.add(Add(0xff));
        opstream.add(Mov(1));
        opstream.add(Mov(-1));
        let mut opstream2 = OpStream::new();
        opstream2.add(Mov(2));
        opstream2.add(Mov(3));
        opstream.add(Loop(opstream2));
        opstream.optimize();

        assert_let!([Mov(2), Add(0xff), Loop(ref s2)], &opstream.ops[..], {
            assert_let!([Mov(5)], &s2.ops[..]);
        });
    }

    #[test]
    fn test_parse() {
        let input = b"+-[+.,]+";
        let mut chars = io::BufReader::new(&input[..]).chars().peekable();
        assert_let!(ParserResult::Something(Add(0x01)), parse(&mut chars));
        assert_let!(ParserResult::Something(Add(0xff)), parse(&mut chars));
        assert_let!(ParserResult::Something(Loop(loop_op)), parse(&mut chars), {
            assert_let!([Add(1), Out, In], &loop_op.ops[..]);
        });
        assert_let!(ParserResult::Something(Add(1)), parse(&mut chars));
    }
}
<commit_msg>feat: detect value-moving loops while optimizing<commit_after>#![feature(collections, io, slice_patterns)]
use std::fs;
use std::io;
use std::io::{Read, Write};
use std::path::Path;

#[derive(Debug)]
enum ParserResult {
    Something(Op),
    Nothing,
    EOF
}

use ParserResult::*;

#[derive(Debug)]
enum Op {
    Add(u8),
    Mov(isize),
    In,
    Out,
    Loop(OpStream),

    Clear,
    ClearAdd(isize),
    ClearSub(isize)
}

use Op::*;

#[derive(Debug)]
struct OpStream {
    ops: Vec<Op>
}

impl OpStream {
    fn add(&mut self, op: Op) {
        self.ops.push(op);
    }

    fn optimize(&mut self) {
        let mut i = 0;
        while i < self.ops.len() {
            match &self.ops[i..] {
                [Add(a), Add(b), ..] => {
                    self.ops[i] = Add(a.wrapping_add(b));
                    self.ops.remove(i + 1);
                }
                [Mov(a), Mov(b), ..] => {
                    self.ops[i] = Mov(a + b);
                    self.ops.remove(i + 1);
                }
                [Add(0), ..] | [Mov(0), ..] => {
                    self.ops.remove(i);
                }
                [Loop(_), ..] => {
                    let mut maybe_new_op: Option<Op> = None;

                    if let &mut Loop(ref mut stream) = &mut self.ops[i] {
                        stream.optimize();
                        match &mut stream.ops[..] {
                            [Add(x)] if x % 2 != 0 => {
                                maybe_new_op = Some(Clear);
                            }
                            [Add(255), Mov(x), Add(1), Mov(y)] if x == -y => {
                                maybe_new_op = Some(ClearAdd(x))
                            }
                            [Add(255), Mov(x), Add(255), Mov(y)] if x == -y => {
                                maybe_new_op = Some(ClearSub(x))
                            }
                            _ => ()
                        }
                    }

                    if let Some(new_op) = maybe_new_op {
                        self.ops[i] = new_op;
                    } else {
                        i += 1
                    }
                }
                _ => i += 1
            }
        }
    }

    fn get(&self) -> &[Op] {
        &self.ops[..]
    }

    fn new() -> OpStream {
        OpStream { ops: Vec::new() }
    }
}

static ZERO: u8 = 0;

struct State {
    index: usize,
    memory: Vec<u8>
}

impl State {
    fn new() -> State {
        State { index: 0, memory: vec![] }
    }

    fn rel_index(&self, relative: isize) -> usize {
        (self.index as isize + relative) as usize
    }

    fn step(&mut self, op: &Op) -> bool {
        match op {
            &Add(i) => {
                self[0] = self[0].wrapping_add(i);
            }
            &Mov(n) => {
                self.index = self.rel_index(n);
            }
            &In => {
                let mut c = vec![0u8];
                if io::stdin().read(&mut c).unwrap() == 0 {
                    return false;
                }
                self[0] = c[0];
            }
            &Out => {
                io::stdout().write(&vec![self[0]]).unwrap();
            }
            &Loop(ref ops) => {
                while self[0] != 0 {
                    if !self.run(ops.get()) {
                        return false;
                    }
                }
            }
            &Clear => {
                self[0] = 0;
            }
            &ClearAdd(offset) => {
                if self[0] != 0 {
                    self[offset] = self[offset].wrapping_add(self[0]);
                    self[0] = 0;
                }
            }
            &ClearSub(offset) => {
                if self[0] != 0 {
                    self[offset] = self[offset].wrapping_sub(self[0]);
                    self[0] = 0;
                }
            }
        }
        return true;
    }

    fn run(&mut self, ops: &[Op]) -> bool {
        for op in ops {
            if !self.step(op) {
                return false;
            }
        }
        return true;
    }
}

impl std::ops::Index<isize> for State {
    type Output = u8;
    fn index(&self, _index: isize) -> &u8 {
        let idx = self.rel_index(_index);
        if idx >= self.memory.len() {
            &ZERO
        } else {
            &self.memory[idx]
        }
    }
}

impl std::ops::IndexMut<isize> for State {
    fn index_mut(&mut self, _index: isize) -> &mut u8 {
        let idx = self.rel_index(_index);
        if idx >= self.memory.len() {
            self.memory.resize(idx * 2 + 1, 0);
        }
        &mut self.memory[idx]
    }
}

fn main() {
    let filenames: Vec<String> = std::iter::FromIterator::from_iter(std::env::args());

    for filename in &filenames[1..] {
        match reader(&Path::new(filename)) {
            Ok(reader) => {
                let mut chars = reader.chars().peekable();

                let mut opstream = OpStream::new();
                loop {
                    match parse(&mut chars) {
                        Something(op) => opstream.add(op),
                        EOF => break,
                        _ => {}
                    }
                }

                opstream.optimize();

                State::new().run(opstream.get());
            }
            Err(e) => {
                writeln!(&mut io::stderr(), "Error while processing {}: {}", filename, e).unwrap();
            }
        }
    }
}

fn parse<T: io::Read>(mut chars: &mut std::iter::Peekable<io::Chars<T>>) -> ParserResult {
    match chars.next() {
        Some(Ok(c)) => match c {
            '+' => Something(Add(0x01)),
            '-' => Something(Add(0xff)),
            '<' => Something(Mov(-1)),
            '>' => Something(Mov(1)),
            ',' => Something(In),
            '.' => Something(Out),
            '[' => {
                let mut childstream = OpStream::new();
                while match chars.peek() {
                    Some(&Ok(c)) => c != ']',
                    _ => false
                } {
                    match parse(&mut chars) {
                        Something(op) => childstream.add(op),
                        Nothing => {},
                        EOF => panic!()
                    }
                }
                chars.next();
                Something(Loop(childstream))
            },
            _ => Nothing  // other characters
        },
        _ => EOF  // XXX: really?
    }
}

fn reader(path: &Path) -> Result<io::BufReader<fs::File>, io::Error> {
    Ok(io::BufReader::new(try!(fs::File::open(path))))
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::io::Read;
    use super::{parse, ParserResult, State, OpStream};
    use super::Op::*;

    macro_rules! assert_let(
        ($test:pat, $value:expr, $then:block) => (
            if let $test = $value {
                $then
            } else {
                panic!("{:?} doesn't match {}", $value, stringify!($test))
            }
        );
        ($test:pat, $value:expr) => (
            assert_let!($test, $value, {})
        );
    );

    #[test]
    fn test_state_index() {
        let mut state = State { index: 0, memory: vec![23, 0, 0, 0, 0, 42] };
        assert_eq!(23, state[0]);
        state.index = 5;
        assert_eq!(42, state[0]);
    }

    #[test]
    fn test_state_index_mut() {
        let mut state = State::new();
        state[0] = 23;
        assert_eq!(23, state.memory[state.index]);
        state.index = 5;
        state[0] = 42;
        assert_eq!(42, state.memory[state.index]);
    }

    #[test]
    fn test_state_step_add() {
        let mut state = State::new();
        state.step(&Add(23));
        assert_eq!(23, state[0]);
        state.step(&Add(42));
        assert_eq!(65, state[0]);
        state.step(&Add(190));
        assert_eq!(255, state[0]);
    }

    #[test]
    fn test_state_step_mov() {
        let mut state = State::new();
        state.step(&Mov(1));
        assert_eq!(1, state.index);
        state.step(&Mov(42));
        assert_eq!(43, state.index);
        state.step(&Mov(-1));
        assert_eq!(42, state.index);
    }

    #[test]
    fn test_state_step_loop() {
        let mut state = State::new();
        state[0] = 23;
        state.step(&Loop(OpStream { ops: vec![Add(1)] }));
        assert_eq!(0, state[0]);
    }

    #[test]
    fn test_opstream_new_empty() {
        let opstream = OpStream::new();
        assert_eq!(0, opstream.ops.len());
    }

    #[test]
    fn test_opstream_optimize() {
        let mut opstream = OpStream::new();
        opstream.add(Mov(1));
        opstream.add(Mov(1));
        opstream.add(Add(0x01));
        opstream.add(Add(0xff));
        opstream.add(Add(0xff));
        opstream.add(Mov(1));
        opstream.add(Mov(-1));
        let mut opstream2 = OpStream::new();
        opstream2.add(Mov(2));
        opstream2.add(Mov(3));
        opstream.add(Loop(opstream2));
        opstream.optimize();

        assert_let!([Mov(2), Add(0xff), Loop(ref s2)], &opstream.ops[..], {
            assert_let!([Mov(5)], &s2.ops[..]);
        });
    }

    #[test]
    fn test_parse() {
        let input = b"+-[+.,]+";
        let mut chars = io::BufReader::new(&input[..]).chars().peekable();
        assert_let!(ParserResult::Something(Add(0x01)), parse(&mut chars));
        assert_let!(ParserResult::Something(Add(0xff)), parse(&mut chars));
        assert_let!(ParserResult::Something(Loop(loop_op)), parse(&mut chars), {
            assert_let!([Add(1), Out, In], &loop_op.ops[..]);
        });
        assert_let!(ParserResult::Something(Add(1)), parse(&mut chars));
    }
}
<|endoftext|>


<commit_before>use glium;
use glutin;
use std;
use time;

use scene;

#[repr(C)]
#[derive(Clone, Copy)]
pub struct RGB {
  pub r: f32,
  pub g: f32,
  pub b: f32,
}

unsafe impl Send for RGB {}

unsafe impl glium::texture::PixelValue for RGB {
  fn get_format() -> glium::texture::ClientFormat {
    glium::texture::ClientFormat::F32F32F32
  }
}

pub const WINDOW_WIDTH: u32 = 800;
pub const WINDOW_HEIGHT: u32 = 600;

pub fn main() {
  use glium::DisplayBuild;

  let window =
    glutin::WindowBuilder::new()
    .with_dimensions(WINDOW_WIDTH, WINDOW_HEIGHT)
    .build_glium()
    .unwrap();

  let mut image_data = vec!();
  for y in 0 .. WINDOW_HEIGHT {
    let mut row = vec!();
    for x in 0 .. WINDOW_WIDTH {
      row.push(
        RGB {
          r: x as f32 / WINDOW_WIDTH as f32,
          g: y as f32 / WINDOW_HEIGHT as f32,
          b: 0.0,
        }
      );
    }
    image_data.push(row);
  }

  let scene =
    scene::T {
      objects       :
        vec!(
          scene::Object { center: [ -1.0,  0.0, -4.0], radius:   1.0, color: [1.0 , 0.0 , 0.0 ], emittance: 0.0, reflectance: 1.0, transmittance: 0.0, diffuseness: 1.0  },
          scene::Object { center: [  3.0, -1.0, -6.0], radius:   2.0, color: [0.8 , 0.8 , 0.8 ], emittance: 0.0, reflectance: 1.0, transmittance: 0.0, diffuseness: 0.01 },
          scene::Object { center: [ 30.0, 10.0,  4.0], radius:  10.0, color: [1.0 , 1.0 , 1.0 ], emittance: 1.0, reflectance: 0.0, transmittance: 0.4, diffuseness: 1.0  },
          scene::Object { center: [ -1.0,  0.2, -2.0], radius:   0.4, color: [0.9 , 0.9 , 1.0 ], emittance: 0.0, reflectance: 0.1, transmittance: 0.8, diffuseness: 0.01 },
          scene::Object { center: [  0.0,  0.0,  0.0], radius: 100.0, color: [0.02, 0.02, 0.02], emittance: 1.0, reflectance: 0.0, transmittance: 0.0, diffuseness: 0.0  },
        ),
      fovy          : std::f32::consts::FRAC_PI_2,
      eye           : [0.0, 0.0,  0.0],
      look          : [0.0, 0.0, -1.0],
      up            : [0.0, 1.0,  0.0],
    };

  let mut rendered_2d = vec!();
  {
    let scale = 1 << 0;
    let w = scale * WINDOW_WIDTH;
    let h = scale * WINDOW_HEIGHT;

    let before = time::precise_time_ns();
    let rendered = scene.render(w, h);
    let after = time::precise_time_ns();
    println!("Render took {:?}ms", (after - before) as f32 / 1_000_000.0);

    for y in 0 .. h as usize {
      let mut row = vec!();
      for x in 0 .. w as usize {
        row.push(rendered[y * w as usize + x]);
      }
      rendered_2d.push(row);
    }
  }

  let texture = glium::texture::Texture2d::new(&window, rendered_2d).unwrap();

  // building the vertex buffer, which contains all the vertices that we will draw
  let vertex_buffer = {
    #[derive(Copy, Clone)]
    struct Vertex {
      position: [f32; 2],
      tex_coords: [f32; 2],
    }

    implement_vertex!(Vertex, position, tex_coords);

    glium::VertexBuffer::new(&window,
      &[
        Vertex { position: [-1.0, -1.0], tex_coords: [0.0, 0.0] },
        Vertex { position: [-1.0,  1.0], tex_coords: [0.0, 1.0] },
        Vertex { position: [ 1.0,  1.0], tex_coords: [1.0, 1.0] },
        Vertex { position: [ 1.0, -1.0], tex_coords: [1.0, 0.0] }
      ]
    ).unwrap()
  };

  // building the index buffer
  let index_buffer =
    glium::IndexBuffer::new(
      &window,
      glium::index::PrimitiveType::TriangleStrip,
      &[1 as u16, 2, 0, 3],
    ).unwrap();

  // compiling shaders and linking them together
  let program = program!(&window,
    330 => {
      vertex: "
        #version 330

        uniform mat4 matrix;

        in vec2 position;
        in vec2 tex_coords;

        out vec2 v_tex_coords;

        void main() {
          gl_Position = matrix * vec4(position, 0.0, 1.0);
          v_tex_coords = tex_coords;
        }
      ",

      fragment: "
        #version 330
        uniform sampler2D tex;
        in vec2 v_tex_coords;
        out vec4 f_color;

        void main() {
          f_color = texture(tex, v_tex_coords);
        }
      "
    },
  ).unwrap();

  loop {
    use glium::Surface;

    // building the uniforms
    let uniforms = uniform! {
      matrix: [
        [1.0, 0.0, 0.0, 0.0],
        [0.0, 1.0, 0.0, 0.0],
        [0.0, 0.0, 1.0, 0.0],
        [0.0, 0.0, 0.0, 1.0f32]
      ],
      tex: &texture,
    };

    let mut target = window.draw();
    target.clear_color(0.0, 0.0, 0.0, 0.0);
    target.draw(&vertex_buffer, &index_buffer, &program, &uniforms, &Default::default()).unwrap();
    target.finish().unwrap();

    for event in window.poll_events() {
      if let glutin::Event::Closed = event {
        return
      }
    }
  }
}
<commit_msg>specify texture filtering<commit_after>use glium;
use glutin;
use std;
use time;

use scene;

#[repr(C)]
#[derive(Clone, Copy)]
pub struct RGB {
  pub r: f32,
  pub g: f32,
  pub b: f32,
}

unsafe impl Send for RGB {}

unsafe impl glium::texture::PixelValue for RGB {
  fn get_format() -> glium::texture::ClientFormat {
    glium::texture::ClientFormat::F32F32F32
  }
}

pub const WINDOW_WIDTH: u32 = 800;
pub const WINDOW_HEIGHT: u32 = 600;

pub fn main() {
  use glium::DisplayBuild;

  let window =
    glutin::WindowBuilder::new()
    .with_dimensions(WINDOW_WIDTH, WINDOW_HEIGHT)
    .build_glium()
    .unwrap();

  let mut image_data = vec!();
  for y in 0 .. WINDOW_HEIGHT {
    let mut row = vec!();
    for x in 0 .. WINDOW_WIDTH {
      row.push(
        RGB {
          r: x as f32 / WINDOW_WIDTH as f32,
          g: y as f32 / WINDOW_HEIGHT as f32,
          b: 0.0,
        }
      );
    }
    image_data.push(row);
  }

  let scene =
    scene::T {
      objects       :
        vec!(
          scene::Object { center: [ -1.0,  0.0, -4.0], radius:   1.0, color: [1.0 , 0.0 , 0.0 ], emittance: 0.0, reflectance: 1.0, transmittance: 0.0, diffuseness: 1.0  },
          scene::Object { center: [  3.0, -1.0, -6.0], radius:   2.0, color: [0.8 , 0.8 , 0.8 ], emittance: 0.0, reflectance: 1.0, transmittance: 0.0, diffuseness: 0.01 },
          scene::Object { center: [ 30.0, 10.0,  4.0], radius:  10.0, color: [1.0 , 1.0 , 1.0 ], emittance: 1.0, reflectance: 0.0, transmittance: 0.4, diffuseness: 1.0  },
          scene::Object { center: [ -1.0,  0.2, -2.0], radius:   0.4, color: [0.9 , 0.9 , 1.0 ], emittance: 0.0, reflectance: 0.1, transmittance: 0.8, diffuseness: 0.01 },
          scene::Object { center: [  0.0,  0.0,  0.0], radius: 100.0, color: [0.02, 0.02, 0.02], emittance: 1.0, reflectance: 0.0, transmittance: 0.0, diffuseness: 0.0  },
        ),
      fovy          : std::f32::consts::FRAC_PI_2,
      eye           : [0.0, 0.0,  0.0],
      look          : [0.0, 0.0, -1.0],
      up            : [0.0, 1.0,  0.0],
    };

  let mut rendered_2d = vec!();
  {
    let scale = 1 << 0;
    let w = scale * WINDOW_WIDTH;
    let h = scale * WINDOW_HEIGHT;

    let before = time::precise_time_ns();
    let rendered = scene.render(w, h);
    let after = time::precise_time_ns();
    println!("Render took {:?}ms", (after - before) as f32 / 1_000_000.0);

    for y in 0 .. h as usize {
      let mut row = vec!();
      for x in 0 .. w as usize {
        row.push(rendered[y * w as usize + x]);
      }
      rendered_2d.push(row);
    }
  }

  let texture = glium::texture::Texture2d::new(&window, rendered_2d).unwrap();

  // building the vertex buffer, which contains all the vertices that we will draw
  let vertex_buffer = {
    #[derive(Copy, Clone)]
    struct Vertex {
      position: [f32; 2],
      tex_coords: [f32; 2],
    }

    implement_vertex!(Vertex, position, tex_coords);

    glium::VertexBuffer::new(&window,
      &[
        Vertex { position: [-1.0, -1.0], tex_coords: [0.0, 0.0] },
        Vertex { position: [-1.0,  1.0], tex_coords: [0.0, 1.0] },
        Vertex { position: [ 1.0,  1.0], tex_coords: [1.0, 1.0] },
        Vertex { position: [ 1.0, -1.0], tex_coords: [1.0, 0.0] }
      ]
    ).unwrap()
  };

  // building the index buffer
  let index_buffer =
    glium::IndexBuffer::new(
      &window,
      glium::index::PrimitiveType::TriangleStrip,
      &[1 as u16, 2, 0, 3],
    ).unwrap();

  // compiling shaders and linking them together
  let program = program!(&window,
    330 => {
      vertex: "
        #version 330

        uniform mat4 matrix;

        in vec2 position;
        in vec2 tex_coords;

        out vec2 v_tex_coords;

        void main() {
          gl_Position = matrix * vec4(position, 0.0, 1.0);
          v_tex_coords = tex_coords;
        }
      ",

      fragment: "
        #version 330
        uniform sampler2D tex;
        in vec2 v_tex_coords;
        out vec4 f_color;

        void main() {
          f_color = texture(tex, v_tex_coords);
        }
      "
    },
  ).unwrap();

  loop {
    use glium::Surface;

    // building the uniforms
    let uniforms = uniform! {
      matrix: [
        [1.0, 0.0, 0.0, 0.0],
        [0.0, 1.0, 0.0, 0.0],
        [0.0, 0.0, 1.0, 0.0],
        [0.0, 0.0, 0.0, 1.0f32]
      ],
      tex:
        glium::uniforms::Sampler::new(&texture)
        .magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear)
        .minify_filter(glium::uniforms::MinifySamplerFilter::LinearMipmapLinear)
    };

    let mut target = window.draw();
    target.clear_color(0.0, 0.0, 0.0, 0.0);
    target.draw(&vertex_buffer, &index_buffer, &program, &uniforms, &Default::default()).unwrap();
    target.finish().unwrap();

    for event in window.poll_events() {
      if let glutin::Event::Closed = event {
        return
      }
    }
  }
}
<|endoftext|>


<commit_before>extern crate identicon;
extern crate openssl;
extern crate image;

use std::io;
use std::io::{Read, Write, Result};

use image::ColorType;
use image::png::PNGEncoder;
use openssl::crypto::hash::{Hasher, Type};

use identicon::Identicon;

fn main() {
    let bytes = hash().unwrap();
    generate(&bytes[..]).unwrap();
}

fn generate(input: &[u8]) -> Result<()> {
    let identicon = Identicon::new(input);
    let image = identicon.image();
    let (width, height) = image.dimensions();
    let output = &mut io::stdout();
    let encoder = PNGEncoder::new(output);
    encoder.encode(image.as_ref(), width, height, ColorType::RGB(8))
}

fn hash() -> Result<Vec<u8>> {
    let mut hash = Hasher::new(Type::MD5);
    let input = io::stdin();
    let mut reader = input.lock();
    try!(pipe(&mut reader, &mut hash));
    Ok(hash.finish())
}

fn pipe(input: &mut Read, output: &mut Write) -> Result<usize> {
    let mut total = 0;
    let mut buf = [0; 1024];
    loop {
        match try!(input.read(&mut buf)) {
            0 => break,
            n => {
                try!(output.write(&buf[0..n]));
                total += n;
            }
        }
    }
    Ok(total)
}
<commit_msg>Use new ? operator<commit_after>extern crate identicon;
extern crate openssl;
extern crate image;

use std::io;
use std::io::{Read, Write, Result};

use image::ColorType;
use image::png::PNGEncoder;
use openssl::crypto::hash::{Hasher, Type};

use identicon::Identicon;

fn main() {
    let bytes = hash().unwrap();
    generate(&bytes[..]).unwrap();
}

fn generate(input: &[u8]) -> Result<()> {
    let identicon = Identicon::new(input);
    let image = identicon.image();
    let (width, height) = image.dimensions();
    let output = &mut io::stdout();
    let encoder = PNGEncoder::new(output);
    encoder.encode(image.as_ref(), width, height, ColorType::RGB(8))
}

fn hash() -> Result<Vec<u8>> {
    let mut hash = Hasher::new(Type::MD5);
    let input = io::stdin();
    let mut reader = input.lock();
    pipe(&mut reader, &mut hash)?;
    Ok(hash.finish())
}

fn pipe(input: &mut Read, output: &mut Write) -> Result<usize> {
    let mut total = 0;
    let mut buf = [0; 1024];
    loop {
        match input.read(&mut buf)? {
            0 => break,
            n => {
                output.write(&buf[0..n])?;
                total += n;
            }
        }
    }
    Ok(total)
}
<|endoftext|>


<commit_before>#![recursion_limit = "1024"]

#[macro_use]
extern crate error_chain;
extern crate blacklung;
extern crate docopt;
extern crate rustc_serialize;
#[macro_use]
extern crate slog;

use blacklung::server;
use docopt::Docopt;

const USAGE: &'static str = "
Blacklung server.

Usage:
    blacklung [--port=<port>]
    blacklung (-h | --help)

Options:
    -h --help       Show this screen.
    --port=<PORT>   Port to bind to [default: 12345].
";

#[derive(Debug, RustcDecodable)]
struct Args {
    flag_port: u16,
}
use blacklung::logging;

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

    let root_logger = logging::setup();

    info!(root_logger, "Started application");

    if let Err(ref e) = server::start(&root_logger, args.flag_port) {
        use std::io::Write;
        let stderr = &mut ::std::io::stderr();
        let errmsg = "Error writing to stderr";

        writeln!(stderr, "error: {}", e).expect(errmsg);

        for e in e.iter().skip(1) {
            writeln!(stderr, "caused by: {}", e).expect(errmsg);
        }

        if let Some(backtrace) = e.backtrace() {
            writeln!(stderr, "backtrace: {:?}", backtrace).expect(errmsg);
        }

        ::std::process::exit(1);
    }
}
<commit_msg>Added logging of command line arguments.<commit_after>#![recursion_limit = "1024"]

#[macro_use]
extern crate error_chain;
extern crate blacklung;
extern crate docopt;
extern crate rustc_serialize;
#[macro_use]
extern crate slog;

use blacklung::server;
use docopt::Docopt;

const USAGE: &'static str = "
Blacklung server.

Usage:
    blacklung [--port=<port>]
    blacklung (-h | --help)

Options:
    -h --help       Show this screen.
    --port=<PORT>   Port to bind to [default: 12345].
";

#[derive(Debug, RustcDecodable)]
struct Args {
    flag_port: u16,
}
use blacklung::logging;

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

    let root_logger = logging::setup();

    info!(root_logger, "Started application"; "args" => format!("{:?}", args));

    if let Err(ref e) = server::start(&root_logger, args.flag_port) {
        use std::io::Write;
        let stderr = &mut ::std::io::stderr();
        let errmsg = "Error writing to stderr";

        writeln!(stderr, "error: {}", e).expect(errmsg);

        for e in e.iter().skip(1) {
            writeln!(stderr, "caused by: {}", e).expect(errmsg);
        }

        if let Some(backtrace) = e.backtrace() {
            writeln!(stderr, "backtrace: {:?}", backtrace).expect(errmsg);
        }

        ::std::process::exit(1);
    }
}
<|endoftext|>


<commit_before>#![feature(slice_patterns, vec_resize)]
#[macro_use]
extern crate nom;

use nom::{IResult, eof};
use std::collections::BTreeMap;
use std::fs;
use std::io;
use std::io::{Read, Write};
use std::path::Path;
use std::thread;

#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Eq)]
enum Op {
    Add(u8),
    Mov(isize),
    In,
    Out,
    Loop(OpStream),

    // extra optimized ops
    Transfer(u8, Vec<(isize, u8)>)
}

use Op::*;

#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Eq)]
struct OpStream {
    ops: Vec<Op>
}

impl OpStream {
    fn optimize(&mut self) {
        let mut i = 0;
        while i < self.ops.len() {
            match &self.ops[i..] {
                [Add(a), Add(b), ..] => {
                    self.ops[i] = Add(a.wrapping_add(b));
                    self.ops.remove(i + 1);
                }
                [Mov(a), Mov(b), ..] => {
                    self.ops[i] = Mov(a + b);
                    self.ops.remove(i + 1);
                }
                [Add(0), ..] | [Mov(0), ..] => {
                    self.ops.remove(i);
                    if i > 0 {
                        i -= 1;
                    }
                }
                [Loop(_), ..] => {
                    let mut maybe_new_op = None;

                    if let &mut Loop(ref mut stream) = &mut self.ops[i] {
                        stream.optimize();
                        maybe_new_op = stream.find_alternative();
                    }

                    if let Some(new_op) = maybe_new_op {
                        self.ops[i] = new_op;
                    }

                    i += 1
                }
                _ => i += 1
            }
        }
    }

    fn find_alternative(&self) -> Option<Op> {
        let mut map: BTreeMap<isize, u8> = BTreeMap::new();
        let mut rel_index = 0;

        for op in &self.ops[..] {
            match op {
                &Add(x) => {
                    let new_val = map.get(&rel_index).unwrap_or(&0).wrapping_add(x);
                    map.insert(rel_index, new_val);
                }
                &Mov(x) => {
                    rel_index += x;
                }
                _ => {
                    return None;
                }
            }
        }

        if rel_index != 0 {
            return None;
        }

        Some(Transfer(map.remove(&0).unwrap_or(0), map.into_iter().collect()))
    }

    fn get(&self) -> &[Op] {
        &self.ops[..]
    }
}

static ZERO: u8 = 0;

struct State {
    index: usize,
    memory: Vec<u8>
}

impl State {
    fn new() -> State {
        State { index: 0, memory: vec![] }
    }

    fn rel_index(&self, relative: isize) -> usize {
        (self.index as isize + relative) as usize
    }

    fn step(&mut self, op: &Op) -> bool {
        match op {
            &Add(i) => {
                self[0] = self[0].wrapping_add(i);
            }
            &Mov(n) => {
                self.index = self.rel_index(n);
            }
            &In => {
                let mut c = [0u8];
                if io::stdin().read(&mut c).unwrap() == 0 {
                    return false;
                }
                self[0] = c[0];
            }
            &Out => {
                io::stdout().write(&[self[0]]).unwrap();
            }
            &Loop(ref ops) => {
                while self[0] != 0 {
                    if !self.run(ops.get()) {
                        return false;
                    }
                }
            }
            &Transfer(d, ref map) => {
                if self[0] == 0 {
                    return true
                }

                let mut _v = self[0];
                let mut _n = 0;

                while _v != 0 {
                    _v = _v.wrapping_add(d);
                    if _v == self[0] {
                        // stalled: the current transfer will never complete
                        loop {
                            thread::park()
                        }
                    }
                    _n += 1
                }

                self[0] = 0;
                for &(k, v) in &map[..] {
                    self[k] = self[k].wrapping_add(v.wrapping_mul(_n));
                }
            }
        }
        return true;
    }

    fn run(&mut self, ops: &[Op]) -> bool {
        for op in ops {
            if !self.step(op) {
                return false;
            }
        }
        return true;
    }
}

impl std::ops::Index<isize> for State {
    type Output = u8;
    fn index(&self, _index: isize) -> &u8 {
        let idx = self.rel_index(_index);
        if idx >= self.memory.len() {
            &ZERO
        } else {
            &self.memory[idx]
        }
    }
}

impl std::ops::IndexMut<isize> for State {
    fn index_mut(&mut self, _index: isize) -> &mut u8 {
        let idx = self.rel_index(_index);
        if idx >= self.memory.len() {
            self.memory.resize(idx * 2 + 1, 0);
        }
        &mut self.memory[idx]
    }
}

fn main() {
    let filenames: Vec<String> = std::iter::FromIterator::from_iter(std::env::args());

    for filename in &filenames[1..] {
        match reader(&Path::new(filename)).and_then(|mut reader| {
            let mut buffer = Vec::new();
            reader.read_to_end(&mut buffer).map(|_| buffer)
        }).map_err(|e| format!("{}", e)).and_then(|buffer| {
            match bf_parse_file(&buffer[..]) {
                IResult::Done(_, o) => Ok(o),
                IResult::Error(e) => Err(format!("Parsing error: {:?}", e)),
                IResult::Incomplete(m) => Err(format!("Incomplete file: {:?}", m)),
            }
        }) {
            Ok(ops) => {
                let mut opstream = OpStream { ops: ops };
                opstream.optimize();
                State::new().run(opstream.get());
            }
            Err(e) => {
                writeln!(&mut io::stderr(), "Error while processing {}: {}", filename, e).unwrap();
            }
        };
    }
}

named!(bf_parse_file<&[u8], Vec<Op> >, chain!(ops: bf_parse ~ eof, || ops));
named!(bf_parse<&[u8], Vec<Op> >,
    many0!(
        chain!(
            opt!(is_not!("+-<>.,[]")) ~
            op: alt!(
                chain!(tag!("+"), || Add(0x01)) |
                chain!(tag!("-"), || Add(0xff)) |
                chain!(tag!(">"), || Mov(1)) |
                chain!(tag!("<"), || Mov(-1)) |
                chain!(tag!("."), || Out) |
                chain!(tag!(","), || In) |
                chain!(subops: delimited!(tag!("["), bf_parse, tag!("]")), || Loop(OpStream { ops: subops }))
            ) ~
            opt!(is_not!("+-<>.,[]")), || op)
        )
    );

fn reader(path: &Path) -> Result<io::BufReader<fs::File>, io::Error> {
    fs::File::open(path).map(|f| io::BufReader::new(f))
}

#[cfg(test)]
mod tests {
    use nom::IResult::Done;
    use super::{bf_parse_file, State, OpStream};
    use super::Op::*;

    #[test]
    fn test_state_index() {
        let mut state = State { index: 0, memory: vec![23, 0, 0, 0, 0, 42] };
        assert_eq!(23, state[0]);
        state.index = 5;
        assert_eq!(42, state[0]);
    }

    #[test]
    fn test_state_index_mut() {
        let mut state = State::new();
        state[0] = 23;
        assert_eq!(23, state.memory[state.index]);
        state.index = 5;
        state[0] = 42;
        assert_eq!(42, state.memory[state.index]);
    }

    #[test]
    fn test_state_step_add() {
        let mut state = State::new();
        state.step(&Add(23));
        assert_eq!(23, state[0]);
        state.step(&Add(42));
        assert_eq!(65, state[0]);
        state.step(&Add(190));
        assert_eq!(255, state[0]);
    }

    #[test]
    fn test_state_step_mov() {
        let mut state = State::new();
        state.step(&Mov(1));
        assert_eq!(1, state.index);
        state.step(&Mov(42));
        assert_eq!(43, state.index);
        state.step(&Mov(-1));
        assert_eq!(42, state.index);
    }

    #[test]
    fn test_state_step_loop() {
        let mut state = State::new();
        state[0] = 23;
        state.step(&Loop(OpStream { ops: vec![Add(1)] }));
        assert_eq!(0, state[0]);
    }

    #[test]
    fn test_state_step_transfer() {
        let mut state = State::new();
        state[0] = 15;
        state[1] = 7;
        state.step(&Transfer(5, vec![(1, 2)]));
        assert_eq!(0, state[0]);
        assert_eq!(1, state[1]);
    }

    #[test]
    fn test_opstream_optimize() {
        let mut opstream = OpStream { ops: vec![
            Mov(1),
            Mov(1),
            Add(0x01),
            Add(0x0ff),
            Add(0x0ff),
            Mov(1),
            Mov(-1),
            Loop(OpStream { ops: vec![
                Mov(2),
                Mov(3)
            ] })
        ] };
        opstream.optimize();

        assert_eq!(opstream, OpStream { ops: vec![Mov(2), Add(0xff), Loop(OpStream { ops: vec![Mov(5)] } )] });
    }

    #[test]
    fn test_opstream_optimize_transfer() {
        let mut opstream = OpStream { ops: vec![
            Loop(OpStream { ops: vec![
                Add(0x01),
                Mov(3),
                Add(0xff),
                Mov(-3)
            ] })
        ] };
        opstream.optimize();

        assert_eq!(opstream, OpStream { ops: vec![Transfer(1, vec![(3, 255)])] } );
    }

    #[test]
    fn test_parse() {
        let input = b"+-[+.,]+";
        assert_eq!(
            bf_parse_file(&input[..]),
            Done(&b""[..],
                vec![Add(0x01), Add(0xff), Loop(
                    OpStream { ops: vec![Add(1), Out, In] }
                ), Add(0x01)]
            )
        );
    }
}
<commit_msg>style: make the patterns look nicer<commit_after>#![feature(slice_patterns, vec_resize)]
#[macro_use]
extern crate nom;

use nom::{IResult, eof};
use std::collections::BTreeMap;
use std::fs;
use std::io;
use std::io::{Read, Write};
use std::path::Path;
use std::thread;

#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Eq)]
enum Op {
    Add(u8),
    Mov(isize),
    In,
    Out,
    Loop(OpStream),

    // extra optimized ops
    Transfer(u8, Vec<(isize, u8)>)
}

use Op::*;

#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Eq)]
struct OpStream {
    ops: Vec<Op>
}

impl OpStream {
    fn optimize(&mut self) {
        let mut i = 0;
        while i < self.ops.len() {
            match &self.ops[i..] {
                [Add(a), Add(b), ..] => {
                    self.ops[i] = Add(a.wrapping_add(b));
                    self.ops.remove(i + 1);
                }
                [Mov(a), Mov(b), ..] => {
                    self.ops[i] = Mov(a + b);
                    self.ops.remove(i + 1);
                }
                [Add(0), ..] | [Mov(0), ..] => {
                    self.ops.remove(i);
                    if i > 0 {
                        i -= 1;
                    }
                }
                [Loop(_), ..] => {
                    let mut maybe_new_op = None;

                    if let &mut Loop(ref mut stream) = &mut self.ops[i] {
                        stream.optimize();
                        maybe_new_op = stream.find_alternative();
                    }

                    if let Some(new_op) = maybe_new_op {
                        self.ops[i] = new_op;
                    }

                    i += 1
                }
                _ => i += 1
            }
        }
    }

    fn find_alternative(&self) -> Option<Op> {
        let mut map: BTreeMap<isize, u8> = BTreeMap::new();
        let mut rel_index = 0;

        for op in &self.ops[..] {
            match op {
                &Add(x) => {
                    let new_val = map.get(&rel_index).unwrap_or(&0).wrapping_add(x);
                    map.insert(rel_index, new_val);
                }
                &Mov(x) => {
                    rel_index += x;
                }
                _ => {
                    return None;
                }
            }
        }

        if rel_index != 0 {
            return None;
        }

        Some(Transfer(map.remove(&0).unwrap_or(0), map.into_iter().collect()))
    }

    fn get(&self) -> &[Op] {
        &self.ops[..]
    }
}

static ZERO: u8 = 0;

struct State {
    index: usize,
    memory: Vec<u8>
}

impl State {
    fn new() -> State {
        State { index: 0, memory: vec![] }
    }

    fn rel_index(&self, relative: isize) -> usize {
        (self.index as isize + relative) as usize
    }

    fn step(&mut self, op: &Op) -> bool {
        match *op {
            Add(i) => {
                self[0] = self[0].wrapping_add(i);
            }
            Mov(n) => {
                self.index = self.rel_index(n);
            }
            In => {
                let mut c = [0u8];
                if io::stdin().read(&mut c).unwrap() == 0 {
                    return false;
                }
                self[0] = c[0];
            }
            Out => {
                io::stdout().write(&[self[0]]).unwrap();
            }
            Loop(ref ops) => {
                while self[0] != 0 {
                    if !self.run(ops.get()) {
                        return false;
                    }
                }
            }
            Transfer(d, ref map) => {
                if self[0] == 0 {
                    return true
                }

                let mut _v = self[0];
                let mut _n = 0;

                while _v != 0 {
                    _v = _v.wrapping_add(d);
                    if _v == self[0] {
                        // stalled: the current transfer will never complete
                        loop {
                            thread::park()
                        }
                    }
                    _n += 1
                }

                self[0] = 0;
                for &(k, v) in &map[..] {
                    self[k] = self[k].wrapping_add(v.wrapping_mul(_n));
                }
            }
        }
        return true;
    }

    fn run(&mut self, ops: &[Op]) -> bool {
        for op in ops {
            if !self.step(op) {
                return false;
            }
        }
        return true;
    }
}

impl std::ops::Index<isize> for State {
    type Output = u8;
    fn index(&self, _index: isize) -> &u8 {
        let idx = self.rel_index(_index);
        if idx >= self.memory.len() {
            &ZERO
        } else {
            &self.memory[idx]
        }
    }
}

impl std::ops::IndexMut<isize> for State {
    fn index_mut(&mut self, _index: isize) -> &mut u8 {
        let idx = self.rel_index(_index);
        if idx >= self.memory.len() {
            self.memory.resize(idx * 2 + 1, 0);
        }
        &mut self.memory[idx]
    }
}

fn main() {
    let filenames: Vec<String> = std::iter::FromIterator::from_iter(std::env::args());

    for filename in &filenames[1..] {
        match reader(&Path::new(filename)).and_then(|mut reader| {
            let mut buffer = Vec::new();
            reader.read_to_end(&mut buffer).map(|_| buffer)
        }).map_err(|e| format!("{}", e)).and_then(|buffer| {
            match bf_parse_file(&buffer[..]) {
                IResult::Done(_, o) => Ok(o),
                IResult::Error(e) => Err(format!("Parsing error: {:?}", e)),
                IResult::Incomplete(m) => Err(format!("Incomplete file: {:?}", m)),
            }
        }) {
            Ok(ops) => {
                let mut opstream = OpStream { ops: ops };
                opstream.optimize();
                State::new().run(opstream.get());
            }
            Err(e) => {
                writeln!(&mut io::stderr(), "Error while processing {}: {}", filename, e).unwrap();
            }
        };
    }
}

named!(bf_parse_file<&[u8], Vec<Op> >, chain!(ops: bf_parse ~ eof, || ops));
named!(bf_parse<&[u8], Vec<Op> >,
    many0!(
        chain!(
            opt!(is_not!("+-<>.,[]")) ~
            op: alt!(
                chain!(tag!("+"), || Add(0x01)) |
                chain!(tag!("-"), || Add(0xff)) |
                chain!(tag!(">"), || Mov(1)) |
                chain!(tag!("<"), || Mov(-1)) |
                chain!(tag!("."), || Out) |
                chain!(tag!(","), || In) |
                chain!(subops: delimited!(tag!("["), bf_parse, tag!("]")), || Loop(OpStream { ops: subops }))
            ) ~
            opt!(is_not!("+-<>.,[]")), || op)
        )
    );

fn reader(path: &Path) -> Result<io::BufReader<fs::File>, io::Error> {
    fs::File::open(path).map(|f| io::BufReader::new(f))
}

#[cfg(test)]
mod tests {
    use nom::IResult::Done;
    use super::{bf_parse_file, State, OpStream};
    use super::Op::*;

    #[test]
    fn test_state_index() {
        let mut state = State { index: 0, memory: vec![23, 0, 0, 0, 0, 42] };
        assert_eq!(23, state[0]);
        state.index = 5;
        assert_eq!(42, state[0]);
    }

    #[test]
    fn test_state_index_mut() {
        let mut state = State::new();
        state[0] = 23;
        assert_eq!(23, state.memory[state.index]);
        state.index = 5;
        state[0] = 42;
        assert_eq!(42, state.memory[state.index]);
    }

    #[test]
    fn test_state_step_add() {
        let mut state = State::new();
        state.step(&Add(23));
        assert_eq!(23, state[0]);
        state.step(&Add(42));
        assert_eq!(65, state[0]);
        state.step(&Add(190));
        assert_eq!(255, state[0]);
    }

    #[test]
    fn test_state_step_mov() {
        let mut state = State::new();
        state.step(&Mov(1));
        assert_eq!(1, state.index);
        state.step(&Mov(42));
        assert_eq!(43, state.index);
        state.step(&Mov(-1));
        assert_eq!(42, state.index);
    }

    #[test]
    fn test_state_step_loop() {
        let mut state = State::new();
        state[0] = 23;
        state.step(&Loop(OpStream { ops: vec![Add(1)] }));
        assert_eq!(0, state[0]);
    }

    #[test]
    fn test_state_step_transfer() {
        let mut state = State::new();
        state[0] = 15;
        state[1] = 7;
        state.step(&Transfer(5, vec![(1, 2)]));
        assert_eq!(0, state[0]);
        assert_eq!(1, state[1]);
    }

    #[test]
    fn test_opstream_optimize() {
        let mut opstream = OpStream { ops: vec![
            Mov(1),
            Mov(1),
            Add(0x01),
            Add(0x0ff),
            Add(0x0ff),
            Mov(1),
            Mov(-1),
            Loop(OpStream { ops: vec![
                Mov(2),
                Mov(3)
            ] })
        ] };
        opstream.optimize();

        assert_eq!(opstream, OpStream { ops: vec![Mov(2), Add(0xff), Loop(OpStream { ops: vec![Mov(5)] } )] });
    }

    #[test]
    fn test_opstream_optimize_transfer() {
        let mut opstream = OpStream { ops: vec![
            Loop(OpStream { ops: vec![
                Add(0x01),
                Mov(3),
                Add(0xff),
                Mov(-3)
            ] })
        ] };
        opstream.optimize();

        assert_eq!(opstream, OpStream { ops: vec![Transfer(1, vec![(3, 255)])] } );
    }

    #[test]
    fn test_parse() {
        let input = b"+-[+.,]+";
        assert_eq!(
            bf_parse_file(&input[..]),
            Done(&b""[..],
                vec![Add(0x01), Add(0xff), Loop(
                    OpStream { ops: vec![Add(1), Out, In] }
                ), Add(0x01)]
            )
        );
    }
}
<|endoftext|>


<commit_before>extern crate cargo;
extern crate tabwriter;

use cargo::core::Package;
use cargo::core::Workspace;
use cargo::ops;
use cargo::util::Config;

use std::collections::BTreeSet;
use std::fmt;
use std::io;
use std::io::prelude::*;
use std::path;

#[derive(Debug)]
enum Licenses<'a> {
    Licenses(BTreeSet<&'a str>),
    File(String),
    Missing,
}

impl<'a> fmt::Display for Licenses<'a> {
    fn fmt(self: &Self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
        match *self {
            Licenses::File(_) => write!(f, "Specified in license file")?,
            Licenses::Missing => write!(f, "Missing")?,
            Licenses::Licenses(ref lic_names) => {
                let lics: Vec<String> = lic_names.iter().map(|s| String::from(*s)).collect();
                write!(f, "{}", lics.join(", "))?
            }
        }
        Ok(())
    }
}

fn main() {
    let config = Config::default().expect("cargo config");
    let manifest = config.cwd().join("Cargo.toml");
    let ws = Workspace::new(&manifest, &config).expect("cargo workspace");
    let members: Vec<&Package> = ws.members().collect();
    let (package_ids, resolve) = ops::resolve_ws(&ws).expect("resolve workspace");

    let mut packages = Vec::new();
    for package_id in resolve.iter() {
        let package = package_ids.get(package_id).expect("get package ids");
        if members.contains(&package) {
            // Skip listing our own packages in our workspace
            continue;
        }
        let name = package.name().to_owned();
        let version = format!("{}", package.version());
        let licenses = format!("{}", package_licenses(package));
        let license_files = package_license_files(package);
        packages.push((name, version, licenses, license_files));
    }

    packages.sort();

    let stdout = io::stdout();
    let mut out = stdout.lock();

    {
        let mut tw = tabwriter::TabWriter::new(&mut out);
        writeln!(tw, "Name\t| Version\t| Licenses").expect("write");
        for (name, version, licenses, _) in packages.clone() {
            writeln!(tw, "{}\t| {}\t| {}", &name, &version, &licenses).expect("write");
        }
        tw.flush().expect("tw.flush"); // TabWriter flush() makes the actual write to stdout.
    }

    println!();

    for (name, version, _, license_files) in packages {
        if license_files.is_empty() {
            continue;
        }

        println!("-----BEGIN {} {} LICENSES-----", name, version);

        let mut buf = Vec::new();
        for file in license_files {
            let mut fs = std::fs::File::open(file).expect("File::open");
            fs.read_to_end(&mut buf).expect("read_to_end");
            out.write_all(&buf).expect("write_all");
            buf.clear();
        }

        println!("-----END {} {} LICENSES-----", name, version);
        println!();
    }
}

fn package_licenses(package: &Package) -> Licenses {
    let metadata = package.manifest().metadata();

    if let Some(ref license_str) = metadata.license {
        let mut licenses: BTreeSet<&str> = license_str
            .split('/')
            .map(|s| s.trim())
            .collect();
        return Licenses::Licenses(licenses);
    }

    if let Some(ref license_file) = metadata.license_file {
        return Licenses::File(license_file.to_owned());
    }

    Licenses::Missing
}

fn package_license_files(package: &Package) -> Vec<path::PathBuf> {
    let mut result = Vec::new();

    if let Some(path) = package.manifest_path().parent() {
        for entry in path.read_dir().expect("read_dir call failed") {
            if let Ok(entry) = entry {
                if let Ok(name) = entry.file_name().into_string() {
                    if name.starts_with("LICENSE") {
                        result.push(entry.path())
                    }
                }
            }
        }
    }

    result
}
<commit_msg>Add lifetime parameter<commit_after>extern crate cargo;
extern crate tabwriter;

use cargo::core::Package;
use cargo::core::Workspace;
use cargo::ops;
use cargo::util::Config;

use std::collections::BTreeSet;
use std::fmt;
use std::io;
use std::io::prelude::*;
use std::path;

#[derive(Debug)]
enum Licenses<'a> {
    Licenses(BTreeSet<&'a str>),
    File(String),
    Missing,
}

impl<'a> fmt::Display for Licenses<'a> {
    fn fmt(self: &Self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
        match *self {
            Licenses::File(_) => write!(f, "Specified in license file")?,
            Licenses::Missing => write!(f, "Missing")?,
            Licenses::Licenses(ref lic_names) => {
                let lics: Vec<String> = lic_names.iter().map(|s| String::from(*s)).collect();
                write!(f, "{}", lics.join(", "))?
            }
        }
        Ok(())
    }
}

fn main() {
    let config = Config::default().expect("cargo config");
    let manifest = config.cwd().join("Cargo.toml");
    let ws = Workspace::new(&manifest, &config).expect("cargo workspace");
    let members: Vec<&Package> = ws.members().collect();
    let (package_ids, resolve) = ops::resolve_ws(&ws).expect("resolve workspace");

    let mut packages = Vec::new();
    for package_id in resolve.iter() {
        let package = package_ids.get(package_id).expect("get package ids");
        if members.contains(&package) {
            // Skip listing our own packages in our workspace
            continue;
        }
        let name = package.name().to_owned();
        let version = format!("{}", package.version());
        let licenses = format!("{}", package_licenses(package));
        let license_files = package_license_files(package);
        packages.push((name, version, licenses, license_files));
    }

    packages.sort();

    let stdout = io::stdout();
    let mut out = stdout.lock();

    {
        let mut tw = tabwriter::TabWriter::new(&mut out);
        writeln!(tw, "Name\t| Version\t| Licenses").expect("write");
        for (name, version, licenses, _) in packages.clone() {
            writeln!(tw, "{}\t| {}\t| {}", &name, &version, &licenses).expect("write");
        }
        tw.flush().expect("tw.flush"); // TabWriter flush() makes the actual write to stdout.
    }

    println!();

    for (name, version, _, license_files) in packages {
        if license_files.is_empty() {
            continue;
        }

        println!("-----BEGIN {} {} LICENSES-----", name, version);

        let mut buf = Vec::new();
        for file in license_files {
            let mut fs = std::fs::File::open(file).expect("File::open");
            fs.read_to_end(&mut buf).expect("read_to_end");
            out.write_all(&buf).expect("write_all");
            buf.clear();
        }

        println!("-----END {} {} LICENSES-----", name, version);
        println!();
    }
}

fn package_licenses(package: &Package) -> Licenses<'_> {
    let metadata = package.manifest().metadata();

    if let Some(ref license_str) = metadata.license {
        let mut licenses: BTreeSet<&str> = license_str
            .split('/')
            .map(|s| s.trim())
            .collect();
        return Licenses::Licenses(licenses);
    }

    if let Some(ref license_file) = metadata.license_file {
        return Licenses::File(license_file.to_owned());
    }

    Licenses::Missing
}

fn package_license_files(package: &Package) -> Vec<path::PathBuf> {
    let mut result = Vec::new();

    if let Some(path) = package.manifest_path().parent() {
        for entry in path.read_dir().expect("read_dir call failed") {
            if let Ok(entry) = entry {
                if let Ok(name) = entry.file_name().into_string() {
                    if name.starts_with("LICENSE") {
                        result.push(entry.path())
                    }
                }
            }
        }
    }

    result
}
<|endoftext|>


<commit_before>extern crate chattium_oxide_client;
extern crate chattium_oxide_lib;
extern crate hyper;

use hyper::client::Client;
use chattium_oxide_lib::{ChatMessage, ChatUser};
use chattium_oxide_lib::json::ToJsonnable;
use chattium_oxide_client::Options;

fn main() {
	let client = Client::new();
	let options = Options::parse();

	match ChatMessage::new(ChatUser::me(options.name), "Noobel sucks".to_string()).to_json_string() {
		Ok(json) =>
			match client.post(options.server).body(&*&json).send() {
				Ok(response) => println!("Server responded with status {}", response.status),
				Err(error) => println!("POSTing the message failed: {}", error),
			},
		Err(error) => println!("Couldn't serialize message: {}", error),
	};
}
<commit_msg>Types! Types!<commit_after>extern crate chattium_oxide_client;
extern crate chattium_oxide_lib;
extern crate hyper;

use hyper::client::Client;
use chattium_oxide_lib::{ChatMessage, ChatUser};
use chattium_oxide_lib::json::ToJsonnable;
use chattium_oxide_client::Options;

fn main() {
	let client = Client::new();
	let options = Options::parse();

	match ChatMessage::new(ChatUser::me(options.name.clone()), "Noobel sucks".to_string()).to_json_string() {
		Ok(json) =>
			match client.post(&*&options.server).body(&*&json).send() {
				Ok(response) => println!("Server responded with status {}", response.status),
				Err(error) => println!("POSTing the message failed: {}", error),
			},
		Err(error) => println!("Couldn't serialize message: {}", error),
	};
}
<|endoftext|>


<commit_before>#![feature(collections)]
#![feature(cstr_to_str)]
#![feature(result_expect)]
#![feature(convert)]
#![feature(iter_arith)]
#![feature(io)]
extern crate unicode_width;
extern crate term;
extern crate libc;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::io::prelude::*;

use std::io::BufReader;
use std::sync::Arc;
use std::sync::mpsc::Sender;
use std::sync::atomic::{AtomicBool, Ordering};
use std::fs::File;
use std::iter::FromIterator;
use std::thread::JoinHandle;
use std::ops::Deref;

use std::sync::mpsc;
use std::thread;
use std::mem;
use std::env;
use std::io;

use ui::UI;
use terminal::Terminal;
use search::{SearchBase, LineInfo};

use types::*;

mod constants;
#[macro_use]
mod error;
mod search;
mod types;
mod bis_c;
mod terminal;
mod ui;

fn read_history(emit: Sender<Event>) {
    thread::spawn(move || {
        let history_path = env::var("HISTFILE").expect("Failed to get bash history file");
        let input_file = BufReader::new(File::open(history_path).expect("Cauld not open history file"));
        let mut count = -1;
        let base = SearchBase::from_iter(input_file.lines().map(|maybe| {
            count += 1;
            trace!("New line with count {}", count);
            LineInfo::new(maybe.expect("Failed to read line from file"), count)
        }));
        // if this fails, we can't search anything
        emit.send(Event::SearchReady(base)).expect("Failed to emit search ready signal");
    });
}

fn read_input(emit: Sender<Event>, stop: Arc<AtomicBool>) -> JoinHandle<()> {
    thread::spawn(move || {
        // this thread is joined on quit, so none of its sends should fail
        for maybe_chr in io::stdin().chars() {
            match maybe_chr {
                Err(_) => {
                    error!("Failed to read input, quitting");
                    emit.send(Event::Quit(false)).expect("Failed to emit quit signal");
                    break;
                },
                Ok(chr) => {
                    emit.send(Event::Input(chr)).expect("Failed to send character");
                    if stop.load(Ordering::Relaxed) {
                        debug!("Input thread exiting");
                        break;
                    }
                }
            }
        }
    })
}

fn read_signals(emit: Sender<Event>) {
    thread::spawn(move || {
        // wait for a sigint
        bis_c::wait_sigint().expect("Failed to wait for sigint");

        debug!("Caught sigint");

        // send a quit signal
        emit.send(Event::Quit(false)).is_ok();
        // might happen after events is closed, so don't fail
    });
}

fn main() {
    // init logging
    env_logger::init().expect("Failed to initialize logging");

    debug!("Getting terminal instance");

    let mut terminal = Terminal::create().expect("Failed to create terminal instance");

    debug!("Creating UI instance");

    let ui = UI::create().expect("Failed to create UI instance");

    let (emit, events) = mpsc::channel();
    let mut query = String::default();
    let mut search = None;
    let mut success = false;
    let mut best_match = None;
    let input_stop = Arc::new(AtomicBool::new(false));

    // mask sigint
    bis_c::mask_sigint().expect("Failed to mask sigint");

    // wait for a sigint
    read_signals(emit.clone());

    // start reading history
    read_history(emit.clone());

    // start the input thread
    let input_thread = read_input(emit.clone(), input_stop.clone());

    // draw the prompt
    terminal.output_str(ui.render_prompt()).expect("Failed to render prompt");

    loop {
        match events.recv() {
            Err(_) => break,
            Ok(event) => {
                match event {
                    Event::SearchReady(base) => {
                        search = Some(Arc::new(base));
                    },
                    Event::Input(chr) => {
                        debug!("Got input event: {:?}", chr);
                        query = match ui.input_char(query, chr) {
                            Err(s) => {
                                success = s;
                                // quit out of the event loop
                                break;
                            },
                            Ok((q, out)) => {
                                terminal.output_str(out).expect("Failed to write to output");
                                q
                            }
                        };

                        // don't search until we have a search base
                        search.clone().map(|base| {
                            let query = query.clone();
                            let emit = emit.clone();

                            thread::spawn(move || {
                                let result = base.query(&query);
                                emit.send(Event::Match(result, query)).and_then(|_| {
                                    trace!("Finished query");
                                    Ok(())
                                }).is_ok();
                                // don't panic on fail send, events might be already closed
                            });
                        });
                    },
                    Event::Match(matches, q) => {
                        debug!("Got match event: {:?}, {:?}", matches, q);
                        if q == query {
                            best_match = matches.first().cloned();
                            // only draw matches for the current query
                            terminal.output_str(ui.render_matches(matches)).expect("Failed to draw matches");
                        }
                    },
                    Event::Quit(s) => {
                        debug!("Got quit event: {:?}", s);
                        success = s;
                        break;
                    }
                }

                debug!("Flushing output");
                terminal.flush().expect("Failed to flush terminal");
            }
        }
    }

    // prompt the input thread to stop
    input_stop.store(true, Ordering::Relaxed);

    // insert a bogus byte to wake it up
    terminal.insert_input(" ").expect("Failed to insert bogus byte");

    // join the thread
    input_thread.join().expect("Failed to wait for input thread");

    // draw the best match if it exists
    match best_match {
        Some(ref m) => {
            terminal.output_str(ui.render_best_match(Deref::deref(m)))
                .expect("Failed to draw best match");
        },
        None => {
            terminal.output_str("\n").expect("Failed to draw newline");
        }
    }

    debug!("Flushing output");
    terminal.flush().expect("Failed to flush terminal");

    if success {
        match best_match {
            Some(ref m) => {
                terminal.insert_input(Deref::deref(m))
                    .expect("Failed to insert input");
            },
            None => {}
        }
    }

    // restore the terminal
    mem::drop(terminal);
}
<commit_msg>Flush the terminal after drawing prompt<commit_after>#![feature(collections)]
#![feature(cstr_to_str)]
#![feature(result_expect)]
#![feature(convert)]
#![feature(iter_arith)]
#![feature(io)]
extern crate unicode_width;
extern crate term;
extern crate libc;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::io::prelude::*;

use std::io::BufReader;
use std::sync::Arc;
use std::sync::mpsc::Sender;
use std::sync::atomic::{AtomicBool, Ordering};
use std::fs::File;
use std::iter::FromIterator;
use std::thread::JoinHandle;
use std::ops::Deref;

use std::sync::mpsc;
use std::thread;
use std::mem;
use std::env;
use std::io;

use ui::UI;
use terminal::Terminal;
use search::{SearchBase, LineInfo};

use types::*;

mod constants;
#[macro_use]
mod error;
mod search;
mod types;
mod bis_c;
mod terminal;
mod ui;

fn read_history(emit: Sender<Event>) {
    thread::spawn(move || {
        let history_path = env::var("HISTFILE").expect("Failed to get bash history file");
        let input_file = BufReader::new(File::open(history_path).expect("Cauld not open history file"));
        let mut count = -1;
        let base = SearchBase::from_iter(input_file.lines().map(|maybe| {
            count += 1;
            trace!("New line with count {}", count);
            LineInfo::new(maybe.expect("Failed to read line from file"), count)
        }));
        // if this fails, we can't search anything
        emit.send(Event::SearchReady(base)).expect("Failed to emit search ready signal");
    });
}

fn read_input(emit: Sender<Event>, stop: Arc<AtomicBool>) -> JoinHandle<()> {
    thread::spawn(move || {
        // this thread is joined on quit, so none of its sends should fail
        for maybe_chr in io::stdin().chars() {
            match maybe_chr {
                Err(_) => {
                    error!("Failed to read input, quitting");
                    emit.send(Event::Quit(false)).expect("Failed to emit quit signal");
                    break;
                },
                Ok(chr) => {
                    emit.send(Event::Input(chr)).expect("Failed to send character");
                    if stop.load(Ordering::Relaxed) {
                        debug!("Input thread exiting");
                        break;
                    }
                }
            }
        }
    })
}

fn read_signals(emit: Sender<Event>) {
    thread::spawn(move || {
        // wait for a sigint
        bis_c::wait_sigint().expect("Failed to wait for sigint");

        debug!("Caught sigint");

        // send a quit signal
        emit.send(Event::Quit(false)).is_ok();
        // might happen after events is closed, so don't fail
    });
}

fn main() {
    // init logging
    env_logger::init().expect("Failed to initialize logging");

    debug!("Getting terminal instance");

    let mut terminal = Terminal::create().expect("Failed to create terminal instance");

    debug!("Creating UI instance");

    let ui = UI::create().expect("Failed to create UI instance");

    let (emit, events) = mpsc::channel();
    let mut query = String::default();
    let mut search = None;
    let mut success = false;
    let mut best_match = None;
    let input_stop = Arc::new(AtomicBool::new(false));

    // mask sigint
    bis_c::mask_sigint().expect("Failed to mask sigint");

    // wait for a sigint
    read_signals(emit.clone());

    // start reading history
    read_history(emit.clone());

    // start the input thread
    let input_thread = read_input(emit.clone(), input_stop.clone());

    // draw the prompt
    terminal.output_str(ui.render_prompt()).expect("Failed to render prompt");

    // flush the terminal
    terminal.flush().expect("Failed to flush terminal");

    loop {
        match events.recv() {
            Err(_) => break,
            Ok(event) => {
                match event {
                    Event::SearchReady(base) => {
                        search = Some(Arc::new(base));
                    },
                    Event::Input(chr) => {
                        debug!("Got input event: {:?}", chr);
                        query = match ui.input_char(query, chr) {
                            Err(s) => {
                                success = s;
                                // quit out of the event loop
                                break;
                            },
                            Ok((q, out)) => {
                                terminal.output_str(out).expect("Failed to write to output");
                                q
                            }
                        };

                        // don't search until we have a search base
                        search.clone().map(|base| {
                            let query = query.clone();
                            let emit = emit.clone();

                            thread::spawn(move || {
                                let result = base.query(&query);
                                emit.send(Event::Match(result, query)).and_then(|_| {
                                    trace!("Finished query");
                                    Ok(())
                                }).is_ok();
                                // don't panic on fail send, events might be already closed
                            });
                        });
                    },
                    Event::Match(matches, q) => {
                        debug!("Got match event: {:?}, {:?}", matches, q);
                        if q == query {
                            best_match = matches.first().cloned();
                            // only draw matches for the current query
                            terminal.output_str(ui.render_matches(matches)).expect("Failed to draw matches");
                        }
                    },
                    Event::Quit(s) => {
                        debug!("Got quit event: {:?}", s);
                        success = s;
                        break;
                    }
                }

                debug!("Flushing output");
                terminal.flush().expect("Failed to flush terminal");
            }
        }
    }

    // prompt the input thread to stop
    input_stop.store(true, Ordering::Relaxed);

    // insert a bogus byte to wake it up
    terminal.insert_input(" ").expect("Failed to insert bogus byte");

    // join the thread
    input_thread.join().expect("Failed to wait for input thread");

    // draw the best match if it exists
    match best_match {
        Some(ref m) => {
            terminal.output_str(ui.render_best_match(Deref::deref(m)))
                .expect("Failed to draw best match");
        },
        None => {
            terminal.output_str("\n").expect("Failed to draw newline");
        }
    }

    debug!("Flushing output");
    terminal.flush().expect("Failed to flush terminal");

    if success {
        match best_match {
            Some(ref m) => {
                terminal.insert_input(Deref::deref(m))
                    .expect("Failed to insert input");
            },
            None => {}
        }
    }

    // restore the terminal
    mem::drop(terminal);
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015-2016 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! # SOS kernel
//! This crate contains the kernel for SOS, the Stupid Operating System.
//!
//! # SOS: the Stupid Operating System
//! SOS is a simple, tiny toy OS implemented in Rust. It targets the x86,
//! x86_64, and ARM v7 CPU architectures.
//!
//! I'm writing this mostly for fun, to learn more about OS design and kernel
//! hacking, so don't expect anything new or exciting out of this project.
//!
//! SOS is copyright 2015-2016 Hawk Weisman, and is released under the terms
//! of the MIT license.

// #![crate_name = "sos_kernel"]
// #![crate_type = "staticlib"]

#![doc(html_root_url = "https://hawkw.github.io/sos-kernel/")]

#![feature(core_intrinsics)]
#![feature( lang_items, asm, naked_functions )]
#![feature( linkage )]
#![feature( const_fn
          , slice_patterns
          , associated_consts
          , unique
          , type_ascription
          , custom_derive )]
#![feature(collections)]
#![feature(question_mark)]

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

#![no_std]
#![cfg_attr(not(test), no_main)]

// -- non-SOS dependencies --------------------------------------------------
extern crate collections;
extern crate rlibc;
extern crate spin;

#[macro_use] extern crate lazy_static;
#[macro_use] extern crate bitflags;
#[macro_use] extern crate custom_derive;

// -- SOS dependencies ------------------------------------------------------
extern crate sos_alloc as alloc;

#[macro_use] extern crate sos_vga as vga;

#[macro_use] pub mod macros;
#[macro_use] pub mod memory;
#[macro_use] pub mod io;

pub mod util;
// pub mod multiboot2;
pub mod elf;
pub mod arch;

/// SOS version number
pub const VERSION_STRING: &'static str
    = concat!("Stupid Operating System v", env!("CARGO_PKG_VERSION"));

// pub const BUILD_STRING: &'static str
//     = concat!("Built with ", env!("RUST_VERSION"));
//
// Since the test module contains lang items, it can't be compiled when
// running tests.
#[cfg(not(test))] pub mod panic;

use arch::cpu;
use memory::PAddr;

#[macro_use]
macro_rules! init_log {
    (f$dots:expr, $task:expr, $msg:expr) => (
        println!( "{task:<40}{res:>38}\n{msg:>.width$}"
                , task = format!("{:>.width$}", $task, width = $dots)
                , res = "[ FAIL ]"
                , msg = $msg
                , width = $dots + 1
                )
    );
    (fail: $dots:expr, $task:expr) => (
            println!( "{task:<40}{res:>38}"
                    , task = format!("{:>.width$}", $task, width = $dots)
                    , res = "[ FAIL ]"
                    )
    );
    (okay: $dots:expr, $task:expr, $msg:expr) => (
        println!( "{task:<40}{res:>38}\n{msg:>.width$}"
                , task = format!("{:>.width$}", $task, width = $dots)
                , res = "[ OKAY ]"
                , msg = $msg
                , width = $dots + 1
                )
    );
    (okay: $dots:expr, $task:expr) => (
            println!( "{task:<40}{res:>38}"
                    , task = format!("{:>.width$}", $task, width = $dots)
                    , res = "[ OKAY ]"
                    )
    );
}

macro_rules! init_try {
    ($dots:expr, $task:expr, $result:expr) => (
        match $result {
            Ok(value) => {
                println!( "{task:<40}{res:>38}"
                        , task = format!("{:>.width$}", $task, width = $dots)
                        , res = "[ OKAY ]"
                        );
                value
            }
          , Err(why) => {
                println!( "{task:<40}{res:>38}\n\n{msg:>.width$}"
                        , task = format!("{:>.width$}", $task, width = $dots)
                        , res = "[ FAIL ]"
                        , msg = why
                        , width = $dots + 1
                        );
                return $expr
            }
        }
    )
}

/// Kernel main loop
pub fn kernel_main() {
    let mut a_vec = collections::vec::Vec::<usize>::new();
    println!( "TEST: Created a vector in kernel space! {:?}", a_vec);
    a_vec.push(1);
    println!( "TEST: pushed to vec: {:?}", a_vec);
    a_vec.push(2);
    println!( "TEST: pushed to vec: {:?}", a_vec);
    // loop {
    //     unsafe { asm!("int $0" :: "N" (0x80)) };
    //     println!("Test interrupt okay");
    // }
    loop { }
}

/// Kernel initialization function called from ASM
///
/// The kernel main loop expects to be passed the address of a valid
/// Multiboot 2 info struct. It's the bootloader's responsibility to ensure
/// that this is passed in the correct register as expected by the calling
/// convention (`edi` on x86). If this isn't there, you can expect to have a
/// bad problem and not go to space today.
//  TODO: since multiboot2 is x86-specific, this needs to move to `arch`.
//  we then want the kernel entry point to be `arch_init`. we can then
//  call into `kernel_init`.
#[no_mangle]
pub extern "C" fn kernel_start(multiboot_addr: PAddr) {
    io::term::CONSOLE.lock().clear();

    println!("Hello from the kernel!");

    // -- jump to architecture-specific init ---------------------------------
    arch::arch_init(multiboot_addr);

    // -- initialize interrupts ----------------------------------------------
    unsafe {
        println!(" . Enabling interrupts:");
        cpu::interrupts::initialize();
        println!("{:<38}{:>40}", " . Enabling interrupts", "[ OKAY ]");
    };

    // -- initialize the heap ------------------------------------------------
    unsafe {
        println!( "{:<38}{:>40}\n \
                    . . Heap begins at {:#x} and ends at {:#x}"
                , " . Intializing heap"
                , memory::init_heap().unwrap_or("[ FAIL ]")
                , memory::HEAP_BASE
                , memory::HEAP_TOP);
    };

    println!("\n{} {}-bit\n", VERSION_STRING, arch::ARCH_BITS);
    // -- call into kernel main loop ------------------------------------------
    // (currently, this does nothing)
    kernel_main()

}

/// This fake `main` function exists only to placate `cargo test`.
#[cfg(test)]
fn main() {

}
<commit_msg>[kernel] add missing_docs warnings<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015-2016 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! # SOS kernel
//! This crate contains the kernel for SOS, the Stupid Operating System.
//!
//! # SOS: the Stupid Operating System
//! SOS is a simple, tiny toy OS implemented in Rust. It targets the x86,
//! x86_64, and ARM v7 CPU architectures.
//!
//! I'm writing this mostly for fun, to learn more about OS design and kernel
//! hacking, so don't expect anything new or exciting out of this project.
//!
//! SOS is copyright 2015-2016 Hawk Weisman, and is released under the terms
//! of the MIT license.

// #![crate_name = "sos_kernel"]
// #![crate_type = "staticlib"]

#![doc(html_root_url = "https://hawkw.github.io/sos-kernel/")]

#![feature( core_intrinsics )]
#![feature( lang_items, asm, naked_functions )]
#![feature( linkage )]
#![feature( const_fn
          , slice_patterns
          , associated_consts
          , unique
          , type_ascription
          , custom_derive )]
#![feature( collections )]
#![feature( question_mark )]
#![warn( missing_docs )]

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

#![no_std]
#![cfg_attr(not(test), no_main)]

// -- non-SOS dependencies --------------------------------------------------
extern crate collections;
extern crate rlibc;
extern crate spin;

#[macro_use] extern crate lazy_static;
#[macro_use] extern crate bitflags;
#[macro_use] extern crate custom_derive;

// -- SOS dependencies ------------------------------------------------------
extern crate sos_alloc as alloc;

#[macro_use] extern crate sos_vga as vga;

#[macro_use] pub mod macros;
#[macro_use] pub mod memory;
#[macro_use] pub mod io;

pub mod util;
// pub mod multiboot2;
pub mod elf;
pub mod arch;

/// SOS version number
pub const VERSION_STRING: &'static str
    = concat!("Stupid Operating System v", env!("CARGO_PKG_VERSION"));

// pub const BUILD_STRING: &'static str
//     = concat!("Built with ", env!("RUST_VERSION"));
//
// Since the test module contains lang items, it can't be compiled when
// running tests.
#[cfg(not(test))] pub mod panic;

use arch::cpu;
use memory::PAddr;

#[macro_use]
macro_rules! init_log {
    (f$dots:expr, $task:expr, $msg:expr) => (
        println!( "{task:<40}{res:>38}\n{msg:>.width$}"
                , task = format!("{:>.width$}", $task, width = $dots)
                , res = "[ FAIL ]"
                , msg = $msg
                , width = $dots + 1
                )
    );
    (fail: $dots:expr, $task:expr) => (
            println!( "{task:<40}{res:>38}"
                    , task = format!("{:>.width$}", $task, width = $dots)
                    , res = "[ FAIL ]"
                    )
    );
    (okay: $dots:expr, $task:expr, $msg:expr) => (
        println!( "{task:<40}{res:>38}\n{msg:>.width$}"
                , task = format!("{:>.width$}", $task, width = $dots)
                , res = "[ OKAY ]"
                , msg = $msg
                , width = $dots + 1
                )
    );
    (okay: $dots:expr, $task:expr) => (
            println!( "{task:<40}{res:>38}"
                    , task = format!("{:>.width$}", $task, width = $dots)
                    , res = "[ OKAY ]"
                    )
    );
}

macro_rules! init_try {
    ($dots:expr, $task:expr, $result:expr) => (
        match $result {
            Ok(value) => {
                println!( "{task:<40}{res:>38}"
                        , task = format!("{:>.width$}", $task, width = $dots)
                        , res = "[ OKAY ]"
                        );
                value
            }
          , Err(why) => {
                println!( "{task:<40}{res:>38}\n\n{msg:>.width$}"
                        , task = format!("{:>.width$}", $task, width = $dots)
                        , res = "[ FAIL ]"
                        , msg = why
                        , width = $dots + 1
                        );
                return $expr
            }
        }
    )
}

/// Kernel main loop
pub fn kernel_main() {
    let mut a_vec = collections::vec::Vec::<usize>::new();
    println!( "TEST: Created a vector in kernel space! {:?}", a_vec);
    a_vec.push(1);
    println!( "TEST: pushed to vec: {:?}", a_vec);
    a_vec.push(2);
    println!( "TEST: pushed to vec: {:?}", a_vec);
    // loop {
    //     unsafe { asm!("int $0" :: "N" (0x80)) };
    //     println!("Test interrupt okay");
    // }
    loop { }
}

/// Kernel initialization function called from ASM
///
/// The kernel main loop expects to be passed the address of a valid
/// Multiboot 2 info struct. It's the bootloader's responsibility to ensure
/// that this is passed in the correct register as expected by the calling
/// convention (`edi` on x86). If this isn't there, you can expect to have a
/// bad problem and not go to space today.
//  TODO: since multiboot2 is x86-specific, this needs to move to `arch`.
//  we then want the kernel entry point to be `arch_init`. we can then
//  call into `kernel_init`.
#[no_mangle]
pub extern "C" fn kernel_start(multiboot_addr: PAddr) {
    io::term::CONSOLE.lock().clear();

    println!("Hello from the kernel!");

    // -- jump to architecture-specific init ---------------------------------
    arch::arch_init(multiboot_addr);

    // -- initialize interrupts ----------------------------------------------
    unsafe {
        println!(" . Enabling interrupts:");
        cpu::interrupts::initialize();
        println!("{:<38}{:>40}", " . Enabling interrupts", "[ OKAY ]");
    };

    // -- initialize the heap ------------------------------------------------
    unsafe {
        println!( "{:<38}{:>40}\n \
                    . . Heap begins at {:#x} and ends at {:#x}"
                , " . Intializing heap"
                , memory::init_heap().unwrap_or("[ FAIL ]")
                , memory::HEAP_BASE
                , memory::HEAP_TOP);
    };

    println!("\n{} {}-bit\n", VERSION_STRING, arch::ARCH_BITS);
    // -- call into kernel main loop ------------------------------------------
    // (currently, this does nothing)
    kernel_main()

}

/// This fake `main` function exists only to placate `cargo test`.
#[cfg(test)]
fn main() {

}
<|endoftext|>