<commit_before>// TODO: cursor visibility (reverse?)

use core::mem;
use core::ptr::Unique;
use spin::Mutex;
use volatile::Volatile;

const SCREEN_HEIGHT: usize = 25;
const SCREEN_WIDTH: usize = 80;
pub const VGA_BUFFER_ADDRESS: usize = 0xb8000;

/// A VGA color
#[allow(dead_code)]
#[repr(u8)]
pub enum Color {
    Black      = 0,
    Blue       = 1,
    Green      = 2,
    Cyan       = 3,
    Red        = 4,
    Magenta    = 5,
    Brown      = 6,
    LightGray  = 7,
    DarkGray   = 8,
    LightBlue  = 9,
    LightGreen = 10,
    LightCyan  = 11,
    LightRed   = 12,
    Pink       = 13,
    Yellow     = 14,
    White      = 15,
}

/// Color of single cell, back- and foreground
#[derive(Clone, Copy)]
pub struct CellColor(u8);

impl CellColor {
    pub const fn new(foreground: Color, background: Color) -> CellColor {
        CellColor((background as u8) << 4 | (foreground as u8))
    }

    pub fn foreground(&self) -> Color {
        unsafe {
            mem::transmute::<u8, Color>(self.0 & 0xf)
        }
    }

    pub fn background(&self) -> Color {
        unsafe {
            mem::transmute::<u8, Color>((self.0 & 0xf0) >> 4)
        }
    }

    pub fn invert(&self) -> CellColor {
        CellColor::new(self.background(), self.foreground())
    }
}

/// Character cell: one character and color in screen
#[derive(Clone, Copy)]
#[repr(C,packed)]
pub struct CharCell {
    pub character: u8,
    pub color: CellColor,
}

/// A Virtual tty buffer
pub struct Buffer {
    pub chars: [[Volatile<CharCell>; SCREEN_WIDTH]; SCREEN_HEIGHT],
}

/// Cursor
pub struct Cursor {
    /// Current row
    pub row: usize,
    /// Current column
    pub col: usize,
}

impl Cursor {
    /// Next character
    pub fn next(&mut self) {
        if self.col < SCREEN_WIDTH {
            self.col+=1;
        }
    }

    /// New line
    /// # Returns
    /// true if terminal should be scrolled
    pub fn newline(&mut self) -> bool {
        self.col = 0;
        if self.row < SCREEN_HEIGHT-1 {
            self.row += 1;
            false
        }
        else {
            true
        }
    }

    /// Set position
    pub fn set_position(&mut self, row: usize, col: usize) {
        assert!(row < SCREEN_HEIGHT);
        assert!(col < SCREEN_WIDTH);

        self.row = row;
        self.col = col;
    }

    pub fn position(&self) -> (usize, usize) {
        (self.row, self.col)
    }
}

/// Terminal: an interface to hardware terminal
pub struct Terminal {
    output_color: CellColor,
    cursor: Cursor,
    buffer: Unique<Buffer>,
}

impl Terminal {
    /// Init terminal
    pub fn reset(&mut self) {
        self.output_color = CellColor::new(Color::White, Color::Black);
        self.clear();
    }

    /// Clear screen
    pub fn clear(&mut self) {
        self.cursor.set_position(0, 0);
        let clear_color = self.output_color;
        let buffer = self.get_buffer();
        for col in 0..SCREEN_WIDTH {
            for row in 0..SCREEN_HEIGHT {
                buffer.chars[row][col].write(CharCell {
                    character: b' ',
                    color: clear_color,
                });
            }
        }
    }

    /// Clear screen
    pub fn update_cursor(&mut self) {
        let color = self.output_color.invert();
        let (row, col) = self.cursor.position();

        let buffer = self.get_buffer();
        buffer.chars[row][col].update(|cell| {
            cell.color = color;
        });
    }

    /// Write single byte to terminal's stdout
    pub fn write_byte(&mut self, byte: u8) {
        if byte == b'\n' {
            self.newline();
        }
        else {
            assert!(self.cursor.col < SCREEN_WIDTH);

            let color = self.output_color;
            let (row, col) = self.cursor.position();

            self.get_buffer().chars[row][col].write(CharCell {
                character: byte,
                color: color
            });

            self.cursor.next();

            if self.cursor.col >= SCREEN_WIDTH {
                self.newline();
            }

            self.update_cursor();
        }
    }

    /// Set color
    pub fn set_color(&mut self, color: CellColor) {
        self.output_color = color;
    }

    /// Newline
    pub fn newline(&mut self) {
        let scroll = self.cursor.newline();
        if scroll {
            self.scroll_line();
        }
    }

    /// Scroll up one line
    fn scroll_line(&mut self) {
        for row in 0..(SCREEN_HEIGHT-1) {
            for col in 0..SCREEN_WIDTH {
                let new_value = self.get_buffer().chars[row+1][col].read();
                self.get_buffer().chars[row][col].write(new_value);
            }
        }
        for col in 0..SCREEN_WIDTH {
            let color = self.output_color;
            self.get_buffer().chars[SCREEN_HEIGHT-1][col].write(CharCell {character: b' ', color: color});
        }
    }

    /// Get pointer to memory buffer
    fn get_buffer(&mut self) -> &mut Buffer {
        unsafe {self.buffer.as_mut()}
    }
}

/// Allow formatting
impl ::core::fmt::Write for Terminal {
    fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
        if s.bytes().all(|b| b.is_ascii_whitespace()) {
            self.set_color(CellColor::new(Color::White, Color::Blue));
        }
        else {
            self.set_color(CellColor::new(Color::White, Color::Green));
        }
        for byte in s.bytes() {
            self.write_byte(byte)
        }
        Ok(())  // Success. Always.
    }
}

/// Actual print function. This should only be externally called using the rprint! and rprintln! macros.
pub fn print(fmt: ::core::fmt::Arguments) {
    use core::fmt::Write;
    TERMINAL.lock().write_fmt(fmt).unwrap();
}

// Create static pointer mutex with spinlock to make TERMINAL thread-safe
pub static TERMINAL: Mutex<Terminal> = Mutex::new(Terminal {
    output_color: CellColor::new(Color::White, Color::Black),
    cursor: Cursor {row: 0, col: 0},
    buffer: unsafe { Unique::new_unchecked(VGA_BUFFER_ADDRESS as *mut _) },
});

/// "Raw" output macros
macro_rules! rprint {
    ($($arg:tt)*) => ({
        $crate::vga_buffer::print(format_args!($($arg)*));
    });
}
macro_rules! rprintln {
    ($fmt:expr) => (rprint!(concat!($fmt, "\n")));
    ($fmt:expr, $($arg:tt)*) => (rprint!(concat!($fmt, "\n"), $($arg)*));
}
macro_rules! rreset {
    () => ({
        $crate::vga_buffer::TERMINAL.lock().reset();
    });
}
macro_rules! rforce_unlock {
    () => ({
        $crate::vga_buffer::TERMINAL.force_unlock();
    });
}
macro_rules! panic_indicator {
    ($x:expr) => ({
        asm!(concat!("mov eax, ", stringify!($x), "; mov [0xb809c], eax") ::: "eax", "memory" : "volatile", "intel");
    });
    () => ({
        panic_indicator!(0x4f214f70);   // !p
    });
}
<commit_msg>Remove useless cursor visiblity<commit_after>use core::mem;
use core::ptr::Unique;
use spin::Mutex;
use volatile::Volatile;

const SCREEN_HEIGHT: usize = 25;
const SCREEN_WIDTH: usize = 80;
pub const VGA_BUFFER_ADDRESS: usize = 0xb8000;

/// A VGA color
#[allow(dead_code)]
#[repr(u8)]
pub enum Color {
    Black      = 0,
    Blue       = 1,
    Green      = 2,
    Cyan       = 3,
    Red        = 4,
    Magenta    = 5,
    Brown      = 6,
    LightGray  = 7,
    DarkGray   = 8,
    LightBlue  = 9,
    LightGreen = 10,
    LightCyan  = 11,
    LightRed   = 12,
    Pink       = 13,
    Yellow     = 14,
    White      = 15,
}

/// Color of single cell, back- and foreground
#[derive(Clone, Copy)]
pub struct CellColor(u8);

impl CellColor {
    pub const fn new(foreground: Color, background: Color) -> CellColor {
        CellColor((background as u8) << 4 | (foreground as u8))
    }

    pub fn foreground(&self) -> Color {
        unsafe {
            mem::transmute::<u8, Color>(self.0 & 0xf)
        }
    }

    pub fn background(&self) -> Color {
        unsafe {
            mem::transmute::<u8, Color>((self.0 & 0xf0) >> 4)
        }
    }

    pub fn invert(&self) -> CellColor {
        CellColor::new(self.background(), self.foreground())
    }
}

/// Character cell: one character and color in screen
#[derive(Clone, Copy)]
#[repr(C,packed)]
pub struct CharCell {
    pub character: u8,
    pub color: CellColor,
}

/// A Virtual tty buffer
pub struct Buffer {
    pub chars: [[Volatile<CharCell>; SCREEN_WIDTH]; SCREEN_HEIGHT],
}

/// Cursor
pub struct Cursor {
    /// Current row
    pub row: usize,
    /// Current column
    pub col: usize,
}

