<commit_before>#![feature(globs)]

extern crate piston;
extern crate rand;
extern crate native;
extern crate sdl2_game_window;
extern crate opengl_graphics;
extern crate gfx_graphics;
extern crate gfx;
extern crate sdl2;

use opengl_graphics::Gl;
use gfx_graphics::{
    G2D,
};
use piston::graphics::{
    AddColor,
    Context,
    Draw,
};
use gfx::{Device, DeviceHelper};
use sdl2_game_window::WindowSDL2;
use piston::{
    EventIterator,
    EventSettings,
    WindowSettings,
    Render,
    Update,
    Input,
};
use piston::input;
use piston::{Window};

mod snakeapp;
mod object;
mod settings;
mod text;
mod bar;
mod player;
mod snake;
mod action;
mod game_state;
mod character;
mod air_bottle;

#[deriving(Show)]
pub enum GraphicsBackEnd {
    Gfx,
    OpenGL,
}

fn main() {
    use snakeapp::SnakeApp;

    let mut backend = Gfx;
    println!("Running with graphics backend {}", backend);
    println!("Use 'S' to swap back-end");

    let opengl = piston::shader_version::opengl::OpenGL_3_2;
    let mut window = WindowSDL2::new(
        opengl,
        WindowSettings {
            title: "Sea Snake Escape".to_string(),
            size: [512, 512],
            fullscreen: false,
            exit_on_esc: true,
            samples: 4,
        }
    );

    let mut device = gfx::GlDevice::new(|s| unsafe {
        std::mem::transmute(sdl2::video::gl_get_proc_address(s))
    });
    let (w, h) = window.get_size();
    let frame = gfx::Frame::new(w as u16, h as u16);

    let mut renderer = device.create_renderer();

    let mut app = SnakeApp::new();
    app.load();

    let mut event_iterator = EventIterator::new(&mut window,
        &EventSettings {
            updates_per_second: 120,
            max_frames_per_second: 60
        });
    let ref mut gl = Gl::new(opengl);
    let mut g2d = G2D::new(&mut device);
    let mut fps_counter = piston::FPSCounter::new();
    loop {
        let e = match event_iterator.next() {
                None => { break; }
                Some(e) => e
            };

        match e {
            Render(args) => {
                match backend {
                    Gfx => {
                        g2d.render(&mut renderer, &frame, |c, g| {
                            c.color(settings::WATER_COLOR).draw(g);
                            app.render(&c, g);
                        });
                        device.submit(renderer.as_buffer());
                        renderer.reset();
                    }
                    OpenGL => {
                        gl.viewport(0, 0, args.width as i32, args.height as i32);
                        gl.clear_program();
                        let c = Context::abs(
                            args.width as f64,
                            args.height as f64
                        );
                        c.color(settings::WATER_COLOR).draw(gl);
                        app.render(&c, gl);
                    }
                };

                event_iterator.window.window.set_title(fps_counter.tick().to_string().as_slice());
            },
            Update(args) => {
                app.update(args.dt);
            },
            Input(input::Press(input::Keyboard(input::keyboard::S))) => {
                backend = match backend {
                        Gfx => { println!("Swapped to OpenGL"); OpenGL }
                        OpenGL => { println!("Swapped to Gfx"); Gfx }
                    };
            }
            Input(input::Press(input::Keyboard(key))) => {
                app.key_press(key);
            },
            Input(input::Release(input::Keyboard(key))) => {
                app.key_release(key);
            },
            _ => {},
        }
    }
}

<commit_msg>Fixed use statement<commit_after>#![feature(globs)]

extern crate piston;
extern crate rand;
extern crate native;
extern crate sdl2_game_window;
extern crate opengl_graphics;
extern crate gfx_graphics;
extern crate gfx;
extern crate sdl2;

use opengl_graphics::Gl;
use gfx_graphics::G2D;
use piston::graphics::{
    AddColor,
    Context,
    Draw,
};
use gfx::{Device, DeviceHelper};
use sdl2_game_window::WindowSDL2;
use piston::{
    EventIterator,
    EventSettings,
    WindowSettings,
    Render,
    Update,
    Input,
};
use piston::input;
use piston::{Window};

mod snakeapp;
mod object;
mod settings;
mod text;
mod bar;
mod player;
mod snake;
mod action;
mod game_state;
mod character;
mod air_bottle;

#[deriving(Show)]
pub enum GraphicsBackEnd {
    Gfx,
    OpenGL,
}

fn main() {
    use snakeapp::SnakeApp;

    let mut backend = Gfx;
    println!("Running with graphics backend {}", backend);
    println!("Use 'S' to swap back-end");

    let opengl = piston::shader_version::opengl::OpenGL_3_2;
    let mut window = WindowSDL2::new(
        opengl,
        WindowSettings {
            title: "Sea Snake Escape".to_string(),
            size: [512, 512],
            fullscreen: false,
            exit_on_esc: true,
            samples: 4,
        }
    );

    let mut device = gfx::GlDevice::new(|s| unsafe {
        std::mem::transmute(sdl2::video::gl_get_proc_address(s))
    });
    let (w, h) = window.get_size();
    let frame = gfx::Frame::new(w as u16, h as u16);

    let mut renderer = device.create_renderer();

    let mut app = SnakeApp::new();
    app.load();

    let mut event_iterator = EventIterator::new(&mut window,
        &EventSettings {
            updates_per_second: 120,
            max_frames_per_second: 60
        });
    let ref mut gl = Gl::new(opengl);
    let mut g2d = G2D::new(&mut device);
    let mut fps_counter = piston::FPSCounter::new();
    loop {
        let e = match event_iterator.next() {
                None => { break; }
                Some(e) => e
            };

        match e {
            Render(args) => {
                match backend {
                    Gfx => {
                        g2d.render(&mut renderer, &frame, |c, g| {
                            c.color(settings::WATER_COLOR).draw(g);
                            app.render(&c, g);
                        });
                        device.submit(renderer.as_buffer());
                        renderer.reset();
                    }
                    OpenGL => {
                        gl.viewport(0, 0, args.width as i32, args.height as i32);
                        gl.clear_program();
                        let c = Context::abs(
                            args.width as f64,
                            args.height as f64
                        );
                        c.color(settings::WATER_COLOR).draw(gl);
                        app.render(&c, gl);
                    }
                };

                event_iterator.window.window.set_title(fps_counter.tick().to_string().as_slice());
            },
            Update(args) => {
                app.update(args.dt);
            },
            Input(input::Press(input::Keyboard(input::keyboard::S))) => {
                backend = match backend {
                        Gfx => { println!("Swapped to OpenGL"); OpenGL }
                        OpenGL => { println!("Swapped to Gfx"); Gfx }
                    };
            }
            Input(input::Press(input::Keyboard(key))) => {
                app.key_press(key);
            },
            Input(input::Release(input::Keyboard(key))) => {
                app.key_release(key);
            },
            _ => {},
        }
    }
}

<|endoftext|>


<commit_before>extern crate rtlsdr;
extern crate num;

use rtlsdr::{RTLSDRDevice, RTLSDRError};
use num::complex::Complex;
use std::env;

fn main() {
    let sdr_index: i32 = env::args().nth(1)
        .expect("Please specify the SDR index")
        .parse::<i32>()
        .unwrap();
    let fm_freq_mhz: f32 = env::args().nth(2)
        .expect("Please specify a center frequency (MHz).")
        .parse::<f32>()
        .unwrap();

    let fm_freq: u32 = (fm_freq_mhz * 1e6) as u32;
    let mut sdr = init_sdr(sdr_index, fm_freq);
}

fn init_sdr(sdr_index: i32, fm_freq: u32) -> Result<RTLSDRDevice, RTLSDRError> {
    let mut sdr = try!(rtlsdr::open(sdr_index));
    try!(sdr.set_center_freq(fm_freq));
    Ok(sdr)
}

fn read_samples(bytes: Vec<u8>) -> Option<Complex<f32>> {
    // The docs tell us that RTL-SDR sends us data in bytes alternating between
    // I and Q. I'm not normalizing here, but I might have to in the future.

    // If we read an odd number of bytes, I don't think we can do anything.
    // (Make sure that this can actually happen)./
    let iter = bytes.chunks(2);
    if iter.count() % 2 != 0 {
        return None
    }

    // Right now I'm just putting None here so we'll compile.
    None
}
<commit_msg>Added code to translate the raw bytes to normalized IQ pairs.<commit_after>extern crate rtlsdr;
extern crate num;

use rtlsdr::{RTLSDRDevice, RTLSDRError};
use num::complex::Complex;
use std::env;

// Make sure that the buffer size is radix-2, otherwise the read_sync function
// will fail with an error code of -8.
const BUF_SIZE: usize = 131072;

// Most other sample rates fail, but this one works for my particular device.
// I will investigate exactly what's happening here and generate a list of
// possible sample rates (if there are others besides this one).
const SAMPLE_RATE: i32 = 2048000;

fn main() {
    let sdr_index: i32 = env::args()
        .nth(1)
        .expect("Please specify the SDR index")
        .parse::<i32>()
        .unwrap();
    let fm_freq_mhz: f32 = env::args()
        .nth(2)
        .expect("Please specify a center frequency (MHz).")
        .parse::<f32>()
        .unwrap();

    let fm_freq: u32 = (fm_freq_mhz * 1e6) as u32;
    let mut sdr = match init_sdr(sdr_index, fm_freq) {
        Ok(s) => s,
        Err(e) => return println!("Couldn't initialize SDR, {}", e),
    };

    loop {
        let bytes = match sdr.read_sync(BUF_SIZE) {
            Ok(b) => b,
            Err(e) => return println!("Couldn't read bytes from SDR, {}", e),
        };
        let iq_vec = read_samples(bytes);
        match iq_vec {
            // TODO: Here is where we would start demodulating. For now, just
            // leave it be.
            Some(iq) => println!("We got some bytes: {:?}", iq.get(0)),
            None => println!("No bytes. :("),
        }
    }
}

fn init_sdr(sdr_index: i32, fm_freq: u32) -> Result<RTLSDRDevice, RTLSDRError> {
    let mut sdr = try!(rtlsdr::open(sdr_index));
    try!(sdr.set_center_freq(fm_freq));
    try!(sdr.set_sample_rate(SAMPLE_RATE));
    try!(sdr.reset_buffer());
    Ok(sdr)
}

