<commit_before>#![crate_name = "cat"]
#![allow(unstable)]

#![feature(box_syntax, unsafe_destructor)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: cat (GNU coreutils) 8.13 */

extern crate getopts;

use std::io::{print, File};
use std::io::stdio::{stdout_raw, stdin_raw, stderr};
use std::io::{IoResult};
use std::ptr::{copy_nonoverlapping_memory};

pub fn uumain(args: Vec<String>) -> isize {
    let program = args[0].as_slice();
    let opts = [
        getopts::optflag("A", "show-all", "equivalent to -vET"),
        getopts::optflag("b", "number-nonblank",
                         "number nonempty output lines, overrides -n"),
        getopts::optflag("e", "", "equivalent to -vE"),
        getopts::optflag("E", "show-ends", "display $ at end of each line"),
        getopts::optflag("n", "number", "number all output lines"),
        getopts::optflag("s", "squeeze-blank", "suppress repeated empty output lines"),
        getopts::optflag("t", "", "equivalent to -vT"),
        getopts::optflag("T", "show-tabs", "display TAB characters as ^I"),
        getopts::optflag("v", "show-nonprinting",
                         "use ^ and M- notation, except for LF (\\n) and TAB (\\t)"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit"),
    ];
    let matches = match getopts::getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => panic!("Invalid options\n{}", f)
    };
    if matches.opt_present("help") {
        println!("cat 1.0.0");
        println!("");
        println!("Usage:");
        println!("  {0} [OPTION]... [FILE]...", program);
        println!("");
        print(getopts::usage("Concatenate FILE(s), or standard input, to \
                             standard output.", &opts).as_slice());
        println!("");
        println!("With no FILE, or when FILE is -, read standard input.");
        return 0;
    }
    if matches.opt_present("version") {
        println!("cat 1.0.0");
        return 0;
    }

    let mut number_mode = NumberingMode::NumberNone;
    if matches.opt_present("n") {
        number_mode = NumberingMode::NumberAll;
    }
    if matches.opt_present("b") {
        number_mode = NumberingMode::NumberNonEmpty;
    }
    let show_nonprint = matches.opts_present(&["A".to_string(), "e".to_string(),
                                              "t".to_string(), "v".to_string()]);
    let show_ends = matches.opts_present(&["E".to_string(), "A".to_string(),
                                          "e".to_string()]);
    let show_tabs = matches.opts_present(&["A".to_string(), "T".to_string(),
                                          "t".to_string()]);
    let squeeze_blank = matches.opt_present("s");
    let mut files = matches.free;
    if files.is_empty() {
        files.push("-".to_string());
    }

    exec(files, number_mode, show_nonprint, show_ends, show_tabs, squeeze_blank);

    0
}

#[derive(Eq, PartialEq)]
enum NumberingMode {
    NumberNone,
    NumberNonEmpty,
    NumberAll,
}

fn write_lines(files: Vec<String>, number: NumberingMode, squeeze_blank: bool,
               show_ends: bool) {

    let mut line_counter: usize = 1;

    for (mut reader, interactive) in files.iter().filter_map(|p| open(&p[])) {

        let mut in_buf  = [0; 1024 * 31];
        let mut out_buf = [0; 1024 * 64];
        let mut writer = UnsafeWriter::new(out_buf.as_mut_slice(), stdout_raw());
        let mut at_line_start = true;
        while let Ok(n) = reader.read(&mut in_buf) {
            if n == 0 { break }

            let in_buf = &in_buf[..n];
            let mut buf_pos = range(0, n);
            loop {
                writer.possibly_flush();
                let pos = match buf_pos.next() {
                    Some(p) => p,
                    None => break,
                };
                if in_buf[pos] == '\n' as u8 {
                    if !at_line_start || !squeeze_blank {
                        if at_line_start && number == NumberingMode::NumberAll {
                            (write!(&mut writer, "{0:6}\t", line_counter)).unwrap();
                            line_counter += 1;
                        }
                        if show_ends {
                            writer.write_u8('$' as u8).unwrap();
                        }
                        writer.write_u8('\n' as u8).unwrap();
                        if interactive {
                            writer.flush().unwrap();
                        }
                    }
                    at_line_start = true;
                    continue;
                }
                if at_line_start && number != NumberingMode::NumberNone {
                    (write!(&mut writer, "{0:6}\t", line_counter)).unwrap();
                    line_counter += 1;
                }
                match in_buf[pos..].iter().position(|c| *c == '\n' as u8) {
                    Some(p) => {
                        writer.write(&in_buf[pos..pos + p]).unwrap();
                        if show_ends {
                            writer.write_u8('$' as u8).unwrap();
                        }
                        writer.write_u8('\n' as u8).unwrap();
                        if interactive {
                            writer.flush().unwrap();
                        }
                        buf_pos = range(pos + p + 1, n);
                        at_line_start = true;
                    },
                    None => {
                        writer.write(&in_buf[pos..]).unwrap();
                        at_line_start = false;
                        break;
                    }
                };
            }
        }
    }
}

fn write_bytes(files: Vec<String>, number: NumberingMode, squeeze_blank: bool,
               show_ends: bool, show_nonprint: bool, show_tabs: bool) {

    let mut line_counter: usize = 1;

    for (mut reader, interactive) in files.iter().filter_map(|p| open(&p[])) {

        // Flush all 1024 iterations.
        let mut flush_counter = range(0us, 1024);

        let mut in_buf  = [0; 1024 * 32];
        let mut out_buf = [0; 1024 * 64];
        let mut writer = UnsafeWriter::new(out_buf.as_mut_slice(), stdout_raw());
        let mut at_line_start = true;
        while let Ok(n) = reader.read(&mut in_buf) {
            if n == 0 { break }

            for &byte in in_buf[..n].iter() {
                if flush_counter.next().is_none() {
                    writer.possibly_flush();
                    flush_counter = range(0us, 1024);
                }
                if byte == '\n' as u8 {
                    if !at_line_start || !squeeze_blank {
                        if at_line_start && number == NumberingMode::NumberAll {
                            (write!(&mut writer, "{0:6}\t", line_counter)).unwrap();
                            line_counter += 1;
                        }
                        if show_ends {
                            writer.write_u8('$' as u8).unwrap();
                        }
                        writer.write_u8('\n' as u8).unwrap();
                        if interactive {
                            writer.flush().unwrap();
                        }
                    }
                    at_line_start = true;
                    continue;
                }
                if at_line_start && number != NumberingMode::NumberNone {
                    (write!(&mut writer, "{0:6}\t", line_counter)).unwrap();
                    line_counter += 1;
                    at_line_start = false;
                }
                // This code is slow because of the many branches. cat in glibc avoids
                // this by having the whole loop inside show_nonprint.
                if byte == '\t' as u8 {
                    if show_tabs {
                        writer.write_str("^I")
                    } else {
                        writer.write_u8(byte)
                    }
                } else if show_nonprint {
                    let byte = match byte {
                        128 ... 255 => {
                            writer.write_str("M-").unwrap();
                            byte - 128
                        },
                        _ => byte,
                    };
                    match byte {
                        0 ... 31 => writer.write(&['^' as u8, byte + 64]),
                        127      => writer.write(&['^' as u8, byte - 64]),
                        _        => writer.write_u8(byte),
                    }
                } else {
                    writer.write_u8(byte)
                }.unwrap();
            }
        }
    }
}

fn write_fast(files: Vec<String>) {
    let mut writer = stdout_raw();
    let mut in_buf = [0; 1024 * 64];

    for (mut reader, _) in files.iter().filter_map(|p| open(&p[])) {
        while let Ok(n) = reader.read(&mut in_buf) {
            if n == 0 { break }
            // This interface is completely broken.
            writer.write(&in_buf[..n]).unwrap();
        }
    }
}

fn exec(files: Vec<String>, number: NumberingMode, show_nonprint: bool,
        show_ends: bool, show_tabs: bool, squeeze_blank: bool) {

    if show_nonprint || show_tabs {
        write_bytes(files, number, squeeze_blank, show_ends, show_nonprint, show_tabs);
    } else if number != NumberingMode::NumberNone || squeeze_blank || show_ends {
        write_lines(files, number, squeeze_blank, show_ends);
    } else {
        write_fast(files);
    }
}

fn open(path: &str) -> Option<(Box<Reader>, bool)> {
    if path == "-" {
        let stdin = stdin_raw();
        let interactive = stdin.isatty();
        return Some((box stdin as Box<Reader>, interactive));
    }

    match File::open(&std::path::Path::new(path)) {
        Ok(f) => Some((box f as Box<Reader>, false)),
        Err(e) => {
            (writeln!(&mut stderr(), "cat: {0}: {1}", path, e.to_string())).unwrap();
            None
        },
    }
}

struct UnsafeWriter<'a, W> {
    inner: W,
    buf: &'a mut [u8],
    pos: usize,
    threshold: usize,
}

impl<'a, W: Writer> UnsafeWriter<'a, W> {
    fn new(buf: &'a mut [u8], inner: W) -> UnsafeWriter<'a, W> {
        let threshold = buf.len()/2;
        UnsafeWriter {
            inner: inner,
            buf: buf,
            pos: 0,
            threshold: threshold,
        }
    }

    fn flush_buf(&mut self) -> IoResult<()> {
        if self.pos != 0 {
            let ret = self.inner.write(&self.buf[..self.pos]);
            self.pos = 0;
            ret
        } else {
            Ok(())
        }
    }

    fn possibly_flush(&mut self) {
        if self.pos > self.threshold {
            self.inner.write(&self.buf[..self.pos]).unwrap();
            self.pos = 0;
        }
    }
}

#[inline(never)]
fn fail() -> ! {
    panic!("assertion failed");
}

impl<'a, W: Writer> Writer for UnsafeWriter<'a, W> {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        let dst = &mut self.buf[self.pos..];
        if buf.len() > dst.len() {
            fail();
        }
        unsafe {
            copy_nonoverlapping_memory(dst.as_mut_ptr(), buf.as_ptr(), buf.len())
        }
        self.pos += buf.len();
        Ok(())
    }

    fn flush(&mut self) -> IoResult<()> {
        self.flush_buf().and_then(|()| self.inner.flush())
    }
}

#[unsafe_destructor]
impl<'a, W: Writer> Drop for UnsafeWriter<'a, W> {
    fn drop(&mut self) {
        let _ = self.flush_buf();
    }
}

/* vim: set ai ts=4 sw=4 sts=4 et : */
<commit_msg>Cleanup cat: use slicing syntax.<commit_after>#![crate_name = "cat"]
#![allow(unstable)]

#![feature(box_syntax, unsafe_destructor)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: cat (GNU coreutils) 8.13 */

extern crate getopts;

use std::io::{print, File};
use std::io::stdio::{stdout_raw, stdin_raw, stderr};
use std::io::{IoResult};
use std::ptr::{copy_nonoverlapping_memory};

