<commit_before>#![crate_name = "uu_unexpand"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Virgile Andreani <virgile.andreani@anbuco.fr>
 * (c) kwantam <kwantam@gmail.com>
 *     20150428 updated to work with both UTF-8 and non-UTF-8 encodings
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;
extern crate unicode_width;

#[macro_use]
extern crate uucore;

use std::fs::File;
use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Read, Stdout, Write};
use std::str::from_utf8;
use unicode_width::UnicodeWidthChar;

static NAME: &str = "unexpand";
static VERSION: &str = env!("CARGO_PKG_VERSION");

const DEFAULT_TABSTOP: usize = 8;

fn tabstops_parse(s: String) -> Vec<usize> {
    let words = s.split(',').collect::<Vec<&str>>();

    let nums = words
        .into_iter()
        .map(|sn| {
            sn.parse()
                .unwrap_or_else(|_| crash!(1, "{}\n", "tab size contains invalid character(s)"))
        })
        .collect::<Vec<usize>>();

    if nums.iter().any(|&n| n == 0) {
        crash!(1, "{}\n", "tab size cannot be 0");
    }

    if let (false, _) = nums
        .iter()
        .fold((true, 0), |(acc, last), &n| (acc && last <= n, n))
    {
        crash!(1, "{}\n", "tab sizes must be ascending");
    }

    nums
}

struct Options {
    files: Vec<String>,
    tabstops: Vec<usize>,
    aflag: bool,
    uflag: bool,
}

impl Options {
    fn new(matches: getopts::Matches) -> Options {
        let tabstops = match matches.opt_str("t") {
            None => vec![DEFAULT_TABSTOP],
            Some(s) => tabstops_parse(s),
        };

        let aflag = (matches.opt_present("all") || matches.opt_present("tabs"))
            && !matches.opt_present("first-only");
        let uflag = !matches.opt_present("U");

        let files = if matches.free.is_empty() {
            vec!["-".to_owned()]
        } else {
            matches.free
        };

        Options {
            files,
            tabstops,
            aflag,
            uflag,
        }
    }
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = getopts::Options::new();

    opts.optflag(
        "a",
        "all",
        "convert all blanks, instead of just initial blanks",
    );
    opts.optflag(
        "",
        "first-only",
        "convert only leading sequences of blanks (overrides -a)",
    );
    opts.optopt(
        "t",
        "tabs",
        "have tabs N characters apart instead of 8 (enables -a)",
        "N",
    );
    opts.optopt(
        "t",
        "tabs",
        "use comma separated LIST of tab positions (enables -a)",
        "LIST",
    );
    opts.optflag(
        "U",
        "no-utf8",
        "interpret input file as 8-bit ASCII rather than UTF-8",
    );
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => crash!(1, "{}", f),
    };

    if matches.opt_present("help") {
        println!("{} {}\n", NAME, VERSION);
        println!("Usage: {} [OPTION]... [FILE]...\n", NAME);
        println!(
            "{}",
            opts.usage(
                "Convert blanks in each FILE to tabs, writing to standard output.\n\
                 With no FILE, or when FILE is -, read standard input."
            )
        );
        return 0;
    }

    if matches.opt_present("V") {
        println!("{} {}", NAME, VERSION);
        return 0;
    }

    unexpand(Options::new(matches));

    0
}

fn open(path: String) -> BufReader<Box<dyn Read + 'static>> {
    let file_buf;
    if path == "-" {
        BufReader::new(Box::new(stdin()) as Box<dyn Read>)
    } else {
        file_buf = match File::open(&path[..]) {
            Ok(a) => a,
            Err(e) => crash!(1, "{}: {}", &path[..], e),
        };
        BufReader::new(Box::new(file_buf) as Box<dyn Read>)
    }
}

fn next_tabstop(tabstops: &[usize], col: usize) -> Option<usize> {
    if tabstops.len() == 1 {
        Some(tabstops[0] - col % tabstops[0])
    } else {
        // find next larger tab
        match tabstops.iter().find(|&&t| t > col) {
            Some(t) => Some(t - col),
            None => None, // if there isn't one in the list, tab becomes a single space
        }
    }
}

fn write_tabs(
    output: &mut BufWriter<Stdout>,
    tabstops: &[usize],
    mut scol: usize,
    col: usize,
    prevtab: bool,
    init: bool,
    amode: bool,
) {
    // This conditional establishes the following:
    // We never turn a single space before a non-blank into
    // a tab, unless it's at the start of the line.
    let ai = init || amode;
    if (ai && !prevtab && col > scol + 1) || (col > scol && (init || ai && prevtab)) {
        while let Some(nts) = next_tabstop(tabstops, scol) {
            if col < scol + nts {
                break;
            }

            safe_unwrap!(output.write_all(b"\t"));
            scol += nts;
        }
    }

    while col > scol {
        safe_unwrap!(output.write_all(b" "));
        scol += 1;
    }
}

#[derive(PartialEq, Eq, Debug)]
enum CharType {
    Backspace,
    Space,
    Tab,
    Other,
}

fn unexpand(options: Options) {
    use self::CharType::*;

    let mut output = BufWriter::new(stdout());
    let ts = &options.tabstops[..];
    let mut buf = Vec::new();
    let lastcol = if ts.len() > 1 { *ts.last().unwrap() } else { 0 };

    for file in options.files.into_iter() {
        let mut fh = open(file);

        while match fh.read_until(b'\n', &mut buf) {
            Ok(s) => s > 0,
            Err(_) => !buf.is_empty(),
        } {
            let mut byte = 0; // offset into the buffer
            let mut col = 0; // the current column
            let mut scol = 0; // the start col for the current span, i.e., the already-printed width
            let mut init = true; // are we at the start of the line?
            let mut pctype = Other;

            while byte < buf.len() {
                // when we have a finite number of columns, never convert past the last column
                if lastcol > 0 && col >= lastcol {
                    write_tabs(&mut output, ts, scol, col, pctype == Tab, init, true);
                    safe_unwrap!(output.write_all(&buf[byte..]));
                    scol = col;
                    break;
                }

                let (ctype, cwidth, nbytes) = if options.uflag {
                    let nbytes = char::from(buf[byte]).len_utf8();

                    // figure out how big the next char is, if it's UTF-8
                    if byte + nbytes > buf.len() {
                        // make sure we don't overrun the buffer because of invalid UTF-8
                        (Other, 1, 1)
                    } else if let Ok(t) = from_utf8(&buf[byte..byte + nbytes]) {
                        // Now that we think it's UTF-8, figure out what kind of char it is
                        match t.chars().next() {
                            Some(' ') => (Space, 0, 1),
                            Some('\t') => (Tab, 0, 1),
                            Some('\x08') => (Backspace, 0, 1),
                            Some(c) => (Other, UnicodeWidthChar::width(c).unwrap_or(0), nbytes),
                            None => {
                                // invalid char snuck past the utf8_validation_iterator somehow???
                                (Other, 1, 1)
                            }
                        }
                    } else {
                        // otherwise, it's not valid
                        (Other, 1, 1) // implicit assumption: non-UTF8 char has display width 1
                    }
                } else {
                    (
                        match buf[byte] {
                            // always take exactly 1 byte in strict ASCII mode
                            0x20 => Space,
                            0x09 => Tab,
                            0x08 => Backspace,
                            _ => Other,
                        },
                        1,
                        1,
                    )
                };

                // now figure out how many columns this char takes up, and maybe print it
                let tabs_buffered = init || options.aflag;
                match ctype {
                    Space | Tab => {
                        // compute next col, but only write space or tab chars if not buffering
                        col += if ctype == Space {
                            1
                        } else {
                            next_tabstop(ts, col).unwrap_or(1)
                        };

                        if !tabs_buffered {
                            safe_unwrap!(output.write_all(&buf[byte..byte + nbytes]));
                            scol = col; // now printed up to this column
                        }
                    }
                    Other | Backspace => {
                        // always
                        write_tabs(
                            &mut output,
                            ts,
                            scol,
                            col,
                            pctype == Tab,
                            init,
                            options.aflag,
                        );
                        init = false; // no longer at the start of a line
                        col = if ctype == Other {
                            // use computed width
                            col + cwidth
                        } else if col > 0 {
                            // Backspace case, but only if col > 0
                            col - 1
                        } else {
                            0
                        };
                        safe_unwrap!(output.write_all(&buf[byte..byte + nbytes]));
                        scol = col; // we've now printed up to this column
                    }
                }

                byte += nbytes; // move on to next char
                pctype = ctype; // save the previous type
            }

            // write out anything remaining
            write_tabs(&mut output, ts, scol, col, pctype == Tab, init, true);
            safe_unwrap!(output.flush());
            buf.truncate(0); // clear out the buffer
        }
    }
    crash_if_err!(1, output.flush())
}
<commit_msg>fix clippy warning: extract function<commit_after>#![crate_name = "uu_unexpand"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Virgile Andreani <virgile.andreani@anbuco.fr>
 * (c) kwantam <kwantam@gmail.com>
 *     20150428 updated to work with both UTF-8 and non-UTF-8 encodings
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;
extern crate unicode_width;

#[macro_use]
extern crate uucore;

use std::fs::File;
use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Read, Stdout, Write};
use std::str::from_utf8;
use unicode_width::UnicodeWidthChar;

static NAME: &str = "unexpand";
static VERSION: &str = env!("CARGO_PKG_VERSION");

const DEFAULT_TABSTOP: usize = 8;

fn tabstops_parse(s: String) -> Vec<usize> {
    let words = s.split(',').collect::<Vec<&str>>();

    let nums = words
        .into_iter()
        .map(|sn| {
            sn.parse()
                .unwrap_or_else(|_| crash!(1, "{}\n", "tab size contains invalid character(s)"))
        })
        .collect::<Vec<usize>>();

    if nums.iter().any(|&n| n == 0) {
        crash!(1, "{}\n", "tab size cannot be 0");
    }

    if let (false, _) = nums
        .iter()
        .fold((true, 0), |(acc, last), &n| (acc && last <= n, n))
    {
        crash!(1, "{}\n", "tab sizes must be ascending");
    }

    nums
}

struct Options {
    files: Vec<String>,
    tabstops: Vec<usize>,
    aflag: bool,
    uflag: bool,
}

impl Options {
    fn new(matches: getopts::Matches) -> Options {
        let tabstops = match matches.opt_str("t") {
            None => vec![DEFAULT_TABSTOP],
            Some(s) => tabstops_parse(s),
        };

        let aflag = (matches.opt_present("all") || matches.opt_present("tabs"))
            && !matches.opt_present("first-only");
        let uflag = !matches.opt_present("U");

        let files = if matches.free.is_empty() {
            vec!["-".to_owned()]
        } else {
            matches.free
        };

        Options {
            files,
            tabstops,
            aflag,
            uflag,
        }
    }
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = getopts::Options::new();

    opts.optflag(
        "a",
        "all",
        "convert all blanks, instead of just initial blanks",
    );
    opts.optflag(
        "",
        "first-only",
        "convert only leading sequences of blanks (overrides -a)",
    );
    opts.optopt(
        "t",
        "tabs",
        "have tabs N characters apart instead of 8 (enables -a)",
        "N",
    );
    opts.optopt(
        "t",
        "tabs",
        "use comma separated LIST of tab positions (enables -a)",
        "LIST",
    );
    opts.optflag(
        "U",
        "no-utf8",
        "interpret input file as 8-bit ASCII rather than UTF-8",
    );
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => crash!(1, "{}", f),
    };

    if matches.opt_present("help") {
        println!("{} {}\n", NAME, VERSION);
        println!("Usage: {} [OPTION]... [FILE]...\n", NAME);
        println!(
            "{}",
            opts.usage(
                "Convert blanks in each FILE to tabs, writing to standard output.\n\
                 With no FILE, or when FILE is -, read standard input."
            )
        );
        return 0;
    }

    if matches.opt_present("V") {
        println!("{} {}", NAME, VERSION);
        return 0;
    }

    unexpand(Options::new(matches));

    0
}