fn read_samples(bytes: Vec<u8>) -> Option<Vec<Complex<f32>>> {
    // The docs tell us that RTL-SDR sends us data in bytes alternating between
    // I and Q. I'm not normalizing here, but I might have to in the future.

    // First, check that we've been given an even number of bytes. Not sure
    // what to do if we don't get I and Q.
    let bytes_len = bytes.len();
    if bytes_len % 2 != 0 {
        return None;

    }
    let mut iter = bytes.chunks(2);
    let mut iq_vec: Vec<Complex<f32>> = Vec::with_capacity(bytes_len / 2);

    // Write the values to the complex value and normalize from [0, 255] to
    // [-1, 1].
    for iq in iter.next() {
        iq_vec.push(Complex::new((iq[0] as f32 - 127.5) / 127.5,
                                 (iq[1] as f32 - 127.5) / 127.5));
    }

    Some(iq_vec)
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::fmt;
use std::io::{self, Write};
use std::process::{Command, ExitStatus};

extern crate itertools;
use itertools::Itertools;

// TODO(tsion): Use the readline library.
fn prompt(line: &mut String) -> io::Result<usize> {
    let current_dir = try!(std::env::current_dir());
    print!("{}> ", current_dir.display());
    try!(io::stdout().flush());
    io::stdin().read_line(line)
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum Expr {
    Text(String),
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum Ast {
    Empty,
    Call { command: String, args: Vec<Vec<Expr>> }
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum Token {
    Newline,
    Whitespace,
    Text(String),
}

#[derive(Clone)]
struct Lexer<'src> {
    source: &'src str,
    position: usize,
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum ParseError {
    UnclosedDelimiter(char),
    UnexpectedChar(char),
}

type ParseResult<T> = Result<T, ParseError>;

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ParseError::UnclosedDelimiter(c) => write!(f, "unclosed delimiter: {}", c),
            ParseError::UnexpectedChar(c) => write!(f, "unexpected character: {}", c),
        }
    }
}

impl<'src> Lexer<'src> {
    fn new(source: &str) -> Lexer {
        Lexer {
            source: source,
            position: 0,
        }
    }

    fn read_char(&mut self) -> Option<char> {
        let opt_c = self.source[self.position..].chars().next();

        if let Some(c) = opt_c {
            self.position += c.len_utf8();
        }

        opt_c
    }

    /// Step backwards one `char` in the input. Must not be called more times than `read_char` has
    /// been called.
    fn unread_char(&mut self) {
        assert!(self.position != 0);
        let (prev_pos, _) = self.source[..self.position].char_indices().next_back().unwrap();
        self.position = prev_pos;
    }

    fn is_whitespace(c: char) -> bool {
        c == ' ' || c == '\t'
    }

    fn is_unquoted_text(c: char) -> bool {
        match c {
            'a'...'z' | 'A'...'Z' | '0'...'9' | '-' | '+' | '/' | '_' | '.' | ',' => true,
            _ => false,
        }
    }

    fn skip_while<F>(&mut self, mut predicate: F) where F: FnMut(char) -> bool {
        while let Some(c) = self.read_char() {
            if !predicate(c) {
                self.unread_char();
                break;
            }
        }
    }

    fn lex_whitespace(&mut self) -> ParseResult<Token> {
        self.skip_while(Lexer::is_whitespace);
        Ok(Token::Whitespace)
    }

    fn lex_unquoted_text(&mut self) -> ParseResult<Token> {
        let start = self.position;
        self.skip_while(Lexer::is_unquoted_text);
        let end = self.position;

        let text = String::from(&self.source[start..end]);
        Ok(Token::Text(text))
    }

    fn lex_quoted_text(&mut self, delimiter: char) -> ParseResult<Token> {
        let mut text = String::new();

        while let Some(c) = self.read_char() {
            if c == delimiter {
                return Ok(Token::Text(text));
            }

            match c {
                '\\' => unimplemented!(),
                c => text.push(c),
            }
        }

        Err(ParseError::UnclosedDelimiter(delimiter))
    }
}

impl<'a> Iterator for Lexer<'a> {
    type Item = ParseResult<Token>;

    fn next(&mut self) -> Option<ParseResult<Token>> {
        self.read_char().map(|c| {
            match c {
                c if Lexer::is_whitespace(c)    => self.lex_whitespace(),
                c if Lexer::is_unquoted_text(c) => {
                    self.unread_char();
                    self.lex_unquoted_text()
                },
                '\r' | '\n'                     => Ok(Token::Newline),
                '"' | '\''                      => self.lex_quoted_text(c),
                c                               => Err(ParseError::UnexpectedChar(c)),
            }
        })
    }
}

#[derive(Clone)]
struct Parser<'a> {
    lexer: Lexer<'a>,
}

impl<'a> Parser<'a> {
    fn new(input: &str) -> Parser {
        Parser { lexer: Lexer::new(input) }
    }

    fn parse(&mut self) -> ParseResult<Ast> {
        if let Some(token_result) = self.lexer.next() {
            let token = try!(token_result);
            match token {
                Token::Whitespace | Token::Newline => self.parse(),
                Token::Text(command) => self.parse_call(command),
            }
        } else {
            Ok(Ast::Empty)
        }
    }

    fn parse_call(&mut self, command: String) -> ParseResult<Ast> {
        let mut args = vec![];
        let mut current_arg = vec![];

        for token_result in &mut self.lexer {
            let token = try!(token_result);
            match token {
                Token::Newline => {
                    if !current_arg.is_empty() {
                        args.push(current_arg);
                    }
                    break;
                },

                Token::Whitespace => {
                    if !current_arg.is_empty() {
                        args.push(current_arg);
                        current_arg = vec![];
                    }
                },

                Token::Text(text) => {
                    current_arg.push(Expr::Text(text));
                },
            }
        }

        Ok(Ast::Call { command: command, args: args })
    }
}

struct Builtin {
    name: &'static str,
    min_args: usize,
    max_args: usize,
    func: fn(&[String]) -> i32,
}

fn result_to_exit_code(cmd: &'static str, result: io::Result<()>) -> i32 {
    match result {
        Ok(()) => 0,
        Err(e) => {
            writeln!(&mut io::stderr(), "shroom: {}: {}", cmd, e).unwrap();
            1
        },
    }
}

fn builtin_cd(args: &[String]) -> i32 {
    if let Some(path) = args.get(0) {
        result_to_exit_code("cd", std::env::set_current_dir(path))
    } else if let Some(home) = std::env::home_dir() {
        result_to_exit_code("cd", std::env::set_current_dir(home))
    } else {
        writeln!(&mut io::stderr(), "shroom: cd: couldn't find home dir").unwrap();
        1
    }
}

fn builtin_exit(args: &[String]) -> i32 {
    if let Some(exit_code_str) = args.get(0) {
        match exit_code_str.parse() {
            Ok(exit_code) => std::process::exit(exit_code),
            Err(e) => {
                writeln!(&mut io::stderr(), "shroom: exit: can't parse exit code: {}", e).unwrap();
                1
            },
        }
    } else {
        std::process::exit(0);
    }
}

fn execute(ast: &Ast) -> i32 {
    let mut builtins = HashMap::new();

    builtins.insert("cd", Builtin {
        name: "cd",
        min_args: 0,
        max_args: 1,
        func: builtin_cd,
    });

    builtins.insert("exit", Builtin {
        name: "exit",
        min_args: 0,
        max_args: 1,
        func: builtin_exit,
    });

    match *ast {
        Ast::Empty => 0,

        Ast::Call { ref command, ref args } => {
            // Evaluate argument expressions.
            let evaluated_args: Vec<String> = args.iter().map(|arg| {
                arg.iter().map(|expr| {
                    match *expr {
                        Expr::Text(ref text) => text,
                    }
                }).join("")
            }).collect();

            if let Some(builtin) = builtins.get(&command[..]) {
                if args.len() < builtin.min_args {
                    writeln!(&mut io::stderr(), "shroom: {}: not enough arguments",
                             builtin.name).unwrap();
                    1
                } else if args.len() > builtin.max_args {
                    writeln!(&mut io::stderr(), "shroom: {}: too many arguments",
                             builtin.name).unwrap();
                    1
                } else {
                    (builtin.func)(&evaluated_args)
                }
            } else {
                match Command::new(command).args(&evaluated_args).status() {
                    Ok(exit_status) => {
                        #[cfg(unix)]
                        fn exit_signal(exit_status: &ExitStatus) -> Option<i32> {
                            use std::os::unix::process::ExitStatusExt;
                            exit_status.signal()
                        }

                        #[cfg(not(unix))]
                        fn exit_signal(_exit_status: &ExitStatus) -> Option<i32> {
                            None
                        }

                        if let Some(code) = exit_status.code() {
                            code
                        } else if let Some(signal) = exit_signal(&exit_status) {
                            128 + signal
                        } else {
                            127
                        }
                    },

                    Err(e) => {
                        writeln!(&mut io::stderr(), "shroom: {}: {}", command, e).unwrap();
                        127
                    },
                }
            }
        },
    }
}

fn main() {
    let mut line = String::new();
    loop {
        prompt(&mut line).unwrap();

        match Parser::new(&line).parse() {
            Ok(ast) => {
                let exit_code = execute(&ast);
                if exit_code != 0 {
                    println!("shroom: exit code: {}", exit_code);
                }
            },

            Err(parse_error) => {
                println!("shroom: parse error: {}", parse_error);
            },
        }

        line.clear();
    }
}
<commit_msg>Change the rest of the source string lifetimes to match Lexer.<commit_after>use std::collections::HashMap;
use std::fmt;
use std::io::{self, Write};
use std::process::{Command, ExitStatus};

extern crate itertools;
use itertools::Itertools;

// TODO(tsion): Use the readline library.
fn prompt(line: &mut String) -> io::Result<usize> {
    let current_dir = try!(std::env::current_dir());
    print!("{}> ", current_dir.display());
    try!(io::stdout().flush());
    io::stdin().read_line(line)
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum Expr {
    Text(String),
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum Ast {
    Empty,
    Call { command: String, args: Vec<Vec<Expr>> }
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum Token {
    Newline,
    Whitespace,
    Text(String),
}

#[derive(Clone)]
struct Lexer<'src> {
    source: &'src str,
    position: usize,
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum ParseError {
    UnclosedDelimiter(char),
    UnexpectedChar(char),
}

type ParseResult<T> = Result<T, ParseError>;

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ParseError::UnclosedDelimiter(c) => write!(f, "unclosed delimiter: {}", c),
            ParseError::UnexpectedChar(c) => write!(f, "unexpected character: {}", c),
        }
    }
}

impl<'src> Lexer<'src> {
    fn new(source: &str) -> Lexer {
        Lexer {
            source: source,
            position: 0,
        }
    }

    fn read_char(&mut self) -> Option<char> {
        let opt_c = self.source[self.position..].chars().next();

        if let Some(c) = opt_c {
            self.position += c.len_utf8();
        }

        opt_c
    }

    /// Step backwards one `char` in the input. Must not be called more times than `read_char` has
    /// been called.
    fn unread_char(&mut self) {
        assert!(self.position != 0);
        let (prev_pos, _) = self.source[..self.position].char_indices().next_back().unwrap();
        self.position = prev_pos;
    }

    fn is_whitespace(c: char) -> bool {
        c == ' ' || c == '\t'
    }

    fn is_unquoted_text(c: char) -> bool {
        match c {
            'a'...'z' | 'A'...'Z' | '0'...'9' | '-' | '+' | '/' | '_' | '.' | ',' => true,
            _ => false,
        }
    }

    fn skip_while<F>(&mut self, mut predicate: F) where F: FnMut(char) -> bool {
        while let Some(c) = self.read_char() {
            if !predicate(c) {
                self.unread_char();
                break;
            }
        }
    }

    fn lex_whitespace(&mut self) -> ParseResult<Token> {
        self.skip_while(Lexer::is_whitespace);
        Ok(Token::Whitespace)
    }

    fn lex_unquoted_text(&mut self) -> ParseResult<Token> {
        let start = self.position;
        self.skip_while(Lexer::is_unquoted_text);
        let end = self.position;

        let text = String::from(&self.source[start..end]);
        Ok(Token::Text(text))
    }

    fn lex_quoted_text(&mut self, delimiter: char) -> ParseResult<Token> {
        let mut text = String::new();

        while let Some(c) = self.read_char() {
            if c == delimiter {
                return Ok(Token::Text(text));
            }

            match c {
                '\\' => unimplemented!(),
                c => text.push(c),
            }
        }

        Err(ParseError::UnclosedDelimiter(delimiter))
    }
}

impl<'src> Iterator for Lexer<'src> {
    type Item = ParseResult<Token>;

    fn next(&mut self) -> Option<ParseResult<Token>> {
        self.read_char().map(|c| {
            match c {
                c if Lexer::is_whitespace(c)    => self.lex_whitespace(),
                c if Lexer::is_unquoted_text(c) => {
                    self.unread_char();
                    self.lex_unquoted_text()
                },
                '\r' | '\n'                     => Ok(Token::Newline),
                '"' | '\''                      => self.lex_quoted_text(c),
                c                               => Err(ParseError::UnexpectedChar(c)),
            }
        })
    }
}