impl Cursor {
    /// Next character
    pub fn next(&mut self) {
        if self.col < SCREEN_WIDTH {
            self.col+=1;
        }
    }

    /// New line
    /// # Returns
    /// true if terminal should be scrolled
    pub fn newline(&mut self) -> bool {
        self.col = 0;
        if self.row < SCREEN_HEIGHT-1 {
            self.row += 1;
            false
        }
        else {
            true
        }
    }

    /// Set position
    pub fn set_position(&mut self, row: usize, col: usize) {
        assert!(row < SCREEN_HEIGHT);
        assert!(col < SCREEN_WIDTH);

        self.row = row;
        self.col = col;
    }

    pub fn position(&self) -> (usize, usize) {
        (self.row, self.col)
    }
}

/// Terminal: an interface to hardware terminal
pub struct Terminal {
    output_color: CellColor,
    cursor: Cursor,
    buffer: Unique<Buffer>,
}

impl Terminal {
    /// Init terminal
    pub fn reset(&mut self) {
        self.output_color = CellColor::new(Color::White, Color::Black);
        self.clear();
    }

    /// Clear screen
    pub fn clear(&mut self) {
        self.cursor.set_position(0, 0);
        let clear_color = self.output_color;
        let buffer = self.get_buffer();
        for col in 0..SCREEN_WIDTH {
            for row in 0..SCREEN_HEIGHT {
                buffer.chars[row][col].write(CharCell {
                    character: b' ',
                    color: clear_color,
                });
            }
        }
    }

    /// Write single byte to terminal's stdout
    pub fn write_byte(&mut self, byte: u8) {
        if byte == b'\n' {
            self.newline();
        }
        else {
            assert!(self.cursor.col < SCREEN_WIDTH);

            let color = self.output_color;
            let (row, col) = self.cursor.position();

            self.get_buffer().chars[row][col].write(CharCell {
                character: byte,
                color: color
            });

            self.cursor.next();

            if self.cursor.col >= SCREEN_WIDTH {
                self.newline();
            }
        }
    }

    /// Set color
    pub fn set_color(&mut self, color: CellColor) {
        self.output_color = color;
    }

    /// Newline
    pub fn newline(&mut self) {
        let scroll = self.cursor.newline();
        if scroll {
            self.scroll_line();
        }
    }

    /// Scroll up one line
    fn scroll_line(&mut self) {
        // move lines up
        for row in 0..(SCREEN_HEIGHT-1) {
            for col in 0..SCREEN_WIDTH {
                let new_value = self.get_buffer().chars[row+1][col].read();
                self.get_buffer().chars[row][col].write(new_value);
            }
        }
        // clear the bottom line
        for col in 0..SCREEN_WIDTH {
            let color = self.output_color;
            self.get_buffer().chars[SCREEN_HEIGHT-1][col].write(CharCell {character: b' ', color: color});
        }
    }

    /// Get pointer to memory buffer
    fn get_buffer(&mut self) -> &mut Buffer {
        unsafe {self.buffer.as_mut()}
    }
}

/// Allow formatting
impl ::core::fmt::Write for Terminal {
    fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
        for byte in s.bytes() {
            self.write_byte(byte)
        }
        Ok(())  // Success. Always.
    }
}

/// Actual print function. This should only be externally called using the rprint! and rprintln! macros.
pub fn print(fmt: ::core::fmt::Arguments) {
    use core::fmt::Write;
    TERMINAL.lock().write_fmt(fmt).unwrap();
}

// Create static pointer mutex with spinlock to make TERMINAL thread-safe
pub static TERMINAL: Mutex<Terminal> = Mutex::new(Terminal {
    output_color: CellColor::new(Color::White, Color::Black),
    cursor: Cursor {row: 0, col: 0},
    buffer: unsafe { Unique::new_unchecked(VGA_BUFFER_ADDRESS as *mut _) },
});

/// "Raw" output macros
macro_rules! rprint {
    ($($arg:tt)*) => ({
        $crate::vga_buffer::print(format_args!($($arg)*));
    });
}
macro_rules! rprintln {
    ($fmt:expr) => (rprint!(concat!($fmt, "\n")));
    ($fmt:expr, $($arg:tt)*) => (rprint!(concat!($fmt, "\n"), $($arg)*));
}
macro_rules! rreset {
    () => ({
        $crate::vga_buffer::TERMINAL.lock().reset();
    });
}
macro_rules! rforce_unlock {
    () => ({
        $crate::vga_buffer::TERMINAL.force_unlock();
    });
}
macro_rules! panic_indicator {
    ($x:expr) => ({
        asm!(concat!("mov eax, ", stringify!($x), "; mov [0xb809c], eax") ::: "eax", "memory" : "volatile", "intel");
    });
    () => ({
        panic_indicator!(0x4f214f70);   // !p
    });
}
<|endoftext|>


<commit_before>use prelude::*;

use BytesError;

use winapi::shared::guiddef;

impl Uuid {
    /// Attempts to create a [`Uuid`] from a winapi `GUID`
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    fn from_guid(guid: guiddef::GUID) -> Result<Uuid, BytesError> {
        Uuid::from_fields(
            guid.Data1 as u32,
            guid.Data2 as u16,
            guid.Data3 as u16,
            &(guid.Data4 as [u8; 8]),
        )
    }

    /// Converts a [`Uuid`] into a little endian winapi `GUID`
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    fn to_guid(&self) -> guiddef::GUID {
        let (data1, data2, data3, data4) = self.as_fields();

        guiddef::GUID {
            Data1: data1,
            Data2: data2,
            Data3: data3,
            Data4: *data4,
        }
    }
}

#[cfg(test)]
mod tests {
    use prelude::*;
    use std::str::FromStr;
    use winapi::shared::guiddef;

    #[test]
    fn test_to_uuid() {
        let uuid = Uuid::from_str("735d359d-4bc4-4e07-8c49-eb3e99a048dc").unwrap();
        let guid = uuid.to_guid();
        assert_eq!(Ok(uuid), Uuid::from_guid(guid));
    }

    #[test]
    fn test_from_guid() {
        let guid = guiddef::GUID {
            Data1: 0x4a35229d,
            Data2: 0x5527,
            Data3: 0x4f30,
            Data4: [0x86, 0x47, 0x9d, 0xc5, 0x4e, 0x1e, 0xe1, 0xe8],
        };

        let uuid = Uuid::from_guid(guid).unwrap();
        assert_eq!("4a35229d-5527-4f30-8647-9dc54e1ee1e8", uuid.to_hyphenated().to_string());
        assert_eq!(Ok(uuid), Uuid::from_guid(guid));
    }
}<commit_msg>Run cargo fmt<commit_after>use prelude::*;

use BytesError;

use winapi::shared::guiddef;

impl Uuid {
    /// Attempts to create a [`Uuid`] from a winapi `GUID`
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    fn from_guid(guid: guiddef::GUID) -> Result<Uuid, BytesError> {
        Uuid::from_fields(
            guid.Data1 as u32,
            guid.Data2 as u16,
            guid.Data3 as u16,
            &(guid.Data4 as [u8; 8]),
        )
    }

    /// Converts a [`Uuid`] into a little endian winapi `GUID`
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    fn to_guid(&self) -> guiddef::GUID {
        let (data1, data2, data3, data4) = self.as_fields();

        guiddef::GUID {
            Data1: data1,
            Data2: data2,
            Data3: data3,
            Data4: *data4,
        }
    }
}

#[cfg(test)]
mod tests {
    use prelude::*;
    use std::str::FromStr;
    use winapi::shared::guiddef;

    #[test]
    fn test_to_uuid() {
        let uuid =
            Uuid::from_str("735d359d-4bc4-4e07-8c49-eb3e99a048dc").unwrap();
        let guid = uuid.to_guid();
        assert_eq!(Ok(uuid), Uuid::from_guid(guid));
    }

    #[test]
    fn test_from_guid() {
        let guid = guiddef::GUID {
            Data1: 0x4a35229d,
            Data2: 0x5527,
            Data3: 0x4f30,
            Data4: [0x86, 0x47, 0x9d, 0xc5, 0x4e, 0x1e, 0xe1, 0xe8],
        };

        let uuid = Uuid::from_guid(guid).unwrap();
        assert_eq!(
            "4a35229d-5527-4f30-8647-9dc54e1ee1e8",
            uuid.to_hyphenated().to_string()
        );
        assert_eq!(Ok(uuid), Uuid::from_guid(guid));
    }
}
<|endoftext|>


<commit_before>// TOML test suite for [1]
//
// [1]: https://github.com/BurntSushi/toml-test
//
// If given a path, it will perform the same tests like toml-test [1],
// so no need to install "go" :).

extern crate extra = "extra#0.10-pre";
extern crate collections = "collections#0.10-pre";
extern crate toml = "toml#0.1";

use extra::json::{Json,String,List,Object};

use collections::treemap::TreeMap;
use toml::{Unsigned,Signed,Float};
use std::os;
use std::path::Path;
use std::io::fs::walk_dir;
use std::io::File;

fn to_json_type(typ: ~str, val: Json) -> Json {
    let mut tree = ~TreeMap::new();
    tree.insert(~"type", String(typ));
    tree.insert(~"value", val);
    Object(tree)
}