fn open(path: String) -> BufReader<Box<dyn Read + 'static>> {
    let file_buf;
    if path == "-" {
        BufReader::new(Box::new(stdin()) as Box<dyn Read>)
    } else {
        file_buf = match File::open(&path[..]) {
            Ok(a) => a,
            Err(e) => crash!(1, "{}: {}", &path[..], e),
        };
        BufReader::new(Box::new(file_buf) as Box<dyn Read>)
    }
}

fn next_tabstop(tabstops: &[usize], col: usize) -> Option<usize> {
    if tabstops.len() == 1 {
        Some(tabstops[0] - col % tabstops[0])
    } else {
        // find next larger tab
        match tabstops.iter().find(|&&t| t > col) {
            Some(t) => Some(t - col),
            None => None, // if there isn't one in the list, tab becomes a single space
        }
    }
}

fn write_tabs(
    output: &mut BufWriter<Stdout>,
    tabstops: &[usize],
    mut scol: usize,
    col: usize,
    prevtab: bool,
    init: bool,
    amode: bool,
) {
    // This conditional establishes the following:
    // We never turn a single space before a non-blank into
    // a tab, unless it's at the start of the line.
    let ai = init || amode;
    if (ai && !prevtab && col > scol + 1) || (col > scol && (init || ai && prevtab)) {
        while let Some(nts) = next_tabstop(tabstops, scol) {
            if col < scol + nts {
                break;
            }

            safe_unwrap!(output.write_all(b"\t"));
            scol += nts;
        }
    }

    while col > scol {
        safe_unwrap!(output.write_all(b" "));
        scol += 1;
    }
}

#[derive(PartialEq, Eq, Debug)]
enum CharType {
    Backspace,
    Space,
    Tab,
    Other,
}

fn next_char_info(uflag: bool, buf: &[u8], byte: usize) -> (CharType, usize, usize) {
    let (ctype, cwidth, nbytes) = if uflag {
        let nbytes = char::from(buf[byte]).len_utf8();

        if byte + nbytes > buf.len() {
            // make sure we don't overrun the buffer because of invalid UTF-8
            (CharType::Other, 1, 1)
        } else if let Ok(t) = from_utf8(&buf[byte..byte + nbytes]) {
            // Now that we think it's UTF-8, figure out what kind of char it is
            match t.chars().next() {
                Some(' ') => (CharType::Space, 0, 1),
                Some('\t') => (CharType::Tab, 0, 1),
                Some('\x08') => (CharType::Backspace, 0, 1),
                Some(c) => (
                    CharType::Other,
                    UnicodeWidthChar::width(c).unwrap_or(0),
                    nbytes,
                ),
                None => {
                    // invalid char snuck past the utf8_validation_iterator somehow???
                    (CharType::Other, 1, 1)
                }
            }
        } else {
            // otherwise, it's not valid
            (CharType::Other, 1, 1) // implicit assumption: non-UTF8 char has display width 1
        }
    } else {
        (
            match buf[byte] {
                // always take exactly 1 byte in strict ASCII mode
                0x20 => CharType::Space,
                0x09 => CharType::Tab,
                0x08 => CharType::Backspace,
                _ => CharType::Other,
            },
            1,
            1,
        )
    };

    (ctype, cwidth, nbytes)
}

fn unexpand(options: Options) {
    let mut output = BufWriter::new(stdout());
    let ts = &options.tabstops[..];
    let mut buf = Vec::new();
    let lastcol = if ts.len() > 1 { *ts.last().unwrap() } else { 0 };

    for file in options.files.into_iter() {
        let mut fh = open(file);

        while match fh.read_until(b'\n', &mut buf) {
            Ok(s) => s > 0,
            Err(_) => !buf.is_empty(),
        } {
            let mut byte = 0; // offset into the buffer
            let mut col = 0; // the current column
            let mut scol = 0; // the start col for the current span, i.e., the already-printed width
            let mut init = true; // are we at the start of the line?
            let mut pctype = CharType::Other;

            while byte < buf.len() {
                // when we have a finite number of columns, never convert past the last column
                if lastcol > 0 && col >= lastcol {
                    write_tabs(
                        &mut output,
                        ts,
                        scol,
                        col,
                        pctype == CharType::Tab,
                        init,
                        true,
                    );
                    safe_unwrap!(output.write_all(&buf[byte..]));
                    scol = col;
                    break;
                }

                // figure out how big the next char is, if it's UTF-8
                let (ctype, cwidth, nbytes) = next_char_info(options.uflag, &buf, byte);

                // now figure out how many columns this char takes up, and maybe print it
                let tabs_buffered = init || options.aflag;
                match ctype {
                    CharType::Space | CharType::Tab => {
                        // compute next col, but only write space or tab chars if not buffering
                        col += if ctype == CharType::Space {
                            1
                        } else {
                            next_tabstop(ts, col).unwrap_or(1)
                        };

                        if !tabs_buffered {
                            safe_unwrap!(output.write_all(&buf[byte..byte + nbytes]));
                            scol = col; // now printed up to this column
                        }
                    }
                    CharType::Other | CharType::Backspace => {
                        // always
                        write_tabs(
                            &mut output,
                            ts,
                            scol,
                            col,
                            pctype == CharType::Tab,
                            init,
                            options.aflag,
                        );
                        init = false; // no longer at the start of a line
                        col = if ctype == CharType::Other {
                            // use computed width
                            col + cwidth
                        } else if col > 0 {
                            // Backspace case, but only if col > 0
                            col - 1
                        } else {
                            0
                        };
                        safe_unwrap!(output.write_all(&buf[byte..byte + nbytes]));
                        scol = col; // we've now printed up to this column
                    }
                }

                byte += nbytes; // move on to next char
                pctype = ctype; // save the previous type
            }

            // write out anything remaining
            write_tabs(
                &mut output,
                ts,
                scol,
                col,
                pctype == CharType::Tab,
                init,
                true,
            );
            safe_unwrap!(output.flush());
            buf.truncate(0); // clear out the buffer
        }
    }
    crash_if_err!(1, output.flush())
}
<|endoftext|>


<commit_before>use error::RuntimeError;

use sys::x11;
use sys::xcb;

pub struct LinuxApplication {
   pub x11_display_handler: X11DisplayHandler,
   pub connection_handler: ConnectionHandler,
}

impl LinuxApplication {
   pub fn new() -> Result<Self, RuntimeError> {
      let x11_display_handler = try!(X11DisplayHandler::new());
      let connection_handler = try!(ConnectionHandler::new(&x11_display_handler));

      Ok(LinuxApplication {
         x11_display_handler: x11_display_handler,
         connection_handler: connection_handler,
      })
   }

   pub fn desktop_size(&self) -> (u32, u32) {
      (1200, 800)
   }
}

pub struct X11DisplayHandler {
   pub display: x11::Display,
}

impl X11DisplayHandler {
   #[inline]
   pub fn new() -> Result<Self, RuntimeError> {
      Ok(X11DisplayHandler {
         display: try!(x11::Display::default())
      })
   }

   #[inline]
   pub fn connection(&self) -> Result<xcb::Connection, RuntimeError> {
      self.display.xcb_connection()
   }
}

pub struct ConnectionHandler {
   pub connection: xcb::Connection,
}

impl ConnectionHandler {
   #[inline]
   pub fn new(display_handler: &X11DisplayHandler) -> Result<Self, RuntimeError> {
      Ok(ConnectionHandler {
         connection: try!(display_handler.connection())
      })
   }
}
<commit_msg>xcb_own_event_queue in X11DisplayHandler<commit_after>use error::RuntimeError;

use sys::x11;
use sys::xcb;

pub struct LinuxApplication {
   pub x11_display_handler: X11DisplayHandler,
   pub connection_handler: ConnectionHandler,
}

impl LinuxApplication {
   pub fn new() -> Result<Self, RuntimeError> {
      let x11_display_handler = try!(X11DisplayHandler::new());
      let connection_handler = try!(ConnectionHandler::new(&x11_display_handler));

      Ok(LinuxApplication {
         x11_display_handler: x11_display_handler,
         connection_handler: connection_handler,
      })
   }

   pub fn desktop_size(&self) -> (u32, u32) {
      (1200, 800)
   }
}

pub struct X11DisplayHandler {
   pub display: x11::Display,
}

impl X11DisplayHandler {
   #[inline]
   pub fn new() -> Result<Self, RuntimeError> {
      let display = try!(x11::Display::default());

      display.xcb_own_event_queue();

      Ok(X11DisplayHandler {
         display: display
      })
   }

   #[inline]
   pub fn connection(&self) -> Result<xcb::Connection, RuntimeError> {
      self.display.xcb_connection()
   }
}

pub struct ConnectionHandler {
   pub connection: xcb::Connection,
}

impl ConnectionHandler {
   #[inline]
   pub fn new(display_handler: &X11DisplayHandler) -> Result<Self, RuntimeError> {
      Ok(ConnectionHandler {
         connection: try!(display_handler.connection())
      })
   }
}
<|endoftext|>


<commit_before>use std::rc::Rc;

pub trait SliceParser  {
  type I;
  type O;

  fn parse<'a>(&self, data: &'a[Self::I]) -> ParseResult<&'a [Self::I], Self::O>;
}

pub trait ParserCombinator : SliceParser + Clone {

  fn then<P: SliceParser<I=Self::I>>(&self, p: P) -> ChainedParser<Self::I, Self,P> {
    ChainedParser{first: self.clone(), second: p}
  }

  fn then_r<P: ParserCombinator<I=Self::I>>(&self, p: P) -> MapParser<ChainedParser<Self::I, Self, P>, P::O> {
    self.then(p).map(|(_, t)| t)
  }

  fn then_l<P: ParserCombinator<I=Self::I>>(&self, p: P) -> MapParser<ChainedParser<Self::I, Self, P>, Self::O> {
    self.then(p).map(|(t, _)| t)
  }

  fn repeat(&self) -> RepeatParser<Self> {
    RepeatParser{parser: self.clone()}
  }

  fn map<T, F: 'static + Fn(Self::O) -> T>(&self, f: F) -> MapParser<Self, T> {
    MapParser{parser: self.clone(), mapper: Rc::new(Box::new(f))}
  }

  fn or<P: SliceParser<I=Self::I, O=Self::O>>(&self, p: P) -> OrParser<Self::I, Self::O, Self,P> {
    OrParser{first: self.clone(), second: p}
  }

}

pub type ParseResult<I,O> = Result<(O, I), String>;

pub struct ChainedParser<C, A: SliceParser<I=C>, B: SliceParser<I=C>> {
  first: A,
  second: B,
}
impl<C, A: SliceParser<I=C>, B: SliceParser<I=C>> SliceParser for ChainedParser<C, A, B> {
  type I = C;
  type O = (A::O,B::O);

  fn parse<'a>(&self, data: &'a[Self::I]) -> ParseResult<&'a [Self::I], Self::O>{
    match self.first.parse(data) {
      Ok((a, d2)) => match self.second.parse(d2) {
        Ok((b, remain)) => Ok(((a, b), remain)),
        Err(err) => Err(err)
      },
      Err(err) => Err(err)
    }
  }
}

impl<C, A: ParserCombinator<I=C>, B: ParserCombinator<I=C>>  Clone for ChainedParser<C, A, B> {

  fn clone(&self) -> Self {
    ChainedParser{first: self.first.clone(), second: self.second.clone()}
  }
}

impl<C, A: ParserCombinator<I=C>, B: ParserCombinator<I=C>>  ParserCombinator for ChainedParser<C, A, B> {}

pub fn lit<T: Eq + Clone>(l: T) -> LiteralParser<T> {
  LiteralParser{literal: l}
}
pub fn opt<T: SliceParser>(t: T) -> OptionParser<T> {
  OptionParser{parser: t}
}

#[derive(Clone)]
pub struct LiteralParser< T: Eq + Clone> {
  pub literal: T,
}

impl<T: Eq + Clone> SliceParser for LiteralParser< T> {
  type I = T;
  type O = T;

  fn parse<'a>(&self, data: &'a [T]) -> ParseResult<&'a [T], T> {
    if data.len() < 1 {
      return Err(format!("ran out of data"))
    }
    if data[0] == self.literal {
      Ok((data[0].clone(), data.tail()))
    } else {
      Err(format!("Literal mismatch"))
    }
  }
}