pub fn uumain(args: Vec<String>) -> isize {
    let program = &args[0];
    let opts = [
        getopts::optflag("A", "show-all", "equivalent to -vET"),
        getopts::optflag("b", "number-nonblank",
                         "number nonempty output lines, overrides -n"),
        getopts::optflag("e", "", "equivalent to -vE"),
        getopts::optflag("E", "show-ends", "display $ at end of each line"),
        getopts::optflag("n", "number", "number all output lines"),
        getopts::optflag("s", "squeeze-blank", "suppress repeated empty output lines"),
        getopts::optflag("t", "", "equivalent to -vT"),
        getopts::optflag("T", "show-tabs", "display TAB characters as ^I"),
        getopts::optflag("v", "show-nonprinting",
                         "use ^ and M- notation, except for LF (\\n) and TAB (\\t)"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit"),
    ];
    let matches = match getopts::getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => panic!("Invalid options\n{}", f)
    };
    if matches.opt_present("help") {
        println!("cat 1.0.0");
        println!("");
        println!("Usage:");
        println!("  {0} [OPTION]... [FILE]...", program);
        println!("");
        print(&getopts::usage("Concatenate FILE(s), or standard input, to \
                             standard output.", &opts)[]);
        println!("");
        println!("With no FILE, or when FILE is -, read standard input.");
        return 0;
    }
    if matches.opt_present("version") {
        println!("cat 1.0.0");
        return 0;
    }

    let mut number_mode = NumberingMode::NumberNone;
    if matches.opt_present("n") {
        number_mode = NumberingMode::NumberAll;
    }
    if matches.opt_present("b") {
        number_mode = NumberingMode::NumberNonEmpty;
    }
    let show_nonprint = matches.opts_present(&["A".to_string(), "e".to_string(),
                                              "t".to_string(), "v".to_string()]);
    let show_ends = matches.opts_present(&["E".to_string(), "A".to_string(),
                                          "e".to_string()]);
    let show_tabs = matches.opts_present(&["A".to_string(), "T".to_string(),
                                          "t".to_string()]);
    let squeeze_blank = matches.opt_present("s");
    let mut files = matches.free;
    if files.is_empty() {
        files.push("-".to_string());
    }

    exec(files, number_mode, show_nonprint, show_ends, show_tabs, squeeze_blank);

    0
}

#[derive(Eq, PartialEq)]
enum NumberingMode {
    NumberNone,
    NumberNonEmpty,
    NumberAll,
}

fn write_lines(files: Vec<String>, number: NumberingMode, squeeze_blank: bool,
               show_ends: bool) {

    let mut line_counter: usize = 1;

    for (mut reader, interactive) in files.iter().filter_map(|p| open(&p[])) {

        let mut in_buf  = [0; 1024 * 31];
        let mut out_buf = [0; 1024 * 64];
        let mut writer = UnsafeWriter::new(out_buf.as_mut_slice(), stdout_raw());
        let mut at_line_start = true;
        while let Ok(n) = reader.read(&mut in_buf) {
            if n == 0 { break }

            let in_buf = &in_buf[..n];
            let mut buf_pos = range(0, n);
            loop {
                writer.possibly_flush();
                let pos = match buf_pos.next() {
                    Some(p) => p,
                    None => break,
                };
                if in_buf[pos] == '\n' as u8 {
                    if !at_line_start || !squeeze_blank {
                        if at_line_start && number == NumberingMode::NumberAll {
                            (write!(&mut writer, "{0:6}\t", line_counter)).unwrap();
                            line_counter += 1;
                        }
                        if show_ends {
                            writer.write_u8('$' as u8).unwrap();
                        }
                        writer.write_u8('\n' as u8).unwrap();
                        if interactive {
                            writer.flush().unwrap();
                        }
                    }
                    at_line_start = true;
                    continue;
                }
                if at_line_start && number != NumberingMode::NumberNone {
                    (write!(&mut writer, "{0:6}\t", line_counter)).unwrap();
                    line_counter += 1;
                }
                match in_buf[pos..].iter().position(|c| *c == '\n' as u8) {
                    Some(p) => {
                        writer.write(&in_buf[pos..pos + p]).unwrap();
                        if show_ends {
                            writer.write_u8('$' as u8).unwrap();
                        }
                        writer.write_u8('\n' as u8).unwrap();
                        if interactive {
                            writer.flush().unwrap();
                        }
                        buf_pos = range(pos + p + 1, n);
                        at_line_start = true;
                    },
                    None => {
                        writer.write(&in_buf[pos..]).unwrap();
                        at_line_start = false;
                        break;
                    }
                };
            }
        }
    }
}

fn write_bytes(files: Vec<String>, number: NumberingMode, squeeze_blank: bool,
               show_ends: bool, show_nonprint: bool, show_tabs: bool) {

    let mut line_counter: usize = 1;

    for (mut reader, interactive) in files.iter().filter_map(|p| open(&p[])) {

        // Flush all 1024 iterations.
        let mut flush_counter = range(0us, 1024);

        let mut in_buf  = [0; 1024 * 32];
        let mut out_buf = [0; 1024 * 64];
        let mut writer = UnsafeWriter::new(out_buf.as_mut_slice(), stdout_raw());
        let mut at_line_start = true;
        while let Ok(n) = reader.read(&mut in_buf) {
            if n == 0 { break }

            for &byte in in_buf[..n].iter() {
                if flush_counter.next().is_none() {
                    writer.possibly_flush();
                    flush_counter = range(0us, 1024);
                }
                if byte == '\n' as u8 {
                    if !at_line_start || !squeeze_blank {
                        if at_line_start && number == NumberingMode::NumberAll {
                            (write!(&mut writer, "{0:6}\t", line_counter)).unwrap();
                            line_counter += 1;
                        }
                        if show_ends {
                            writer.write_u8('$' as u8).unwrap();
                        }
                        writer.write_u8('\n' as u8).unwrap();
                        if interactive {
                            writer.flush().unwrap();
                        }
                    }
                    at_line_start = true;
                    continue;
                }
                if at_line_start && number != NumberingMode::NumberNone {
                    (write!(&mut writer, "{0:6}\t", line_counter)).unwrap();
                    line_counter += 1;
                    at_line_start = false;
                }
                // This code is slow because of the many branches. cat in glibc avoids
                // this by having the whole loop inside show_nonprint.
                if byte == '\t' as u8 {
                    if show_tabs {
                        writer.write_str("^I")
                    } else {
                        writer.write_u8(byte)
                    }
                } else if show_nonprint {
                    let byte = match byte {
                        128 ... 255 => {
                            writer.write_str("M-").unwrap();
                            byte - 128
                        },
                        _ => byte,
                    };
                    match byte {
                        0 ... 31 => writer.write(&['^' as u8, byte + 64]),
                        127      => writer.write(&['^' as u8, byte - 64]),
                        _        => writer.write_u8(byte),
                    }
                } else {
                    writer.write_u8(byte)
                }.unwrap();
            }
        }
    }
}

fn write_fast(files: Vec<String>) {
    let mut writer = stdout_raw();
    let mut in_buf = [0; 1024 * 64];

    for (mut reader, _) in files.iter().filter_map(|p| open(&p[])) {
        while let Ok(n) = reader.read(&mut in_buf) {
            if n == 0 { break }
            // This interface is completely broken.
            writer.write(&in_buf[..n]).unwrap();
        }
    }
}

fn exec(files: Vec<String>, number: NumberingMode, show_nonprint: bool,
        show_ends: bool, show_tabs: bool, squeeze_blank: bool) {

    if show_nonprint || show_tabs {
        write_bytes(files, number, squeeze_blank, show_ends, show_nonprint, show_tabs);
    } else if number != NumberingMode::NumberNone || squeeze_blank || show_ends {
        write_lines(files, number, squeeze_blank, show_ends);
    } else {
        write_fast(files);
    }
}

fn open(path: &str) -> Option<(Box<Reader>, bool)> {
    if path == "-" {
        let stdin = stdin_raw();
        let interactive = stdin.isatty();
        return Some((box stdin as Box<Reader>, interactive));
    }

    match File::open(&std::path::Path::new(path)) {
        Ok(f) => Some((box f as Box<Reader>, false)),
        Err(e) => {
            (writeln!(&mut stderr(), "cat: {0}: {1}", path, e.to_string())).unwrap();
            None
        },
    }
}

struct UnsafeWriter<'a, W> {
    inner: W,
    buf: &'a mut [u8],
    pos: usize,
    threshold: usize,
}

impl<'a, W: Writer> UnsafeWriter<'a, W> {
    fn new(buf: &'a mut [u8], inner: W) -> UnsafeWriter<'a, W> {
        let threshold = buf.len()/2;
        UnsafeWriter {
            inner: inner,
            buf: buf,
            pos: 0,
            threshold: threshold,
        }
    }

    fn flush_buf(&mut self) -> IoResult<()> {
        if self.pos != 0 {
            let ret = self.inner.write(&self.buf[..self.pos]);
            self.pos = 0;
            ret
        } else {
            Ok(())
        }
    }

    fn possibly_flush(&mut self) {
        if self.pos > self.threshold {
            self.inner.write(&self.buf[..self.pos]).unwrap();
            self.pos = 0;
        }
    }
}

#[inline(never)]
fn fail() -> ! {
    panic!("assertion failed");
}

impl<'a, W: Writer> Writer for UnsafeWriter<'a, W> {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        let dst = &mut self.buf[self.pos..];
        if buf.len() > dst.len() {
            fail();
        }
        unsafe {
            copy_nonoverlapping_memory(dst.as_mut_ptr(), buf.as_ptr(), buf.len())
        }
        self.pos += buf.len();
        Ok(())
    }

    fn flush(&mut self) -> IoResult<()> {
        self.flush_buf().and_then(|()| self.inner.flush())
    }
}

#[unsafe_destructor]
impl<'a, W: Writer> Drop for UnsafeWriter<'a, W> {
    fn drop(&mut self) {
        let _ = self.flush_buf();
    }
}

/* vim: set ai ts=4 sw=4 sts=4 et : */
<|endoftext|>


<commit_before>use flate2::read::ZlibDecoder;
use gateway::GatewayError;
use internal::prelude::*;
use serde_json;
use websocket::{
    message::OwnedMessage,
    sync::stream::{TcpStream, TlsStream},
    sync::Client as WsClient
};

pub trait ReceiverExt {
    fn recv_json(&mut self) -> Result<Option<Value>>;
}

pub trait SenderExt {
    fn send_json(&mut self, value: &Value) -> Result<()>;
}