#[derive(Clone)]
struct Parser<'src> {
    lexer: Lexer<'src>,
}

impl<'src> Parser<'src> {
    fn new(input: &str) -> Parser {
        Parser { lexer: Lexer::new(input) }
    }

    fn parse(&mut self) -> ParseResult<Ast> {
        if let Some(token_result) = self.lexer.next() {
            let token = try!(token_result);
            match token {
                Token::Whitespace | Token::Newline => self.parse(),
                Token::Text(command) => self.parse_call(command),
            }
        } else {
            Ok(Ast::Empty)
        }
    }

    fn parse_call(&mut self, command: String) -> ParseResult<Ast> {
        let mut args = vec![];
        let mut current_arg = vec![];

        for token_result in &mut self.lexer {
            let token = try!(token_result);
            match token {
                Token::Newline => {
                    if !current_arg.is_empty() {
                        args.push(current_arg);
                    }
                    break;
                },

                Token::Whitespace => {
                    if !current_arg.is_empty() {
                        args.push(current_arg);
                        current_arg = vec![];
                    }
                },

                Token::Text(text) => {
                    current_arg.push(Expr::Text(text));
                },
            }
        }

        Ok(Ast::Call { command: command, args: args })
    }
}

struct Builtin {
    name: &'static str,
    min_args: usize,
    max_args: usize,
    func: fn(&[String]) -> i32,
}

fn result_to_exit_code(cmd: &'static str, result: io::Result<()>) -> i32 {
    match result {
        Ok(()) => 0,
        Err(e) => {
            writeln!(&mut io::stderr(), "shroom: {}: {}", cmd, e).unwrap();
            1
        },
    }
}

fn builtin_cd(args: &[String]) -> i32 {
    if let Some(path) = args.get(0) {
        result_to_exit_code("cd", std::env::set_current_dir(path))
    } else if let Some(home) = std::env::home_dir() {
        result_to_exit_code("cd", std::env::set_current_dir(home))
    } else {
        writeln!(&mut io::stderr(), "shroom: cd: couldn't find home dir").unwrap();
        1
    }
}

fn builtin_exit(args: &[String]) -> i32 {
    if let Some(exit_code_str) = args.get(0) {
        match exit_code_str.parse() {
            Ok(exit_code) => std::process::exit(exit_code),
            Err(e) => {
                writeln!(&mut io::stderr(), "shroom: exit: can't parse exit code: {}", e).unwrap();
                1
            },
        }
    } else {
        std::process::exit(0);
    }
}

fn execute(ast: &Ast) -> i32 {
    let mut builtins = HashMap::new();

    builtins.insert("cd", Builtin {
        name: "cd",
        min_args: 0,
        max_args: 1,
        func: builtin_cd,
    });

    builtins.insert("exit", Builtin {
        name: "exit",
        min_args: 0,
        max_args: 1,
        func: builtin_exit,
    });

    match *ast {
        Ast::Empty => 0,

        Ast::Call { ref command, ref args } => {
            // Evaluate argument expressions.
            let evaluated_args: Vec<String> = args.iter().map(|arg| {
                arg.iter().map(|expr| {
                    match *expr {
                        Expr::Text(ref text) => text,
                    }
                }).join("")
            }).collect();

            if let Some(builtin) = builtins.get(&command[..]) {
                if args.len() < builtin.min_args {
                    writeln!(&mut io::stderr(), "shroom: {}: not enough arguments",
                             builtin.name).unwrap();
                    1
                } else if args.len() > builtin.max_args {
                    writeln!(&mut io::stderr(), "shroom: {}: too many arguments",
                             builtin.name).unwrap();
                    1
                } else {
                    (builtin.func)(&evaluated_args)
                }
            } else {
                match Command::new(command).args(&evaluated_args).status() {
                    Ok(exit_status) => {
                        #[cfg(unix)]
                        fn exit_signal(exit_status: &ExitStatus) -> Option<i32> {
                            use std::os::unix::process::ExitStatusExt;
                            exit_status.signal()
                        }

                        #[cfg(not(unix))]
                        fn exit_signal(_exit_status: &ExitStatus) -> Option<i32> {
                            None
                        }

                        if let Some(code) = exit_status.code() {
                            code
                        } else if let Some(signal) = exit_signal(&exit_status) {
                            128 + signal
                        } else {
                            127
                        }
                    },

                    Err(e) => {
                        writeln!(&mut io::stderr(), "shroom: {}: {}", command, e).unwrap();
                        127
                    },
                }
            }
        },
    }
}

fn main() {
    let mut line = String::new();
    loop {
        prompt(&mut line).unwrap();

        match Parser::new(&line).parse() {
            Ok(ast) => {
                let exit_code = execute(&ast);
                if exit_code != 0 {
                    println!("shroom: exit code: {}", exit_code);
                }
            },

            Err(parse_error) => {
                println!("shroom: parse error: {}", parse_error);
            },
        }

        line.clear();
    }
}
<|endoftext|>


<commit_before>extern crate dotenv;
extern crate schani_store;

fn main() {
    dotenv::dotenv().unwrap();

    let app = schani_store::StoreWebApp::new("http://127.0.0.1:9100".parse().unwrap());
    app.run();
}
<commit_msg>Fix panic if .env is missing<commit_after>extern crate dotenv;
extern crate schani_store;

fn main() {
    if dotenv::dotenv().is_err() {
        println!("No .env found, relying solely on env vars.");
    }

    let app = schani_store::StoreWebApp::new("http://127.0.0.1:9100".parse().unwrap());
    app.run();
}
<|endoftext|>


<commit_before>extern crate sdl2;
extern crate fps_clock;
#[macro_use]
extern crate lazy_static;

use std::cmp::PartialEq;

use sdl2::video::Window;
use sdl2::render::Canvas;
use sdl2::render::Texture;
use sdl2::EventPump;
use sdl2::pixels::Color;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::image::{LoadTexture, INIT_PNG};
use sdl2::rect::{Rect, Point};
use sdl2::ttf::Sdl2TtfContext;
use sdl2::surface::Surface;
use sdl2::pixels::PixelFormatEnum;

use fps_clock::FpsClock;

macro_rules! rect {
    ($x:expr, $y:expr, $w:expr, $h:expr) => (Rect::new($x as i32, $y as i32, $w as u32, $h as u32))
}

const LEVELS: &'static str = include_str!("../levels.txt");
const SPRITESHEET_PATH: &'static str = "resources/images/sokoban_spritesheet.png";
const FONT_PATH: &'static str = "resources/font/swansea.ttf";