impl<T: Eq + Clone> ParserCombinator for LiteralParser<T>{}

pub struct RepeatParser<P: SliceParser> {
  parser: P
}
impl<T: SliceParser> SliceParser for RepeatParser<T> {
  type I = T::I;
  type O = Vec<T::O>;

  fn parse<'a>(&self, data: &'a [Self::I]) -> ParseResult<&'a [Self::I], Self::O> {
    let mut remain = data;
    let mut v: Vec<T::O> = Vec::new();
    loop {
      match self.parser.parse(remain.clone()) {
        Ok((result, rest)) => {
          v.push(result);
          remain = rest;
        }
        Err(_) => {
          return Ok((v, remain));
        }
      }
    }
  }
}

impl<T: ParserCombinator> ParserCombinator for RepeatParser<T> {}

impl<T: ParserCombinator> Clone for RepeatParser<T> {
  fn clone(&self) -> Self {
    RepeatParser{parser: self.parser.clone()}
  }
}

pub struct MapParser<P: SliceParser, T> {
  parser: P,
  mapper: Rc<Box<Fn(P::O) -> T>>,
}

impl<P: SliceParser, T> SliceParser for MapParser<P,T> {
  type I = P::I;
  type O = T;

  fn parse<'a>(&self, data: &'a [Self::I]) -> ParseResult<&'a [Self::I], Self::O> {
    self.parser.parse(data).map(|(output, input)| ((self.mapper)(output), input))
  }

}

impl<P: ParserCombinator, T> Clone for MapParser<P,T> {

  fn clone(&self) -> Self {
    MapParser{parser: self.parser.clone(), mapper: self.mapper.clone()}
  }
}

impl<P: ParserCombinator, T> ParserCombinator for MapParser<P,T> {}

pub struct OrParser<I,O, S: SliceParser<I=I,O=O>, T: SliceParser<I=I,O=O>> {
  first: S,
  second: T,
}

impl<I,O, S: SliceParser<I=I,O=O>, T: SliceParser<I=I,O=O>> SliceParser for OrParser<I,O,S,T> {
  type I = I;
  type O = O;

  fn parse<'a>(&self, data: &'a [Self::I]) -> ParseResult<&'a [Self::I], Self::O> {
    match self.first.parse(data.clone()) {
      Ok((a, d2)) => Ok((a, d2)),
      Err(_) => match self.second.parse(data.clone()) {
        Ok((b, remain)) => Ok((b, remain)),
        Err(err) => Err(err)
      }
    }
  }
}

impl<I,O, S: ParserCombinator<I=I,O=O>, T: ParserCombinator<I=I,O=O>> Clone for OrParser<I,O,S,T> {

  fn clone(&self) -> Self {
    OrParser{first: self.first.clone(), second: self.second.clone()}
  }
}

impl<I,O, S: ParserCombinator<I=I,O=O>, T: ParserCombinator<I=I,O=O>> ParserCombinator for OrParser<I,O,S,T> {}

#[derive(Clone)]
pub struct OptionParser<P: SliceParser> {
  parser: P
}
impl<P: SliceParser> SliceParser for OptionParser<P> {
  type I = P::I;
  type O = Option<P::O>;

  fn parse<'a>(&self, data: &'a [Self::I]) -> ParseResult<&'a [Self::I], Self::O> {
    match self.parser.parse(data.clone()) {
      Ok((result, rest))  => Ok((Some(result), rest)),
      Err(_)              => Ok((None, data)),
    }
  }
}

pub struct RecursiveParser<I, O, F> where F: Fn() -> Box<SliceParser<I=I,O=O>>{
  parser: Rc<F>
}

impl<I, O, F> SliceParser for RecursiveParser<I, O, F> where F: Fn() -> Box<SliceParser<I=I,O=O>> {

  type I = I;
  type O = O;

  fn parse<'a>(&self, data: &'a [Self::I]) -> ParseResult<&'a [Self::I], Self::O> {
    (self.parser)().parse(data)
  }

}

impl<I, O, F> ParserCombinator for RecursiveParser<I, O, F> where F: Fn() -> Box<SliceParser<I=I,O=O>> {}

impl<I, O, F> Clone for RecursiveParser<I, O, F> where F: Fn() -> Box<SliceParser<I=I,O=O>> {
  fn clone(&self) -> Self {
    RecursiveParser{parser: self.parser.clone()}
  }
}

pub fn recursive<I,O, F:  Fn() -> Box<SliceParser<I=I,O=O>>>(f: F) -> RecursiveParser<I,O,F> {
  RecursiveParser{parser: Rc::new(f)}
}
<commit_msg>adding some comments<commit_after>use std::rc::Rc;

/// A SliceParser is a parser that parses some elements out of the beginning of
/// a slice and returns a parsed value along with the rest of the unparsed slice
pub trait SliceParser  {
  type I;
  type O;

  fn parse<'a>(&self, data: &'a[Self::I]) -> ParseResult<&'a [Self::I], Self::O>;
}

/// Combinator methods for slice parsers.  In most cases, these methods copy
/// the caller into a higher-order parser
pub trait ParserCombinator : SliceParser + Clone {

  /// Chain this parser with another parser, creating new parser that returns a
  /// tuple of their results
  fn then<P: SliceParser<I=Self::I>>(&self, p: P) -> ChainedParser<Self::I, Self,P> {
    ChainedParser{first: self.clone(), second: p}
  }

  /// Chain this parser with another parser, but toss the value from this parser
  fn then_r<P: ParserCombinator<I=Self::I>>(&self, p: P) -> MapParser<ChainedParser<Self::I, Self, P>, P::O> {
    self.then(p).map(|(_, t)| t)
  }

  /// Chain this parser with another parser, but toss the value from the other parser
  fn then_l<P: ParserCombinator<I=Self::I>>(&self, p: P) -> MapParser<ChainedParser<Self::I, Self, P>, Self::O> {
    self.then(p).map(|(t, _)| t)
  }

  /// Create a new parser that will repeat this parser until it returns an error
  fn repeat(&self) -> RepeatParser<Self> {
    RepeatParser{parser: self.clone()}
  }

  /// Map the value of this parser
  fn map<T, F: 'static + Fn(Self::O) -> T>(&self, f: F) -> MapParser<Self, T> {
    MapParser{parser: self.clone(), mapper: Rc::new(Box::new(f))}
  }

  /// Create a disjunction with another parser.  If this parser produces an error, the other parser will be used
  fn or<P: SliceParser<I=Self::I, O=Self::O>>(&self, p: P) -> OrParser<Self::I, Self::O, Self,P> {
    OrParser{first: self.clone(), second: p}
  }

}

pub type ParseResult<I,O> = Result<(O, I), String>;

pub struct ChainedParser<C, A: SliceParser<I=C>, B: SliceParser<I=C>> {
  first: A,
  second: B,
}
impl<C, A: SliceParser<I=C>, B: SliceParser<I=C>> SliceParser for ChainedParser<C, A, B> {
  type I = C;
  type O = (A::O,B::O);

  fn parse<'a>(&self, data: &'a[Self::I]) -> ParseResult<&'a [Self::I], Self::O>{
    match self.first.parse(data) {
      Ok((a, d2)) => match self.second.parse(d2) {
        Ok((b, remain)) => Ok(((a, b), remain)),
        Err(err) => Err(err)
      },
      Err(err) => Err(err)
    }
  }
}

impl<C, A: ParserCombinator<I=C>, B: ParserCombinator<I=C>>  Clone for ChainedParser<C, A, B> {

  fn clone(&self) -> Self {
    ChainedParser{first: self.first.clone(), second: self.second.clone()}
  }
}

impl<C, A: ParserCombinator<I=C>, B: ParserCombinator<I=C>>  ParserCombinator for ChainedParser<C, A, B> {}

/// Create a parser that only recognizes the given literal value
pub fn lit<T: Eq + Clone>(l: T) -> LiteralParser<T> {
  LiteralParser{literal: l}
}

/// Create a parser that will return Some if the given parser is successful, None otherwise
pub fn opt<T: SliceParser>(t: T) -> OptionParser<T> {
  OptionParser{parser: t}
}

#[derive(Clone)]
pub struct LiteralParser< T: Eq + Clone> {
  pub literal: T,
}

impl<T: Eq + Clone> SliceParser for LiteralParser< T> {
  type I = T;
  type O = T;

  fn parse<'a>(&self, data: &'a [T]) -> ParseResult<&'a [T], T> {
    if data.len() < 1 {
      return Err(format!("ran out of data"))
    }
    if data[0] == self.literal {
      Ok((data[0].clone(), data.tail()))
    } else {
      Err(format!("Literal mismatch"))
    }
  }
}

impl<T: Eq + Clone> ParserCombinator for LiteralParser<T>{}

pub struct RepeatParser<P: SliceParser> {
  parser: P
}
impl<T: SliceParser> SliceParser for RepeatParser<T> {
  type I = T::I;
  type O = Vec<T::O>;

  fn parse<'a>(&self, data: &'a [Self::I]) -> ParseResult<&'a [Self::I], Self::O> {
    let mut remain = data;
    let mut v: Vec<T::O> = Vec::new();
    loop {
      match self.parser.parse(remain.clone()) {
        Ok((result, rest)) => {
          v.push(result);
          remain = rest;
        }
        Err(_) => {
          return Ok((v, remain));
        }
      }
    }
  }
}

impl<T: ParserCombinator> ParserCombinator for RepeatParser<T> {}

impl<T: ParserCombinator> Clone for RepeatParser<T> {
  fn clone(&self) -> Self {
    RepeatParser{parser: self.parser.clone()}
  }
}

pub struct MapParser<P: SliceParser, T> {
  parser: P,
  mapper: Rc<Box<Fn(P::O) -> T>>,
}

impl<P: SliceParser, T> SliceParser for MapParser<P,T> {
  type I = P::I;
  type O = T;

  fn parse<'a>(&self, data: &'a [Self::I]) -> ParseResult<&'a [Self::I], Self::O> {
    self.parser.parse(data).map(|(output, input)| ((self.mapper)(output), input))
  }

}

impl<P: ParserCombinator, T> Clone for MapParser<P,T> {

  fn clone(&self) -> Self {
    MapParser{parser: self.parser.clone(), mapper: self.mapper.clone()}
  }
}

impl<P: ParserCombinator, T> ParserCombinator for MapParser<P,T> {}

pub struct OrParser<I,O, S: SliceParser<I=I,O=O>, T: SliceParser<I=I,O=O>> {
  first: S,
  second: T,
}

impl<I,O, S: SliceParser<I=I,O=O>, T: SliceParser<I=I,O=O>> SliceParser for OrParser<I,O,S,T> {
  type I = I;
  type O = O;

  fn parse<'a>(&self, data: &'a [Self::I]) -> ParseResult<&'a [Self::I], Self::O> {
    match self.first.parse(data.clone()) {
      Ok((a, d2)) => Ok((a, d2)),
      Err(_) => match self.second.parse(data.clone()) {
        Ok((b, remain)) => Ok((b, remain)),
        Err(err) => Err(err)
      }
    }
  }
}

impl<I,O, S: ParserCombinator<I=I,O=O>, T: ParserCombinator<I=I,O=O>> Clone for OrParser<I,O,S,T> {

  fn clone(&self) -> Self {
    OrParser{first: self.first.clone(), second: self.second.clone()}
  }
}

impl<I,O, S: ParserCombinator<I=I,O=O>, T: ParserCombinator<I=I,O=O>> ParserCombinator for OrParser<I,O,S,T> {}

#[derive(Clone)]
pub struct OptionParser<P: SliceParser> {
  parser: P
}
impl<P: SliceParser> SliceParser for OptionParser<P> {
  type I = P::I;
  type O = Option<P::O>;

  fn parse<'a>(&self, data: &'a [Self::I]) -> ParseResult<&'a [Self::I], Self::O> {
    match self.parser.parse(data.clone()) {
      Ok((result, rest))  => Ok((Some(result), rest)),
      Err(_)              => Ok((None, data)),
    }
  }
}