impl ReceiverExt for WsClient<TlsStream<TcpStream>> {
    fn recv_json(&mut self) -> Result<Option<Value>> {
        Ok(match self.recv_message()? {
            OwnedMessage::Binary(bytes) => {
                println!("{:?}", bytes);
                serde_json::from_reader(ZlibDecoder::new(&bytes[..])).map(Some)?
            },
            OwnedMessage::Close(data) => return Err(Error::Gateway(GatewayError::Closed(data))),
            OwnedMessage::Text(payload) => {
                println!("{}", payload);
                serde_json::from_str(&payload).map(Some)?
            },
            OwnedMessage::Ping(x) => {
                self.send_message(&OwnedMessage::Pong(x))
                    .map_err(Error::from)?;

                None
            },
            OwnedMessage::Pong(_) => None,
        })
    }
}

impl SenderExt for WsClient<TlsStream<TcpStream>> {
    fn send_json(&mut self, value: &Value) -> Result<()> {
        serde_json::to_string(value)
            .map(OwnedMessage::Text)
            .map_err(Error::from)
            .and_then(|m| self.send_message(&m).map_err(Error::from))
    }
}
<commit_msg>Remove some debugs<commit_after>use flate2::read::ZlibDecoder;
use gateway::GatewayError;
use internal::prelude::*;
use serde_json;
use websocket::{
    message::OwnedMessage,
    sync::stream::{TcpStream, TlsStream},
    sync::Client as WsClient
};

pub trait ReceiverExt {
    fn recv_json(&mut self) -> Result<Option<Value>>;
}

pub trait SenderExt {
    fn send_json(&mut self, value: &Value) -> Result<()>;
}

impl ReceiverExt for WsClient<TlsStream<TcpStream>> {
    fn recv_json(&mut self) -> Result<Option<Value>> {
        Ok(match self.recv_message()? {
            OwnedMessage::Binary(bytes) => {
                serde_json::from_reader(ZlibDecoder::new(&bytes[..])).map(Some)?
            },
            OwnedMessage::Close(data) => return Err(Error::Gateway(GatewayError::Closed(data))),
            OwnedMessage::Text(payload) => {
                serde_json::from_str(&payload).map(Some)?
            },
            OwnedMessage::Ping(x) => {
                self.send_message(&OwnedMessage::Pong(x))
                    .map_err(Error::from)?;

                None
            },
            OwnedMessage::Pong(_) => None,
        })
    }
}

impl SenderExt for WsClient<TlsStream<TcpStream>> {
    fn send_json(&mut self, value: &Value) -> Result<()> {
        serde_json::to_string(value)
            .map(OwnedMessage::Text)
            .map_err(Error::from)
            .and_then(|m| self.send_message(&m).map_err(Error::from))
    }
}
<|endoftext|>


<commit_before>use parser;
use interpreter::Interpreter;
use value::Value;
use value::Number;

fn run_and_get_last_value(code: &str) -> Value {
    let ast = parser::program(code);
    match ast {
        Ok(ast) => {
            let mut machine = Interpreter::new();
            machine.run_ast_as_program(&ast).unwrap().unwrap().unwrap_value()
        }
        Err(_) => panic!("{:?}", ast),
    }
}

#[test]
fn literal_value_int() {
    assert_eq!(run_and_get_last_value("7;"),
               Value::Number(Number::Integer(7)));
}

#[test]
fn literal_value_float() {
    assert_eq!(run_and_get_last_value("7.0;"),
               Value::Number(Number::Float(7.0)));
}

#[test]
fn literal_value_bool_true() {
    assert_eq!(run_and_get_last_value("true;"), Value::Bool(true));
}

#[test]
fn literal_value_bool_false() {
    assert_eq!(run_and_get_last_value("false;"), Value::Bool(false));
}

#[test]
fn variable_reassignment_with_type_change() {
    assert_eq!(run_and_get_last_value("var x = 10; x = false; x;"),
               Value::Bool(false));
}

#[test]
fn arithmetic_1() {
    assert_eq!(run_and_get_last_value("(1 + 3 / (1 + 1)) * 12 - 1;"),
               Value::Number(Number::Float(29.0)));
}

#[test]
fn arithmetic_2() {
    assert_eq!(run_and_get_last_value("3 - 5 + 12 / 4 - 1;"),
               Value::Number(Number::Float(0.0)));
}

#[test]
fn arithmetic_3() {
    assert_eq!(run_and_get_last_value("10 // 3 + 5 - 12;"),
               Value::Number(Number::Integer(-4)));
}

#[test]
fn arithmetic_4() {
    assert_eq!(run_and_get_last_value("-10 / 4 + -5 - 12;"),
               Value::Number(Number::Float(-19.5)));
}

#[test]
fn i64_support() {
    assert_eq!(run_and_get_last_value("9223372036854775807;"),
               Value::Number(Number::Integer(9223372036854775807)));
}

#[test]
fn f64_support() {
    assert_eq!(run_and_get_last_value("1234567890.012345678;"),
               Value::Number(Number::Float(1234567890.012345678)));
}