lazy_static! {
    static ref BACKGROUND_COLOR: Color = Color::RGB(45, 168, 18);
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Direction {
    Up,
    Down,
    Left,
    Right
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Tile {
    Wall,
    Player,
    PlayerOnGoal,
    Star,
    StarOnGoal,
    Goal,
    OutsideFloor,
    InsideFloor
}
impl Tile {
    /// Character to tile mapping taken from http://sokobano.de/wiki/index.php?title=Level_format
    /// I renamed Box to Star to not conflict with the Box type.
    fn from_char(c: char) -> Result<Tile, String> {
        match c {
            '#' => Ok(Tile::Wall),
            '@' => Ok(Tile::Player),
            '+' => Ok(Tile::PlayerOnGoal),
            '$' => Ok(Tile::Star),
            '*' => Ok(Tile::StarOnGoal),
            '.' => Ok(Tile::Goal),
            ' ' => Ok(Tile::OutsideFloor),
            _ => Err(format!("'{}' is an invalid tile", c)),
        }
    }
    fn to_char(&self) -> char {
        match *self {
            Tile::Wall => '#',
            Tile::Player => '@',
            Tile::PlayerOnGoal => '+',
            Tile::Star => '$',
            Tile::StarOnGoal => '*',
            Tile::Goal => '.',
            Tile::OutsideFloor => '~',
            Tile::InsideFloor => ' ',
        }
    }
    fn spritesheet_rect(&self) -> Rect {
        match *self {
            Tile::Wall => rect!(448, 64, 64, 64),
            Tile::PlayerOnGoal | Tile::Goal | Tile::StarOnGoal => rect!(60, 576, 20, 20),
            Tile::Star => rect!(384, 0, 64, 64),
            Tile::InsideFloor => rect!(192, 528, 64, 64),
            _ => panic!()
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Position {
    x: usize,
    y: usize,
}
impl Position {
    fn new(x: usize, y: usize) -> Position {
        Position {x, y}
    }
    fn move_in_direction(&self, dir: Direction) -> Position {
        match dir {
            Direction::Down => Position {y: self.y+1, ..*self},
            Direction::Up => Position {y: self.y-1, ..*self},
            Direction::Left => Position {x: self.x-1, ..*self},
            Direction::Right => Position {x: self.x-1, ..*self},
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Player {
    position: Position,
    direction: Direction,
}
impl Player {
    fn new(position: Position, direction: Direction) -> Player {
        Player {
            position,
            direction,
        }
    }
    fn move_in_direction(&self, direction: Direction) -> Player {
        Player::new(self.position.move_in_direction(direction), direction)
    }
    fn spritesheet_rect(&self) -> Rect {
        match self.direction {
            Direction::Down => rect!(554, 208, 42, 50),
            Direction::Left => rect!(543, 440, 45, 50),
            Direction::Right => rect!(512, 108, 45, 50),
            Direction::Up => rect!(554, 158, 42, 50),
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Star {
    position: Position
}
impl Star {
    fn new(position: Position) -> Star {
        Star { position }
    }
    fn move_in_direction(&self, direction: Direction) -> Star {
        Star::new(self.position.move_in_direction(direction))
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Goal {
    position: Position
}
impl Goal {
    fn new(position: Position) -> Goal {
        Goal { position }
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
struct GameState {
    player: Player,
    stars: Vec<Star>,
    goals: Vec<Goal>,
    steps: usize,
}
impl GameState {
    fn new(player: Player, stars: Vec<Star>, goals: Vec<Goal>,  steps: usize) -> GameState {
        GameState { player, stars, goals, steps }
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
struct Level {
    width: usize,
    height: usize,
    map: Vec<Vec<Tile>>,
    start_state: GameState,
}
impl Level {
    fn from_lines(lines: Vec<&str>) -> Result<Level, String> {
        let longest_line_len = lines.iter()
                                .map(|l| l.len())
                                .max()
                                .ok_or_else(|| "Invalid level: Level is empty")?;
        let mut map = Vec::with_capacity(lines.len());
        let mut stars = Vec::new();
        let mut goals = Vec::new();
        let mut player_pos = None;
        for (y, line) in lines.iter().enumerate() {
            let mut row = Vec::with_capacity(line.len());
            for (x, tile) in line.chars().enumerate() {
                let tile = Tile::from_char(tile)?;
                if tile == Tile::Player || tile == Tile::PlayerOnGoal {
                    // This tile is the starting position
                    player_pos = Some(Position::new(x, y));
                    row.push(Tile::OutsideFloor);
                } else if tile == Tile::Star || tile == Tile::StarOnGoal {
                    stars.push(Star::new(Position::new(x, y)));
                    row.push(Tile::OutsideFloor);
                } else if tile == Tile::PlayerOnGoal
                          || tile == Tile::StarOnGoal
                          || tile == Tile::Goal {
                    goals.push(Goal::new(Position::new(x, y)));
                    row.push(Tile::OutsideFloor);
                } else {
                    row.push(tile);
                }
            }
            if line.len() < longest_line_len {
                for _ in 0..(longest_line_len - line.len()) {
                    row.push(Tile::OutsideFloor);
                }
            }
            map.push(row);
        }
        let pos = player_pos.ok_or_else(|| "Invalid level: Level has no starting position")?;
        let start_state = GameState::new(Player::new(pos, Direction::Right),
                                         stars,
                                         goals,
                                         0);
        let height = map.len();
        floodfill(&mut map, Tile::OutsideFloor, Tile::InsideFloor, pos.x, pos.y);
        Ok(Level { map, width: longest_line_len, height, start_state})
    }
    fn as_string(&self) -> String {
        let mut map = String::new();
        for line in &self.map {
            for tile in line {
                map.push(tile.to_char());
            }
            map.push('\n');
        }
        map
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
struct Game {
    level: Level,
    state: GameState,
}
impl Game {
    fn new(level: Level, state: GameState) -> Game {
        Game { level, state }
    }
    fn from_level(level: Level) -> Game {
        Game::new(level.clone(), level.start_state)
    }
    fn step(&mut self, event: &Event) {
        match *event {
            Event::KeyDown{keycode: Some(Keycode::Up), ..} => self.make_move(Direction::Up),
            Event::KeyDown{keycode: Some(Keycode::Down), ..} => self.make_move(Direction::Down),
            Event::KeyDown{keycode: Some(Keycode::Left), ..} => self.make_move(Direction::Left),
            Event::KeyDown{keycode: Some(Keycode::Right), ..} => self.make_move(Direction::Right),
            _ => ()
        }
    }
    fn render_to_surface(&self, spritesheet_path: &str) -> Surface<'static> {
        let level = &self.level;
        let state = &self.state;
        let map = &level.map;
        let surf = Surface::new((level.width * 64) as u32,
                                    (level.height * 64) as u32,
                                    PixelFormatEnum::ABGR1555 /* <- I have no clue if this is right or not */).unwrap();
        let mut canvas = surf.into_canvas().unwrap();
        let texture_creator = canvas.texture_creator();
        let spritesheet = texture_creator.load_texture(spritesheet_path).unwrap();
        canvas.set_draw_color(*BACKGROUND_COLOR);
        canvas.clear();
        for (y, row) in map.iter().enumerate() {
            for (x, tile) in row.iter().enumerate() {
                match *tile {
                    Tile::OutsideFloor => (),
                    Tile::InsideFloor | Tile::Wall => {
                        canvas.copy(&spritesheet, tile.spritesheet_rect(), rect!(x*64, y*64, 64, 64)).unwrap();
                    },
                    _ => ()
                }
            }
        }
        for goal in &state.goals {
            let (x, y) = (&goal.position.x, &goal.position.y);
            canvas.copy(&spritesheet, Tile::Goal.spritesheet_rect(), rect!(x*64+22, y*64+22, 20, 20)).unwrap();
        }
        for star in &state.stars {
            let (x, y) = (&star.position.x, &star.position.y);
            canvas.copy(&spritesheet, Tile::Star.spritesheet_rect(), rect!(x*64, y*64, 64, 64)).unwrap();
        }
        let player = state.player;
        let (player_x, player_y) = (player.position.x, player.position.y);
        let player_rect = player.spritesheet_rect();
        let w = player_rect.width();
        let h = player_rect.height();
        let r = Rect::from_center(Point::new((player_x*64+32) as i32, (player_y*64+32) as i32), w, h);
        canvas.copy(&spritesheet, player_rect, r).unwrap();
        canvas.into_surface()
    }
    fn make_move(&mut self, direction: Direction) {
        self.state.player.direction = direction;
    }
}

fn load_levels(levels: &str) -> Result<Vec<Level>, String> {
    let mut parsed_levels = Vec::new();
    let mut map_lines = Vec::new();
    for line in levels.lines() {
        let line = line.trim_right();
        let line = if let Some(i) = line.find(';') {
            &line[0..i]
        } else {
            line
        };
        if !line.is_empty() {
            map_lines.push(line);
        } else if line.is_empty() && !map_lines.is_empty() {
            parsed_levels.push(Level::from_lines(map_lines)?);
            map_lines = Vec::new();
        }
    }
    Ok(parsed_levels)
}

fn floodfill<T: PartialEq + Copy>(map: &mut Vec<Vec<T>>, old: T, new: T, x: usize, y: usize) {
    if map[y][x] == old {
        map[y][x] = new;
    }
    if x > 0 && map[y][x-1] == old {
        floodfill(map, old, new, x-1, y);
    }
    if x + 1 < map[y].len() && map[y][x+1] == old {
        floodfill(map, old, new, x+1, y);
    }
    if y > 0 && map[y-1][x] == old {
        floodfill(map, old, new, x, y-1)
    }
    if y + 1 < map.len() && map[y+1][x] == old {
        floodfill(map, old, new, x, y+1)
    }
}

fn init_sdl(app_name: &str, width: u32, height: u32) -> Result<(Canvas<Window>, EventPump, Sdl2TtfContext), String> {
    let sdl_context = sdl2::init()?;
    let _image_context = sdl2::image::init(INIT_PNG)?;
    let video_subsystem = sdl_context.video()?;

    let window = video_subsystem.window(app_name, width, height)
        .position_centered()
        .opengl()
        .build()
        .map_err(|e| format!("{}", e))?;

    let canvas = window.into_canvas().build().map_err(|e| format!("{}", e))?;
    let event_pump = sdl_context.event_pump()?;
    let ttf_context = sdl2::ttf::init().map_err(|e| format!("{}", e))?;
    Ok((canvas, event_pump, ttf_context))
}

fn main() {
    let parsed_levels = load_levels(LEVELS).unwrap();
    let mut game = Game::from_level(parsed_levels[1].clone());
    let (width, height) = (800, 600);
    let (mut canvas, mut event_pump, ttf_context) = init_sdl("Sokoban", width, height).unwrap();
    let texture_creator = canvas.texture_creator();
    let mut clock = FpsClock::new(60);
    'main: loop {
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                    break 'main
                },
                event => game.step(&event),
            }
        }
        let level_surf = game.render_to_surface(SPRITESHEET_PATH);
        let center_rect = Rect::from_center(Point::new((width/2) as i32, (height/2) as i32), level_surf.width(), level_surf.height());
        let level_texture = texture_creator.create_texture_from_surface(level_surf).unwrap();
        canvas.set_draw_color(*BACKGROUND_COLOR);
        canvas.clear();
        canvas.copy(&level_texture, None, Some(center_rect)).expect("Render failed");
        canvas.present();
        clock.tick();
    }
}
<commit_msg>Add game over test<commit_after>extern crate sdl2;
extern crate fps_clock;
#[macro_use]
extern crate lazy_static;

use std::cmp::PartialEq;

use sdl2::video::Window;
use sdl2::render::Canvas;
use sdl2::render::Texture;
use sdl2::EventPump;
use sdl2::pixels::Color;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::image::{LoadTexture, INIT_PNG};
use sdl2::rect::{Rect, Point};
use sdl2::ttf::Sdl2TtfContext;
use sdl2::surface::Surface;
use sdl2::pixels::PixelFormatEnum;

use fps_clock::FpsClock;

macro_rules! rect {
    ($x:expr, $y:expr, $w:expr, $h:expr) => (Rect::new($x as i32, $y as i32, $w as u32, $h as u32))
}

const LEVELS: &'static str = include_str!("../levels.txt");
const SPRITESHEET_PATH: &'static str = "resources/images/sokoban_spritesheet.png";
const FONT_PATH: &'static str = "resources/font/swansea.ttf";

lazy_static! {
    static ref BACKGROUND_COLOR: Color = Color::RGB(45, 168, 18);
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Direction {
    Up,
    Down,
    Left,
    Right
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Tile {
    Wall,
    Player,
    PlayerOnGoal,
    Star,
    StarOnGoal,
    Goal,
    OutsideFloor,
    InsideFloor
}
impl Tile {
    /// Character to tile mapping taken from http://sokobano.de/wiki/index.php?title=Level_format
    /// I renamed Box to Star to not conflict with the Box type.
    fn from_char(c: char) -> Result<Tile, String> {
        match c {
            '#' => Ok(Tile::Wall),
            '@' => Ok(Tile::Player),
            '+' => Ok(Tile::PlayerOnGoal),
            '$' => Ok(Tile::Star),
            '*' => Ok(Tile::StarOnGoal),
            '.' => Ok(Tile::Goal),
            ' ' => Ok(Tile::OutsideFloor),
            _ => Err(format!("'{}' is an invalid tile", c)),
        }
    }
    fn to_char(&self) -> char {
        match *self {
            Tile::Wall => '#',
            Tile::Player => '@',
            Tile::PlayerOnGoal => '+',
            Tile::Star => '$',
            Tile::StarOnGoal => '*',
            Tile::Goal => '.',
            Tile::OutsideFloor => '~',
            Tile::InsideFloor => ' ',
        }
    }
    fn spritesheet_rect(&self) -> Rect {
        match *self {
            Tile::Wall => rect!(448, 64, 64, 64),
            Tile::PlayerOnGoal | Tile::Goal | Tile::StarOnGoal => rect!(60, 576, 20, 20),
            Tile::Star => rect!(384, 0, 64, 64),
            Tile::InsideFloor => rect!(192, 528, 64, 64),
            _ => panic!()
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Position {
    x: usize,
    y: usize,
}
impl Position {
    fn new(x: usize, y: usize) -> Position {
        Position {x, y}
    }
    fn move_in_direction(&self, dir: Direction) -> Position {
        match dir {
            Direction::Down => Position {y: self.y+1, ..*self},
            Direction::Up => Position {y: self.y-1, ..*self},
            Direction::Left => Position {x: self.x-1, ..*self},
            Direction::Right => Position {x: self.x-1, ..*self},
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Player {
    position: Position,
    direction: Direction,
}
impl Player {
    fn new(position: Position, direction: Direction) -> Player {
        Player {
            position,
            direction,
        }
    }
    fn move_in_direction(&self, direction: Direction) -> Player {
        Player::new(self.position.move_in_direction(direction), direction)
    }
    fn spritesheet_rect(&self) -> Rect {
        match self.direction {
            Direction::Down => rect!(554, 208, 42, 50),
            Direction::Left => rect!(543, 440, 45, 50),
            Direction::Right => rect!(512, 108, 45, 50),
            Direction::Up => rect!(554, 158, 42, 50),
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Star {
    position: Position
}
impl Star {
    fn new(position: Position) -> Star {
        Star { position }
    }
    fn move_in_direction(&self, direction: Direction) -> Star {
        Star::new(self.position.move_in_direction(direction))
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Goal {
    position: Position
}
impl Goal {
    fn new(position: Position) -> Goal {
        Goal { position }
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
struct GameState {
    player: Player,
    stars: Vec<Star>,
    goals: Vec<Goal>,
    steps: usize,
}
impl GameState {
    fn new(player: Player, stars: Vec<Star>, goals: Vec<Goal>,  steps: usize) -> GameState {
        GameState { player, stars, goals, steps }
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
struct Level {
    width: usize,
    height: usize,
    map: Vec<Vec<Tile>>,
    start_state: GameState,
}
impl Level {
    fn from_lines(lines: Vec<&str>) -> Result<Level, String> {
        let longest_line_len = lines.iter()
                                .map(|l| l.len())
                                .max()
                                .ok_or_else(|| "Invalid level: Level is empty")?;
        let mut map = Vec::with_capacity(lines.len());
        let mut stars = Vec::new();
        let mut goals = Vec::new();
        let mut player_pos = None;
        for (y, line) in lines.iter().enumerate() {
            let mut row = Vec::with_capacity(line.len());
            for (x, tile) in line.chars().enumerate() {
                let tile = Tile::from_char(tile)?;
                if tile == Tile::Player || tile == Tile::PlayerOnGoal {
                    // This tile is the starting position
                    player_pos = Some(Position::new(x, y));
                    row.push(Tile::OutsideFloor);
                } else if tile == Tile::Star || tile == Tile::StarOnGoal {
                    stars.push(Star::new(Position::new(x, y)));
                    row.push(Tile::OutsideFloor);
                } else if tile == Tile::PlayerOnGoal
                          || tile == Tile::StarOnGoal
                          || tile == Tile::Goal {
                    goals.push(Goal::new(Position::new(x, y)));
                    row.push(Tile::OutsideFloor);
                } else {
                    row.push(tile);
                }
            }
            if line.len() < longest_line_len {
                for _ in 0..(longest_line_len - line.len()) {
                    row.push(Tile::OutsideFloor);
                }
            }
            map.push(row);
        }
        let pos = player_pos.ok_or_else(|| "Invalid level: Level has no starting position")?;
        let start_state = GameState::new(Player::new(pos, Direction::Right),
                                         stars,
                                         goals,
                                         0);
        let height = map.len();
        floodfill(&mut map, Tile::OutsideFloor, Tile::InsideFloor, pos.x, pos.y);
        Ok(Level { map, width: longest_line_len, height, start_state})
    }
    fn as_string(&self) -> String {
        let mut map = String::new();
        for line in &self.map {
            for tile in line {
                map.push(tile.to_char());
            }
            map.push('\n');
        }
        map
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
struct Game {
    level: Level,
    state: GameState,
}
impl Game {
    fn new(level: Level, state: GameState) -> Game {
        Game { level, state }
    }
    fn from_level(level: Level) -> Game {
        Game::new(level.clone(), level.start_state)
    }
    fn step(&mut self, event: &Event) {
        match *event {
            Event::KeyDown{keycode: Some(Keycode::Up), ..} => self.make_move(Direction::Up),
            Event::KeyDown{keycode: Some(Keycode::Down), ..} => self.make_move(Direction::Down),
            Event::KeyDown{keycode: Some(Keycode::Left), ..} => self.make_move(Direction::Left),
            Event::KeyDown{keycode: Some(Keycode::Right), ..} => self.make_move(Direction::Right),
            _ => ()
        }
    }
    fn render_to_surface(&self, spritesheet_path: &str) -> Surface<'static> {
        let level = &self.level;
        let state = &self.state;
        let map = &level.map;
        let surf = Surface::new((level.width * 64) as u32,
                                    (level.height * 64) as u32,
                                    PixelFormatEnum::ABGR1555 /* <- I have no clue if this is right or not */).unwrap();
        let mut canvas = surf.into_canvas().unwrap();
        let texture_creator = canvas.texture_creator();
        let spritesheet = texture_creator.load_texture(spritesheet_path).unwrap();
        canvas.set_draw_color(*BACKGROUND_COLOR);
        canvas.clear();
        for (y, row) in map.iter().enumerate() {
            for (x, tile) in row.iter().enumerate() {
                match *tile {
                    Tile::OutsideFloor => (),
                    Tile::InsideFloor | Tile::Wall => {
                        canvas.copy(&spritesheet, tile.spritesheet_rect(), rect!(x*64, y*64, 64, 64)).unwrap();
                    },
                    _ => ()
                }
            }
        }
        for goal in &state.goals {
            let (x, y) = (&goal.position.x, &goal.position.y);
            canvas.copy(&spritesheet, Tile::Goal.spritesheet_rect(), rect!(x*64+22, y*64+22, 20, 20)).unwrap();
        }
        for star in &state.stars {
            let (x, y) = (&star.position.x, &star.position.y);
            canvas.copy(&spritesheet, Tile::Star.spritesheet_rect(), rect!(x*64, y*64, 64, 64)).unwrap();
        }
        let player = state.player;
        let (player_x, player_y) = (player.position.x, player.position.y);
        let player_rect = player.spritesheet_rect();
        let w = player_rect.width();
        let h = player_rect.height();
        let r = Rect::from_center(Point::new((player_x*64+32) as i32, (player_y*64+32) as i32), w, h);
        canvas.copy(&spritesheet, player_rect, r).unwrap();
        canvas.into_surface()
    }
    fn make_move(&mut self, direction: Direction) {
        self.state.player.direction = direction;
    }
    fn game_over(&self) -> bool {
        self.state.stars.iter().all(|s| self.state.goals.contains(&Goal::new(s.position)))
    }
}

fn load_levels(levels: &str) -> Result<Vec<Level>, String> {
    let mut parsed_levels = Vec::new();
    let mut map_lines = Vec::new();
    for line in levels.lines() {
        let line = line.trim_right();
        let line = if let Some(i) = line.find(';') {
            &line[0..i]
        } else {
            line
        };
        if !line.is_empty() {
            map_lines.push(line);
        } else if line.is_empty() && !map_lines.is_empty() {
            parsed_levels.push(Level::from_lines(map_lines)?);
            map_lines = Vec::new();
        }
    }
    Ok(parsed_levels)
}

fn floodfill<T: PartialEq + Copy>(map: &mut Vec<Vec<T>>, old: T, new: T, x: usize, y: usize) {
    if map[y][x] == old {
        map[y][x] = new;
    }
    if x > 0 && map[y][x-1] == old {
        floodfill(map, old, new, x-1, y);
    }
    if x + 1 < map[y].len() && map[y][x+1] == old {
        floodfill(map, old, new, x+1, y);
    }
    if y > 0 && map[y-1][x] == old {
        floodfill(map, old, new, x, y-1)
    }
    if y + 1 < map.len() && map[y+1][x] == old {
        floodfill(map, old, new, x, y+1)
    }
}

fn init_sdl(app_name: &str, width: u32, height: u32) -> Result<(Canvas<Window>, EventPump, Sdl2TtfContext), String> {
    let sdl_context = sdl2::init()?;
    let _image_context = sdl2::image::init(INIT_PNG)?;
    let video_subsystem = sdl_context.video()?;

    let window = video_subsystem.window(app_name, width, height)
        .position_centered()
        .opengl()
        .build()
        .map_err(|e| format!("{}", e))?;

    let canvas = window.into_canvas().build().map_err(|e| format!("{}", e))?;
    let event_pump = sdl_context.event_pump()?;
    let ttf_context = sdl2::ttf::init().map_err(|e| format!("{}", e))?;
    Ok((canvas, event_pump, ttf_context))
}

fn main() {
    let parsed_levels = load_levels(LEVELS).unwrap();
    let mut game = Game::from_level(parsed_levels[1].clone());
    let (width, height) = (800, 600);
    let (mut canvas, mut event_pump, ttf_context) = init_sdl("Sokoban", width, height).unwrap();
    let texture_creator = canvas.texture_creator();
    let mut clock = FpsClock::new(60);
    'main: loop {
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                    break 'main
                },
                event => game.step(&event),
            }
        }
        let level_surf = game.render_to_surface(SPRITESHEET_PATH);
        let center_rect = Rect::from_center(Point::new((width/2) as i32, (height/2) as i32), level_surf.width(), level_surf.height());
        let level_texture = texture_creator.create_texture_from_surface(level_surf).unwrap();
        canvas.set_draw_color(*BACKGROUND_COLOR);
        canvas.clear();
        canvas.copy(&level_texture, None, Some(center_rect)).expect("Render failed");
        canvas.present();
        clock.tick();
    }
}
<|endoftext|>


<commit_before>extern crate ratel;
extern crate iron;

use std::io::Read;
use iron::prelude::*;
use iron::status;

fn compile(source: String) -> String {
    let mut ast = match ratel::parser::parse(source) {
        Ok(ast)    => ast,
        Err(error) => return format!("{}", error),
    };

    let settings = ratel::transformer::Settings::target_es5();
    ratel::transformer::transform(&mut ast, settings);

    ratel::codegen::generate_code(&ast, false)
}

fn main() {
    fn handler(req: &mut Request) -> IronResult<Response> {
        let mut source = String::new();

        match req.body.read_to_string(&mut source) {
            Ok(_)  => {},
            Err(_) => return Ok(Response::with((status::BadRequest, ":(")))
        }

        Ok(Response::with((status::Ok, compile(source))))
    }

    let _server = Iron::new(handler).http("0.0.0.0:3000").unwrap();
    println!("On 3000");
}
<commit_msg>Returning 422 in case of errors, adding minify boolean<commit_after>extern crate ratel;
extern crate iron;

use std::io::Read;
use iron::prelude::*;
use iron::status;
use ratel::error::ParseError;

fn compile(source: String, minify: bool) -> Result<String, ParseError> {
    let mut ast = match ratel::parser::parse(source) {
        Ok(ast)    => ast,
        Err(error) => return Err(error),
    };

    let settings = ratel::transformer::Settings::target_es5();
    ratel::transformer::transform(&mut ast, settings);

    Ok(ratel::codegen::generate_code(&ast, minify))
}

fn main() {
    fn handler(req: &mut Request) -> IronResult<Response> {
        let mut source = String::new();

        match req.body.read_to_string(&mut source) {
            Ok(_)  => {},
            Err(_) => return Ok(Response::with((status::BadRequest, ":("))),
        }

        Ok(match compile(source, false) {
            Ok(source) => Response::with((status::Ok, source)),
            Err(error) => Response::with((status::UnprocessableEntity, format!("{:?}", error))),
        })
    }

    let _server = Iron::new(handler).http("0.0.0.0:3000").unwrap();
    println!("On 3000");
}
<|endoftext|>


<commit_before>#![deny(
    absolute_paths_not_starting_with_crate,
    anonymous_parameters,
    const_err,
    dead_code,
    deprecated,
    duplicate_associated_type_bindings,
    duplicate_macro_exports,
    ellipsis_inclusive_range_patterns,
    exceeding_bitshifts,
    explicit_outlives_requirements,
    illegal_floating_point_literal_pattern,
    improper_ctypes,
    incoherent_fundamental_impls,
    intra_doc_link_resolution_failure,
    invalid_type_param_default,
    irrefutable_let_patterns,
    keyword_idents,
    late_bound_lifetime_arguments,
    legacy_constructor_visibility,
    legacy_directory_ownership,
    macro_expanded_macro_exports_accessed_by_absolute_paths,
    missing_copy_implementations,
    missing_docs,
    missing_fragment_specifier,
    mutable_transmutes,
    no_mangle_const_items,
    no_mangle_generic_items,
    non_camel_case_types,
    non_shorthand_field_patterns,
    non_snake_case,
    non_upper_case_globals,
    overflowing_literals,
    parenthesized_params_in_types_and_modules,
    path_statements,
    patterns_in_fns_without_body,
    plugin_as_library,
    private_in_public,
    proc_macro_derive_resolution_fallback,
    pub_use_of_private_extern_crate,
    question_mark_macro_sep,
    safe_extern_statics,
    safe_packed_borrows,
    trivial_bounds,
    trivial_casts,
    trivial_numeric_casts,
    type_alias_bounds,
    tyvar_behind_raw_pointer,
    unconditional_recursion,
    unions_with_drop_fields,
    unknown_crate_types,
    unnameable_test_items,
    unreachable_code,
    unreachable_patterns,
    unreachable_pub,
    unsafe_code,
    unstable_name_collisions,
    unused_allocation,
    unused_assignments,
    unused_attributes,
    unused_comparisons,
    unused_doc_comments,
    unused_extern_crates,
    unused_features,
    unused_import_braces,
    unused_imports,
    unused_labels,
    unused_lifetimes,
    unused_macros,
    unused_must_use,
    unused_mut,
    unused_parens,
    unused_qualifications,
    unused_unsafe,
    unused_variables,
    where_clauses_object_safety,
    while_true
)]
#![warn(macro_use_extern_crate, unknown_lints)]
#![allow(
    bare_trait_objects,
    box_pointers,
    elided_lifetimes_in_paths,
    missing_doc_code_examples,
    missing_debug_implementations,
    single_use_lifetimes,
    stable_features,
    unstable_features,
    unused_results,
    variant_size_differences,
    warnings,
    renamed_and_removed_lints
)]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![feature(crate_in_paths)]

//! # cargo-make
//!
//! Rust task runner and build tool.

//! The cargo-make task runner enables to define and configure sets of tasks and run them as a flow.

//! A task is a command or a script to execute.

//! Tasks can have dependencies which are also tasks that will be executed before the task itself.

//! With a simple toml based configuration file, you can define a multi platform build script that can run build, test,
//! documentation generation, bench tests execution, security validations and more by running a single command.
//!
//! ## Installation
//! In order to install, just run the following command
//!
//! ```sh
//! cargo install cargo-make
//! ```
//!
//! This will install cargo-make in your ~/.cargo/bin.

//! Make sure to add ~/.cargo/bin directory to your PATH variable.
//!
//! # Contributing
//! See [contributing guide](https://github.com/sagiegurari/simple_redis/blob/master/.github/CONTRIBUTING.md)
//!
//! # License
//! Developed by Sagie Gur-Ari and licensed under the
//! [Apache 2](https://github.com/sagiegurari/simple_redis/blob/master/LICENSE) open source license.
//!

extern crate ci_info;
extern crate clap;
extern crate dirs;
extern crate fern;
extern crate glob;
extern crate indexmap;
#[macro_use]
extern crate log;
extern crate rand;
extern crate run_script;
extern crate rust_info;
extern crate semver;
#[macro_use]
extern crate serde_derive;
extern crate shell2batch;
extern crate toml;

// make types public for docs
pub mod types;

mod cache;
mod cli;
mod command;
mod condition;
mod config;
mod descriptor;
mod environment;
mod installer;
mod legacy;
mod logger;
mod runner;
mod scriptengine;
mod storage;
mod version;

#[cfg(test)]
#[path = "./main_test.rs"]
mod main_test;

#[cfg(test)]
#[path = "./test.rs"]
mod test;

fn main() {
    cli::run_cli();
}
<commit_msg>revert compiler feature flags #126<commit_after>#![deny(
    absolute_paths_not_starting_with_crate,
    anonymous_parameters,
    const_err,
    dead_code,
    deprecated,
    duplicate_associated_type_bindings,
    duplicate_macro_exports,
    ellipsis_inclusive_range_patterns,
    exceeding_bitshifts,
    explicit_outlives_requirements,
    illegal_floating_point_literal_pattern,
    improper_ctypes,
    incoherent_fundamental_impls,
    intra_doc_link_resolution_failure,
    invalid_type_param_default,
    irrefutable_let_patterns,
    keyword_idents,
    late_bound_lifetime_arguments,
    legacy_constructor_visibility,
    legacy_directory_ownership,
    macro_expanded_macro_exports_accessed_by_absolute_paths,
    missing_copy_implementations,
    missing_docs,
    missing_fragment_specifier,
    mutable_transmutes,
    no_mangle_const_items,
    no_mangle_generic_items,
    non_camel_case_types,
    non_shorthand_field_patterns,
    non_snake_case,
    non_upper_case_globals,
    overflowing_literals,
    parenthesized_params_in_types_and_modules,
    path_statements,
    patterns_in_fns_without_body,
    plugin_as_library,
    private_in_public,
    proc_macro_derive_resolution_fallback,
    pub_use_of_private_extern_crate,
    question_mark_macro_sep,
    safe_extern_statics,
    safe_packed_borrows,
    stable_features,
    trivial_bounds,
    trivial_casts,
    trivial_numeric_casts,
    type_alias_bounds,
    tyvar_behind_raw_pointer,
    unconditional_recursion,
    unions_with_drop_fields,
    unknown_crate_types,
    unnameable_test_items,
    unreachable_code,
    unreachable_patterns,
    unreachable_pub,
    unsafe_code,
    unstable_features,
    unstable_name_collisions,
    unused_allocation,
    unused_assignments,
    unused_attributes,
    unused_comparisons,
    unused_doc_comments,
    unused_extern_crates,
    unused_features,
    unused_import_braces,
    unused_imports,
    unused_labels,
    unused_lifetimes,
    unused_macros,
    unused_must_use,
    unused_mut,
    unused_parens,
    unused_qualifications,
    unused_unsafe,
    unused_variables,
    where_clauses_object_safety,
    while_true
)]
#![warn(macro_use_extern_crate, unknown_lints)]
#![allow(
    bare_trait_objects,
    box_pointers,
    elided_lifetimes_in_paths,
    missing_doc_code_examples,
    missing_debug_implementations,
    single_use_lifetimes,
    unused_results,
    variant_size_differences,
    warnings,
    renamed_and_removed_lints
)]
#![cfg_attr(feature = "clippy", feature(plugin))]

//! # cargo-make
//!
//! Rust task runner and build tool.

//! The cargo-make task runner enables to define and configure sets of tasks and run them as a flow.

//! A task is a command or a script to execute.

//! Tasks can have dependencies which are also tasks that will be executed before the task itself.

//! With a simple toml based configuration file, you can define a multi platform build script that can run build, test,
//! documentation generation, bench tests execution, security validations and more by running a single command.
//!
//! ## Installation
//! In order to install, just run the following command
//!
//! ```sh
//! cargo install cargo-make
//! ```
//!
//! This will install cargo-make in your ~/.cargo/bin.

//! Make sure to add ~/.cargo/bin directory to your PATH variable.
//!
//! # Contributing
//! See [contributing guide](https://github.com/sagiegurari/simple_redis/blob/master/.github/CONTRIBUTING.md)
//!
//! # License
//! Developed by Sagie Gur-Ari and licensed under the
//! [Apache 2](https://github.com/sagiegurari/simple_redis/blob/master/LICENSE) open source license.
//!

extern crate ci_info;
extern crate clap;
extern crate dirs;
extern crate fern;
extern crate glob;
extern crate indexmap;
#[macro_use]
extern crate log;
extern crate rand;
extern crate run_script;
extern crate rust_info;
extern crate semver;
#[macro_use]
extern crate serde_derive;
extern crate shell2batch;
extern crate toml;

// make types public for docs
pub mod types;

mod cache;
mod cli;
mod command;
mod condition;
mod config;
mod descriptor;
mod environment;
mod installer;
mod legacy;
mod logger;
mod runner;
mod scriptengine;
mod storage;
mod version;

#[cfg(test)]
#[path = "./main_test.rs"]
mod main_test;

#[cfg(test)]
#[path = "./test.rs"]
mod test;

fn main() {
    cli::run_cli();
}
<|endoftext|>


<commit_before>extern crate image;

use std::path::Path;
use image::{GenericImage, Rgba};

fn main() {
    let img = image::open(&Path::new("small.png")).unwrap();
    let mut pallete: Vec<Rgba<u8>> = Vec::new();

    let (width, height) = img.dimensions();

    for pixel in img.pixels() {
        let (_,_,pix) = pixel;
        if is_unique(&mut pallete, &pix) {
            println!("pixel: {:?}", pixel);
            //println!("UNIQUE");
            pallete.push(pix.clone());
        }
    }

    println!("color: {:?}", img.color());

    println!("width: {:?}, height: {:?}", width, height);
    println!("number of total pixels:  {}", width * height);
    println!("number of unique pixels: {}", pallete.len());
}

fn is_unique(pallete: &mut Vec<Rgba<u8>>, pixel: &Rgba<u8>) -> bool {
    let mut does_exist: bool = false;
    for pix in pallete.iter() {
        if pix == pixel {
            does_exist = true;
        }
    }
    !does_exist
}
<commit_msg>Generating color palette from an image<commit_after>extern crate image;

use std::path::Path;
use image::{GenericImage, ImageBuffer, Rgba};

fn main() {
    let img = image::open(&Path::new("small.png")).unwrap();
    let mut palette: Vec<Rgba<u8>> = Vec::new();

    let (width, height) = img.dimensions();

    for pixel in img.pixels() {
        let (_,_,pix) = pixel;
        if is_unique(&mut palette, &pix) {
            println!("pixel: {:?}", pixel);
            palette.push(pix.clone());
        }
    }

    gen_palette(&mut palette, 100, 100);

    println!("color: {:?}", img.color());
    println!("width: {:?}, height: {:?}", width, height);
    println!("number of total pixels:  {}", width * height);
}

fn is_unique(palette: &mut Vec<Rgba<u8>>, pixel: &Rgba<u8>) -> bool {
    let mut does_exist: bool = false;
    for pix in palette.iter() {
        if pix == pixel {
            does_exist = true;
        }
    }
    !does_exist
}

fn gen_palette(palette: &mut Vec<Rgba<u8>>, width: u32, height: u32) {
    let mut new_img = ImageBuffer::new(width, height);

    for y in 0..height {
        for x in 0..width {
            match palette.pop() {
                Some(s) => new_img.put_pixel(x, y, s),
                _ => continue
            }
        }
    }

    let _ = new_img.save(&Path::new("small_palette.png"));
}
<|endoftext|>


<commit_before>fn main() {
    let home = std::env::home_dir().unwrap();
    let mut sbt_jar = std::path::PathBuf::from(home);
    sbt_jar.push(".sbt/launchers/0.13.13/sbt-launch.jar");
    let sbt_jar = sbt_jar;
    use std::os::unix::process::CommandExt;
    let err = std::process::Command::new("java")
        .args(&["-Xms512m", "-Xmx1536m", "-Xss2m"])
        .args(&[&"-jar".as_ref(), &sbt_jar.as_os_str()])
        .arg("shell")
        .exec();
    println!("error: {}", err);
    if let Some(err) = err.raw_os_error() {
        std::process::exit(err);
    }
    std::process::exit(-1)
}
<commit_msg>Define arg groups & extract exec_runner<commit_after>use std::ffi::{OsStr, OsString};

fn exec_runner<S: AsRef<OsStr>>(args: &[S]) {
    use std::os::unix::process::CommandExt;
    let err = std::process::Command::new(&args[0]).args(&args[1..]).exec();
    println!("error: {}", err);
    if let Some(err) = err.raw_os_error() {
        std::process::exit(err);
    }
    std::process::exit(-1)
}

fn main() {
    let home = std::env::home_dir().unwrap();

    let mut sbt_jar = std::path::PathBuf::from(home);
    sbt_jar.push(".sbt/launchers/0.13.13/sbt-launch.jar");
    let sbt_jar = sbt_jar;

    let extra_jvm_opts = [OsStr::new("-Xms512m").to_os_string(),
                          OsStr::new("-Xmx1536m").to_os_string(),
                          OsStr::new("-Xss2m").to_os_string()];
    let java_args: [OsString; 0] = [];
    let sbt_commands: [OsString; 0] = [];
    let residual_args: [OsString; 0] = [];

    let mut exec_args: Vec<OsString> = Vec::new();
    exec_args.push(OsStr::new("java").to_os_string());
    exec_args.extend_from_slice(&extra_jvm_opts);
    exec_args.extend_from_slice(&java_args);
    exec_args.extend_from_slice(&[OsStr::new("-jar").to_os_string(), sbt_jar.into_os_string()]);
    exec_args.push(OsStr::new("shell").to_os_string());
    exec_args.extend_from_slice(&sbt_commands);
    exec_args.extend_from_slice(&residual_args);
    let exec_args = exec_args;

    exec_runner(&exec_args)
}
<|endoftext|>


<commit_before>mod frontmatter;
mod post;
use post::Post;

use std::path::{Path, PathBuf};

fn load_posts<P: AsRef<Path>>(src: P) -> Result<Vec<Post>, Box<dyn std::error::Error>> {
    let mut posts: Vec<Post> = Vec::default();

    for entry in src.as_ref().read_dir()? {
        let entry = entry?;
        let path = entry.path();
        if let Some("md") = path.extension().map(std::ffi::OsStr::to_str).flatten() {
            let name = path.file_stem().map(std::ffi::OsStr::to_str).flatten();
            if name.is_none() { continue; }
            match Post::load(&path) {
                Ok(Some(p)) => posts.push(p),
                Ok(None) => (),
                Err(e) => eprintln!("skipping `{}` as it failed to parse: {:?}", path.display(), e),
            };
        }
    }

    posts.sort_by(|a, b| b.front.date.cmp(&a.front.date));
    Ok(posts)
}

fn main() {
    use rayon::prelude::*;

    let outdir: PathBuf = PathBuf::from("docs").join("posts");
    std::fs::create_dir_all(&outdir).expect("can create docs/posts/ folder");

    let posts = load_posts("posts").expect("can load posts from posts/ folder");
    println!("Found {} posts, rendering them...", posts.len());
    posts
        .par_iter()
        .for_each(|post| {
            print!("  Rendering `{}`...", post.front.title);
            use std::io::Write;
            std::io::stdout().flush().expect("can flush stdout");

            let html = match post.render() {
                Ok(h) => h,
                Err(e) => {
                    eprintln!(" failed: {:?}", e);
                    return;
                }
            };
            let outdir = outdir.join(&post.front.slug);
            std::fs::create_dir_all(&outdir).expect("can create dir for post");
            let outfile = outdir.join("index.html");
            std::fs::write(outfile, html).expect("can write post to index.html file");

            println!(" done!");
        });

    println!("Copying assets...");
    let outdir = PathBuf::from("docs");
    let mut paths: Vec<PathBuf> = Vec::default();
    for entry in ignore::Walk::new("assets") {
        let entry = entry.expect("can get path entry");
        if let Some(t) = entry.file_type() {
            if t.is_file() {
                if let Some("md") = entry.path().extension().map(std::ffi::OsStr::to_str).flatten() {
                    // ignore markdown files
                }
                else {
                    // we found an asset to copy!
                    paths.push(entry.path().to_owned());
                }
            }
        }
    }
    paths
        .par_iter()
        .for_each(|path| {
            let dest_path: PathBuf = outdir.join(path.iter().skip(1).map(PathBuf::from).collect::<PathBuf>());
            if let Some(parent) = dest_path.parent() {
                if !parent.exists() {
                    std::fs::create_dir_all(parent).expect("can create directory");
                }
            }
            std::fs::copy(path, &dest_path).expect("can copy file");
        });
}
<commit_msg>tidied up error reporting for rendering<commit_after>mod frontmatter;
mod post;
use post::Post;

use std::path::{Path, PathBuf};

fn load_posts<P: AsRef<Path>>(src: P) -> Result<Vec<Post>, Box<dyn std::error::Error>> {
    let mut posts: Vec<Post> = Vec::default();

    for entry in src.as_ref().read_dir()? {
        let entry = entry?;
        let path = entry.path();
        if let Some("md") = path.extension().map(std::ffi::OsStr::to_str).flatten() {
            let name = path.file_stem().map(std::ffi::OsStr::to_str).flatten();
            if name.is_none() { continue; }
            match Post::load(&path) {
                Ok(Some(p)) => posts.push(p),
                Ok(None) => (),
                Err(e) => eprintln!("skipping `{}` as it failed to parse: {:?}", path.display(), e),
            };
        }
    }

    posts.sort_by(|a, b| b.front.date.cmp(&a.front.date));
    Ok(posts)
}

fn main() {
    use rayon::prelude::*;

    let outdir: PathBuf = PathBuf::from("docs").join("posts");
    std::fs::create_dir_all(&outdir).expect("can create docs/posts/ folder");

    let posts = load_posts("posts").expect("can load posts from posts/ folder");
    println!("Found {} posts, rendering them...", posts.len());
    let errors: Vec<String> = posts
        .par_iter()
        .filter_map(|post| {
            let html = match post.render() {
                Ok(h) => h,
                Err(e) => {
                    return Some(format!("failed to render `{}`: {:?}", post.source.display(), e));
                }
            };
            let outdir = outdir.join(&post.front.slug);
            std::fs::create_dir_all(&outdir).expect("can create dir for post");
            let outfile = outdir.join("index.html");
            std::fs::write(outfile, html).expect("can write post to index.html file");
            return None;
        })
        .collect();
    if errors.len() > 0 {
        eprintln!("Failed to render some posts:");
        for error in errors.iter() {
            eprintln!("  {}", error);
        }
    }
    else {
        println!("Posts rendered!");
    }

    println!("Copying assets...");
    let outdir = PathBuf::from("docs");
    let mut paths: Vec<PathBuf> = Vec::default();
    for entry in ignore::Walk::new("assets") {
        let entry = entry.expect("can get path entry");
        if let Some(t) = entry.file_type() {
            if t.is_file() {
                if let Some("md") = entry.path().extension().map(std::ffi::OsStr::to_str).flatten() {
                    // ignore markdown files
                }
                else {
                    // we found an asset to copy!
                    paths.push(entry.path().to_owned());
                }
            }
        }
    }
    paths
        .par_iter()
        .for_each(|path| {
            let dest_path: PathBuf = outdir.join(path.iter().skip(1).map(PathBuf::from).collect::<PathBuf>());
            if let Some(parent) = dest_path.parent() {
                if !parent.exists() {
                    std::fs::create_dir_all(parent).expect("can create directory");
                }
            }
            std::fs::copy(path, &dest_path).expect("can copy file");
        });
}
<|endoftext|>


<commit_before>#[macro_use] extern crate quick_error;

extern crate clap;
extern crate html5ever;
extern crate rsdocs2docset;
extern crate sqlite;
extern crate url;

use clap::Shell;
use html5ever::driver::{ParseOpts, parse_document};
use html5ever::rcdom::RcDom;
use html5ever::serialize::{SerializeOpts, serialize};
use html5ever::tendril::TendrilSink;
use std::ffi::OsStr;
use std::fs::{self, DirBuilder, DirEntry, File};
use std::io::{self,Write};
use std::path::Path;

use rsdocs2docset::dom::{manipulator, parser};

mod cli;

type Result = std::result::Result<(), RsDoc2DocsetError>;

quick_error! {
    #[derive(Debug)]
    pub enum RsDoc2DocsetError {
        Io(err: std::io::Error) {
            from()
                cause(err)
                description(err.description())
        }
        Utf8(err: std::string::FromUtf8Error) {
            from()
                cause(err)
                description(err.description())
        }
        Sqlite(err: sqlite::Error) {
            from()
                cause(err)
                description(err.description())
        }
    }
}

fn main() {
    let mut app = cli::build();
    let args = app.clone().get_matches();

    if args.is_present("bash-completion-code") {
        app.gen_completions_to(env!("CARGO_PKG_NAME"), Shell::Bash, &mut io::stdout());
        return
    }

    match (args.value_of("indir"), args.value_of("name")) {
        (Some(indir), Some(name)) => {
            create_docset(indir, name).expect("error creating docset");
            println!("\n{}.docset successfully created!", name)
        }
        (_, _) => {
            let _ = app.print_help();
            println!();
            std::process::exit(1);
        }
    }
}

fn create_docset(indir: &str, name: &str) -> Result {
    let db_filename = format!("{}.docset/Contents/Resources/docSet.dsidx", name);
    let db_path = Path::new(&db_filename);

    try!(write_file(Path::new(format!("{}.docset/Contents/Info.plist", name).as_str()), format!(include_str!("Info.plist.tmpl"), name = name, identifier = name.replace(" ", "_").replace("-", "_").to_lowercase()).as_ref()));
    try!(write_file(Path::new(format!("{}.docset/icon.png", name).as_str()), include_bytes!("icon.png")));
    try!(write_file(Path::new(format!("{}.docset/icon@2x.png", name).as_str()), include_bytes!("icon@2x.png")));

    try!(mkdir_parent_p(db_path));
    try!(sqlite::open(db_path).and_then(|c| c.execute("CREATE TABLE searchIndex(id INTEGER PRIMARY KEY, name TEXT, type TEXT, path TEXT);")));

    try!(docset_from_rs_doc_tree(&Path::new(indir), format!("{}.docset/Contents/Resources/Documents/", name).as_str(), Path::new(db_path)));

    Ok(())
}

// recursivly creates the parent dir of `path`
fn mkdir_parent_p(path: &Path) -> Result {
    let dir = path.parent().expect(format!("can't create parent dir of {}", path.to_str().unwrap()).as_str());

    try!(DirBuilder::new()
         .recursive(true)
         .create(dir));
    Ok(())
}

fn write_file(path: &Path, data: &[u8]) -> Result {
    try!(mkdir_parent_p(path));
    try!(File::create(path).and_then(|mut f| f.write_all(data)));
    Ok(())
}

fn docset_from_rs_doc_tree(source_dir: &Path, out_dir: &str, db_path: &Path) -> Result {
    if !source_dir.exists() {
        return Err(io::Error::new(io::ErrorKind::NotFound, format!("{} does not exist", source_dir.to_str().unwrap())).into());
    }

    if source_dir.is_dir() {
        for entry in fs::read_dir(source_dir)? {
            let entry = entry?;
            if entry.path().is_dir() {
                try!(docset_from_rs_doc_tree(&entry.path(), &out_dir, &db_path));
            } else {
                try!(annotate_file(&entry, &out_dir, &db_path));
            }
        }
    }
    Ok(())
}

fn annotate_file(in_file: &DirEntry, output_prefix: &str, db_path: &Path) -> Result {
    let out_file = Path::new(output_prefix).join(in_file.path());

    if in_file.path().extension() == Some(OsStr::new("html")) {
        let mut dom = parse_document(RcDom::default(), ParseOpts::default())
            .from_utf8()
            .read_from( &mut File::open(&in_file.path())? )?;

        let entries = parser::find_entry_elements(&mut dom);
        for entry in entries.iter().filter_map(|x| x.as_ref()).filter(|x| !x.is_section) {
            //println!("{:70} | {}", in_file.path().display(), entry);

            let sql_cmd = format!("INSERT OR IGNORE INTO searchIndex(name, type, path) VALUES (\"{}\", \"{}\", \"{}#{}\");", entry.entry_name, entry.entry_type, in_file.path().to_str().unwrap(), entry.anchor_name);
            try!(sqlite::open(db_path).and_then(|c| c.execute(&sql_cmd)))
        }
        manipulator::add_dash_links(&mut dom, &entries);

        let mut bytes = vec![];
        try!(serialize(&mut bytes, &dom.document, SerializeOpts::default()));
        try!(write_file(&out_file, bytes.as_ref()));

        print!("o"); io::stdout().flush().expect("error flushing stdout?!");
    } else {
        try!(mkdir_parent_p(&out_file));
        try!(fs::copy(in_file.path(), &out_file));
        //println!("{:70} | ", in_file.path().display());
        print!("."); io::stdout().flush().expect("error flushing stdout?!");
    }

    Ok(())
}
<commit_msg>Some cosmetics<commit_after>#[macro_use] extern crate quick_error;

extern crate clap;
extern crate html5ever;
extern crate rsdocs2docset;
extern crate sqlite;
extern crate url;

use clap::Shell;
use html5ever::driver::{ParseOpts, parse_document};
use html5ever::rcdom::RcDom;
use html5ever::serialize::{SerializeOpts, serialize};
use html5ever::tendril::TendrilSink;
use std::ffi::OsStr;
use std::fs::{self, DirBuilder, DirEntry, File};
use std::io::{self,Write};
use std::path::Path;

use rsdocs2docset::dom::{manipulator, parser};

mod cli;

type Result = std::result::Result<(), RsDoc2DocsetError>;

quick_error! {
    #[derive(Debug)]
    pub enum RsDoc2DocsetError {
        Io(err: std::io::Error) {
            from()
                cause(err)
                description(err.description())
        }
        Utf8(err: std::string::FromUtf8Error) {
            from()
                cause(err)
                description(err.description())
        }
        Sqlite(err: sqlite::Error) {
            from()
                cause(err)
                description(err.description())
        }
    }
}

fn main() {
    let mut app = cli::build();
    let args = app.clone().get_matches();

    if args.is_present("bash-completion-code") {
        app.gen_completions_to(env!("CARGO_PKG_NAME"), Shell::Bash, &mut io::stdout());
        return
    }

    match (args.value_of("indir"), args.value_of("name")) {
        (Some(indir), Some(name)) => {
            create_docset(indir, name).expect("error creating docset");
            println!("\n{}.docset successfully created!", name)
        }
        (_, _) => {
            let _ = app.print_help();
            println!();
            std::process::exit(1);
        }
    }
}

fn create_docset(indir: &str, name: &str) -> Result {
    let db_filename = format!("{}.docset/Contents/Resources/docSet.dsidx", name);
    let db_path = Path::new(&db_filename);

    try!(write_file(Path::new(format!("{}.docset/Contents/Info.plist", name).as_str()), format!(include_str!("Info.plist.tmpl"), name = name, identifier = name.replace(" ", "_").replace("-", "_").to_lowercase()).as_ref()));
    try!(write_file(Path::new(format!("{}.docset/icon.png", name).as_str()), include_bytes!("icon.png")));
    try!(write_file(Path::new(format!("{}.docset/icon@2x.png", name).as_str()), include_bytes!("icon@2x.png")));

    try!(mkdir_parent_p(db_path));
    try!(sqlite::open(db_path).and_then(|c| c.execute("CREATE TABLE searchIndex(id INTEGER PRIMARY KEY, name TEXT, type TEXT, path TEXT);")));

    try!(docset_from_rs_doc_tree(&Path::new(indir), format!("{}.docset/Contents/Resources/Documents/", name).as_str(), Path::new(db_path)));

    Ok(())
}

fn write_file(path: &Path, data: &[u8]) -> Result {
    try!(mkdir_parent_p(path));
    try!(File::create(path).and_then(|mut f| f.write_all(data)));
    Ok(())
}

// recursivly creates the parent dir of `path`
fn mkdir_parent_p(path: &Path) -> Result {
    let dir = path.parent().expect(format!("can't create parent dir of {}", path.to_str().unwrap()).as_str());

    try!(DirBuilder::new().recursive(true).create(dir));
    Ok(())
}

fn docset_from_rs_doc_tree(source_dir: &Path, out_dir: &str, db_path: &Path) -> Result {
    if !source_dir.exists() {
        return Err(io::Error::new(io::ErrorKind::NotFound, format!("{} does not exist", source_dir.to_str().unwrap())).into());
    }

    if source_dir.is_dir() {
        for entry in fs::read_dir(source_dir)?.filter_map(|e| e.ok()) {
            if entry.path().is_dir() {
                try!(docset_from_rs_doc_tree(&entry.path(), &out_dir, &db_path));
            } else {
                try!(add_file_to_docset(&entry, &out_dir, &db_path));
            }
        }
    }
    Ok(())
}

fn add_file_to_docset(in_file: &DirEntry, output_prefix: &str, db_path: &Path) -> Result {
    let out_file = Path::new(output_prefix).join(in_file.path());

    if in_file.path().extension() == Some(OsStr::new("html")) {
        let mut dom = parse_document(RcDom::default(), ParseOpts::default())
            .from_utf8()
            .read_from( &mut File::open(&in_file.path())? )?;

        let entries = parser::find_entry_elements(&mut dom);
        for entry in entries.iter().filter_map(|x| x.as_ref()).filter(|x| !x.is_section) {
            //println!("{:70} | {}", in_file.path().display(), entry);

            let sql_cmd = format!("INSERT OR IGNORE INTO searchIndex(name, type, path) VALUES (\"{}\", \"{}\", \"{}#{}\");", entry.entry_name, entry.entry_type, in_file.path().to_str().unwrap(), entry.anchor_name);
            try!(sqlite::open(db_path).and_then(|c| c.execute(&sql_cmd)))
        }
        manipulator::add_dash_links(&mut dom, &entries);

        let mut bytes = vec![];
        try!(serialize(&mut bytes, &dom.document, SerializeOpts::default()));
        try!(write_file(&out_file, bytes.as_ref()));

        print!("o"); io::stdout().flush().expect("error flushing stdout?!");
    } else {
        try!(mkdir_parent_p(&out_file));
        try!(fs::copy(in_file.path(), &out_file));
        //println!("{:70} | ", in_file.path().display());
        print!("."); io::stdout().flush().expect("error flushing stdout?!");
    }

    Ok(())
}
<|endoftext|>


<commit_before>extern crate image;
extern crate tray_rust;

use std::iter;
use std::vec::Vec;
use std::sync::{Arc, TaskPool};
use std::sync::mpsc;
use std::sync::mpsc::{Sender, Receiver};
use std::time::duration::Duration;

use tray_rust::film;
use tray_rust::geometry::Geometry;
use tray_rust::sampler;
use tray_rust::sampler::{Sampler};
use tray_rust::scene;
use tray_rust::integrator::Integrator;

static WIDTH: usize = 800;
static HEIGHT: usize = 600;

/// Threads are each sent a sender end of the channel that is
/// read from by the render target thread which then saves the
/// values recieved to the render target
fn thread_work(tx: Sender<(f32, f32, film::Colorf)>, queue: Arc<sampler::BlockQueue>,
               scene: Arc<scene::Scene>) {
    let mut sampler = sampler::Uniform::new(queue.block_dim());
    let mut samples = Vec::with_capacity(sampler.max_spp());
    let mut sample_pos = Vec::with_capacity(sampler.max_spp());
    // Grab a block from the queue and start working on it, submitting samples
    // to the render target thread after each pixel
    for b in queue.iter() {
        sampler.select_block(&b);
        while sampler.has_samples() {
            // Get samples for a pixel and render them
            sampler.get_samples(&mut sample_pos);
            for px in sample_pos.iter() {
                let mut ray = scene.camera.generate_ray(px);
                if let Some(hit) = scene.intersect(&mut ray) {
                    let c = scene.integrator.illumination(&*scene, &ray, &hit);
                    samples.push((px.0, px.1, c));
                }
            }
            for s in samples.iter() {
                if let Err(e) = tx.send(*s) {
                    println!("Worker thread exiting with send error {:?}", e);
                    return;
                }
            }
            samples.clear();
        }
    }
}

/// Spawn `n` worker threads to render the scene in parallel. Returns the receive end
/// of the channel where the threads will write their samples so that the receiver
/// can write these samples to the render target
fn spawn_workers(pool: &TaskPool, n: usize, scene: Arc<scene::Scene>) -> Receiver<(f32, f32, film::Colorf)> {
    let (tx, rx) = mpsc::channel();
    let block_queue = Arc::new(sampler::BlockQueue::new((WIDTH as u32, HEIGHT as u32), (8, 8)));
    // TODO: the .. operator precedence is very low so we need this paren here at the moment
    // once (hopefully) it's raised we can remove the parens
    for _ in (0..n) {
        let q = block_queue.clone();
        let t = tx.clone();
        let s = scene.clone();
        pool.execute(move || {
            thread_work(t, q, s);
        });
    }
    rx
}

/// Render in the scene in parallel to the render target
fn render_parallel(rt: &mut film::RenderTarget){
    let scene = Arc::new(scene::Scene::new(WIDTH, HEIGHT));
    let n = 8;
    let pool = TaskPool::new(n);
    let rx = spawn_workers(&pool, n, scene);
    for m in rx.iter() {
        rt.write(m.0, m.1, &m.2);
    }
}

fn main() {
    let mut rt = film::RenderTarget::new(WIDTH, HEIGHT);
    let d = Duration::span(|| render_parallel(&mut rt));
    println!("Rendering took {}ms", d.num_milliseconds());
    let img = rt.get_render();
    image::save_buffer(&Path::new("out.png"), &img[], WIDTH as u32, HEIGHT as u32, image::RGB(8));
}

<commit_msg>Better name for sample we're taking, px is a bad choice<commit_after>extern crate image;
extern crate tray_rust;

use std::iter;
use std::vec::Vec;
use std::sync::{Arc, TaskPool};
use std::sync::mpsc;
use std::sync::mpsc::{Sender, Receiver};
use std::time::duration::Duration;

use tray_rust::film;
use tray_rust::geometry::Geometry;
use tray_rust::sampler;
use tray_rust::sampler::{Sampler};
use tray_rust::scene;
use tray_rust::integrator::Integrator;

static WIDTH: usize = 800;
static HEIGHT: usize = 600;

/// Threads are each sent a sender end of the channel that is
/// read from by the render target thread which then saves the
/// values recieved to the render target
fn thread_work(tx: Sender<(f32, f32, film::Colorf)>, queue: Arc<sampler::BlockQueue>,
               scene: Arc<scene::Scene>) {
    let mut sampler = sampler::Uniform::new(queue.block_dim());
    let mut samples = Vec::with_capacity(sampler.max_spp());
    let mut sample_pos = Vec::with_capacity(sampler.max_spp());
    // Grab a block from the queue and start working on it, submitting samples
    // to the render target thread after each pixel
    for b in queue.iter() {
        sampler.select_block(&b);
        while sampler.has_samples() {
            // Get samples for a pixel and render them
            sampler.get_samples(&mut sample_pos);
            for s in sample_pos.iter() {
                let mut ray = scene.camera.generate_ray(s);
                if let Some(hit) = scene.intersect(&mut ray) {
                    let c = scene.integrator.illumination(&*scene, &ray, &hit);
                    samples.push((s.0, s.1, c));
                }
            }
            for s in samples.iter() {
                if let Err(e) = tx.send(*s) {
                    println!("Worker thread exiting with send error {:?}", e);
                    return;
                }
            }
            samples.clear();
        }
    }
}

/// Spawn `n` worker threads to render the scene in parallel. Returns the receive end
/// of the channel where the threads will write their samples so that the receiver
/// can write these samples to the render target
fn spawn_workers(pool: &TaskPool, n: usize, scene: Arc<scene::Scene>) -> Receiver<(f32, f32, film::Colorf)> {
    let (tx, rx) = mpsc::channel();
    let block_queue = Arc::new(sampler::BlockQueue::new((WIDTH as u32, HEIGHT as u32), (8, 8)));
    // TODO: the .. operator precedence is very low so we need this paren here at the moment
    // once (hopefully) it's raised we can remove the parens
    for _ in (0..n) {
        let q = block_queue.clone();
        let t = tx.clone();
        let s = scene.clone();
        pool.execute(move || {
            thread_work(t, q, s);
        });
    }
    rx
}

/// Render in the scene in parallel to the render target
fn render_parallel(rt: &mut film::RenderTarget){
    let scene = Arc::new(scene::Scene::new(WIDTH, HEIGHT));
    let n = 8;
    let pool = TaskPool::new(n);
    let rx = spawn_workers(&pool, n, scene);
    for m in rx.iter() {
        rt.write(m.0, m.1, &m.2);
    }
}

fn main() {
    let mut rt = film::RenderTarget::new(WIDTH, HEIGHT);
    let d = Duration::span(|| render_parallel(&mut rt));
    println!("Rendering took {}ms", d.num_milliseconds());
    let img = rt.get_render();
    image::save_buffer(&Path::new("out.png"), &img[], WIDTH as u32, HEIGHT as u32, image::RGB(8));
}

<|endoftext|>