pub struct RecursiveParser<I, O, F> where F: Fn() -> Box<SliceParser<I=I,O=O>>{
  parser: Rc<F>
}

impl<I, O, F> SliceParser for RecursiveParser<I, O, F> where F: Fn() -> Box<SliceParser<I=I,O=O>> {

  type I = I;
  type O = O;

  fn parse<'a>(&self, data: &'a [Self::I]) -> ParseResult<&'a [Self::I], Self::O> {
    (self.parser)().parse(data)
  }

}

impl<I, O, F> ParserCombinator for RecursiveParser<I, O, F> where F: Fn() -> Box<SliceParser<I=I,O=O>> {}

impl<I, O, F> Clone for RecursiveParser<I, O, F> where F: Fn() -> Box<SliceParser<I=I,O=O>> {
  fn clone(&self) -> Self {
    RecursiveParser{parser: self.parser.clone()}
  }
}

/// Create a lazily evaluated parser from a function.  This can be used to generate recursive parsers
pub fn recursive<I,O, F:  Fn() -> Box<SliceParser<I=I,O=O>>>(f: F) -> RecursiveParser<I,O,F> {
  RecursiveParser{parser: Rc::new(f)}
}
<|endoftext|>


<commit_before>use std::default::Default;
use std::mem;
use glium;
use glium::texture;

pub struct Renderer {
    shader: glium::Program,
    texture: texture::Texture2d,
    params: glium::DrawParameters,

    pub vertices: Vec<Vertex>,
    pub indices: Vec<u16>,
}

impl Renderer {
    pub fn new<T>(display: &glium::Display, texture_image: T) -> Renderer
        where T: texture::Texture2dData {
        let shader = glium::Program::from_source(display,
            // Vertex
            "
                #version 120

                attribute vec3 pos;
                attribute vec4 color;
                attribute vec2 tex_coord;

                varying vec2 v_tex_coord;
                varying vec4 v_color;

                void main() {
                    v_tex_coord = tex_coord;
                    v_color = color;
                    gl_Position = vec4(pos, 1.0);
                }
            ",
            // Fragment
            "
                #version 120

                uniform sampler2D texture;

                varying vec2 v_tex_coord;
                varying vec4 v_color;

                void main() {
                    vec4 tex_color = texture2D(texture, v_tex_coord);
                    if (tex_color.a == 0.0) discard;
                    gl_FragColor = v_color * tex_color;
                }
            ",
            None).unwrap();
        let texture = texture::Texture2d::new(display, texture_image);

        let mut params: glium::DrawParameters = Default::default();
        params.backface_culling = glium::BackfaceCullingMode::CullCounterClockWise;
        params.depth_function = glium::DepthFunction::IfLessOrEqual;
        params.blending_function = Some(glium::BlendingFunction::LerpBySourceAlpha);

        Renderer {
            shader: shader,
            texture: texture,
            params: params,
            vertices: Vec::new(),
            indices: Vec::new(),
        }
    }

    pub fn clear(&mut self) {
        self.vertices = Vec::new();
        self.indices = Vec::new();
    }

    /// Draw the accumulated geometry and clear the accum buffers.
    pub fn draw<S>(&mut self, display: &glium::Display, target: &mut S)
        where S: glium::Surface {
        target.clear_color(0.0, 0.0, 0.0, 0.0);
        target.clear_depth(1.0);
        // Extract the geometry accumulation buffers and convert into
        // temporary Glium buffers.
        let vertices = glium::VertexBuffer::new(
            display, mem::replace(&mut self.vertices, Vec::new()));
        let indices = glium::IndexBuffer::new(
            display,
            glium::index_buffer::TrianglesList(
                mem::replace(&mut self.indices, Vec::new())));

        let uniforms = glium::uniforms::UniformsStorage::new("texture",
            glium::uniforms::Sampler(&self.texture, glium::uniforms::SamplerBehavior {
                magnify_filter: glium::uniforms::MagnifySamplerFilter::Nearest,
                .. Default::default() }));

        target.draw(&vertices, &indices, &self.shader, &uniforms, &self.params);
    }
}

#[vertex_format]
#[derive(Copy)]
pub struct Vertex {
    pub pos: [f32; 3],
    pub color: [f32; 4],
    pub tex_coord: [f32; 2],
}
<commit_msg>Comment explaining the sprite fragment shader discard<commit_after>use std::default::Default;
use std::mem;
use glium;
use glium::texture;

pub struct Renderer {
    shader: glium::Program,
    texture: texture::Texture2d,
    params: glium::DrawParameters,

    pub vertices: Vec<Vertex>,
    pub indices: Vec<u16>,
}

impl Renderer {
    pub fn new<T>(display: &glium::Display, texture_image: T) -> Renderer
        where T: texture::Texture2dData {
        let shader = glium::Program::from_source(display,
            // Vertex
            "
                #version 120

                attribute vec3 pos;
                attribute vec4 color;
                attribute vec2 tex_coord;

                varying vec2 v_tex_coord;
                varying vec4 v_color;

                void main() {
                    v_tex_coord = tex_coord;
                    v_color = color;
                    gl_Position = vec4(pos, 1.0);
                }
            ",
            // Fragment
            "
                #version 120

                uniform sampler2D texture;

                varying vec2 v_tex_coord;
                varying vec4 v_color;

                void main() {
                    vec4 tex_color = texture2D(texture, v_tex_coord);

                    // Discard fully transparent pixels to keep them from
                    // writing into the depth buffer.
                    if (tex_color.a == 0.0) discard;

                    gl_FragColor = v_color * tex_color;
                }
            ",
            None).unwrap();
        let texture = texture::Texture2d::new(display, texture_image);

        let mut params: glium::DrawParameters = Default::default();
        params.backface_culling = glium::BackfaceCullingMode::CullCounterClockWise;
        params.depth_function = glium::DepthFunction::IfLessOrEqual;
        params.blending_function = Some(glium::BlendingFunction::LerpBySourceAlpha);

        Renderer {
            shader: shader,
            texture: texture,
            params: params,
            vertices: Vec::new(),
            indices: Vec::new(),
        }
    }

    pub fn clear(&mut self) {
        self.vertices = Vec::new();
        self.indices = Vec::new();
    }

    /// Draw the accumulated geometry and clear the accum buffers.
    pub fn draw<S>(&mut self, display: &glium::Display, target: &mut S)
        where S: glium::Surface {
        target.clear_color(0.0, 0.0, 0.0, 0.0);
        target.clear_depth(1.0);
        // Extract the geometry accumulation buffers and convert into
        // temporary Glium buffers.
        let vertices = glium::VertexBuffer::new(
            display, mem::replace(&mut self.vertices, Vec::new()));
        let indices = glium::IndexBuffer::new(
            display,
            glium::index_buffer::TrianglesList(
                mem::replace(&mut self.indices, Vec::new())));

        let uniforms = glium::uniforms::UniformsStorage::new("texture",
            glium::uniforms::Sampler(&self.texture, glium::uniforms::SamplerBehavior {
                magnify_filter: glium::uniforms::MagnifySamplerFilter::Nearest,
                .. Default::default() }));

        target.draw(&vertices, &indices, &self.shader, &uniforms, &self.params);
    }
}

#[vertex_format]
#[derive(Copy)]
pub struct Vertex {
    pub pos: [f32; 3],
    pub color: [f32; 4],
    pub tex_coord: [f32; 2],
}
<|endoftext|>


<commit_before>use std::default::Default;
use std::mem;
use glium;
use glium::texture;

pub struct Renderer {
    shader: glium::Program,
    texture: texture::Texture2d,
    params: glium::DrawParameters,

    pub vertices: Vec<Vertex>,
    pub indices: Vec<u16>,
}

impl Renderer {
    pub fn new<T>(display: &glium::Display, texture_image: T) -> Renderer
        where T: texture::Texture2dData {
        let shader = glium::Program::from_source(display,
            // Vertex
            "
                #version 120

                attribute vec3 pos;
                attribute vec4 color;
                attribute vec2 tex_coord;

                varying vec2 v_tex_coord;
                varying vec4 v_color;

                void main() {
                    v_tex_coord = tex_coord;
                    v_color = color;
                    gl_Position = vec4(pos, 1.0);
                }
            ",
            // Fragment
            "
                #version 120

                uniform sampler2D texture;

                varying vec2 v_tex_coord;
                varying vec4 v_color;

                void main() {
                    vec4 tex_color = texture2D(texture, v_tex_coord);
                    gl_FragColor = v_color * tex_color;
                }
            ",
            None).unwrap();
        let texture = texture::Texture2d::new(display, texture_image);

        let mut params: glium::DrawParameters = Default::default();
        params.backface_culling = glium::BackfaceCullingMode::CullCounterClockWise;
        params.depth_function = glium::DepthFunction::IfLessOrEqual;
        params.blending_function = Some(glium::BlendingFunction::LerpBySourceAlpha);

        Renderer {
            shader: shader,
            texture: texture,
            params: params,
            vertices: Vec::new(),
            indices: Vec::new(),
        }
    }

    pub fn clear(&mut self) {
        self.vertices = Vec::new();
        self.indices = Vec::new();
    }

    /// Draw the accumulated geometry and clear the accum buffers.
    pub fn draw<S>(&mut self, display: &glium::Display, target: &mut S)
        where S: glium::Surface {
        target.clear_color(0.0, 0.0, 0.0, 0.0);
        target.clear_depth(1.0);
        // Extract the geometry accumulation buffers and convert into
        // temporary Glium buffers.
        let vertices = glium::VertexBuffer::new(
            display, mem::replace(&mut self.vertices, Vec::new()));
        let indices = glium::IndexBuffer::new(
            display,
            glium::index_buffer::TrianglesList(
                mem::replace(&mut self.indices, Vec::new())));

        let uniforms = glium::uniforms::UniformsStorage::new("texture",
            glium::uniforms::Sampler(&self.texture, glium::uniforms::SamplerBehavior {
                magnify_filter: glium::uniforms::MagnifySamplerFilter::Nearest,
                .. Default::default() }));

        target.draw(&vertices, &indices, &self.shader, &uniforms, &self.params);
    }
}

#[vertex_format]
#[derive(Copy)]
pub struct Vertex {
    pub pos: [f32; 3],
    pub color: [f32; 4],
    pub tex_coord: [f32; 2],
}
<commit_msg>Put alpha discarding back<commit_after>use std::default::Default;
use std::mem;
use glium;
use glium::texture;

pub struct Renderer {
    shader: glium::Program,
    texture: texture::Texture2d,
    params: glium::DrawParameters,

    pub vertices: Vec<Vertex>,
    pub indices: Vec<u16>,
}

impl Renderer {
    pub fn new<T>(display: &glium::Display, texture_image: T) -> Renderer
        where T: texture::Texture2dData {
        let shader = glium::Program::from_source(display,
            // Vertex
            "
                #version 120

                attribute vec3 pos;
                attribute vec4 color;
                attribute vec2 tex_coord;

                varying vec2 v_tex_coord;
                varying vec4 v_color;

                void main() {
                    v_tex_coord = tex_coord;
                    v_color = color;
                    gl_Position = vec4(pos, 1.0);
                }
            ",
            // Fragment
            "
                #version 120

                uniform sampler2D texture;

                varying vec2 v_tex_coord;
                varying vec4 v_color;

                void main() {
                    vec4 tex_color = texture2D(texture, v_tex_coord);
                    if (tex_color.a == 0.0) discard;
                    gl_FragColor = v_color * tex_color;
                }
            ",
            None).unwrap();
        let texture = texture::Texture2d::new(display, texture_image);

        let mut params: glium::DrawParameters = Default::default();
        params.backface_culling = glium::BackfaceCullingMode::CullCounterClockWise;
        params.depth_function = glium::DepthFunction::IfLessOrEqual;
        params.blending_function = Some(glium::BlendingFunction::LerpBySourceAlpha);

        Renderer {
            shader: shader,
            texture: texture,
            params: params,
            vertices: Vec::new(),
            indices: Vec::new(),
        }
    }

    pub fn clear(&mut self) {
        self.vertices = Vec::new();
        self.indices = Vec::new();
    }