#[test]
fn logical_and() {
    assert_eq!(run_and_get_last_value("true and true;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("false and true;"),
               Value::Bool(false));
    assert_eq!(run_and_get_last_value("true and false;"),
               Value::Bool(false));
    assert_eq!(run_and_get_last_value("false and false;"),
               Value::Bool(false));

    assert_eq!(run_and_get_last_value("2 and 1;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("3.0 and 22.5;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("5 and 0;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("5.6 and 0.0;"), Value::Bool(false));
}

#[test]
fn logical_or() {
    assert_eq!(run_and_get_last_value("true or true;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("false or true;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("true or false;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("false or false;"),
               Value::Bool(false));

    assert_eq!(run_and_get_last_value("2 or 1;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("3.0 or 22.5;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("5 or 0;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("0 or 0.0;"), Value::Bool(false));
}

#[test]
fn logical_not() {
    assert_eq!(run_and_get_last_value("not true;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("not false;"), Value::Bool(true));

    assert_eq!(run_and_get_last_value("not 5;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("not 0;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("not 0.0;"), Value::Bool(true));
}

#[test]
fn comparisons() {
    assert_eq!(run_and_get_last_value("1 < 2;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("1 > 2;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("1.0 < 2.0;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("1.0 > 2.0;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("4 <= 4;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("2 >= 2;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("3 == 3;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("7 == 7.0;"), Value::Bool(true));
}

#[test]
fn variable_declaration() {
    assert_eq!(run_and_get_last_value("var x = 5; x;"),
               Value::Number(Number::Integer(5)));
}

#[test]
fn variable_reassignment() {
    assert_eq!(run_and_get_last_value("var x = 10; x = 42; x;"),
               Value::Number(Number::Integer(42)));
}

#[test]
fn id_in_expr() {
    assert_eq!(run_and_get_last_value("var x = 5; x / 2 + x;"),
               Value::Number(Number::Float(7.5)));
}

#[test]
fn if_expr_true() {
    assert_eq!(run_and_get_last_value("var x = 5; if 1 < 2 { x = 6; } else { x = 7; } x;"),
               Value::Number(Number::Integer(6)));
}

#[test]
fn if_expr_false() {
    assert_eq!(run_and_get_last_value("var x = 5; if 1 > 2 { x = 6; } else { x = 7; } x;"),
               Value::Number(Number::Integer(7)));
}

#[test]
fn loop_and_break() {
    assert_eq!(run_and_get_last_value("var x = 5; loop { if x > 20 { break; } x = x + 5; } x;"),
               Value::Number(Number::Integer(25)));
}
<commit_msg>Add more == tests<commit_after>use parser;
use interpreter::Interpreter;
use value::Value;
use value::Number;

fn run_and_get_last_value(code: &str) -> Value {
    let ast = parser::program(code);
    match ast {
        Ok(ast) => {
            let mut machine = Interpreter::new();
            machine.run_ast_as_program(&ast).unwrap().unwrap().unwrap_value()
        }
        Err(_) => panic!("{:?}", ast),
    }
}

#[test]
fn literal_value_int() {
    assert_eq!(run_and_get_last_value("7;"),
               Value::Number(Number::Integer(7)));
}

#[test]
fn literal_value_float() {
    assert_eq!(run_and_get_last_value("7.0;"),
               Value::Number(Number::Float(7.0)));
}

#[test]
fn literal_value_bool_true() {
    assert_eq!(run_and_get_last_value("true;"), Value::Bool(true));
}

#[test]
fn literal_value_bool_false() {
    assert_eq!(run_and_get_last_value("false;"), Value::Bool(false));
}

#[test]
fn variable_reassignment_with_type_change() {
    assert_eq!(run_and_get_last_value("var x = 10; x = false; x;"),
               Value::Bool(false));
}

#[test]
fn arithmetic_1() {
    assert_eq!(run_and_get_last_value("(1 + 3 / (1 + 1)) * 12 - 1;"),
               Value::Number(Number::Float(29.0)));
}

#[test]
fn arithmetic_2() {
    assert_eq!(run_and_get_last_value("3 - 5 + 12 / 4 - 1;"),
               Value::Number(Number::Float(0.0)));
}

#[test]
fn arithmetic_3() {
    assert_eq!(run_and_get_last_value("10 // 3 + 5 - 12;"),
               Value::Number(Number::Integer(-4)));
}

#[test]
fn arithmetic_4() {
    assert_eq!(run_and_get_last_value("-10 / 4 + -5 - 12;"),
               Value::Number(Number::Float(-19.5)));
}

#[test]
fn i64_support() {
    assert_eq!(run_and_get_last_value("9223372036854775807;"),
               Value::Number(Number::Integer(9223372036854775807)));
}

#[test]
fn f64_support() {
    assert_eq!(run_and_get_last_value("1234567890.012345678;"),
               Value::Number(Number::Float(1234567890.012345678)));
}

#[test]
fn logical_and() {
    assert_eq!(run_and_get_last_value("true and true;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("false and true;"),
               Value::Bool(false));
    assert_eq!(run_and_get_last_value("true and false;"),
               Value::Bool(false));
    assert_eq!(run_and_get_last_value("false and false;"),
               Value::Bool(false));

    assert_eq!(run_and_get_last_value("2 and 1;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("3.0 and 22.5;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("5 and 0;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("5.6 and 0.0;"), Value::Bool(false));
}

#[test]
fn logical_or() {
    assert_eq!(run_and_get_last_value("true or true;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("false or true;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("true or false;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("false or false;"),
               Value::Bool(false));

    assert_eq!(run_and_get_last_value("2 or 1;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("3.0 or 22.5;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("5 or 0;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("0 or 0.0;"), Value::Bool(false));
}

#[test]
fn logical_not() {
    assert_eq!(run_and_get_last_value("not true;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("not false;"), Value::Bool(true));

    assert_eq!(run_and_get_last_value("not 5;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("not 0;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("not 0.0;"), Value::Bool(true));
}

#[test]
fn comparisons() {
    assert_eq!(run_and_get_last_value("1 < 2;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("1 > 2;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("1.0 < 2.0;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("1.0 > 2.0;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("4 <= 4;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("2 >= 2;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("3 == 3;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("7 == 7.0;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("7 == 7.1;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("true == 1;"), Value::Bool(false));
}

#[test]
fn variable_declaration() {
    assert_eq!(run_and_get_last_value("var x = 5; x;"),
               Value::Number(Number::Integer(5)));
}

#[test]
fn variable_reassignment() {
    assert_eq!(run_and_get_last_value("var x = 10; x = 42; x;"),
               Value::Number(Number::Integer(42)));
}

#[test]
fn id_in_expr() {
    assert_eq!(run_and_get_last_value("var x = 5; x / 2 + x;"),
               Value::Number(Number::Float(7.5)));
}

#[test]
fn if_expr_true() {
    assert_eq!(run_and_get_last_value("var x = 5; if 1 < 2 { x = 6; } else { x = 7; } x;"),
               Value::Number(Number::Integer(6)));
}

#[test]
fn if_expr_false() {
    assert_eq!(run_and_get_last_value("var x = 5; if 1 > 2 { x = 6; } else { x = 7; } x;"),
               Value::Number(Number::Integer(7)));
}

#[test]
fn loop_and_break() {
    assert_eq!(run_and_get_last_value("var x = 5; loop { if x > 20 { break; } x = x + 5; } x;"),
               Value::Number(Number::Integer(25)));
}
<|endoftext|>


<commit_before>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate serde_json;

use serde_json::{from_str, Value};

#[test]
fn test_map_order() {
    // Sorted order
    #[cfg(not(feature = "preserve_order"))]
    const EXPECTED: &'static [&'static str] = &["a", "b", "c"];

    // Insertion order
    #[cfg(feature = "preserve_order")]
    const EXPECTED: &'static [&'static str] = &["b", "a", "c"];

    let v: Value = from_str(r#"{"b":null,"a":null,"c":null}"#).unwrap();
    let keys: Vec<_> = v.as_object().unwrap().keys().collect();
    assert_eq!(keys, EXPECTED);
}
<commit_msg>Remove unnecessary 'static in consts<commit_after>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate serde_json;

use serde_json::{from_str, Value};

#[test]
fn test_map_order() {
    // Sorted order
    #[cfg(not(feature = "preserve_order"))]
    const EXPECTED: &[&str] = &["a", "b", "c"];

    // Insertion order
    #[cfg(feature = "preserve_order")]
    const EXPECTED: &[&str] = &["b", "a", "c"];

    let v: Value = from_str(r#"{"b":null,"a":null,"c":null}"#).unwrap();
    let keys: Vec<_> = v.as_object().unwrap().keys().collect();
    assert_eq!(keys, EXPECTED);
}
<|endoftext|>


<commit_before>use std::fmt::Debug;

use quick_xml::de::from_str;
use serde::{de, ser};
use serde::{Deserialize, Serialize};

use pretty_assertions::assert_eq;

#[derive(PartialEq, Debug, Serialize, Deserialize)]
struct Simple {
    a: (),
    b: usize,
    c: String,
    d: Option<String>,
}

fn test_parse_ok<'a, T: std::fmt::Debug>(errors: &[(&'a str, T)])
where
    T: PartialEq + Debug + ser::Serialize + for<'de> de::Deserialize<'de>,
{
    for (i, &(s, ref value)) in errors.iter().enumerate() {
        match from_str::<T>(s) {
            Ok(v) => assert_eq!(
                v, *value,
                "{} error, expected: {:?}, found: {:?}",
                i, value, v
            ),
            Err(e) => panic!("{} error, expected {:?}, found error {}", i, value, e),
        }

        // // Make sure we can deserialize into an `Element`.
        // let xml_value: Element = from_str(s).unwrap();

        // // Make sure we can deserialize from an `Element`.
        // let v: T = from_value(xml_value.clone()).unwrap();
        // assert_eq!(v, *value);
    }
}

fn test_parse_err<'a, T>(errors: &[&'a str])
where
    T: PartialEq + Debug + ser::Serialize + for<'de> de::Deserialize<'de>,
{
    for &s in errors {
        assert!(from_str::<T>(s).is_err());
    }
}

#[test]
fn test_namespaces() {
    #[derive(PartialEq, Serialize, Deserialize, Debug)]
    struct Envelope {
        subject: String,
    }
    let s = r#"
    <?xml version="1.0" encoding="UTF-8"?>
    <gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
        <gesmes:subject>Reference rates</gesmes:subject>
    </gesmes:Envelope>"#;
    test_parse_ok(&[(
        s,
        Envelope {
            subject: "Reference rates".to_string(),
        },
    )]);
}

#[test]
#[ignore] // FIXME
fn test_forwarded_namespace() {
    #[derive(PartialEq, Serialize, Deserialize, Debug)]
    struct Graphml {
        #[serde(rename = "xsi:schemaLocation")]
        schema_location: String,
    }
    let s = r#"
    <?xml version="1.0" encoding="UTF-8"?>
    <graphml xmlns="http://graphml.graphdrawing.org/xmlns"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
        http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
    </graphml>"#;
    test_parse_ok(&[(
        s,
        Graphml {
            schema_location: "http://graphml.graphdrawing.org/xmlns
        http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"
                .to_string(),
        },
    )]);
}

#[test]
fn test_parse_string() {
    test_parse_ok(&[
        (
            "<bla>This is a String</bla>",
            "This is a String".to_string(),
        ),
        ("<bla></bla>", "".to_string()),
        ("<bla>     </bla>", "".to_string()),
        ("<bla><boom/></bla>", "<boom/>".to_string()),
        ("<bla>♫</bla>", "♫".to_string()),
        ("<bla>♫</bla>", "♫".to_string()),
        //(
        //    "<bla>♫<![CDATA[<cookies/>]]>♫</bla>",
        //    "♫<cookies/>♫".to_string(),
        //),
    ]);
}

#[test]
#[ignore] // FIXME
fn test_parse_string_not_trim() {
    test_parse_ok(&[("<bla>     </bla>", "     ".to_string())]);
}

#[test]
#[ignore] // FIXME
fn test_parse_enum() {
    use Animal::*;

    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum Animal {
        Dog,
        Frog(String),
        Ant(Simple),
        Cat { age: usize, name: String },
    }

    test_parse_ok(&[
        ("<Animal xsi:type=\"Dog\"/>", Dog),
        (
            "<Animal xsi:type=\"Frog\">Quak</Animal>",
            Frog("Quak".to_string()),
        ),
        (
            "<Animal xsi:type=\"Ant\"><c>bla</c>15<d>Foo</d></Animal>",
            Ant(Simple {
                a: (),
                b: 15,
                c: "bla".to_string(),
                d: Some("Foo".to_string()),
            }),
        ),
        (
            "<Animal xsi:type=\"Ant\"><c>bla</c>15</Animal>",
            Ant(Simple {
                a: (),
                b: 15,
                c: "bla".to_string(),
                d: None,
            }),
        ),
        (
            "<Animal xsi:type=\"Cat\"><age>42</age><name>Shere Khan</name></Animal>",
            Cat {
                age: 42,
                name: "Shere Khan".to_string(),
            },
        ),
    ]);

    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Helper {
        x: Animal,
    }

    test_parse_ok(&[
        ("<Helper><x xsi:type=\"Dog\"/></Helper>", Helper { x: Dog }),
        (
            "<Helper><x xsi:type=\"Frog\">Quak</Animal></Helper>",
            Helper {
                x: Frog("Quak".to_string()),
            },
        ),
        (
            "<Helper><x xsi:type=\"Cat\">
                <age>42</age>
                <name>Shere Khan</name>
            </x></Helper>",
            Helper {
                x: Cat {
                    age: 42,
                    name: "Shere Khan".to_string(),
                },
            },
        ),
    ]);
}

#[test]
fn test_option() {
    test_parse_ok(&[
        ("", Some("".to_string())),
        ("", Some("".to_string())),
        (" ", Some("".to_string())),
        ("42", Some("42".to_string())),
    ]);
}

#[test]
#[ignore] // FIXME
fn test_option_not_trim() {
    test_parse_ok(&[(" ", Some(" ".to_string()))]);
}

#[test]
fn test_parse_unfinished() {
    test_parse_err::<Simple>(&["<Simple>
            <c>abc</c>

            2
            <d/>"]);
}

#[test]
fn test_things_qc_found() {
    test_parse_err::<u32>(&["<\u{0}:/"]);
}
<commit_msg>Use track_caller attribute on the util functions to get a correct line number when test fail<commit_after>use std::fmt::Debug;

use quick_xml::de::from_str;
use serde::{de, ser};
use serde::{Deserialize, Serialize};

use pretty_assertions::assert_eq;

#[derive(PartialEq, Debug, Serialize, Deserialize)]
struct Simple {
    a: (),
    b: usize,
    c: String,
    d: Option<String>,
}

#[track_caller]
fn test_parse_ok<'a, T: std::fmt::Debug>(errors: &[(&'a str, T)])
where
    T: PartialEq + Debug + ser::Serialize + for<'de> de::Deserialize<'de>,
{
    for (i, &(s, ref value)) in errors.iter().enumerate() {
        match from_str::<T>(s) {
            Ok(v) => assert_eq!(
                v, *value,
                "{} error, expected: {:?}, found: {:?}",
                i, value, v
            ),
            Err(e) => panic!("{} error, expected {:?}, found error {}", i, value, e),
        }

        // // Make sure we can deserialize into an `Element`.
        // let xml_value: Element = from_str(s).unwrap();

        // // Make sure we can deserialize from an `Element`.
        // let v: T = from_value(xml_value.clone()).unwrap();
        // assert_eq!(v, *value);
    }
}

#[track_caller]
fn test_parse_err<'a, T>(errors: &[&'a str])
where
    T: PartialEq + Debug + ser::Serialize + for<'de> de::Deserialize<'de>,
{
    for &s in errors {
        assert!(from_str::<T>(s).is_err());
    }
}

#[test]
fn test_namespaces() {
    #[derive(PartialEq, Serialize, Deserialize, Debug)]
    struct Envelope {
        subject: String,
    }
    let s = r#"
    <?xml version="1.0" encoding="UTF-8"?>
    <gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
        <gesmes:subject>Reference rates</gesmes:subject>
    </gesmes:Envelope>"#;
    test_parse_ok(&[(
        s,
        Envelope {
            subject: "Reference rates".to_string(),
        },
    )]);
}

#[test]
#[ignore] // FIXME
fn test_forwarded_namespace() {
    #[derive(PartialEq, Serialize, Deserialize, Debug)]
    struct Graphml {
        #[serde(rename = "xsi:schemaLocation")]
        schema_location: String,
    }
    let s = r#"
    <?xml version="1.0" encoding="UTF-8"?>
    <graphml xmlns="http://graphml.graphdrawing.org/xmlns"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
        http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
    </graphml>"#;
    test_parse_ok(&[(
        s,
        Graphml {
            schema_location: "http://graphml.graphdrawing.org/xmlns
        http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"
                .to_string(),
        },
    )]);
}

#[test]
fn test_parse_string() {
    test_parse_ok(&[
        (
            "<bla>This is a String</bla>",
            "This is a String".to_string(),
        ),
        ("<bla></bla>", "".to_string()),
        ("<bla>     </bla>", "".to_string()),
        ("<bla><boom/></bla>", "<boom/>".to_string()),
        ("<bla>♫</bla>", "♫".to_string()),
        ("<bla>♫</bla>", "♫".to_string()),
        //(
        //    "<bla>♫<![CDATA[<cookies/>]]>♫</bla>",
        //    "♫<cookies/>♫".to_string(),
        //),
    ]);
}

#[test]
#[ignore] // FIXME
fn test_parse_string_not_trim() {
    test_parse_ok(&[("<bla>     </bla>", "     ".to_string())]);
}

#[test]
#[ignore] // FIXME
fn test_parse_enum() {
    use Animal::*;

    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum Animal {
        Dog,
        Frog(String),
        Ant(Simple),
        Cat { age: usize, name: String },
    }

    test_parse_ok(&[
        ("<Animal xsi:type=\"Dog\"/>", Dog),
        (
            "<Animal xsi:type=\"Frog\">Quak</Animal>",
            Frog("Quak".to_string()),
        ),
        (
            "<Animal xsi:type=\"Ant\"><c>bla</c>15<d>Foo</d></Animal>",
            Ant(Simple {
                a: (),
                b: 15,
                c: "bla".to_string(),
                d: Some("Foo".to_string()),
            }),
        ),
        (
            "<Animal xsi:type=\"Ant\"><c>bla</c>15</Animal>",
            Ant(Simple {
                a: (),
                b: 15,
                c: "bla".to_string(),
                d: None,
            }),
        ),
        (
            "<Animal xsi:type=\"Cat\"><age>42</age><name>Shere Khan</name></Animal>",
            Cat {
                age: 42,
                name: "Shere Khan".to_string(),
            },
        ),
    ]);

    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Helper {
        x: Animal,
    }

    test_parse_ok(&[
        ("<Helper><x xsi:type=\"Dog\"/></Helper>", Helper { x: Dog }),
        (
            "<Helper><x xsi:type=\"Frog\">Quak</Animal></Helper>",
            Helper {
                x: Frog("Quak".to_string()),
            },
        ),
        (
            "<Helper><x xsi:type=\"Cat\">
                <age>42</age>
                <name>Shere Khan</name>
            </x></Helper>",
            Helper {
                x: Cat {
                    age: 42,
                    name: "Shere Khan".to_string(),
                },
            },
        ),
    ]);
}

#[test]
fn test_option() {
    test_parse_ok(&[
        ("", Some("".to_string())),
        ("", Some("".to_string())),
        (" ", Some("".to_string())),
        ("42", Some("42".to_string())),
    ]);
}

#[test]
#[ignore] // FIXME
fn test_option_not_trim() {
    test_parse_ok(&[(" ", Some(" ".to_string()))]);
}

#[test]
fn test_parse_unfinished() {
    test_parse_err::<Simple>(&["<Simple>
            <c>abc</c>

            2
            <d/>"]);
}

#[test]
fn test_things_qc_found() {
    test_parse_err::<u32>(&["<\u{0}:/"]);
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]

extern crate yaml;

use yaml::constructor::{YamlStandardData, YamlMapping, YamlSequence, YamlString, YamlInteger, YamlFloat};
use std::os;
use std::io::{File, BufferedReader};

fn match_utf8(filename: &str, expected: YamlStandardData) {
    match_file(yaml::ffi::YamlUtf8Encoding, filename, expected);
}

fn match_file(encoding: yaml::ffi::YamlEncoding, filename: &str, expected: YamlStandardData) {
    let this_path = os::args().as_slice()[0].clone();
    let file_path = Path::new(this_path).join("../../tests/source").join(filename);
    println!("{}", file_path.display())
    let mut reader = BufferedReader::new(File::open(&file_path));
    match yaml::parse_io(&mut reader, encoding) {
        Ok(docs) => if docs.len() == 1 {
            assert_eq!(docs.as_slice().head().unwrap(), &expected)
        } else {
            panic!("too many number of documents: {}", docs)
        },
        Err(e) => panic!("parse failure: {}", e)
    }
}

macro_rules! ystr(
    ($e: expr) => (
        YamlString($e.to_string())
    )
)

macro_rules! yint(
    ($e: expr) => (
        YamlInteger($e)
    )
)

macro_rules! yfloat(
    ($e: expr) => (
        YamlFloat($e)
    )
)

macro_rules! yseq(
    ($($e:expr),*) => (
        YamlSequence(vec![$(($e),)*])
    )
)

macro_rules! ymap(
    ($($k:expr : $v:expr),*) => (
        YamlMapping(vec![$((ystr!($k), $v),)*])
    )
)

macro_rules! y_cmp_map(
    ($($k:expr : $v:expr),*) => (
        YamlMapping(vec![$(($k, $v),)*])
    )
)

#[test]
fn sequence_of_scalars() {
    match_utf8("ball_players.yml", yseq![ystr!("Mark McGwire"), ystr!("Sammy Sosa"), ystr!("Ken Griffey")]);
}

#[test]
fn scalar_mappings() {
    match_utf8("player_stat.yml", ymap!{
                                    "hr": yint!(65),
                                    "avg": yfloat!(0.278),
                                    "rbi": yint!(147)
                                })
}

#[test]
fn maps_of_sequences() {
    match_utf8("ball_clubs.yml", ymap!{
                                    "american": yseq![ystr!("Boston Red Sox"), ystr!("Detroit Tigers"), ystr!("New York Yankees")],
                                    "national": yseq![ystr!("New York Mets"), ystr!("Chicago Cubs"), ystr!("Atlanta Braves")]
                                })
}

#[test]
fn sequence_of_maps() {
    match_utf8("multiple_player_stat.yml",
    yseq![
        ymap!{
            "name": ystr!("Mark McGwire"),
            "hr": yint!(65)
        },
        ymap!{
            "name": ystr!("Sammy Sosa"),
            "hr": yint!(63)
        }
    ])
}

#[test]
fn sequence_of_sequences() {
    match_utf8("csv.yml",
    yseq![
        yseq![ystr!("name"), ystr!("hr")],
        yseq![ystr!("Mark McGwire"), yint!(65)],
        yseq![ystr!("Sammy Sosa"), yint!(63)]
    ])
}

#[test]
fn mapping_of_mappings() {
    match_utf8("map_map.yml",
    ymap!{
        "Mark McGwire": ymap!{ "hr": yint!(65) },
        "Sammy Sosa": ymap!{ "hr": yint!(63) }
    })
}

#[test]
fn alias() {
    match_utf8("alias.yml",
    ymap!{
        "hr": yseq![ystr!("Mark McGwire"), ystr!("Sammy Sosa")],
        "rbi": yseq![ystr!("Sammy Sosa"), ystr!("Ken Griffey")]
    })
}

#[test]
fn complex_keys() {
    match_utf8("complex_key.yml",
    y_cmp_map!{
        yseq![ystr!("Detroit Tigers"), ystr!("Chicago Cubs")]: yseq![ystr!("2001-07-23")],
        yseq![ystr!("New York Yankees"), ystr!("Atlanta Braves")]: yseq![ystr!("2001-07-02"), ystr!("2001-08-12"), ystr!("2001-08-14")]
    })
}

#[test]
fn block_literal() {
    match_utf8("block_literal.yml", ystr!("\\//||\\/||\n// ||  ||__\n"))
}

#[test]
fn plain_scalar() {
    match_utf8("plain_scalar.yml", ystr!("Mark McGwire's year was crippled by a knee injury."))
}

#[test]
fn quoted_scalar() {
    match_utf8("quoted_scalar.yml",
    ymap!{
        "unicode": ystr!("Sosa did fine.\u263A"),
        "control": ystr!("\x081998\t1999\t2000\n"),
        "hexesc":  ystr!("\x13\x10 is \r\n"),
        "single": ystr!(r#""Howdy!" he cried."#),
        "quoted": ystr!(" # not a 'comment'."),
        "tie-fighter": ystr!(r"|\-*-/|")
    })
}

#[test]
fn multi_line_scalar() {
    match_utf8("multi_line_scalar.yml",
    ymap!{
        "plain": ystr!("This unquoted scalar spans many lines."),
        "quoted": ystr!("So does this quoted scalar.\n")
    })
}

#[test]
fn utf16le() {
    match_file(yaml::ffi::YamlUtf16LeEncoding, "utf16le.yml",
               yseq![ystr!("Hello"), ystr!("世界")]
    )
}

#[test]
fn utf16be() {
    match_file(yaml::ffi::YamlUtf16BeEncoding, "utf16be.yml",
               yseq![ystr!("Hello"), ystr!("世界")]
    )
}
<commit_msg>Enum variants namespace changes<commit_after>#![feature(macro_rules)]

extern crate yaml;

use yaml::constructor::YamlStandardData;
use yaml::ffi::YamlEncoding;
use std::os;
use std::io::{File, BufferedReader};

fn match_utf8(filename: &str, expected: YamlStandardData) {
    match_file(YamlEncoding::YamlUtf8Encoding, filename, expected);
}

fn match_file(encoding: yaml::ffi::YamlEncoding, filename: &str, expected: YamlStandardData) {
    let this_path = os::args().as_slice()[0].clone();
    let file_path = Path::new(this_path).join("../../tests/source").join(filename);
    println!("{}", file_path.display())
    let mut reader = BufferedReader::new(File::open(&file_path));
    match yaml::parse_io(&mut reader, encoding) {
        Ok(docs) => if docs.len() == 1 {
            assert_eq!(docs.as_slice().head().unwrap(), &expected)
        } else {
            panic!("too many number of documents: {}", docs)
        },
        Err(e) => panic!("parse failure: {}", e)
    }
}

macro_rules! ystr(
    ($e: expr) => (
        YamlStandardData::YamlString($e.to_string())
    )
)

macro_rules! yint(
    ($e: expr) => (
        YamlStandardData::YamlInteger($e)
    )
)

macro_rules! yfloat(
    ($e: expr) => (
        YamlStandardData::YamlFloat($e)
    )
)

macro_rules! yseq(
    ($($e:expr),*) => (
        YamlStandardData::YamlSequence(vec![$(($e),)*])
    )
)

macro_rules! ymap(
    ($($k:expr : $v:expr),*) => (
        YamlStandardData::YamlMapping(vec![$((ystr!($k), $v),)*])
    )
)

macro_rules! y_cmp_map(
    ($($k:expr : $v:expr),*) => (
        YamlStandardData::YamlMapping(vec![$(($k, $v),)*])
    )
)

#[test]
fn sequence_of_scalars() {
    match_utf8("ball_players.yml", yseq![ystr!("Mark McGwire"), ystr!("Sammy Sosa"), ystr!("Ken Griffey")]);
}

#[test]
fn scalar_mappings() {
    match_utf8("player_stat.yml", ymap!{
                                    "hr": yint!(65),
                                    "avg": yfloat!(0.278),
                                    "rbi": yint!(147)
                                })
}

#[test]
fn maps_of_sequences() {
    match_utf8("ball_clubs.yml", ymap!{
                                    "american": yseq![ystr!("Boston Red Sox"), ystr!("Detroit Tigers"), ystr!("New York Yankees")],
                                    "national": yseq![ystr!("New York Mets"), ystr!("Chicago Cubs"), ystr!("Atlanta Braves")]
                                })
}

#[test]
fn sequence_of_maps() {
    match_utf8("multiple_player_stat.yml",
    yseq![
        ymap!{
            "name": ystr!("Mark McGwire"),
            "hr": yint!(65)
        },
        ymap!{
            "name": ystr!("Sammy Sosa"),
            "hr": yint!(63)
        }
    ])
}

#[test]
fn sequence_of_sequences() {
    match_utf8("csv.yml",
    yseq![
        yseq![ystr!("name"), ystr!("hr")],
        yseq![ystr!("Mark McGwire"), yint!(65)],
        yseq![ystr!("Sammy Sosa"), yint!(63)]
    ])
}

#[test]
fn mapping_of_mappings() {
    match_utf8("map_map.yml",
    ymap!{
        "Mark McGwire": ymap!{ "hr": yint!(65) },
        "Sammy Sosa": ymap!{ "hr": yint!(63) }
    })
}

#[test]
fn alias() {
    match_utf8("alias.yml",
    ymap!{
        "hr": yseq![ystr!("Mark McGwire"), ystr!("Sammy Sosa")],
        "rbi": yseq![ystr!("Sammy Sosa"), ystr!("Ken Griffey")]
    })
}

#[test]
fn complex_keys() {
    match_utf8("complex_key.yml",
    y_cmp_map!{
        yseq![ystr!("Detroit Tigers"), ystr!("Chicago Cubs")]: yseq![ystr!("2001-07-23")],
        yseq![ystr!("New York Yankees"), ystr!("Atlanta Braves")]: yseq![ystr!("2001-07-02"), ystr!("2001-08-12"), ystr!("2001-08-14")]
    })
}

#[test]
fn block_literal() {
    match_utf8("block_literal.yml", ystr!("\\//||\\/||\n// ||  ||__\n"))
}

#[test]
fn plain_scalar() {
    match_utf8("plain_scalar.yml", ystr!("Mark McGwire's year was crippled by a knee injury."))
}

#[test]
fn quoted_scalar() {
    match_utf8("quoted_scalar.yml",
    ymap!{
        "unicode": ystr!("Sosa did fine.\u263A"),
        "control": ystr!("\x081998\t1999\t2000\n"),
        "hexesc":  ystr!("\x13\x10 is \r\n"),
        "single": ystr!(r#""Howdy!" he cried."#),
        "quoted": ystr!(" # not a 'comment'."),
        "tie-fighter": ystr!(r"|\-*-/|")
    })
}

#[test]
fn multi_line_scalar() {
    match_utf8("multi_line_scalar.yml",
    ymap!{
        "plain": ystr!("This unquoted scalar spans many lines."),
        "quoted": ystr!("So does this quoted scalar.\n")
    })
}

#[test]
fn utf16le() {
    match_file(YamlEncoding::YamlUtf16LeEncoding, "utf16le.yml",
               yseq![ystr!("Hello"), ystr!("世界")]
    )
}

#[test]
fn utf16be() {
    match_file(YamlEncoding::YamlUtf16BeEncoding, "utf16be.yml",
               yseq![ystr!("Hello"), ystr!("世界")]
    )
}
<|endoftext|>


<commit_before>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::net::SocketAddr;
use std::collections::HashMap;

use crypto::PublicKey;
use router::Router;
use iron::prelude::*;

use params::{Params, Value as ParamsValue};
use node::{NodeChannel, ApiSender};
use blockchain::{Service, Blockchain, SharedNodeState};
use api::{Api, ApiError};
use messages::{TEST_NETWORK_ID, PROTOCOL_MAJOR_VERSION};

#[derive(Serialize, Clone, Debug)]
struct ServiceInfo {
    name: String,
    id: u16,
}

/// `DTO` is used to transfer information about node.
#[derive(Serialize, Clone, Debug)]
pub struct NodeInfo {
    network_id: u8,
    protocol_version: u8,
    services: Vec<ServiceInfo>,
}

impl NodeInfo {
    /// Creates new `NodeInfo`, from services list.
    pub fn new<'a, I>(services: I) -> NodeInfo
    where
        I: IntoIterator<Item = &'a Box<Service>>,
    {
        NodeInfo {
            network_id: TEST_NETWORK_ID,
            protocol_version: PROTOCOL_MAJOR_VERSION,
            services: services
                .into_iter()
                .map(|s| {
                    ServiceInfo {
                        name: s.service_name().to_owned(),
                        id: s.service_id(),
                    }
                })
                .collect(),
        }
    }
}

#[derive(Serialize, Default)]
struct ReconnectInfo {
    delay: u64,
}

#[derive(Serialize)]
enum IncommingConnectionState {
    Active,
    Reconnect(ReconnectInfo),
}

impl Default for IncommingConnectionState {
    fn default() -> IncommingConnectionState {
        IncommingConnectionState::Active
    }
}

#[derive(Serialize, Default)]
struct IncommingConnection {
    public_key: Option<PublicKey>,
    state: IncommingConnectionState,
}

#[derive(Serialize)]
struct PeersInfo {
    incoming_connections: Vec<SocketAddr>,
    outgoing_connections: HashMap<SocketAddr, IncommingConnection>,
}

/// Private system API.
#[derive(Clone, Debug)]
pub struct SystemApi {
    blockchain: Blockchain,
    info: NodeInfo,
    shared_api_state: SharedNodeState,
    node_channel: ApiSender<NodeChannel>,
}

impl SystemApi {
    /// Creates a new `public::SystemApi` instance.
    pub fn new(
        info: NodeInfo,
        blockchain: Blockchain,
        shared_api_state: SharedNodeState,
        node_channel: ApiSender<NodeChannel>,
    ) -> SystemApi {
        SystemApi {
            info,
            blockchain,
            node_channel,
            shared_api_state,
        }
    }

    fn get_peers_info(&self) -> PeersInfo {
        let mut outgoing_connections: HashMap<SocketAddr, IncommingConnection> = HashMap::new();

        for socket in self.shared_api_state.outgoing_connections() {
            outgoing_connections.insert(socket, Default::default());
        }

        for (s, delay) in self.shared_api_state.reconnects_timeout() {
            outgoing_connections
                .entry(s)
                .or_insert(Default::default())
                .state = IncommingConnectionState::Reconnect(ReconnectInfo { delay });
        }

        for (s, p) in self.shared_api_state.peers_info() {
            outgoing_connections
                .entry(s)
                .or_insert(Default::default())
                .public_key = Some(p);
        }

        PeersInfo {
            incoming_connections: self.shared_api_state.incoming_connections(),
            outgoing_connections,
        }
    }

    fn get_network_info(&self) -> NodeInfo {
        self.info.clone()
    }

    fn peer_add(&self, ip_str: &str) -> Result<(), ApiError> {
        let addr: SocketAddr = ip_str.parse()?;
        self.node_channel.peer_add(addr)?;
        Ok(())
    }
}

impl Api for SystemApi {
    fn wire(&self, router: &mut Router) {

        let _self = self.clone();
        let peer_add = move |req: &mut Request| -> IronResult<Response> {
            let map = req.get_ref::<Params>().unwrap();
            match map.find(&["ip"]) {
                Some(&ParamsValue::String(ref ip_str)) => {
                    _self.peer_add(ip_str)?;
                    _self.ok_response(&::serde_json::to_value("Ok").unwrap())
                }
                _ => {
                    Err(ApiError::IncorrectRequest(
                        "Required parameter of peer 'ip' is missing".into(),
                    ))?
                }
            }
        };

        let _self = self.clone();
        let peers_info = move |_: &mut Request| -> IronResult<Response> {
            let info = _self.get_peers_info();
            _self.ok_response(&::serde_json::to_value(info).unwrap())
        };

        let _self = self.clone();
        let network = move |_: &mut Request| -> IronResult<Response> {
            let info = _self.get_network_info();
            _self.ok_response(&::serde_json::to_value(info).unwrap())
        };

        router.get("/v1/peers", peers_info, "peers_info");
        router.post("/v1/peers", peer_add, "peer_add");
        router.get("/v1/network", network, "network_info");
    }
}
<commit_msg>add tag<commit_after>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::net::SocketAddr;
use std::collections::HashMap;

use crypto::PublicKey;
use router::Router;
use iron::prelude::*;

use params::{Params, Value as ParamsValue};
use node::{NodeChannel, ApiSender};
use blockchain::{Service, Blockchain, SharedNodeState};
use api::{Api, ApiError};
use messages::{TEST_NETWORK_ID, PROTOCOL_MAJOR_VERSION};

#[derive(Serialize, Clone, Debug)]
struct ServiceInfo {
    name: String,
    id: u16,
}

/// `DTO` is used to transfer information about node.
#[derive(Serialize, Clone, Debug)]
pub struct NodeInfo {
    network_id: u8,
    protocol_version: u8,
    services: Vec<ServiceInfo>,
}

impl NodeInfo {
    /// Creates new `NodeInfo`, from services list.
    pub fn new<'a, I>(services: I) -> NodeInfo
    where
        I: IntoIterator<Item = &'a Box<Service>>,
    {
        NodeInfo {
            network_id: TEST_NETWORK_ID,
            protocol_version: PROTOCOL_MAJOR_VERSION,
            services: services
                .into_iter()
                .map(|s| {
                    ServiceInfo {
                        name: s.service_name().to_owned(),
                        id: s.service_id(),
                    }
                })
                .collect(),
        }
    }
}

#[derive(Serialize, Default)]
struct ReconnectInfo {
    delay: u64,
}

#[derive(Serialize)]
#[serde(tag = "type")]
enum IncommingConnectionState {
    Active,
    Reconnect(ReconnectInfo),
}

impl Default for IncommingConnectionState {
    fn default() -> IncommingConnectionState {
        IncommingConnectionState::Active
    }
}

#[derive(Serialize, Default)]
struct IncommingConnection {
    public_key: Option<PublicKey>,
    state: IncommingConnectionState,
}

#[derive(Serialize)]
struct PeersInfo {
    incoming_connections: Vec<SocketAddr>,
    outgoing_connections: HashMap<SocketAddr, IncommingConnection>,
}

/// Private system API.
#[derive(Clone, Debug)]
pub struct SystemApi {
    blockchain: Blockchain,
    info: NodeInfo,
    shared_api_state: SharedNodeState,
    node_channel: ApiSender<NodeChannel>,
}

impl SystemApi {
    /// Creates a new `public::SystemApi` instance.
    pub fn new(
        info: NodeInfo,
        blockchain: Blockchain,
        shared_api_state: SharedNodeState,
        node_channel: ApiSender<NodeChannel>,
    ) -> SystemApi {
        SystemApi {
            info,
            blockchain,
            node_channel,
            shared_api_state,
        }
    }

    fn get_peers_info(&self) -> PeersInfo {
        let mut outgoing_connections: HashMap<SocketAddr, IncommingConnection> = HashMap::new();

        for socket in self.shared_api_state.outgoing_connections() {
            outgoing_connections.insert(socket, Default::default());
        }

        for (s, delay) in self.shared_api_state.reconnects_timeout() {
            outgoing_connections
                .entry(s)
                .or_insert(Default::default())
                .state = IncommingConnectionState::Reconnect(ReconnectInfo { delay });
        }

        for (s, p) in self.shared_api_state.peers_info() {
            outgoing_connections
                .entry(s)
                .or_insert(Default::default())
                .public_key = Some(p);
        }

        PeersInfo {
            incoming_connections: self.shared_api_state.incoming_connections(),
            outgoing_connections,
        }
    }

    fn get_network_info(&self) -> NodeInfo {
        self.info.clone()
    }

    fn peer_add(&self, ip_str: &str) -> Result<(), ApiError> {
        let addr: SocketAddr = ip_str.parse()?;
        self.node_channel.peer_add(addr)?;
        Ok(())
    }
}

impl Api for SystemApi {
    fn wire(&self, router: &mut Router) {

        let _self = self.clone();
        let peer_add = move |req: &mut Request| -> IronResult<Response> {
            let map = req.get_ref::<Params>().unwrap();
            match map.find(&["ip"]) {
                Some(&ParamsValue::String(ref ip_str)) => {
                    _self.peer_add(ip_str)?;
                    _self.ok_response(&::serde_json::to_value("Ok").unwrap())
                }
                _ => {
                    Err(ApiError::IncorrectRequest(
                        "Required parameter of peer 'ip' is missing".into(),
                    ))?
                }
            }
        };

        let _self = self.clone();
        let peers_info = move |_: &mut Request| -> IronResult<Response> {
            let info = _self.get_peers_info();
            _self.ok_response(&::serde_json::to_value(info).unwrap())
        };

        let _self = self.clone();
        let network = move |_: &mut Request| -> IronResult<Response> {
            let info = _self.get_network_info();
            _self.ok_response(&::serde_json::to_value(info).unwrap())
        };

        router.get("/v1/peers", peers_info, "peers_info");
        router.post("/v1/peers", peer_add, "peer_add");
        router.get("/v1/network", network, "network_info");
    }
}
<|endoftext|>


<commit_before>use std::io::{Error, ErrorKind, Read};
use crate::PcapError;

const BUF_SIZE: usize = 1_000_000;

#[derive(Debug)]
pub(crate) struct ReadBuffer<R: Read> {
    reader: R,
    buffer: Vec<u8>,
    pos: usize,
    len: usize
}

impl<R: Read> ReadBuffer<R> {
    pub fn new(reader: R) -> Self {
        Self {
            reader,
            buffer: vec![0_u8; BUF_SIZE],
            pos: 0,
            len: 0
        }
    }

    pub fn fill_buf(&mut self) -> Result<usize, std::io::Error> {
        // Copy the remaining data to the start of the buffer
        let (start, rem) = self.buffer.split_at_mut(self.pos);
        let rem = &rem[..self.len];
        start.copy_from_slice(rem);
        let rem_len = rem.len();

        let nb_read = self.reader.read(&mut self.buffer[rem_len..])?;

        self.len = rem_len + nb_read;
        self.pos = 0;

        Ok(nb_read)
    }

    pub fn buffer(&self) -> &[u8] {
        &self.buffer[self.pos..self.len]
    }

    pub fn advance(&mut self, rem: &[u8]) {
        Self::advance_raw(&self.buffer, &mut self.pos, &mut self.len, rem)
    }

    fn advance_raw(buffer: &[u8], pos: &mut usize, len: &mut usize, slice: &[u8]) {
        // Compute the length between the buffer and the slice
        let diff_len = slice.as_ptr() as usize - buffer.as_ptr() as usize;

        // Assert that the slice is a subslice of the buffer
        assert!(diff_len <= *len);
        assert!(diff_len + slice.len() <= *len);

        *pos = diff_len;
        *len = diff_len + slice.len();
    }

    pub fn parse_with<'a, F, O>(&'a mut self, mut parser: F) -> Result<O, PcapError>
        where F: FnMut(&'a [u8]) -> Result<(&'a [u8], O), PcapError>,
              O: 'a
    {
        loop {
            let buf: &'static [u8] = unsafe{std::mem::transmute(&self.buffer[self.pos..self.len])};
            match parser(buf) {
                Ok((rem, value)) => {
                    Self::advance_raw(&self.buffer, &mut self.pos, &mut self.len, rem);
                    return Ok(value);
                },

                Err(PcapError::IncompleteBuffer(_)) => {
                    let nb_read = self.fill_buf()?;
                    if nb_read == 0 {
                        return Err(PcapError::IoError(Error::from(ErrorKind::UnexpectedEof)));
                    }
                },

                Err(e) => return Err(e)
            }
        }
    }

    /*
    pub fn parse_with_raw<'a, 'b: 'a, F, O>(reader: &mut R, buffer: &'b mut [u8], pos: &mut usize, len: &mut usize, mut parser: F) -> Result<O, PcapError>
        where F: FnMut(&'a [u8]) -> Result<(&'a [u8], O), PcapError>
    {
        loop {
            let buf = &buffer[*pos.. *len];
            match parser(buf) {
                Ok((rem, value)) => {
                    Self::advance_raw(&buffer, pos, len, rem);
                    return Ok(value);
                },

                Err(PcapError::IncompleteBuffer(_)) => {
                    let nb_read = Self::fill_buf_raw(reader, buffer, pos, len)?;
                    if nb_read == 0 {
                        return Err(PcapError::IoError(Error::from(ErrorKind::UnexpectedEof)));
                    }
                },

                Err(e) => return Err(e)
            }
        }
    }
    */

    /*
    pub fn fill_buf_raw(reader: &mut R, buffer: &mut [u8], pos: &mut usize, len: &mut usize) -> Result<usize, std::io::Error> {
        // Copy the remaining data to the start of the buffer
        let (start, rem) = buffer.split_at_mut(*pos);
        start.copy_from_slice(&rem[.. *len]);
        let rem_len = rem.len();

        let nb_read = reader.read(&mut buffer[rem_len..])?;

        *len = rem_len + nb_read;
        *pos = 0;

        Ok(nb_read)
    }*/

    pub fn is_empty(&mut self) -> Result<bool, std::io::Error> {
        // The buffer can be empty and the reader can still have data
        if self.buffer().is_empty() {
            let nb_read = self.fill_buf()?;
            if nb_read == 0 {
                return Ok(true);
            }
        }

        Ok(false)
    }

    pub fn into_inner(self) -> R {
        self.reader
    }
}<commit_msg>Fix a bug in ReadBuffer::fill_buf()<commit_after>use std::io::{Error, ErrorKind, Read};
use crate::PcapError;

const BUF_SIZE: usize = 1_000_000;

#[derive(Debug)]
pub(crate) struct ReadBuffer<R: Read> {
    reader: R,
    buffer: Vec<u8>,
    pos: usize,
    len: usize
}

impl<R: Read> ReadBuffer<R> {
    pub fn new(reader: R) -> Self {
        Self {
            reader,
            buffer: vec![0_u8; BUF_SIZE],
            pos: 0,
            len: 0
        }
    }

    pub fn fill_buf(&mut self) -> Result<usize, std::io::Error> {
        // Copy the remaining data to the start of the buffer
        let rem_len = unsafe {
            let buf_ptr_mut = self.buffer.as_mut_ptr();
            let rem_ptr_mut = buf_ptr_mut.add(self.pos);
            std::ptr::copy(rem_ptr_mut, buf_ptr_mut, self.len - self.pos);
            self.len - self.pos
        };

        let nb_read = self.reader.read(&mut self.buffer[rem_len..])?;

        self.len = rem_len + nb_read;
        self.pos = 0;

        Ok(nb_read)
    }

    pub fn buffer(&self) -> &[u8] {
        &self.buffer[self.pos..self.len]
    }

    pub fn advance(&mut self, rem: &[u8]) {
        Self::advance_raw(&self.buffer, &mut self.pos, &mut self.len, rem)
    }

    fn advance_raw(buffer: &[u8], pos: &mut usize, len: &mut usize, slice: &[u8]) {
        // Compute the length between the buffer and the slice
        let diff_len = slice.as_ptr() as usize - buffer.as_ptr() as usize;

        // Assert that the slice is a subslice of the buffer
        assert!(diff_len <= *len);
        assert!(diff_len + slice.len() <= *len);

        *pos = diff_len;
        *len = diff_len + slice.len();
    }

    pub fn parse_with<'a, F, O>(&'a mut self, mut parser: F) -> Result<O, PcapError>
        where F: FnMut(&'a [u8]) -> Result<(&'a [u8], O), PcapError>,
              O: 'a
    {
        loop {
            let buf: &'static [u8] = unsafe{std::mem::transmute(&self.buffer[self.pos..self.len])};
            match parser(buf) {
                Ok((rem, value)) => {
                    Self::advance_raw(&self.buffer, &mut self.pos, &mut self.len, rem);
                    return Ok(value);
                },

                Err(PcapError::IncompleteBuffer(_)) => {
                    let nb_read = self.fill_buf()?;
                    if nb_read == 0 {
                        return Err(PcapError::IoError(Error::from(ErrorKind::UnexpectedEof)));
                    }
                },

                Err(e) => return Err(e)
            }
        }
    }

    /*
    pub fn parse_with_raw<'a, 'b: 'a, F, O>(reader: &mut R, buffer: &'b mut [u8], pos: &mut usize, len: &mut usize, mut parser: F) -> Result<O, PcapError>
        where F: FnMut(&'a [u8]) -> Result<(&'a [u8], O), PcapError>
    {
        loop {
            let buf = &buffer[*pos.. *len];
            match parser(buf) {
                Ok((rem, value)) => {
                    Self::advance_raw(&buffer, pos, len, rem);
                    return Ok(value);
                },

                Err(PcapError::IncompleteBuffer(_)) => {
                    let nb_read = Self::fill_buf_raw(reader, buffer, pos, len)?;
                    if nb_read == 0 {
                        return Err(PcapError::IoError(Error::from(ErrorKind::UnexpectedEof)));
                    }
                },

                Err(e) => return Err(e)
            }
        }
    }
    */

    /*
    pub fn fill_buf_raw(reader: &mut R, buffer: &mut [u8], pos: &mut usize, len: &mut usize) -> Result<usize, std::io::Error> {
        // Copy the remaining data to the start of the buffer
        let (start, rem) = buffer.split_at_mut(*pos);
        start.copy_from_slice(&rem[.. *len]);
        let rem_len = rem.len();

        let nb_read = reader.read(&mut buffer[rem_len..])?;

        *len = rem_len + nb_read;
        *pos = 0;

        Ok(nb_read)
    }*/

    pub fn is_empty(&mut self) -> Result<bool, std::io::Error> {
        // The buffer can be empty and the reader can still have data
        if self.buffer().is_empty() {
            let nb_read = self.fill_buf()?;
            if nb_read == 0 {
                return Ok(true);
            }
        }

        Ok(false)
    }

    pub fn into_inner(self) -> R {
        self.reader
    }
}<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::cmp;

use unicode_width::UnicodeWidthChar;
use rustbox::{Style, Color, RustBox};

use command::{Command, BuilderEvent};
use keyboard::Key;

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum OverlayType {
    CommandPrompt,
}

pub trait Overlay {
    fn draw(&self, rb: &mut RustBox);
    fn draw_cursor(&mut self, rb: &mut RustBox);
    fn handle_key_event(&mut self, key: Key) -> BuilderEvent;
}

pub struct CommandPrompt {
    cursor_x: usize,
    data: String,
    prefix: String,
    commands: HashMap<String, Command>,
    selected_index: usize,
}

impl CommandPrompt {
    pub fn new() -> CommandPrompt {
        let mut commands = HashMap::new();

        commands.insert("quit".into(), Command::exit_editor());
        commands.insert("write".into(), Command::save_buffer());

        CommandPrompt {
            cursor_x: 1,
            data: String::new(),
            prefix: String::from(":"),
            commands: commands,
            selected_index: 0,
        }
    }
}

impl CommandPrompt {
    fn get_filtered_command_names(&self) -> Vec<&String> {
        let mut keys: Vec<&String> = self.commands
            .keys()
            .filter(|ref item| (&item).starts_with(&self.data) )
            .collect();
        keys.sort();
        keys.reverse();

        keys
    }
}

impl Overlay for CommandPrompt {
    fn draw(&self, rb: &mut RustBox) {
        let height = rb.height() - 1;
        let offset = self.prefix.len();

        let keys = self.get_filtered_command_names();

        // find the longest command in the resulting list
        let mut max = 20;
        for k in &keys {
            max = cmp::max(max, k.len());
        }

        // draw the command completion list
        let mut index = 1;
        for key in &keys {
            rb.print_char(0, height - index, Style::empty(), Color::White, Color::Black, '│');
            rb.print_char(max + 1, height - index, Style::empty(), Color::White, Color::Black, '│');

            let (fg, bg) = if index == self.selected_index {
                (Color::White, Color::Red)
            } else {
                (Color::White, Color::Black)
            };

            let mut chars = key.chars();
            for x in 0..max {
                if let Some(ch) = chars.next() {
                    rb.print_char(x + 1, height - index, Style::empty(), fg, bg, ch);
                } else {
                    rb.print_char(x + 1, height - index, Style::empty(), fg, bg, ' ');
                }
            }

            index += 1;
        }

        rb.print_char(0, height - index, Style::empty(), Color::White, Color::Black, '╭');
        for x in 1..max + 1 {
            rb.print_char(x, height - keys.len() - 1, Style::empty(), Color::White, Color::Black, '─');
        }
        rb.print_char(max + 1, height - index, Style::empty(), Color::White, Color::Black, '╮');

        // draw the given prefix
        for (index, ch) in self.prefix.chars().enumerate() {
            rb.print_char(index, height, Style::empty(), Color::White, Color::Black, ch);
        }

        // draw the overlay data
        for (index, ch) in self.data.chars().enumerate() {
            rb.print_char(index + offset, height, Style::empty(), Color::White, Color::Black, ch);
        }
    }

    fn draw_cursor(&mut self, rb: &mut RustBox) {
        // Prompt is always on the bottom, so we can use the
        // height given by the frontend here
        let height = rb.height() - 1;
        rb.set_cursor(self.cursor_x as isize, height as isize)
    }

    fn handle_key_event(&mut self, key: Key) -> BuilderEvent {
        match key {
            Key::Esc => return BuilderEvent::Complete(Command::noop()),
            Key::Backspace => {
                if let Some(c) = self.data.pop() {
                    if let Some(width) = UnicodeWidthChar::width(c) {
                        self.cursor_x -= width;
                    }
                }
            }
            Key::Enter => {
                match self.commands.get(&self.data) {
                    Some(command) => {
                        return BuilderEvent::Complete(*command);
                    }
                    None => {
                        return BuilderEvent::Incomplete;
                    }
                }
            }
            Key::Up => {
                let max = self.get_filtered_command_names().len();
                if self.selected_index < max {
                    self.selected_index += 1;
                }
            }
            Key::Down => {
                if self.selected_index > 0 {
                    self.selected_index -= 1;
                }
            }
            Key::Tab => {
                if self.selected_index > 0 {
                    let command = {
                        let keys = self.get_filtered_command_names();
                        keys[self.selected_index - 1].clone()
                    };
                    self.data = command;
                    self.cursor_x = self.data.len() + 1;
                }
            }
            Key::Char(c) => {
                if let Some(width) = UnicodeWidthChar::width(c) {
                    self.data.push(c);
                    self.cursor_x += width;
                }
            }
            _ => {}
        }
        return BuilderEvent::Incomplete;
    }
}
<commit_msg>Calculate cursor_x when needed instead of maintaining it (#135)<commit_after>use std::collections::HashMap;
use std::cmp;

use unicode_width::UnicodeWidthStr;
use rustbox::{Style, Color, RustBox};

use command::{Command, BuilderEvent};
use keyboard::Key;

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum OverlayType {
    CommandPrompt,
}

pub trait Overlay {
    fn draw(&self, rb: &mut RustBox);
    fn draw_cursor(&mut self, rb: &mut RustBox);
    fn handle_key_event(&mut self, key: Key) -> BuilderEvent;
}

pub struct CommandPrompt {
    data: String,
    prefix: String,
    commands: HashMap<String, Command>,
    selected_index: usize,
}

impl CommandPrompt {
    pub fn new() -> CommandPrompt {
        let mut commands = HashMap::new();

        commands.insert("quit".into(), Command::exit_editor());
        commands.insert("write".into(), Command::save_buffer());

        CommandPrompt {
            data: String::new(),
            prefix: String::from(":"),
            commands: commands,
            selected_index: 0,
        }
    }
}

impl CommandPrompt {
    fn get_filtered_command_names(&self) -> Vec<&String> {
        let mut keys: Vec<&String> = self.commands
            .keys()
            .filter(|ref item| (&item).starts_with(&self.data) )
            .collect();
        keys.sort();
        keys.reverse();

        keys
    }
}

impl Overlay for CommandPrompt {
    fn draw(&self, rb: &mut RustBox) {
        let height = rb.height() - 1;
        let offset = self.prefix.len();

        let keys = self.get_filtered_command_names();

        // find the longest command in the resulting list
        let mut max = 20;
        for k in &keys {
            max = cmp::max(max, k.len());
        }

        // draw the command completion list
        let mut index = 1;
        for key in &keys {
            rb.print_char(0, height - index, Style::empty(), Color::White, Color::Black, '│');
            rb.print_char(max + 1, height - index, Style::empty(), Color::White, Color::Black, '│');

            let (fg, bg) = if index == self.selected_index {
                (Color::White, Color::Red)
            } else {
                (Color::White, Color::Black)
            };

            let mut chars = key.chars();
            for x in 0..max {
                if let Some(ch) = chars.next() {
                    rb.print_char(x + 1, height - index, Style::empty(), fg, bg, ch);
                } else {
                    rb.print_char(x + 1, height - index, Style::empty(), fg, bg, ' ');
                }
            }

            index += 1;
        }

        rb.print_char(0, height - index, Style::empty(), Color::White, Color::Black, '╭');
        for x in 1..max + 1 {
            rb.print_char(x, height - keys.len() - 1, Style::empty(), Color::White, Color::Black, '─');
        }
        rb.print_char(max + 1, height - index, Style::empty(), Color::White, Color::Black, '╮');

        // draw the given prefix
        for (index, ch) in self.prefix.chars().enumerate() {
            rb.print_char(index, height, Style::empty(), Color::White, Color::Black, ch);
        }

        // draw the overlay data
        for (index, ch) in self.data.chars().enumerate() {
            rb.print_char(index + offset, height, Style::empty(), Color::White, Color::Black, ch);
        }
    }

    fn draw_cursor(&mut self, rb: &mut RustBox) {
        // Prompt is always on the bottom, so we can use the
        // height given by the frontend here
        let height = rb.height() - 1;
        let prefix_len = UnicodeWidthStr::width(self.prefix.as_str());
        let data_len = UnicodeWidthStr::width(self.data.as_str());
        let cursor_x = prefix_len + data_len;
        rb.set_cursor(cursor_x as isize, height as isize);
    }

    fn handle_key_event(&mut self, key: Key) -> BuilderEvent {
        match key {
            Key::Esc => return BuilderEvent::Complete(Command::noop()),
            Key::Backspace => { self.data.pop(); },
            Key::Enter => {
                match self.commands.get(&self.data) {
                    Some(command) => {
                        return BuilderEvent::Complete(*command);
                    }
                    None => {
                        return BuilderEvent::Incomplete;
                    }
                }
            }
            Key::Up => {
                let max = self.get_filtered_command_names().len();
                if self.selected_index < max {
                    self.selected_index += 1;
                }
            }
            Key::Down => {
                if self.selected_index > 0 {
                    self.selected_index -= 1;
                }
            }
            Key::Tab => {
                if self.selected_index > 0 {
                    let command = {
                        let keys = self.get_filtered_command_names();
                        keys[self.selected_index - 1].clone()
                    };
                    self.data = command;
                }
            }
            Key::Char(c) => { self.data.push(c) },
            _ => {}
        }
        return BuilderEvent::Incomplete;
    }
}
<|endoftext|>