fn format_float(f: f64) -> ~str {
    let str = format!("{:.15f}", f);
    let str = str.as_slice();
    let str = str.trim_right_chars(&'0');
    if str.ends_with(".") {
      str.to_owned() + "0"
    } else {
      str.to_owned()
    }
}

fn to_json(v: &toml::Value) -> Json {
    match v {
        &toml::NoValue => { fail!("Invalid toml document"); }
        &toml::Table(_, ref map) => {
            let mut tree = ~TreeMap::new();
            for (k, v) in map.iter() {
                tree.insert(k.clone(), to_json(v));
            }
            Object(tree)
        }
        &toml::TableArray(ref arr) => {
            List(arr.map(|i| to_json(i)))
        }
        &toml::Array(ref arr) => {
            let list = arr.map(|i| to_json(i));
            to_json_type(~"array", List(list))
        }
        &toml::Boolean(true) => { to_json_type(~"bool", String(~"true")) }
        &toml::Boolean(false) => { to_json_type(~"bool", String(~"false")) }
        &Unsigned(n) => { to_json_type(~"integer", String(n.to_str())) }
        &Signed(n) => { to_json_type(~"integer", String("-" + n.to_str())) }
        &Float(n) => { to_json_type(~"float", String(format_float(n))) }
        &toml::String(ref str) => { to_json_type(~"string", String(str.clone())) }
        &toml::Datetime(y,m,d,h,mi,s) => {
            let s = format!("{:04u}-{:02u}-{:02u}T{:02u}:{:02u}:{:02u}Z", y,m,d,h,mi,s);
            to_json_type(~"datetime", String(s))
        }
    }
}

fn toml_test_runner() {
    let toml = toml::parse_from_bytes(std::io::stdin().read_to_end().unwrap()).unwrap();
    let json = to_json(&toml);
    println!("{:s}", json.to_pretty_str());
}

fn independent_test_runner(path: ~str) {
  let path = Path::new(path);
  let mut tests: int = 0;
  let mut failed: int = 0;
  let mut passed: int = 0;

  for filename in walk_dir(&path.join("invalid")).unwrap() {
    if filename.is_file() && filename.extension_str() == Some("toml") {
      println!("TEST/INVALID: {}", filename.filename_display());
      tests += 1;

      match toml::parse_from_path(&filename) {
          Err(_) => {
              passed += 1;
              println!("   [PASS]");
          }
          _ => {
              failed += 1;
              println!("   [FAIL]");
          }
      }
    }
  }

  for filename in walk_dir(&path.join("valid")).unwrap() {
    if filename.is_file() && filename.extension_str() == Some("toml") {
      let jsonfile = filename.with_extension("json");
      if !jsonfile.is_file() { fail!() }

      println!("TEST/VALID:   {}", filename.filename_display());

      let jsonbytes = File::open(&Path::new(jsonfile)).read_to_end().unwrap();
      let jsonstr = std::str::from_utf8(jsonbytes).unwrap();

      let result = extra::json::from_str(jsonstr);
      if result.is_err() { fail!() }

      tests += 1;

      let json = result.unwrap();
      let toml = toml::parse_from_path(&filename);
      let toml_json = toml.map(|t| to_json(&t));

      if Ok(&json) == toml_json.as_ref() {
          passed += 1;
          println!("   [PASS]");
      } else {
          println!("===============================================");
          println!("{:s}", json.to_pretty_str());
          println!("-----------------------------------------------");
          match toml_json {
              Ok(json) => println!("{:s}", json.to_pretty_str()),
              Err(toml::ParseError) => println!("(parse error)"),
              Err(toml::IOError(e)) => println!("({})", e)
          }
          println!("===============================================");
          failed += 1;
          println!("   [FAIL]");
      }
    }
  }

  println!("");
  println!("Tests/PASS/FAIL: {:d}/{:d}/{:d}", tests, passed, failed);
  if failed > 0 { fail!(); }
}

fn main() {
    match os::args().len() {
      1 => toml_test_runner(),
      2 => independent_test_runner(path),
      _ => fail!("USAGE: {:s} [path]", os::args()[0]),
    }
}
<commit_msg>Fix testrunner<commit_after>// TOML test suite for [1]
//
// [1]: https://github.com/BurntSushi/toml-test
//
// If given a path, it will perform the same tests like toml-test [1],
// so no need to install "go" :).

extern crate extra = "extra#0.10-pre";
extern crate collections = "collections#0.10-pre";
extern crate toml = "toml#0.1";

use extra::json::{Json,String,List,Object};

use collections::treemap::TreeMap;
use toml::{Unsigned,Signed,Float};
use std::os;
use std::path::Path;
use std::io::fs::walk_dir;
use std::io::File;

fn to_json_type(typ: ~str, val: Json) -> Json {
    let mut tree = ~TreeMap::new();
    tree.insert(~"type", String(typ));
    tree.insert(~"value", val);
    Object(tree)
}

fn format_float(f: f64) -> ~str {
    let str = format!("{:.15f}", f);
    let str = str.as_slice();
    let str = str.trim_right_chars(&'0');
    if str.ends_with(".") {
      str.to_owned() + "0"
    } else {
      str.to_owned()
    }
}

fn to_json(v: &toml::Value) -> Json {
    match v {
        &toml::NoValue => { fail!("Invalid toml document"); }
        &toml::Table(_, ref map) => {
            let mut tree = ~TreeMap::new();
            for (k, v) in map.iter() {
                tree.insert(k.clone(), to_json(v));
            }
            Object(tree)
        }
        &toml::TableArray(ref arr) => {
            List(arr.map(|i| to_json(i)))
        }
        &toml::Array(ref arr) => {
            let list = arr.map(|i| to_json(i));
            to_json_type(~"array", List(list))
        }
        &toml::Boolean(true) => { to_json_type(~"bool", String(~"true")) }
        &toml::Boolean(false) => { to_json_type(~"bool", String(~"false")) }
        &Unsigned(n) => { to_json_type(~"integer", String(n.to_str())) }
        &Signed(n) => { to_json_type(~"integer", String("-" + n.to_str())) }
        &Float(n) => { to_json_type(~"float", String(format_float(n))) }
        &toml::String(ref str) => { to_json_type(~"string", String(str.clone())) }
        &toml::Datetime(y,m,d,h,mi,s) => {
            let s = format!("{:04u}-{:02u}-{:02u}T{:02u}:{:02u}:{:02u}Z", y,m,d,h,mi,s);
            to_json_type(~"datetime", String(s))
        }
    }
}

fn toml_test_runner() {
    let toml = toml::parse_from_bytes(std::io::stdin().read_to_end().unwrap()).unwrap();
    let json = to_json(&toml);
    println!("{:s}", json.to_pretty_str());
}

fn independent_test_runner(path: ~str) {
  let path = Path::new(path);
  let mut tests: int = 0;
  let mut failed: int = 0;
  let mut passed: int = 0;

  for filename in walk_dir(&path.join("invalid")).unwrap() {
    if filename.is_file() && filename.extension_str() == Some("toml") {
      println!("TEST/INVALID: {}", filename.filename_display());
      tests += 1;

      match toml::parse_from_path(&filename) {
          Err(_) => {
              passed += 1;
              println!("   [PASS]");
          }
          _ => {
              failed += 1;
              println!("   [FAIL]");
          }
      }
    }
  }

  for filename in walk_dir(&path.join("valid")).unwrap() {
    if filename.is_file() && filename.extension_str() == Some("toml") {
      let jsonfile = filename.with_extension("json");
      if !jsonfile.is_file() { fail!() }

      println!("TEST/VALID:   {}", filename.filename_display());

      let jsonbytes = File::open(&Path::new(jsonfile)).read_to_end().unwrap();
      let jsonstr = std::str::from_utf8(jsonbytes).unwrap();

      let result = extra::json::from_str(jsonstr);
      if result.is_err() { fail!() }

      tests += 1;

      let json = result.unwrap();
      let toml = toml::parse_from_path(&filename);
      let toml_json = toml.map(|t| to_json(&t));

      if Ok(&json) == toml_json.as_ref() {
          passed += 1;
          println!("   [PASS]");
      } else {
          println!("===============================================");
          println!("{:s}", json.to_pretty_str());
          println!("-----------------------------------------------");
          match toml_json {
              Ok(json) => println!("{:s}", json.to_pretty_str()),
              Err(toml::ParseError) => println!("(parse error)"),
              Err(toml::IOError(e)) => println!("({})", e)
          }
          println!("===============================================");
          failed += 1;
          println!("   [FAIL]");
      }
    }
  }

  println!("");
  println!("Tests/PASS/FAIL: {:d}/{:d}/{:d}", tests, passed, failed);
  if failed > 0 { fail!(); }
}

fn main() {
    match os::args().len() {
      1 => toml_test_runner(),
      2 => independent_test_runner(os::args()[1]),
      _ => fail!("USAGE: {:s} [path]", os::args()[0]),
    }
}
<|endoftext|>


<commit_before>use polynomial::Polynomial;
use nalgebra::Vector2;
use std::cmp::max;
use roots::find_roots_quartic;

use std::io::Write;
macro_rules! printlnerr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