    /// Draw the accumulated geometry and clear the accum buffers.
    pub fn draw<S>(&mut self, display: &glium::Display, target: &mut S)
        where S: glium::Surface {
        target.clear_color(0.0, 0.0, 0.0, 0.0);
        target.clear_depth(1.0);
        // Extract the geometry accumulation buffers and convert into
        // temporary Glium buffers.
        let vertices = glium::VertexBuffer::new(
            display, mem::replace(&mut self.vertices, Vec::new()));
        let indices = glium::IndexBuffer::new(
            display,
            glium::index_buffer::TrianglesList(
                mem::replace(&mut self.indices, Vec::new())));

        let uniforms = glium::uniforms::UniformsStorage::new("texture",
            glium::uniforms::Sampler(&self.texture, glium::uniforms::SamplerBehavior {
                magnify_filter: glium::uniforms::MagnifySamplerFilter::Nearest,
                .. Default::default() }));

        target.draw(&vertices, &indices, &self.shader, &uniforms, &self.params);
    }
}

#[vertex_format]
#[derive(Copy)]
pub struct Vertex {
    pub pos: [f32; 3],
    pub color: [f32; 4],
    pub tex_coord: [f32; 2],
}
<|endoftext|>


<commit_before>use std::io;
use std::io::File;

mod lexer;
mod parser;
mod token;
mod view_writer;

fn get_file_contents() -> Result<~[u8], io::IoError> {
    let path = from_str::<Path>("src/compiler/index.rs.html").unwrap();

    File::open(&path).and_then(|file| {
        let mut file = file;
        file.read_to_end()
    })
}

fn main() {
    let contents = match get_file_contents() {
        Ok(contents) => std::str::from_utf8_owned(contents).expect("Non-utf8 source file"),
        Err(e) => fail!(e)
    };

    let mut lexer = lexer::Lexer::new(contents);
    let mut parser = parser::Parser::new(&mut lexer);
    parser.parse();

    println!("Lines: {}\nLast column: {}", parser.lexer.line, parser.lexer.column);

    //debug!("{}", parser.sections);

    view_writer::write_view(&Path::new("src/compiler/index.rs"), parser.sections.as_slice());
}
<commit_msg>Update for rust changes<commit_after>use std::io;
use std::io::File;

mod lexer;
mod parser;
mod token;
mod view_writer;

fn get_file_contents() -> Result<~str, io::IoError> {
    let path = from_str::<Path>("src/compiler/index.rs.html").unwrap();

    File::open(&path).and_then(|file| {
        let mut file = file;
        file.read_to_str()
    })
}

fn main() {
    let contents = match get_file_contents() {
        Ok(contents) => contents,
        Err(e) => fail!(e)
    };

    let mut lexer = lexer::Lexer::new(contents);
    let mut parser = parser::Parser::new(&mut lexer);
    parser.parse();

    println!("Lines: {}\nLast column: {}", parser.lexer.line, parser.lexer.column);

    //debug!("{}", parser.sections);

    view_writer::write_view(&Path::new("src/compiler/index.rs"), parser.sections.as_slice());
}
<|endoftext|>


<commit_before>use crate::Msg;
use seed::prelude::*;
use web_sys::{HtmlInputElement};

fn trial_divide(n: u64, max: u64) -> u64 {
    // Trial divides the positive integer n by the primes from 2 to max
    // Returns the first prime divisor found, or 0 if none found
    // Note: if n < max^2 is a prime, then n will be returned.
    if n % 2 == 0 {
        2
    } else if n % 3 == 0 {
        3
    } else {
        // No need to go past the square root of our number
        let sqrt: u64 = (n as f64).sqrt().floor() as u64;
        let stop = if sqrt > max { max } else { sqrt };
        // Okay, lets "wheel factor" alternately adding 2 and 4
        let mut di = 2;
        let mut i = 5;
        while i <= stop {
            if n % i == 0 {
                return i;
            }
            i += di;
            di = 6 - di;
        }
        if n >= max * max {
            0
        } else {
            n
        }
    }
}

// modadd(a,b,N) finds a+b (mod N) where a, b, and N can be
// up to (2^53-1)/2.  Might up this to 2^53-1 eventually...
fn modadd(a: u64, b: u64, n: u64) -> u64 {
    // When the integers a, b satisfy a+b > 2^53-1, then (a+b)%N is wrong
    // so we add this routine to allow us to reach a, b = 2^53-1.
    if a + b > 9007199254740991 {
        // Could reduce a and b (mod N) here, but assuming that has already been done
        // won't hurt if not... subtract 2^52 from one, 2^52-1 from the other and the
        // add it back modulo N (MaxInt+1)
        let t = ((a - 4503599627370496) + (b - 4503599627370495)) % n;
        return t + (9007199254740991 % n);
    }
    // Usual case: a + b is not too large:
    (a + b) % n
}

fn modmult(mut a: u64, mut b: u64, n: u64) -> u64 {
    if a > n {
        a = a % n;
    }
    if b > n {
        b = b % n;
    }
    if a * b <= 9007199254740991 {
        return (a * b) % n;
    } else {
        if b > a {
            return modmult(b.clone(), a, n);
        }

        // Right to left binary multiplication
        let mut t = 0;
        let mut f = a;
        while b > 1 {
            if (b & 1) == 1 {
                t = modadd(t, f, n);
            }
            //TODO: bitshift might be cleaner and faster
            b = (b as f64 / 2.0).floor() as u64;
            f = modadd(f, f, n);
        }
        t = modadd(t, f, n);
        return t;
    }
}

// modpow(a,exp,N) finds a^exp (mod N) where a, b, and N are
// limited by modmult
fn modpow(a: u64, mut exp: u64, n: u64) -> u64 {
    if exp == 0 {
        return 1;
    }

    // Right to left binary exponentiation
    let mut t = 1;
    let mut f = a;
    while exp > 1 {
        if (exp & 1) == 1 {
            // if exponent is odd
            t = modmult(t, f, n);
        }
        exp = (exp as f64 / 2.0).floor() as u64;
        f = modmult(f, f, n);
    }
    t = modmult(t, f, n);
    return t;
}

// sprp(N,a) checks if N (odd!) is a strong probable prime base a
// (returns true or false)
fn sprp(n: u64, a: u64) -> bool {
    let mut d = n - 1;
    let mut s = 1; // Assumes n is odd!
    while true {
        d = ((d >> 2) & 1);
        if d == 0 {
            break;
        }
        s += 1;
    }
    // Now n-1 = d*2^s with d odd
    let mut b = modpow(a, d, n);
    if b == 1 {
        return true;
    }
    if b + 1 == n {
        return true;
    }
    while s > 1 {
        b = modmult(b, b, n);
        if b + 1 == n {
            return true;
        }
        s = s - 1;
    }
    return false;
}

pub struct Check {
    pub is_prime: bool,
    pub result: String,
}

pub fn check(input: String) -> Check {
    let trial_limit = 1300; // Should be bigger, like 10000
    let n: u64 = input.parse::<u64>().unwrap();
    let mut result;
    let mut is_prime = false;

    if n > 9007199254740991 {
        result = "Sorry, this routine will only handle integers below 9007199254740991.".to_owned();
    } else if n == 1 {
        result = "The number 1 is neither prime or composite (it is the multiplicative identity)."
            .to_owned();
    } else if n < 1 {
        result =
            "We usually restrict the terms prime and composite to positive integers".to_owned();
    } else {
        // Okay, n is of a resonable size, lets trial divide
        let i = trial_divide(n, trial_limit);
        if i > 0 && i != n {
            result = format!("{} is not a prime! It is {} * {}", n, i, n / i);
        } else if n < trial_limit * trial_limit {
            result = format!("{} is a (proven) prime!", n);
            is_prime = true;
        } else if sprp(n, 2)
            && sprp(n, 3)
            && sprp(n, 5)
            && sprp(n, 7)
            && sprp(n, 11)
            && sprp(n, 13)
            && sprp(n, 17)
        {
            // Some of these tests are unnecessary for small numbers, but for
            // small numbers they are quick anyway.
            if n < 341550071728321 {
                result = format!("{} is a (proven) prime.", n);
                is_prime = true;
            } else if n == 341550071728321 {
                result = format!("{} is not a prime! It is 10670053 * 32010157.", n);
            } else {
                result = format!(
                    "{} is probably a prime (it is a sprp bases 2, 3, 5, 7, 11, 13 and  17).",
                    n
                );
                is_prime = true;
            };
        } else {
            result = format!(
                "{} is (proven) composite (failed sprp test base {}).",
                n, 17
            );
        };
    };

    return Check{is_prime, result};
}

pub fn listy(start_number: u64, number_of_primes: u64) -> String {
    let mut i = 0;
    let mut j = start_number;
    let mut list: String = "".to_string();
    while i < number_of_primes {
        let result = check(j.to_string());
        if result.is_prime == true {
            list = list + &result.result + "\n";
            i += 1;
        }
        j += 1;
    }
    list
}

pub fn go_crunch() -> () {
    let window = web_sys::window().expect("no global `window` exists");
    let document = window.document().expect("should have a document on window");
    let body = document.body().expect("document should have a body");

    let el_input_value = document
        .get_element_by_id("input")
        .unwrap()
        .dyn_into::<HtmlInputElement>()
        .unwrap()
        .value();
    let el_output_textarea = document
        .get_element_by_id("prime_check_output")
        .expect("missing output textarea");
    el_output_textarea.set_inner_html(&check(el_input_value).result);
    ()
}

pub fn go_list() {
    let window = web_sys::window().expect("no global `window` exists");
    let document = window.document().expect("should have a document on window");
    let body = document.body().expect("document should have a body");

    let el_start_value = document
        .get_element_by_id("start")
        .unwrap()
        .dyn_into::<HtmlInputElement>()
        .unwrap()
        .value();
    let el_primes_value = document
        .get_element_by_id("primes")
        .unwrap()
        .dyn_into::<HtmlInputElement>()
        .unwrap()
        .value();
    let el_output_textarea = document
        .get_element_by_id("prime_check_list_output")
        .expect("missing output textarea");
    el_output_textarea.set_inner_html(&listy(
        el_start_value.parse::<u64>().unwrap(),
        el_primes_value.parse::<u64>().unwrap(),
    ));
    ()
}

pub fn render() -> Node<Msg> {
    div![
        h1!["Primality Test, Calculate Primes"],
        br![],
        br![],
        br![],
        table![
            attrs! {At::Class => "text", At::Width => "300", At::Style => "border:1px solid #444; background-color:#e0faed"},
            tr![td![
                attrs! {At::Style => "padding: 10px"},
                form![
                    attrs! {At::Id => "primetest", At::OnSubmit => "return false"},
                    "Tool is limited to checking numbers upto 16 digits.",
                    br![],
                    br![],
                    "Is ",
                    input![
                        attrs! {At::Type => "number", At::Size => "19", At::Id => "input", At::Value => "", At::MaxLength => "16"}
                    ],
                    " prime? ",
                    button![
                        "Check!",
                        mouse_ev("mouseup", move |_event| Msg::PrimalityChecker(go_crunch()))
                    ],
                    br![],
                    br![],
                    textarea![
                        attrs! {At::Id => "prime_check_output", At::Cols => 60, At::Rows => 2, At::Disabled => "disabled"}
                    ]
                ]
            ]]
        ],
        br![],
        br![],
        table![
            attrs! {At::Class => "text", At::Width => "300", At::Style => "border:1px solid #444; background-color:#e0faed"},
            tr![td![
                attrs! {At::Style => "padding: 10px"},
                form![
                    attrs! {At::Id => "primelist", At::OnSubmit => "return false"},
                    "This tool is limited to checking numbers upto 15 digits.",
                    br![],
                    br![],
                    "This will show ",
                    input![
                        attrs! {At::Type => "number", At::Size => "4", At::Id => "primes", At::Value => "1", At::MaxLength => "2"}
                    ],
                    " prime numbers after ",
                    input![
                        attrs! {At::Type => "number", At::Size => "19", At::Id => "start", At::Value => "0", At::MaxLength => "15"}
                    ],
                    " ",
                    button![
                        "Go!",
                        mouse_ev("mouseup", move |_event| Msg::PrimalityChecker(go_list()))
                    ],
                    br![],
                    br![],
                    textarea![
                        attrs! {At::Id => "prime_check_list_output", At::Cols => 60, At::Rows => 10, At::Disabled => "disabled"}
                    ]
                ]
            ]]
        ]
    ]
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn trial_divide_test() {
        assert_eq!(trial_divide(2, 2), 2);
        assert_eq!(trial_divide(3, 4), 3);
        assert_eq!(trial_divide(30, 10000), 2);
        assert_eq!(trial_divide(7777771, 10000), 29);
        assert_eq!(trial_divide(7777771111111111, 10000), 11);
        //in the case of a prime
        assert_eq!(trial_divide(777777111111113, 10000), 0);
    }

    #[test]
    fn sprp_test() {
        assert_eq!(sprp(27, 5), false);
        assert_eq!(sprp(31, 7), true);
        assert_eq!(sprp(217, 7), false);
        assert_eq!(sprp(19, 13), true);
    }
}
<commit_msg>Default input values are now small primes for better UX<commit_after>use crate::Msg;
use seed::prelude::*;
use web_sys::{HtmlInputElement};

fn trial_divide(n: u64, max: u64) -> u64 {
    // Trial divides the positive integer n by the primes from 2 to max
    // Returns the first prime divisor found, or 0 if none found
    // Note: if n < max^2 is a prime, then n will be returned.
    if n % 2 == 0 {
        2
    } else if n % 3 == 0 {
        3
    } else {
        // No need to go past the square root of our number
        let sqrt: u64 = (n as f64).sqrt().floor() as u64;
        let stop = if sqrt > max { max } else { sqrt };
        // Okay, lets "wheel factor" alternately adding 2 and 4
        let mut di = 2;
        let mut i = 5;
        while i <= stop {
            if n % i == 0 {
                return i;
            }
            i += di;
            di = 6 - di;
        }
        if n >= max * max {
            0
        } else {
            n
        }
    }
}

// modadd(a,b,N) finds a+b (mod N) where a, b, and N can be
// up to (2^53-1)/2.  Might up this to 2^53-1 eventually...
fn modadd(a: u64, b: u64, n: u64) -> u64 {
    // When the integers a, b satisfy a+b > 2^53-1, then (a+b)%N is wrong
    // so we add this routine to allow us to reach a, b = 2^53-1.
    if a + b > 9007199254740991 {
        // Could reduce a and b (mod N) here, but assuming that has already been done
        // won't hurt if not... subtract 2^52 from one, 2^52-1 from the other and the
        // add it back modulo N (MaxInt+1)
        let t = ((a - 4503599627370496) + (b - 4503599627370495)) % n;
        return t + (9007199254740991 % n);
    }
    // Usual case: a + b is not too large:
    (a + b) % n
}

fn modmult(mut a: u64, mut b: u64, n: u64) -> u64 {
    if a > n {
        a = a % n;
    }
    if b > n {
        b = b % n;
    }
    if a * b <= 9007199254740991 {
        return (a * b) % n;
    } else {
        if b > a {
            return modmult(b.clone(), a, n);
        }

        // Right to left binary multiplication
        let mut t = 0;
        let mut f = a;
        while b > 1 {
            if (b & 1) == 1 {
                t = modadd(t, f, n);
            }
            //TODO: bitshift might be cleaner and faster
            b = (b as f64 / 2.0).floor() as u64;
            f = modadd(f, f, n);
        }
        t = modadd(t, f, n);
        return t;
    }
}

// modpow(a,exp,N) finds a^exp (mod N) where a, b, and N are
// limited by modmult
fn modpow(a: u64, mut exp: u64, n: u64) -> u64 {
    if exp == 0 {
        return 1;
    }

    // Right to left binary exponentiation
    let mut t = 1;
    let mut f = a;
    while exp > 1 {
        if (exp & 1) == 1 {
            // if exponent is odd
            t = modmult(t, f, n);
        }
        exp = (exp as f64 / 2.0).floor() as u64;
        f = modmult(f, f, n);
    }
    t = modmult(t, f, n);
    return t;
}

// sprp(N,a) checks if N (odd!) is a strong probable prime base a
// (returns true or false)
fn sprp(n: u64, a: u64) -> bool {
    let mut d = n - 1;
    let mut s = 1; // Assumes n is odd!
    while true {
        d = ((d >> 2) & 1);
        if d == 0 {
            break;
        }
        s += 1;
    }
    // Now n-1 = d*2^s with d odd
    let mut b = modpow(a, d, n);
    if b == 1 {
        return true;
    }
    if b + 1 == n {
        return true;
    }
    while s > 1 {
        b = modmult(b, b, n);
        if b + 1 == n {
            return true;
        }
        s = s - 1;
    }
    return false;
}

pub struct Check {
    pub is_prime: bool,
    pub result: String,
}

pub fn check(input: String) -> Check {
    let trial_limit = 1300; // Should be bigger, like 10000
    let n: u64 = input.parse::<u64>().unwrap();
    let mut result;
    let mut is_prime = false;

    if n > 9007199254740991 {
        result = "Sorry, this routine will only handle integers below 9007199254740991.".to_owned();
    } else if n == 1 {
        result = "The number 1 is neither prime or composite (it is the multiplicative identity)."
            .to_owned();
    } else if n < 1 {
        result =
            "We usually restrict the terms prime and composite to positive integers".to_owned();
    } else {
        // Okay, n is of a resonable size, lets trial divide
        let i = trial_divide(n, trial_limit);
        if i > 0 && i != n {
            result = format!("{} is not a prime! It is {} * {}", n, i, n / i);
        } else if n < trial_limit * trial_limit {
            result = format!("{} is a (proven) prime!", n);
            is_prime = true;
        } else if sprp(n, 2)
            && sprp(n, 3)
            && sprp(n, 5)
            && sprp(n, 7)
            && sprp(n, 11)
            && sprp(n, 13)
            && sprp(n, 17)
        {
            // Some of these tests are unnecessary for small numbers, but for
            // small numbers they are quick anyway.
            if n < 341550071728321 {
                result = format!("{} is a (proven) prime.", n);
                is_prime = true;
            } else if n == 341550071728321 {
                result = format!("{} is not a prime! It is 10670053 * 32010157.", n);
            } else {
                result = format!(
                    "{} is probably a prime (it is a sprp bases 2, 3, 5, 7, 11, 13 and  17).",
                    n
                );
                is_prime = true;
            };
        } else {
            result = format!(
                "{} is (proven) composite (failed sprp test base {}).",
                n, 17
            );
        };
    };

    return Check{is_prime, result};
}

pub fn listy(start_number: u64, number_of_primes: u64) -> String {
    let mut i = 0;
    let mut j = start_number;
    let mut list: String = "".to_string();
    while i < number_of_primes {
        let result = check(j.to_string());
        if result.is_prime == true {
            list = list + &result.result + "\n";
            i += 1;
        }
        j += 1;
    }
    list
}

pub fn go_crunch() -> () {
    let window = web_sys::window().expect("no global `window` exists");
    let document = window.document().expect("should have a document on window");
    let body = document.body().expect("document should have a body");

    let el_input_value = document
        .get_element_by_id("input")
        .unwrap()
        .dyn_into::<HtmlInputElement>()
        .unwrap()
        .value();
    let el_output_textarea = document
        .get_element_by_id("prime_check_output")
        .expect("missing output textarea");
    el_output_textarea.set_inner_html(&check(el_input_value).result);
    ()
}

pub fn go_list() {
    let window = web_sys::window().expect("no global `window` exists");
    let document = window.document().expect("should have a document on window");
    let body = document.body().expect("document should have a body");

    let el_start_value = document
        .get_element_by_id("start")
        .unwrap()
        .dyn_into::<HtmlInputElement>()
        .unwrap()
        .value();
    let el_primes_value = document
        .get_element_by_id("primes")
        .unwrap()
        .dyn_into::<HtmlInputElement>()
        .unwrap()
        .value();
    let el_output_textarea = document
        .get_element_by_id("prime_check_list_output")
        .expect("missing output textarea");
    el_output_textarea.set_inner_html(&listy(
        el_start_value.parse::<u64>().unwrap(),
        el_primes_value.parse::<u64>().unwrap(),
    ));
    ()
}

pub fn render() -> Node<Msg> {
    div![
        h1!["Primality Test, Calculate Primes"],
        br![],
        br![],
        br![],
        table![
            attrs! {At::Class => "text", At::Width => "300", At::Style => "border:1px solid #444; background-color:#e0faed"},
            tr![td![
                attrs! {At::Style => "padding: 10px"},
                form![
                    attrs! {At::Id => "primetest", At::OnSubmit => "return false"},
                    "Tool is limited to checking numbers upto 16 digits.",
                    br![],
                    br![],
                    "Is ",
                    input![
                        attrs! {At::Type => "number", At::Size => "19", At::Id => "input", At::Value => "31", At::MaxLength => "16"}
                    ],
                    " prime? ",
                    button![
                        "Check!",
                        mouse_ev("mouseup", move |_event| Msg::PrimalityChecker(go_crunch()))
                    ],
                    br![],
                    br![],
                    textarea![
                        attrs! {At::Id => "prime_check_output", At::Cols => 60, At::Rows => 2, At::Disabled => "disabled"}
                    ]
                ]
            ]]
        ],
        br![],
        br![],
        table![
            attrs! {At::Class => "text", At::Width => "300", At::Style => "border:1px solid #444; background-color:#e0faed"},
            tr![td![
                attrs! {At::Style => "padding: 10px"},
                form![
                    attrs! {At::Id => "primelist", At::OnSubmit => "return false"},
                    "This tool is limited to checking numbers upto 15 digits.",
                    br![],
                    br![],
                    "This will show ",
                    input![
                        attrs! {At::Type => "number", At::Size => "4", At::Id => "primes", At::Value => "5", At::MaxLength => "2"}
                    ],
                    " prime numbers after ",
                    input![
                        attrs! {At::Type => "number", At::Size => "19", At::Id => "start", At::Value => "31", At::MaxLength => "15"}
                    ],
                    " ",
                    button![
                        "Go!",
                        mouse_ev("mouseup", move |_event| Msg::PrimalityChecker(go_list()))
                    ],
                    br![],
                    br![],
                    textarea![
                        attrs! {At::Id => "prime_check_list_output", At::Cols => 60, At::Rows => 10, At::Disabled => "disabled"}
                    ]
                ]
            ]]
        ]
    ]
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn trial_divide_test() {
        assert_eq!(trial_divide(2, 2), 2);
        assert_eq!(trial_divide(3, 4), 3);
        assert_eq!(trial_divide(30, 10000), 2);
        assert_eq!(trial_divide(7777771, 10000), 29);
        assert_eq!(trial_divide(7777771111111111, 10000), 11);
        //in the case of a prime
        assert_eq!(trial_divide(777777111111113, 10000), 0);
    }

    #[test]
    fn sprp_test() {
        assert_eq!(sprp(27, 5), false);
        assert_eq!(sprp(31, 7), true);
        assert_eq!(sprp(217, 7), false);
        assert_eq!(sprp(19, 13), true);
    }
}
<|endoftext|>


<commit_before>use basetypes::*;
use position::castling_rights::*;