fn multiply_and_shift_avoiding_overflow_by_rounding (stuff: & [Coordinate], shift: i32)->Coordinate {
let mut sign: Coordinate = 1;
let mut product = 1u64;
let mut shift = shift;
for thing in stuff {
let mut factor = thing.clone();
if factor <0 {factor*= -1; sign *= -1;}
let mut factor = factor as u64;
while product >= (1u64) << 32 && shift >0 {product >>= 1; shift -= 1;}
while factor >= (1u64) << 32 && shift >0 {factor >>= 1; shift -= 1;}
//printlnerr!(" {}, {}, {}", product, factor, shift);
product = product*factor;
}
((product as Coordinate)*sign) >> shift
}

// TODO: polymorphic in number of dimensions, and numeric type
// TODO: optimize away the unnecessary heap-allocation and other inefficiencies of Polynomial, and other pointless inefficiencies I introduced
// TODO replace f64 with a deterministic type (probably mpfr)
// note: the third time is not acceleration, but the coefficient of X squared, which is 2 times acceleration
pub type Coordinate = i64;
#[derive (Clone,)]
pub struct QuadraticTrajectory {
  data: Vector2<Polynomial<Coordinate>>,
  time_scale_shift: i32,
}
fn updated_by(poly: &Polynomial<Coordinate>,
              time: Coordinate,
              time_scale_shift: i32)
              -> Polynomial<Coordinate> {
  &*poly +
  Polynomial::new(vec![multiply_and_shift_avoiding_overflow_by_rounding (& [poly.data().get(1).cloned().unwrap_or(0), time], time_scale_shift) +
                       multiply_and_shift_avoiding_overflow_by_rounding (& [poly.data().get(2).cloned().unwrap_or(0), time, time], time_scale_shift * 2),
                       multiply_and_shift_avoiding_overflow_by_rounding (& [poly.data().get(2).cloned().unwrap_or(0), time * 2], time_scale_shift),
                       0i64])
}
impl QuadraticTrajectory {
  pub fn new(time_scale_shift: i32, coordinates: [Coordinate; 6]) -> QuadraticTrajectory {
    QuadraticTrajectory {
      time_scale_shift: time_scale_shift,
      data: Vector2::new(Polynomial::new(vec![coordinates[0], coordinates[2], coordinates[4]]),
                         Polynomial::new(vec![coordinates[1], coordinates[3], coordinates[5]])),
    }
  }

  pub fn updated_by(&self, time: Coordinate) -> QuadraticTrajectory {
    QuadraticTrajectory {
      data: Vector2::new(updated_by(&self.data[0], time, self.time_scale_shift),
                         updated_by(&self.data[1], time, self.time_scale_shift)),
      ..self.clone()
    }
  }

  pub fn update_by(&mut self, time: Coordinate) {
    *self = self.updated_by(time);
  }

  pub fn add_acceleration(&mut self, acceleration: Vector2<Coordinate>) {
    let changed = &self.data[0] + Polynomial::new(vec![0, 0, acceleration[0]*2]);
    self.data[0].clone_from(&changed);
    let changed = &self.data[1] + Polynomial::new(vec![0, 0, acceleration[1]*2]);
    self.data[1].clone_from(&changed);
  }
  pub fn evaluate(&self) -> Vector2<Coordinate> {
    Vector2::new(self.data[0].data().get(0).cloned().unwrap_or(0),
                 self.data[1].data().get(0).cloned().unwrap_or(0))

  }

  // direction == -1->"when the distance between the trajectories drops below the distance argument"
  // direction == 1->"when the distance between the trajectories exceeds the distance argument"
  pub fn approximately_when_distance_passes(distance: Coordinate,
                                            direction: Coordinate,
                                            first: (Coordinate, &QuadraticTrajectory),
                                            second: (Coordinate, &QuadraticTrajectory))
                                            -> Option<Coordinate> {
    assert!(first.1.time_scale_shift == second.1.time_scale_shift,
            "we don't actually support interactions between trajectories with different scales");
    let error = distance * 6 + 3;
    let ratio = (1i64 << first.1.time_scale_shift) as f64;

    let base = max(first.0, second.0);
    let third = first.1.updated_by(base - first.0);
    let more = second.1.updated_by(base - second.0);
    let displacement_function: Vector2<Polynomial<Coordinate>> = third.data.clone() - more.data.clone();
    let distance_function = &displacement_function[0] * &displacement_function[0] +
                            &displacement_function[1] * &displacement_function[1];
                            //printlnerr!(" distance function {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?}", first.1.data, second.1.data, error, ratio, third.data, more.data, displacement_function, distance_function);
    let roots = find_roots_quartic(distance_function.data().get(4).cloned().unwrap_or(0) as f64 /
                                   ratio.powi(4),
                                   distance_function.data().get(3).cloned().unwrap_or(0) as f64 /
                                   ratio.powi(3),
                                   distance_function.data().get(2).cloned().unwrap_or(0) as f64 /
                                   ratio.powi(2),
                                   distance_function.data().get(1).cloned().unwrap_or(0) as f64 /
                                   ratio.powi(1),
                                   (distance_function.data().get(0).cloned().unwrap_or(0) -
                                    (distance * distance +
                                     error * direction)) as f64);

    for root in roots.as_ref() {
    //printlnerr!(" found group {}", root);
      let result = root.ceil() as Coordinate;
      if result > 0 {
        let checker = Vector2::new(updated_by(&displacement_function[0],
                                              result,
                                              first.1.time_scale_shift),
                                   updated_by(&displacement_function[1],
                                              result,
                                              first.1.time_scale_shift));

        let real_distance_squared = checker[0].data().get(0).cloned().unwrap_or(0) *
                                    checker[0].data().get(0).cloned().unwrap_or(0) +
                                    checker[1].data().get(0).cloned().unwrap_or(0) *
                                    checker[1].data().get(0).cloned().unwrap_or(0);

        if (real_distance_squared - distance * distance) * direction > 0 {
        //printlnerr!(" check past");
          return Some(base + result);
        }
      }
    }
    None
  }
}
<commit_msg>fixes<commit_after>use polynomial::Polynomial;
use nalgebra::Vector2;
use std::cmp::max;
use roots::find_roots_quartic;

use std::io::Write;
macro_rules! printlnerr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

fn multiply_and_shift_avoiding_overflow_by_rounding (stuff: & [Coordinate], shift: i32)->Coordinate {
let mut sign: Coordinate = 1;
let mut product = 1u64;
let mut shift = shift;
for thing in stuff {
let mut factor = thing.clone();
if factor <0 {factor*= -1; sign *= -1;}
let mut factor = factor as u64;
while product >= (1u64) << 32 && shift >0 {product >>= 1; shift -= 1;}
while factor >= (1u64) << 32 && shift >0 {factor >>= 1; shift -= 1;}
//printlnerr!(" {}, {}, {}", product, factor, shift);
product = product*factor;
}
((product as Coordinate)*sign) >> shift
}

// TODO: polymorphic in number of dimensions, and numeric type
// TODO: optimize away the unnecessary heap-allocation and other inefficiencies of Polynomial, and other pointless inefficiencies I introduced
// TODO replace f64 with a deterministic type (probably mpfr)
// note: the third time is not acceleration, but the coefficient of X squared, which is 2 times acceleration
pub type Coordinate = i64;
#[derive (Clone,)]
pub struct QuadraticTrajectory {
  data: Vector2<Polynomial<Coordinate>>,
  time_scale_shift: i32,
}
fn updated_by(poly: &Polynomial<Coordinate>,
              time: Coordinate,
              time_scale_shift: i32)
              -> Polynomial<Coordinate> {
  &*poly +
  Polynomial::new(vec![multiply_and_shift_avoiding_overflow_by_rounding (& [poly.data().get(1).cloned().unwrap_or(0), time], time_scale_shift) +
                       multiply_and_shift_avoiding_overflow_by_rounding (& [poly.data().get(2).cloned().unwrap_or(0), time, time], time_scale_shift * 2),
                       multiply_and_shift_avoiding_overflow_by_rounding (& [poly.data().get(2).cloned().unwrap_or(0), time * 2], time_scale_shift),
                       0i64])
}
impl QuadraticTrajectory {
  pub fn new(time_scale_shift: i32, coordinates: [Coordinate; 6]) -> QuadraticTrajectory {
    QuadraticTrajectory {
      time_scale_shift: time_scale_shift,
      data: Vector2::new(Polynomial::new(vec![coordinates[0], coordinates[2], coordinates[4]]),
                         Polynomial::new(vec![coordinates[1], coordinates[3], coordinates[5]])),
    }
  }

  pub fn updated_by(&self, time: Coordinate) -> QuadraticTrajectory {
    QuadraticTrajectory {
      data: Vector2::new(updated_by(&self.data[0], time, self.time_scale_shift),
                         updated_by(&self.data[1], time, self.time_scale_shift)),
      ..self.clone()
    }
  }

  pub fn update_by(&mut self, time: Coordinate) {
    *self = self.updated_by(time);
  }

  pub fn add_acceleration(&mut self, acceleration: Vector2<Coordinate>) {
    let changed = &self.data[0] + Polynomial::new(vec![0, 0, acceleration[0]*2]);
    self.data[0].clone_from(&changed);
    let changed = &self.data[1] + Polynomial::new(vec![0, 0, acceleration[1]*2]);
    self.data[1].clone_from(&changed);
  }
  pub fn evaluate(&self) -> Vector2<Coordinate> {
    Vector2::new(self.data[0].data().get(0).cloned().unwrap_or(0),
                 self.data[1].data().get(0).cloned().unwrap_or(0))

  }

  // direction == -1->"when the distance between the trajectories drops below the distance argument"
  // direction == 1->"when the distance between the trajectories exceeds the distance argument"
  pub fn approximately_when_distance_passes(distance: Coordinate,
                                            direction: Coordinate,
                                            first: (Coordinate, &QuadraticTrajectory),
                                            second: (Coordinate, &QuadraticTrajectory))
                                            -> Option<Coordinate> {
    assert!(first.1.time_scale_shift == second.1.time_scale_shift,
            "we don't actually support interactions between trajectories with different scales");
    let error = distance * 12 + 6;
    let ratio = (1i64 << first.1.time_scale_shift) as f64;

    let base = max(first.0, second.0);
    let third = first.1.updated_by(base - first.0);
    let more = second.1.updated_by(base - second.0);
    let displacement_function: Vector2<Polynomial<Coordinate>> = third.data.clone() - more.data.clone();
    let distance_function = &displacement_function[0] * &displacement_function[0] +
                            &displacement_function[1] * &displacement_function[1];
                            //printlnerr!(" distance function {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?}", first.1.data, second.1.data, error, ratio, third.data, more.data, displacement_function, distance_function);
    let roots = find_roots_quartic(distance_function.data().get(4).cloned().unwrap_or(0) as f64 /
                                   ratio.powi(4),
                                   distance_function.data().get(3).cloned().unwrap_or(0) as f64 /
                                   ratio.powi(3),
                                   distance_function.data().get(2).cloned().unwrap_or(0) as f64 /
                                   ratio.powi(2),
                                   distance_function.data().get(1).cloned().unwrap_or(0) as f64 /
                                   ratio.powi(1),
                                   (distance_function.data().get(0).cloned().unwrap_or(0) -
                                    (distance * distance +
                                     error * direction)) as f64);

    for root in roots.as_ref() {
    //printlnerr!(" found group {}", root);
      let result = root.ceil() as Coordinate;
      if result > 0 {
    let third = first.1.updated_by(base + result - first.0);
    let more = second.1.updated_by(base + result - second.0);
        let checker = third.data.clone() - more.data.clone();
        //Vector2::new(updated_by(&displacement_function[0],
                                              //result,
                                              //first.1.time_scale_shift),
                                   //updated_by(&displacement_function[1],
                                              //result,
                                              //first.1.time_scale_shift));

        let real_distance_squared = checker[0].data().get(0).cloned().unwrap_or(0) *
                                    checker[0].data().get(0).cloned().unwrap_or(0) +
                                    checker[1].data().get(0).cloned().unwrap_or(0) *
                                    checker[1].data().get(0).cloned().unwrap_or(0);

        if (real_distance_squared - distance * distance) * direction > 0 {
        //printlnerr!(" check past");
          return Some(base + result);
        }
      }
    }
    None
  }
}
<|endoftext|>


<commit_before>// A parser combinator that scans for zeros in a number of bytes. When the
// current byte is all zeros, the parser fails. The last argument is the bit
// offset relative the first byte being parsed.
macro_rules! skip_bytes (
  ($input: expr, $length: expr, $offset: expr) => (
    {
      match take!($input, $length) {
        $crate::nom::IResult::Done(i, bytes)   => {
          let head        = bytes[0] << $offset;
          let tail        = &bytes[1..];
          let is_all_zero = tail.iter().all(|byte| *byte == 0);

          if head == 0 && is_all_zero {
            $crate::nom::IResult::Done(i, bytes)
          } else {
            $crate::nom::IResult::Error($crate::nom::Err::Position(
              $crate::nom::ErrorKind::Digit, $input))
          }
        }
        $crate::nom::IResult::Error(error)     =>
          $crate::nom::IResult::Error(error),
        $crate::nom::IResult::Incomplete(need) =>
          $crate::nom::IResult::Incomplete(need),
      }
    }
  );
  ($input: expr, $length: expr) => (
    skip_bytes!($input, $length, 0);
  );
);

// A parser combiner for previously allocated buffers that can be passed
// in as mutable slices. The macro will parse and fill the total length of
// the passed in slice.
macro_rules! count_slice (
  ($input: expr, $submac: ident!( $($args:tt)* ), $result: expr) => (
    {
      let mut input    = $input;
      let mut count    = 0;
      let mut is_error = false;

      for result in $result {
        match $submac!(input, $($args)*) {
          $crate::nom::IResult::Done(i, o)    => {
            *result = o;

            input   = i;
            count  += 1;
          }
          $crate::nom::IResult::Error(_)      => {
            is_error = true;
            break;
          }
          $crate::nom::IResult::Incomplete(_) => break,
        }
      }

      if is_error {
        $crate::nom::IResult::Error($crate::nom::Err::Position(
          $crate::nom::ErrorKind::Count, $input))
      } else if count == $result.len() {
        $crate::nom::IResult::Done(input, ())
      } else {
        $crate::nom::IResult::Incomplete($crate::nom::Needed::Unknown)
      }
    }
  );
  ($i: expr, $f: expr, $count: expr) => (
    count_slice!($i, call!($f), $count);
  );
);

// A parser combinator for converting parsed unsigned numbers into signed
// two's complement based numbers. Without an explicit type passed in, the
// default return type is `i32`.
macro_rules! take_signed_bits (
  ($input: expr, $signed_type: ty, $count: expr) => (
    map!($input, take_bits!(u32, $count), |value| {
      ::utility::extend_sign(value, $count) as $signed_type
    });
  );
  ($input: expr, $count: expr) => (
    take_signed_bits!($input, i32, $count);
  );
);

// Convert the error returned from parsers to a `utility::ErrorKind` given
// to the macro.
macro_rules! to_custom_error (
  ($error_type: ident) => (
    |_| $crate::nom::Err::Code($crate::nom::ErrorKind::Custom(
          ::utility::ErrorKind::$error_type))
  );
);

// Similar to `try_parse!` macro but not require it to be like a nom parser.
// Essentually a parser that returns `IResult` will only need to return and
// the macro will do what `try!` does.
macro_rules! try_parser (
  ($iresult: expr) => (
    match $iresult {
      $crate::nom::IResult::Done(i, o)    => (i, o),
      $crate::nom::IResult::Error(e)      =>
        return $crate::nom::IResult::Error(e),
      $crate::nom::IResult::Incomplete(i) =>
        return $crate::nom::IResult::Incomplete(i),
    }
  )
);
<commit_msg>Allow for `to_custom_error!` to act like a parser<commit_after>// A parser combinator that scans for zeros in a number of bytes. When the
// current byte is all zeros, the parser fails. The last argument is the bit
// offset relative the first byte being parsed.
macro_rules! skip_bytes (
  ($input: expr, $length: expr, $offset: expr) => (
    {
      match take!($input, $length) {
        $crate::nom::IResult::Done(i, bytes)   => {
          let head        = bytes[0] << $offset;
          let tail        = &bytes[1..];
          let is_all_zero = tail.iter().all(|byte| *byte == 0);

          if head == 0 && is_all_zero {
            $crate::nom::IResult::Done(i, bytes)
          } else {
            $crate::nom::IResult::Error($crate::nom::Err::Position(
              $crate::nom::ErrorKind::Digit, $input))
          }
        }
        $crate::nom::IResult::Error(error)     =>
          $crate::nom::IResult::Error(error),
        $crate::nom::IResult::Incomplete(need) =>
          $crate::nom::IResult::Incomplete(need),
      }
    }
  );
  ($input: expr, $length: expr) => (
    skip_bytes!($input, $length, 0);
  );
);

// A parser combiner for previously allocated buffers that can be passed
// in as mutable slices. The macro will parse and fill the total length of
// the passed in slice.
macro_rules! count_slice (
  ($input: expr, $submac: ident!( $($args:tt)* ), $result: expr) => (
    {
      let mut input    = $input;
      let mut count    = 0;
      let mut is_error = false;

      for result in $result {
        match $submac!(input, $($args)*) {
          $crate::nom::IResult::Done(i, o)    => {
            *result = o;

            input   = i;
            count  += 1;
          }
          $crate::nom::IResult::Error(_)      => {
            is_error = true;
            break;
          }
          $crate::nom::IResult::Incomplete(_) => break,
        }
      }

      if is_error {
        $crate::nom::IResult::Error($crate::nom::Err::Position(
          $crate::nom::ErrorKind::Count, $input))
      } else if count == $result.len() {
        $crate::nom::IResult::Done(input, ())
      } else {
        $crate::nom::IResult::Incomplete($crate::nom::Needed::Unknown)
      }
    }
  );
  ($i: expr, $f: expr, $count: expr) => (
    count_slice!($i, call!($f), $count);
  );
);

// A parser combinator for converting parsed unsigned numbers into signed
// two's complement based numbers. Without an explicit type passed in, the
// default return type is `i32`.
macro_rules! take_signed_bits (
  ($input: expr, $signed_type: ty, $count: expr) => (
    map!($input, take_bits!(u32, $count), |value| {
      ::utility::extend_sign(value, $count) as $signed_type
    });
  );
  ($input: expr, $count: expr) => (
    take_signed_bits!($input, i32, $count);
  );
);