/// Represents a move on the chessboard.
///
/// `Move` contains 3 types of information:
///
/// 1. Information about the played move itself.
///
/// 2. Information needed so as to be able to undo the move and
///    restore the board into the exact same state as before.
///
/// 3. The move score -- moves with higher score are tried
///    first. Ideally the best move should have the highest score.
///
/// `Move` is a 32-bit unsigned number. The lowest 16 bits contain the
/// whole needed information about the move itself (type 1). And is
/// laid out the following way:
///
///  ```text
///   15                                                           0
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
///  | Move  |    Origin square      |   Destination square  | Aux   |
///  | type  |       6 bits          |        6 bits         | data  |
///  | 2 bits|   |   |   |   |   |   |   |   |   |   |   |   | 2 bits|
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |       |
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  ```
///
/// There are 4 "move type"s: `0`) normal move; `1`) en-passant
/// capture; `2`) pawn promotion; `3`) castling. "Aux data" encodes
/// the type of the promoted piece if the move type is a pawn
/// promotion, otherwise it encodes castling rights (see below).
///
/// The highest 16 bits contain the rest ot the info:
///
///  ```text
///   31                                                          16
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
///  |  Move score   |  Captured |  Played   | Cast- |   En-passant  |
///  |    4 bits     |  piece    |  piece    | ling  |      file     |
///  |   |   |   |   |  3 bits   |  3 bits   | 2 bits|     4 bits    |
///  |   |   |   |   |   |   |   |   |   |   |       |   |   |   |   |
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  ```
///
/// "En-passant file" tells on what vertical line on the board there
/// was a passing pawn before the move was played. If there was no
/// passing pawn, "en-passant file" should be `NO_ENPASSANT_FILE`.
///
/// Castling rights are a bit complex. The castling rights for the side
/// that makes the move, before the move was made, are stored in the
/// "Aux data" field. This is OK, because promoting a pawn never
/// changes the moving player's castling rights. The castling rights
/// for the opposite side are stored in "Castling" field. (A move can
/// change the castling rights for the other side when a rook in the
/// corner is captured.)
///
/// When "Captured piece" is stored, its bits are inverted, so that
/// MVV-LVA (Most valuable victim -- least valuable aggressor) ordering
/// of the moves is preserved, even when the "Move score" field stays
/// the same.
#[derive(Debug)]
#[derive(Clone, Copy)]
#[derive(PartialOrd, Ord, PartialEq, Eq)]
pub struct Move(u32);

impl Move {
    /// Creates a new instance of `Move`.
    ///
    /// `us` is the side that makes the move. `castling` are the
    /// castling rights before the move was
    /// played. `promoted_piece_code` should be a number between `0`
    /// and `3` and is used only when the `move_type` is a pawn
    /// promotion, otherwise it is ignored.
    #[inline]
    pub fn new(us: Color,
               score: usize,
               move_type: MoveType,
               piece: PieceType,
               orig_square: Square,
               dest_square: Square,
               captured_piece: PieceType,
               en_passant_file: File,
               castling: CastlingRights,
               promoted_piece_code: usize)
               -> Move {
        assert!(us <= 1);
        assert!(score <= 0b1111);
        assert!(move_type <= 0x11);
        assert!(piece < NO_PIECE);
        assert!(orig_square <= 63);
        assert!(dest_square <= 63);
        assert!(captured_piece != KING && captured_piece <= NO_PIECE);
        assert!(en_passant_file <= 0b1000);
        assert!(promoted_piece_code <= 0b11);
        let aux_data = match move_type {
            MOVE_PROMOTION => promoted_piece_code,
            _ => castling.get_for(us),
        };
        Move((score << M_SHIFT_SCORE | (!captured_piece & 0b111) << M_SHIFT_CAPTURED_PIECE |
              piece << M_SHIFT_PIECE |
              castling.get_for(1 ^ us) << M_SHIFT_CASTLING_DATA |
              en_passant_file << M_SHIFT_ENPASSANT_FILE |
              move_type << M_SHIFT_MOVE_TYPE | orig_square << M_SHIFT_ORIG_SQUARE |
              dest_square << M_SHIFT_DEST_SQUARE |
              aux_data << M_SHIFT_AUX_DATA) as u32)
    }

    /// Sets the "move score" field to a particular value.
    #[inline]
    pub fn set_score(&mut self, score: usize) {
        assert!(score <= 0b1111);
        self.0 &= !M_MASK_SCORE;
        self.0 |= (score << M_SHIFT_SCORE) as u32;
    }

    /// Sets a particular bit in the "move score" field to `1`.
    #[inline]
    pub fn set_score_bit(&mut self, b: usize) {
        assert!(b <= 3);
        self.0 |= 1 << b << M_SHIFT_SCORE;
    }

    /// Sets a particular bit in the "move score" field to `0`.
    #[inline]
    pub fn clear_score_bit(&mut self, b: usize) {
        assert!(b <= 3);
        self.0 &= !(1 << b << M_SHIFT_SCORE);
    }

    #[inline]
    pub fn score(&self) -> usize {
        ((self.0 & M_MASK_SCORE) >> M_SHIFT_SCORE) as usize
    }

    #[inline]
    pub fn move_type(&self) -> MoveType {
        ((self.0 & M_MASK_MOVE_TYPE) >> M_SHIFT_MOVE_TYPE) as MoveType
    }

    #[inline]
    pub fn piece(&self) -> PieceType {
        ((self.0 & M_MASK_PIECE) >> M_SHIFT_PIECE) as PieceType
    }

    #[inline]
    pub fn orig_square(&self) -> Square {
        ((self.0 & M_MASK_ORIG_SQUARE) >> M_SHIFT_ORIG_SQUARE) as Square
    }

    #[inline]
    pub fn dest_square(&self) -> Square {
        ((self.0 & M_MASK_DEST_SQUARE) >> M_SHIFT_DEST_SQUARE) as Square
    }

    #[inline]
    pub fn captured_piece(&self) -> PieceType {
        ((!self.0 & M_MASK_CAPTURED_PIECE) >> M_SHIFT_CAPTURED_PIECE) as PieceType
    }

    #[inline]
    pub fn en_passant_file(&self) -> File {
        ((self.0 & M_MASK_ENPASSANT_FILE) >> M_SHIFT_ENPASSANT_FILE) as File
    }

    #[inline(always)]
    pub fn castling_data(&self) -> usize {
        ((self.0 & M_MASK_CASTLING_DATA) >> M_SHIFT_CASTLING_DATA) as usize
    }

    #[inline(always)]
    pub fn aux_data(&self) -> usize {
        ((self.0 & M_MASK_AUX_DATA) >> M_SHIFT_AUX_DATA) as usize
    }

    /// Returns the algebraic notation of the move.
    pub fn notation(&self) -> String {
        format!("{}{}{}",
                notation(self.orig_square()),
                notation(self.dest_square()),
                match self.move_type() {
                    MOVE_PROMOTION => ["q", "r", "b", "n"][self.aux_data()],
                    _ => "",
                })
    }

    /// Decodes the promoted piece type from the raw value of "aux
    /// data".
    ///
    /// When the "move type" is pawn promotion, "aux data" holds the
    /// promoted piece type encoded with a number from 0 to 3. This
    /// function decodes this number to a piece type.
    #[inline]
    pub fn piece_from_aux_data(pp_code: usize) -> PieceType {
        assert!(pp_code <= 3);
        match pp_code {
            0 => QUEEN,
            1 => ROOK,
            2 => BISHOP,
            _ => KNIGHT,
        }
    }
}

/// Can be normal move, castling, en-passant capture, or pawn
/// promotion.
pub type MoveType = usize;

/// Normal move type.
pub const MOVE_NORMAL: MoveType = 0;

/// En-passant capture move type.
pub const MOVE_ENPASSANT: MoveType = 1;

/// Pawn promotion move type.
pub const MOVE_PROMOTION: MoveType = 2;

/// Castling move type.
pub const MOVE_CASTLING: MoveType = 3;

/// Represents no en-passant file.
pub const NO_ENPASSANT_FILE: Rank = 8;

// Field shifts
const M_SHIFT_SCORE: u32 = 28;
const M_SHIFT_CAPTURED_PIECE: u32 = 25;
const M_SHIFT_PIECE: u32 = 22;
const M_SHIFT_CASTLING_DATA: u32 = 20;
const M_SHIFT_ENPASSANT_FILE: u32 = 16;
const M_SHIFT_MOVE_TYPE: u32 = 14;
const M_SHIFT_ORIG_SQUARE: u32 = 8;
const M_SHIFT_DEST_SQUARE: u32 = 2;
const M_SHIFT_AUX_DATA: u32 = 0;

// Field masks
const M_MASK_SCORE: u32 = 0b1111 << M_SHIFT_SCORE;
const M_MASK_CAPTURED_PIECE: u32 = 0b111 << M_SHIFT_CAPTURED_PIECE;
const M_MASK_PIECE: u32 = 0b111 << M_SHIFT_PIECE;
const M_MASK_CASTLING_DATA: u32 = 0b11 << M_SHIFT_CASTLING_DATA;
const M_MASK_ENPASSANT_FILE: u32 = 0b1111 << M_SHIFT_ENPASSANT_FILE;
const M_MASK_MOVE_TYPE: u32 = 0b11 << M_SHIFT_MOVE_TYPE;
const M_MASK_ORIG_SQUARE: u32 = 0b111111 << M_SHIFT_ORIG_SQUARE;
const M_MASK_DEST_SQUARE: u32 = 0b111111 << M_SHIFT_DEST_SQUARE;
const M_MASK_AUX_DATA: u32 = 0b11 << M_SHIFT_AUX_DATA;

// TODO: Here does not seem to be the right place for
// "MoveStack". Find it other owner.
const MOVE_STACK_SIZE: usize = 32 * 256;

pub struct MoveStack {
    stack: [Move; MOVE_STACK_SIZE],
    next_index: usize,
}

impl MoveStack {
    pub fn new() -> MoveStack {
        use std::mem::uninitialized;
        unsafe {
            MoveStack {
                stack: uninitialized(),
                next_index: 0,
            }
        }
    }

    #[inline(always)]
    pub fn push(&mut self, m: Move) {
        self.stack[self.next_index] = m;
        self.next_index += 1;
    }

    #[inline(always)]
    pub fn pop(&mut self) -> Option<Move> {
        if self.next_index == 0 {
            None
        } else {
            self.next_index -= 1;
            Some(self.stack[self.next_index])
        }
    }

    #[inline(always)]
    pub fn remove_all(&mut self) -> usize {
        let count = self.count();
        self.next_index = 0;
        count
    }

    #[inline(always)]
    pub fn count(&self) -> usize {
        self.next_index
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use position::castling_rights::CastlingRights;

    #[test]
    fn test_move() {
        use basetypes::*;

        let mut cr = CastlingRights::new();
        cr.set_for(WHITE, 0b10);
        cr.set_for(BLACK, 0b11);
        let mut m = Move::new(WHITE,
                              12,
                              MOVE_NORMAL,
                              PAWN,
                              E2,
                              E4,
                              NO_PIECE,
                              NO_ENPASSANT_FILE,
                              cr,
                              0);
        let n1 = Move::new(WHITE,
                           12,
                           MOVE_NORMAL,
                           PAWN,
                           F3,
                           E4,
                           KNIGHT,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n2 = Move::new(WHITE,
                           12,
                           MOVE_NORMAL,
                           KING,
                           F3,
                           E4,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n3 = Move::new(BLACK,
                           0,
                           MOVE_PROMOTION,
                           PAWN,
                           F2,
                           F1,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           1);
        assert!(n1 > m);
        assert!(n2 < m);
        assert_eq!(m.score(), 12);
        assert_eq!(m.piece(), PAWN);
        assert_eq!(m.captured_piece(), NO_PIECE);
        assert_eq!(m.orig_square(), E2);
        assert_eq!(m.dest_square(), E4);
        assert_eq!(m.en_passant_file(), 8);
        assert_eq!(m.aux_data(), 0b10);
        assert_eq!(m.castling_data(), 0b11);
        let m2 = m;
        assert_eq!(m, m2);
        m.set_score(13);
        assert_eq!(m.score(), 13);
        assert!(m > m2);
        m.clear_score_bit(0);
        assert_eq!(m, m2);
        m.set_score_bit(0);
        assert_eq!(m.score(), 13);
        m.set_score(0);
        assert_eq!(m.score(), 0);
        assert_eq!(n3.aux_data(), 1);
    }
}
<commit_msg>change move type constants<commit_after>use basetypes::*;
use position::castling_rights::*;

/// Represents a move on the chessboard.
///
/// `Move` contains 3 types of information:
///
/// 1. Information about the played move itself.
///
/// 2. Information needed so as to be able to undo the move and
///    restore the board into the exact same state as before.
///
/// 3. The move score -- moves with higher score are tried
///    first. Ideally the best move should have the highest score.
///
/// `Move` is a 32-bit unsigned number. The lowest 16 bits contain the
/// whole needed information about the move itself (type 1). And is
/// laid out the following way:
///
///  ```text
///   15                                                           0
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
///  | Move  |    Origin square      |   Destination square  | Aux   |
///  | type  |       6 bits          |        6 bits         | data  |
///  | 2 bits|   |   |   |   |   |   |   |   |   |   |   |   | 2 bits|
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |       |
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  ```
///
/// There are 4 "move type"s: `0`) en-passant capture; `1`) pawn
/// promotion; `2`) castling; `3`) normal move. "Aux data" encodes the
/// type of the promoted piece if the move type is a pawn promotion,
/// otherwise it encodes castling rights (see below).
///
/// The highest 16 bits contain the rest ot the info:
///
///  ```text
///   31                                                          16
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
///  |  Move score   |  Captured |  Played   | Cast- |   En-passant  |
///  |    4 bits     |  piece    |  piece    | ling  |      file     |
///  |   |   |   |   |  3 bits   |  3 bits   | 2 bits|     4 bits    |
///  |   |   |   |   |   |   |   |   |   |   |       |   |   |   |   |
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  ```
///
/// "En-passant file" tells on what vertical line on the board there
/// was a passing pawn before the move was played. If there was no
/// passing pawn, "en-passant file" should be `NO_ENPASSANT_FILE`.
///
/// Castling rights are a bit complex. The castling rights for the side
/// that makes the move, before the move was made, are stored in the
/// "Aux data" field. This is OK, because promoting a pawn never
/// changes the moving player's castling rights. The castling rights
/// for the opposite side are stored in "Castling" field. (A move can
/// change the castling rights for the other side when a rook in the
/// corner is captured.)
///
/// When "Captured piece" is stored, its bits are inverted, so that
/// MVV-LVA (Most valuable victim -- least valuable aggressor) ordering
/// of the moves is preserved, even when the "Move score" field stays
/// the same.
#[derive(Debug)]
#[derive(Clone, Copy)]
#[derive(PartialOrd, Ord, PartialEq, Eq)]
pub struct Move(u32);

impl Move {
    /// Creates a new instance of `Move`.
    ///
    /// `us` is the side that makes the move. `castling` are the
    /// castling rights before the move was
    /// played. `promoted_piece_code` should be a number between `0`
    /// and `3` and is used only when the `move_type` is a pawn
    /// promotion, otherwise it is ignored.
    #[inline]
    pub fn new(us: Color,
               score: usize,
               move_type: MoveType,
               piece: PieceType,
               orig_square: Square,
               dest_square: Square,
               captured_piece: PieceType,
               en_passant_file: File,
               castling: CastlingRights,
               promoted_piece_code: usize)
               -> Move {
        assert!(us <= 1);
        assert!(score <= 0b1111);
        assert!(move_type <= 0x11);
        assert!(piece < NO_PIECE);
        assert!(orig_square <= 63);
        assert!(dest_square <= 63);
        assert!(captured_piece != KING && captured_piece <= NO_PIECE);
        assert!(en_passant_file <= 0b1000);
        assert!(promoted_piece_code <= 0b11);
        let aux_data = match move_type {
            MOVE_PROMOTION => promoted_piece_code,
            _ => castling.get_for(us),
        };
        Move((score << M_SHIFT_SCORE | (!captured_piece & 0b111) << M_SHIFT_CAPTURED_PIECE |
              piece << M_SHIFT_PIECE |
              castling.get_for(1 ^ us) << M_SHIFT_CASTLING_DATA |
              en_passant_file << M_SHIFT_ENPASSANT_FILE |
              move_type << M_SHIFT_MOVE_TYPE | orig_square << M_SHIFT_ORIG_SQUARE |
              dest_square << M_SHIFT_DEST_SQUARE |
              aux_data << M_SHIFT_AUX_DATA) as u32)
    }

    /// Sets the "move score" field to a particular value.
    #[inline]
    pub fn set_score(&mut self, score: usize) {
        assert!(score <= 0b1111);
        self.0 &= !M_MASK_SCORE;
        self.0 |= (score << M_SHIFT_SCORE) as u32;
    }

    /// Sets a particular bit in the "move score" field to `1`.
    #[inline]
    pub fn set_score_bit(&mut self, b: usize) {
        assert!(b <= 3);
        self.0 |= 1 << b << M_SHIFT_SCORE;
    }

    /// Sets a particular bit in the "move score" field to `0`.
    #[inline]
    pub fn clear_score_bit(&mut self, b: usize) {
        assert!(b <= 3);
        self.0 &= !(1 << b << M_SHIFT_SCORE);
    }

    #[inline]
    pub fn score(&self) -> usize {
        ((self.0 & M_MASK_SCORE) >> M_SHIFT_SCORE) as usize
    }

    #[inline]
    pub fn move_type(&self) -> MoveType {
        ((self.0 & M_MASK_MOVE_TYPE) >> M_SHIFT_MOVE_TYPE) as MoveType
    }

    #[inline]
    pub fn piece(&self) -> PieceType {
        ((self.0 & M_MASK_PIECE) >> M_SHIFT_PIECE) as PieceType
    }

    #[inline]
    pub fn orig_square(&self) -> Square {
        ((self.0 & M_MASK_ORIG_SQUARE) >> M_SHIFT_ORIG_SQUARE) as Square
    }

    #[inline]
    pub fn dest_square(&self) -> Square {
        ((self.0 & M_MASK_DEST_SQUARE) >> M_SHIFT_DEST_SQUARE) as Square
    }

    #[inline]
    pub fn captured_piece(&self) -> PieceType {
        ((!self.0 & M_MASK_CAPTURED_PIECE) >> M_SHIFT_CAPTURED_PIECE) as PieceType
    }

    #[inline]
    pub fn en_passant_file(&self) -> File {
        ((self.0 & M_MASK_ENPASSANT_FILE) >> M_SHIFT_ENPASSANT_FILE) as File
    }

    #[inline(always)]
    pub fn castling_data(&self) -> usize {
        ((self.0 & M_MASK_CASTLING_DATA) >> M_SHIFT_CASTLING_DATA) as usize
    }

    #[inline(always)]
    pub fn aux_data(&self) -> usize {
        ((self.0 & M_MASK_AUX_DATA) >> M_SHIFT_AUX_DATA) as usize
    }

    /// Returns the algebraic notation of the move.
    pub fn notation(&self) -> String {
        format!("{}{}{}",
                notation(self.orig_square()),
                notation(self.dest_square()),
                match self.move_type() {
                    MOVE_PROMOTION => ["q", "r", "b", "n"][self.aux_data()],
                    _ => "",
                })
    }

    /// Decodes the promoted piece type from the raw value of "aux
    /// data".
    ///
    /// When the "move type" is pawn promotion, "aux data" holds the
    /// promoted piece type encoded with a number from 0 to 3. This
    /// function decodes this number to a piece type.
    #[inline]
    pub fn piece_from_aux_data(pp_code: usize) -> PieceType {
        assert!(pp_code <= 3);
        match pp_code {
            0 => QUEEN,
            1 => ROOK,
            2 => BISHOP,
            _ => KNIGHT,
        }
    }
}

/// Can be normal move, castling, en-passant capture, or pawn
/// promotion.
pub type MoveType = usize;

/// En-passant capture move type.
pub const MOVE_ENPASSANT: MoveType = 0;

/// Pawn promotion move type.
pub const MOVE_PROMOTION: MoveType = 1;

/// Castling move type.
pub const MOVE_CASTLING: MoveType = 2;

/// Normal move type.
pub const MOVE_NORMAL: MoveType = 3;

/// Represents no en-passant file.
pub const NO_ENPASSANT_FILE: Rank = 8;

// Field shifts
const M_SHIFT_SCORE: u32 = 28;
const M_SHIFT_CAPTURED_PIECE: u32 = 25;
const M_SHIFT_PIECE: u32 = 22;
const M_SHIFT_CASTLING_DATA: u32 = 20;
const M_SHIFT_ENPASSANT_FILE: u32 = 16;
const M_SHIFT_MOVE_TYPE: u32 = 14;
const M_SHIFT_ORIG_SQUARE: u32 = 8;
const M_SHIFT_DEST_SQUARE: u32 = 2;
const M_SHIFT_AUX_DATA: u32 = 0;

// Field masks
const M_MASK_SCORE: u32 = 0b1111 << M_SHIFT_SCORE;
const M_MASK_CAPTURED_PIECE: u32 = 0b111 << M_SHIFT_CAPTURED_PIECE;
const M_MASK_PIECE: u32 = 0b111 << M_SHIFT_PIECE;
const M_MASK_CASTLING_DATA: u32 = 0b11 << M_SHIFT_CASTLING_DATA;
const M_MASK_ENPASSANT_FILE: u32 = 0b1111 << M_SHIFT_ENPASSANT_FILE;
const M_MASK_MOVE_TYPE: u32 = 0b11 << M_SHIFT_MOVE_TYPE;
const M_MASK_ORIG_SQUARE: u32 = 0b111111 << M_SHIFT_ORIG_SQUARE;
const M_MASK_DEST_SQUARE: u32 = 0b111111 << M_SHIFT_DEST_SQUARE;
const M_MASK_AUX_DATA: u32 = 0b11 << M_SHIFT_AUX_DATA;

// TODO: Here does not seem to be the right place for
// "MoveStack". Find it other owner.
const MOVE_STACK_SIZE: usize = 32 * 256;

pub struct MoveStack {
    stack: [Move; MOVE_STACK_SIZE],
    next_index: usize,
}

impl MoveStack {
    pub fn new() -> MoveStack {
        use std::mem::uninitialized;
        unsafe {
            MoveStack {
                stack: uninitialized(),
                next_index: 0,
            }
        }
    }

    #[inline(always)]
    pub fn push(&mut self, m: Move) {
        self.stack[self.next_index] = m;
        self.next_index += 1;
    }

    #[inline(always)]
    pub fn pop(&mut self) -> Option<Move> {
        if self.next_index == 0 {
            None
        } else {
            self.next_index -= 1;
            Some(self.stack[self.next_index])
        }
    }

    #[inline(always)]
    pub fn remove_all(&mut self) -> usize {
        let count = self.count();
        self.next_index = 0;
        count
    }

    #[inline(always)]
    pub fn count(&self) -> usize {
        self.next_index
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use position::castling_rights::CastlingRights;

    #[test]
    fn test_move() {
        use basetypes::*;

        let mut cr = CastlingRights::new();
        cr.set_for(WHITE, 0b10);
        cr.set_for(BLACK, 0b11);
        let mut m = Move::new(WHITE,
                              12,
                              MOVE_NORMAL,
                              PAWN,
                              E2,
                              E4,
                              NO_PIECE,
                              NO_ENPASSANT_FILE,
                              cr,
                              0);
        let n1 = Move::new(WHITE,
                           12,
                           MOVE_NORMAL,
                           PAWN,
                           F3,
                           E4,
                           KNIGHT,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n2 = Move::new(WHITE,
                           12,
                           MOVE_NORMAL,
                           KING,
                           F3,
                           E4,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n3 = Move::new(BLACK,
                           0,
                           MOVE_PROMOTION,
                           PAWN,
                           F2,
                           F1,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           1);
        assert!(n1 > m);
        assert!(n2 < m);
        assert_eq!(m.score(), 12);
        assert_eq!(m.piece(), PAWN);
        assert_eq!(m.captured_piece(), NO_PIECE);
        assert_eq!(m.orig_square(), E2);
        assert_eq!(m.dest_square(), E4);
        assert_eq!(m.en_passant_file(), 8);
        assert_eq!(m.aux_data(), 0b10);
        assert_eq!(m.castling_data(), 0b11);
        let m2 = m;
        assert_eq!(m, m2);
        m.set_score(13);
        assert_eq!(m.score(), 13);
        assert!(m > m2);
        m.clear_score_bit(0);
        assert_eq!(m, m2);
        m.set_score_bit(0);
        assert_eq!(m.score(), 13);
        m.set_score(0);
        assert_eq!(m.score(), 0);
        assert_eq!(n3.aux_data(), 1);
    }
}
<|endoftext|>