// Convert the error returned from parsers to a `utility::ErrorKind` given
// to the macro.
macro_rules! to_custom_error (
  ($input: expr, $submac: ident!( $($args:tt)* ), $error_type: ident) => (
    $submac!($input, $($args)*).map_err(|_| $crate::nom::Err::Code(
      $crate::nom::ErrorKind::Custom(::utility::ErrorKind::$error_type)))
  );
  ($input: expr, $f: expr, $error_type: ident) => (
    to_custom_error!($input, call!($f), $error_type);
  );
  ($error_type: ident) => (
    |_| $crate::nom::Err::Code($crate::nom::ErrorKind::Custom(
          ::utility::ErrorKind::$error_type))
  );
);

// Similar to `try_parse!` macro but not require it to be like a nom parser.
// Essentually a parser that returns `IResult` will only need to return and
// the macro will do what `try!` does.
macro_rules! try_parser (
  ($iresult: expr) => (
    match $iresult {
      $crate::nom::IResult::Done(i, o)    => (i, o),
      $crate::nom::IResult::Error(e)      =>
        return $crate::nom::IResult::Error(e),
      $crate::nom::IResult::Incomplete(i) =>
        return $crate::nom::IResult::Incomplete(i),
    }
  )
);
<|endoftext|>


<commit_before>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Alex Lyon <arcterus@mail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore (ToDO) sbytes slen dlen memmem

#[macro_use]
extern crate uucore;

use clap::{crate_version, App, Arg};
use memchr::memmem;
use std::io::{stdin, stdout, Read, Write};
use std::{fs::read, path::Path};
use uucore::display::Quotable;
use uucore::InvalidEncodingHandling;

static NAME: &str = "tac";
static USAGE: &str = "[OPTION]... [FILE]...";
static SUMMARY: &str = "Write each file to standard output, last line first.";

mod options {
    pub static BEFORE: &str = "before";
    pub static REGEX: &str = "regex";
    pub static SEPARATOR: &str = "separator";
    pub static FILE: &str = "file";
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let args = args
        .collect_str(InvalidEncodingHandling::ConvertLossy)
        .accept_any();

    let matches = uu_app().get_matches_from(args);

    let before = matches.is_present(options::BEFORE);
    let regex = matches.is_present(options::REGEX);
    let raw_separator = matches.value_of(options::SEPARATOR).unwrap_or("\n");
    let separator = if raw_separator.is_empty() {
        "\0"
    } else {
        raw_separator
    };

    let files: Vec<&str> = match matches.values_of(options::FILE) {
        Some(v) => v.collect(),
        None => vec!["-"],
    };

    tac(files, before, regex, separator)
}

pub fn uu_app() -> App<'static, 'static> {
    App::new(uucore::util_name())
        .name(NAME)
        .version(crate_version!())
        .usage(USAGE)
        .about(SUMMARY)
        .arg(
            Arg::with_name(options::BEFORE)
                .short("b")
                .long(options::BEFORE)
                .help("attach the separator before instead of after")
                .takes_value(false),
        )
        .arg(
            Arg::with_name(options::REGEX)
                .short("r")
                .long(options::REGEX)
                .help("interpret the sequence as a regular expression")
                .takes_value(false),
        )
        .arg(
            Arg::with_name(options::SEPARATOR)
                .short("s")
                .long(options::SEPARATOR)
                .help("use STRING as the separator instead of newline")
                .takes_value(true),
        )
        .arg(Arg::with_name(options::FILE).hidden(true).multiple(true))
}

/// Print lines of a buffer in reverse, with line separator given as a regex.
///
/// `data` contains the bytes of the file.
///
/// `pattern` is the regular expression given as a
/// [`regex::bytes::Regex`] (not a [`regex::Regex`], since the input is
/// given as a slice of bytes). If `before` is `true`, then each match
/// of this pattern in `data` is interpreted as the start of a line. If
/// `before` is `false`, then each match of this pattern is interpreted
/// as the end of a line.
///
/// This function writes each line in `data` to [`std::io::Stdout`] in
/// reverse.
///
/// # Errors
///
/// If there is a problem writing to `stdout`, then this function
/// returns [`std::io::Error`].
fn buffer_tac_regex(
    data: &[u8],
    pattern: &regex::bytes::Regex,
    before: bool,
) -> std::io::Result<()> {
    let out = stdout();
    let mut out = out.lock();

    // The index of the line separator for the current line.
    //
    // As we scan through the `data` from right to left, we update this
    // variable each time we find a new line separator. We restrict our
    // regular expression search to only those bytes up to the line
    // separator.
    let mut this_line_end = data.len();

    // The index of the start of the next line in the `data`.
    //
    // As we scan through the `data` from right to left, we update this
    // variable each time we find a new line.
    //
    // If `before` is `true`, then each line starts immediately before
    // the line separator. Otherwise, each line starts immediately after
    // the line separator.
    let mut following_line_start = data.len();

    // Iterate over each byte in the buffer in reverse. When we find a
    // line separator, write the line to stdout.
    //
    // The `before` flag controls whether the line separator appears at
    // the end of the line (as in "abc\ndef\n") or at the beginning of
    // the line (as in "/abc/def").
    for i in (0..data.len()).rev() {
        // Determine if there is a match for `pattern` starting at index
        // `i` in `data`. Only search up to the line ending that was
        // found previously.
        if let Some(match_) = pattern.find_at(&data[..this_line_end], i) {
            // Record this index as the ending of the current line.
            this_line_end = i;

            // The length of the match (that is, the line separator), in bytes.
            let slen = match_.end() - match_.start();

            if before {
                out.write_all(&data[i..following_line_start])?;
                following_line_start = i;
            } else {
                out.write_all(&data[i + slen..following_line_start])?;
                following_line_start = i + slen;
            }
        }
    }

    // After the loop terminates, write whatever bytes are remaining at
    // the beginning of the buffer.
    out.write_all(&data[0..following_line_start])?;
    Ok(())
}

/// Write lines from `data` to stdout in reverse.
///
/// This function writes to [`stdout`] each line appearing in `data`,
/// starting with the last line and ending with the first line. The
/// `separator` parameter defines what characters to use as a line
/// separator.
///
/// If `before` is `false`, then this function assumes that the
/// `separator` appears at the end of each line, as in `"abc\ndef\n"`.
/// If `before` is `true`, then this function assumes that the
/// `separator` appears at the beginning of each line, as in
/// `"/abc/def"`.
fn buffer_tac(data: &[u8], before: bool, separator: &str) -> std::io::Result<()> {
    let out = stdout();
    let mut out = out.lock();

    // The number of bytes in the line separator.
    let slen = separator.as_bytes().len();

    // The index of the start of the next line in the `data`.
    //
    // As we scan through the `data` from right to left, we update this
    // variable each time we find a new line.
    //
    // If `before` is `true`, then each line starts immediately before
    // the line separator. Otherwise, each line starts immediately after
    // the line separator.
    let mut following_line_start = data.len();

    // Iterate over each byte in the buffer in reverse. When we find a
    // line separator, write the line to stdout.
    //
    // The `before` flag controls whether the line separator appears at
    // the end of the line (as in "abc\ndef\n") or at the beginning of
    // the line (as in "/abc/def").
    for i in memmem::rfind_iter(data, separator) {
        if before {
            out.write_all(&data[i..following_line_start])?;
            following_line_start = i;
        } else {
            out.write_all(&data[i + slen..following_line_start])?;
            following_line_start = i + slen;
        }
    }

    // After the loop terminates, write whatever bytes are remaining at
    // the beginning of the buffer.
    out.write_all(&data[0..following_line_start])?;
    Ok(())
}

fn tac(filenames: Vec<&str>, before: bool, regex: bool, separator: &str) -> i32 {
    let mut exit_code = 0;

    let pattern = if regex {
        Some(crash_if_err!(1, regex::bytes::Regex::new(separator)))
    } else {
        None
    };

    for &filename in &filenames {
        let data = if filename == "-" {
            let mut data = Vec::new();
            if let Err(e) = stdin().read_to_end(&mut data) {
                show_error!("failed to read from stdin: {}", e);
                exit_code = 1;
                continue;
            }
            data
        } else {
            let path = Path::new(filename);
            if path.is_dir() || path.metadata().is_err() {
                if path.is_dir() {
                    show_error!("{}: read error: Invalid argument", filename.maybe_quote());
                } else {
                    show_error!(
                        "failed to open {} for reading: No such file or directory",
                        filename.quote()
                    );
                }
                exit_code = 1;
                continue;
            }
            match read(path) {
                Ok(data) => data,
                Err(e) => {
                    show_error!("failed to read {}: {}", filename.quote(), e);
                    exit_code = 1;
                    continue;
                }
            }
        };

        if let Some(pattern) = &pattern {
            buffer_tac_regex(&data, pattern, before)
        } else {
            buffer_tac(&data, before, separator)
        }
        .unwrap_or_else(|e| crash!(1, "failed to write to stdout: {}", e));
    }
    exit_code
}
<commit_msg>tac: buffer stdout more coarsely than line-based following the GNU tac implementation.<commit_after>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Alex Lyon <arcterus@mail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore (ToDO) sbytes slen dlen memmem

#[macro_use]
extern crate uucore;

use clap::{crate_version, App, Arg};
use memchr::memmem;
use std::io::{stdin, stdout, BufWriter, Read, Write};
use std::{fs::read, path::Path};
use uucore::display::Quotable;
use uucore::InvalidEncodingHandling;

static NAME: &str = "tac";
static USAGE: &str = "[OPTION]... [FILE]...";
static SUMMARY: &str = "Write each file to standard output, last line first.";

mod options {
    pub static BEFORE: &str = "before";
    pub static REGEX: &str = "regex";
    pub static SEPARATOR: &str = "separator";
    pub static FILE: &str = "file";
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let args = args
        .collect_str(InvalidEncodingHandling::ConvertLossy)
        .accept_any();

    let matches = uu_app().get_matches_from(args);

    let before = matches.is_present(options::BEFORE);
    let regex = matches.is_present(options::REGEX);
    let raw_separator = matches.value_of(options::SEPARATOR).unwrap_or("\n");
    let separator = if raw_separator.is_empty() {
        "\0"
    } else {
        raw_separator
    };

    let files: Vec<&str> = match matches.values_of(options::FILE) {
        Some(v) => v.collect(),
        None => vec!["-"],
    };

    tac(files, before, regex, separator)
}

pub fn uu_app() -> App<'static, 'static> {
    App::new(uucore::util_name())
        .name(NAME)
        .version(crate_version!())
        .usage(USAGE)
        .about(SUMMARY)
        .arg(
            Arg::with_name(options::BEFORE)
                .short("b")
                .long(options::BEFORE)
                .help("attach the separator before instead of after")
                .takes_value(false),
        )
        .arg(
            Arg::with_name(options::REGEX)
                .short("r")
                .long(options::REGEX)
                .help("interpret the sequence as a regular expression")
                .takes_value(false),
        )
        .arg(
            Arg::with_name(options::SEPARATOR)
                .short("s")
                .long(options::SEPARATOR)
                .help("use STRING as the separator instead of newline")
                .takes_value(true),
        )
        .arg(Arg::with_name(options::FILE).hidden(true).multiple(true))
}

/// Print lines of a buffer in reverse, with line separator given as a regex.
///
/// `data` contains the bytes of the file.
///
/// `pattern` is the regular expression given as a
/// [`regex::bytes::Regex`] (not a [`regex::Regex`], since the input is
/// given as a slice of bytes). If `before` is `true`, then each match
/// of this pattern in `data` is interpreted as the start of a line. If
/// `before` is `false`, then each match of this pattern is interpreted
/// as the end of a line.
///
/// This function writes each line in `data` to [`std::io::Stdout`] in
/// reverse.
///
/// # Errors
///
/// If there is a problem writing to `stdout`, then this function
/// returns [`std::io::Error`].
fn buffer_tac_regex(
    data: &[u8],
    pattern: &regex::bytes::Regex,
    before: bool,
) -> std::io::Result<()> {
    let out = stdout();
    let mut out = BufWriter::new(out.lock());

    // The index of the line separator for the current line.
    //
    // As we scan through the `data` from right to left, we update this
    // variable each time we find a new line separator. We restrict our
    // regular expression search to only those bytes up to the line
    // separator.
    let mut this_line_end = data.len();

    // The index of the start of the next line in the `data`.
    //
    // As we scan through the `data` from right to left, we update this
    // variable each time we find a new line.
    //
    // If `before` is `true`, then each line starts immediately before
    // the line separator. Otherwise, each line starts immediately after
    // the line separator.
    let mut following_line_start = data.len();

    // Iterate over each byte in the buffer in reverse. When we find a
    // line separator, write the line to stdout.
    //
    // The `before` flag controls whether the line separator appears at
    // the end of the line (as in "abc\ndef\n") or at the beginning of
    // the line (as in "/abc/def").
    for i in (0..data.len()).rev() {
        // Determine if there is a match for `pattern` starting at index
        // `i` in `data`. Only search up to the line ending that was
        // found previously.
        if let Some(match_) = pattern.find_at(&data[..this_line_end], i) {
            // Record this index as the ending of the current line.
            this_line_end = i;

            // The length of the match (that is, the line separator), in bytes.
            let slen = match_.end() - match_.start();

            if before {
                out.write_all(&data[i..following_line_start])?;
                following_line_start = i;
            } else {
                out.write_all(&data[i + slen..following_line_start])?;
                following_line_start = i + slen;
            }
        }
    }

    // After the loop terminates, write whatever bytes are remaining at
    // the beginning of the buffer.
    out.write_all(&data[0..following_line_start])?;
    Ok(())
}

/// Write lines from `data` to stdout in reverse.
///
/// This function writes to [`stdout`] each line appearing in `data`,
/// starting with the last line and ending with the first line. The
/// `separator` parameter defines what characters to use as a line
/// separator.
///
/// If `before` is `false`, then this function assumes that the
/// `separator` appears at the end of each line, as in `"abc\ndef\n"`.
/// If `before` is `true`, then this function assumes that the
/// `separator` appears at the beginning of each line, as in
/// `"/abc/def"`.
fn buffer_tac(data: &[u8], before: bool, separator: &str) -> std::io::Result<()> {
    let out = stdout();
    let mut out = BufWriter::new(out.lock());

    // The number of bytes in the line separator.
    let slen = separator.as_bytes().len();

    // The index of the start of the next line in the `data`.
    //
    // As we scan through the `data` from right to left, we update this
    // variable each time we find a new line.
    //
    // If `before` is `true`, then each line starts immediately before
    // the line separator. Otherwise, each line starts immediately after
    // the line separator.
    let mut following_line_start = data.len();

    // Iterate over each byte in the buffer in reverse. When we find a
    // line separator, write the line to stdout.
    //
    // The `before` flag controls whether the line separator appears at
    // the end of the line (as in "abc\ndef\n") or at the beginning of
    // the line (as in "/abc/def").
    for i in memmem::rfind_iter(data, separator) {
        if before {
            out.write_all(&data[i..following_line_start])?;
            following_line_start = i;
        } else {
            out.write_all(&data[i + slen..following_line_start])?;
            following_line_start = i + slen;
        }
    }

    // After the loop terminates, write whatever bytes are remaining at
    // the beginning of the buffer.
    out.write_all(&data[0..following_line_start])?;
    Ok(())
}

fn tac(filenames: Vec<&str>, before: bool, regex: bool, separator: &str) -> i32 {
    let mut exit_code = 0;

    let pattern = if regex {
        Some(crash_if_err!(1, regex::bytes::Regex::new(separator)))
    } else {
        None
    };

    for &filename in &filenames {
        let data = if filename == "-" {
            let mut data = Vec::new();
            if let Err(e) = stdin().read_to_end(&mut data) {
                show_error!("failed to read from stdin: {}", e);
                exit_code = 1;
                continue;
            }
            data
        } else {
            let path = Path::new(filename);
            if path.is_dir() || path.metadata().is_err() {
                if path.is_dir() {
                    show_error!("{}: read error: Invalid argument", filename.maybe_quote());
                } else {
                    show_error!(
                        "failed to open {} for reading: No such file or directory",
                        filename.quote()
                    );
                }
                exit_code = 1;
                continue;
            }
            match read(path) {
                Ok(data) => data,
                Err(e) => {
                    show_error!("failed to read {}: {}", filename.quote(), e);
                    exit_code = 1;
                    continue;
                }
            }
        };

        if let Some(pattern) = &pattern {
            buffer_tac_regex(&data, pattern, before)
        } else {
            buffer_tac(&data, before, separator)
        }
        .unwrap_or_else(|e| crash!(1, "failed to write to stdout: {}", e));
    }
    exit_code
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use std::str::Words;
use std::str::CharSplits;
use std::from_str::FromStr;
use std::io::{BufferedReader, File};
use cgmath::vector::{Vector3, Vector2};
use error_context;
use core::types::{MInt};
use visualizer::types::{VertexCoord, TextureCoord, Normal};

struct Face {
    vertex: [MInt, ..3],
    texture: [MInt, ..3],
    normal: [MInt, ..3],
}

pub struct Model {
    coords: Vec<VertexCoord>,
    normals: Vec<Normal>,
    texture_coords: Vec<TextureCoord>,
    faces: Vec<Face>,
}

fn parse_word<T: FromStr>(words: &mut Words) -> T {
    let str = words.next().expect("Can not read next word");
    from_str(str).expect("Can not convert from string")
}

fn parse_charsplit<T: FromStr>(words: &mut CharSplits<char>) -> T {
    let str = words.next().expect("Can not read next word");
    from_str(str).expect("Can not convert from string")
}

impl Model {
    pub fn new(path: &Path) -> Model {
        set_error_context!("loading obj", path.as_str().unwrap());
        let mut obj = Model {
            coords: Vec::new(),
            normals: Vec::new(),
            texture_coords: Vec::new(),
            faces: Vec::new(),
        };
        obj.read(path);
        obj
    }

    fn read_v(words: &mut Words) -> VertexCoord {
        VertexCoord{v: Vector3 {
            x: parse_word(words),
            y: parse_word(words),
            z: parse_word(words),
        }}
    }

    fn read_vn(words: &mut Words) -> Normal {
        Normal{v: Vector3 {
            x: parse_word(words),
            y: parse_word(words),
            z: parse_word(words),
        }}
    }

    fn read_vt(words: &mut Words) -> TextureCoord {
        TextureCoord{v: Vector2 {
            x: parse_word(words),
            y: 1.0 - parse_word(words), // flip
        }}
    }

    fn read_f(words: &mut Words) -> Face {
        let mut face = Face {
            vertex: [0, 0, 0],
            texture: [0, 0, 0],
            normal: [0, 0, 0],
        };
        let mut i = 0;
        for group in *words {
            let mut w = group.split('/');
            face.vertex[i] = parse_charsplit(&mut w);
            face.texture[i] = parse_charsplit(&mut w);
            face.normal[i] = parse_charsplit(&mut w);
            i += 1;
        }
        face
    }

    fn read_line(&mut self, line: &str) {
        let mut words = line.words();
        fn is_correct_tag(tag: &str) -> bool {
            tag.len() != 0 && tag[0] != ('#' as u8)
        }
        match words.next() {
            Some(tag) if is_correct_tag(tag) => {
                let w = &mut words;
                match tag {
                    "v" => self.coords.push(Model::read_v(w)),
                    "vn" => self.normals.push(Model::read_vn(w)),
                    "vt" => self.texture_coords.push(Model::read_vt(w)),
                    "f" => self.faces.push(Model::read_f(w)),
                    _ => {},
                }
            }
            _ => {},
        };
    }

    fn read(&mut self, path: &Path) {
        let mut file = BufferedReader::new(File::open(path));
        for line in file.lines() {
            match line {
                Ok(line) => self.read_line(line.as_slice()),
                Err(msg) => fail!("Obj: read error: {}", msg),
            }
        }
    }

    pub fn build(&self) -> Vec<VertexCoord> {
        let mut mesh = Vec::new();
        for face in self.faces.iter() {
            for i in range(0u, 3) {
                let vertex_id = face.vertex[i] - 1;
                mesh.push(*self.coords.get(vertex_id as uint));
            }
        }
        mesh
    }

    pub fn build_tex_coord(&self) -> Vec<TextureCoord> {
        let mut tex_coords = Vec::new();
        for face in self.faces.iter() {
            for i in range(0u, 3) {
                let texture_coord_id = face.texture[i] as uint - 1;
                tex_coords.push(*self.texture_coords.get(texture_coord_id));
            }
        }
        tex_coords
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>Updated for Rust 5b11610: indexing of &str<commit_after>// See LICENSE file for copyright and license details.

use std::str::Words;
use std::str::CharSplits;
use std::from_str::FromStr;
use std::io::{BufferedReader, File};
use cgmath::vector::{Vector3, Vector2};
use error_context;
use core::types::{MInt};
use visualizer::types::{VertexCoord, TextureCoord, Normal};

struct Face {
    vertex: [MInt, ..3],
    texture: [MInt, ..3],
    normal: [MInt, ..3],
}

pub struct Model {
    coords: Vec<VertexCoord>,
    normals: Vec<Normal>,
    texture_coords: Vec<TextureCoord>,
    faces: Vec<Face>,
}

fn parse_word<T: FromStr>(words: &mut Words) -> T {
    let str = words.next().expect("Can not read next word");
    from_str(str).expect("Can not convert from string")
}

fn parse_charsplit<T: FromStr>(words: &mut CharSplits<char>) -> T {
    let str = words.next().expect("Can not read next word");
    from_str(str).expect("Can not convert from string")
}

impl Model {
    pub fn new(path: &Path) -> Model {
        set_error_context!("loading obj", path.as_str().unwrap());
        let mut obj = Model {
            coords: Vec::new(),
            normals: Vec::new(),
            texture_coords: Vec::new(),
            faces: Vec::new(),
        };
        obj.read(path);
        obj
    }

    fn read_v(words: &mut Words) -> VertexCoord {
        VertexCoord{v: Vector3 {
            x: parse_word(words),
            y: parse_word(words),
            z: parse_word(words),
        }}
    }

    fn read_vn(words: &mut Words) -> Normal {
        Normal{v: Vector3 {
            x: parse_word(words),
            y: parse_word(words),
            z: parse_word(words),
        }}
    }

    fn read_vt(words: &mut Words) -> TextureCoord {
        TextureCoord{v: Vector2 {
            x: parse_word(words),
            y: 1.0 - parse_word(words), // flip
        }}
    }

    fn read_f(words: &mut Words) -> Face {
        let mut face = Face {
            vertex: [0, 0, 0],
            texture: [0, 0, 0],
            normal: [0, 0, 0],
        };
        let mut i = 0;
        for group in *words {
            let mut w = group.split('/');
            face.vertex[i] = parse_charsplit(&mut w);
            face.texture[i] = parse_charsplit(&mut w);
            face.normal[i] = parse_charsplit(&mut w);
            i += 1;
        }
        face
    }

    fn read_line(&mut self, line: &str) {
        let mut words = line.words();
        fn is_correct_tag(tag: &str) -> bool {
            tag.len() != 0 && tag.as_bytes()[0] != ('#' as u8)
        }
        match words.next() {
            Some(tag) if is_correct_tag(tag) => {
                let w = &mut words;
                match tag {
                    "v" => self.coords.push(Model::read_v(w)),
                    "vn" => self.normals.push(Model::read_vn(w)),
                    "vt" => self.texture_coords.push(Model::read_vt(w)),
                    "f" => self.faces.push(Model::read_f(w)),
                    _ => {},
                }
            }
            _ => {},
        };
    }

    fn read(&mut self, path: &Path) {
        let mut file = BufferedReader::new(File::open(path));
        for line in file.lines() {
            match line {
                Ok(line) => self.read_line(line.as_slice()),
                Err(msg) => fail!("Obj: read error: {}", msg),
            }
        }
    }

    pub fn build(&self) -> Vec<VertexCoord> {
        let mut mesh = Vec::new();
        for face in self.faces.iter() {
            for i in range(0u, 3) {
                let vertex_id = face.vertex[i] - 1;
                mesh.push(*self.coords.get(vertex_id as uint));
            }
        }
        mesh
    }

    pub fn build_tex_coord(&self) -> Vec<TextureCoord> {
        let mut tex_coords = Vec::new();
        for face in self.faces.iter() {
            for i in range(0u, 3) {
                let texture_coord_id = face.texture[i] as uint - 1;
                tex_coords.push(*self.texture_coords.get(texture_coord_id));
            }
        }
        tex_coords
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>use super::{Open, Sink};
use sdl2::audio::{AudioQueue, AudioSpecDesired};
use std::{io, thread, time};

type Channel = i16;

pub struct SdlSink {
    queue: AudioQueue<Channel>,
}

impl Open for SdlSink {
    fn open(device: Option<String>) -> SdlSink {
        debug!("Using SDL sink");

        if device.is_some() {
            panic!("SDL sink does not support specifyng a device name");
        }

        let ctx = sdl2::init().expect("Could not init SDL");
        let audio = ctx.audio().expect("Could not init SDL audio subsystem");

        let desired_spec = AudioSpecDesired {
            freq: Some(44_100),
            channels: Some(2),
            samples: None, // default
        };
        let queue = audio
            .open_queue(None, &desired_spec)
            .expect("Could not open SDL audio device");

        SdlSink { queue: queue }
    }
}

impl Sink for SdlSink {
    fn start(&mut self) -> io::Result<()> {
        self.queue.clear(); //
        self.queue.resume();
        Ok(())
    }

    fn stop(&mut self) -> io::Result<()> {
        self.queue.pause();
        self.queue.clear();
        Ok(())
    }

    fn write(&mut self, data: &[i16]) -> io::Result<()> {
        while self.queue.size() > (2 * 2 * 44_100) {
            // sleep and wait for sdl thread to drain the queue a bit
            thread::sleep(time::Duration::from_millis(10));
        }
        self.queue.queue(data);
        Ok(())
    }
}
<commit_msg>Remove unnecessary comments, fix typo<commit_after>use super::{Open, Sink};
use sdl2::audio::{AudioQueue, AudioSpecDesired};
use std::{io, thread, time};

type Channel = i16;

pub struct SdlSink {
    queue: AudioQueue<Channel>,
}

impl Open for SdlSink {
    fn open(device: Option<String>) -> SdlSink {
        debug!("Using SDL sink");

        if device.is_some() {
            panic!("SDL sink does not support specifying a device name");
        }

        let ctx = sdl2::init().expect("Could not init SDL");
        let audio = ctx.audio().expect("Could not init SDL audio subsystem");

        let desired_spec = AudioSpecDesired {
            freq: Some(44_100),
            channels: Some(2),
            samples: None,
        };
        let queue = audio
            .open_queue(None, &desired_spec)
            .expect("Could not open SDL audio device");

        SdlSink { queue: queue }
    }
}

impl Sink for SdlSink {
    fn start(&mut self) -> io::Result<()> {
        self.queue.clear();
        self.queue.resume();
        Ok(())
    }

    fn stop(&mut self) -> io::Result<()> {
        self.queue.pause();
        self.queue.clear();
        Ok(())
    }

    fn write(&mut self, data: &[i16]) -> io::Result<()> {
        while self.queue.size() > (2 * 2 * 44_100) {
            // sleep and wait for sdl thread to drain the queue a bit
            thread::sleep(time::Duration::from_millis(10));
        }
        self.queue.queue(data);
        Ok(())
    }
}
<|endoftext|>