<commit_before>#![deny(warnings)]

extern crate coreutils;
extern crate extra;

use std::env;
use std::str;
use std::fs::File;
use std::process::exit;
use std::io::{stdout, stderr, stdin, Error, Write, BufRead, BufReader, BufWriter};
use coreutils::ArgParser;
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = r#"
NAME
    uniq - report or omit repeated lines

SYNOPSIS
    uniq [ -h | --help | -d | -u | -i ] [FILE]...

DESCRIPTION
    Filter adjacent matching lines of FILE(s) to standard output.

    With no FILE(s), read standard input.

OPTIONS
    -h
    --help
        display this help and exit
    -c
    --count
        precede each output line with a count of the number of times the line occurred in the input
    -i
    --ignore-case
        compare lines case-insensitively
    -d
    --repeated-lines
        only print duplicate lines, one for each group
    -u
    --unique-lines
        only print unique lines
"#; /* @MANEND */

fn lines_from_stdin() -> Result<Vec<Vec<u8>>, Error> {
    let stdin = stdin();
    let mut lines = Vec::new();

    let f = BufReader::new(stdin.lock());
    for line in f.split(b'\n') {
        lines.push(line?);
    }
    Ok(lines)
}

fn lines_from_files(paths: &Vec<&String>) -> Result<Vec<Vec<u8>>, Error> {
    let mut lines = Vec::new();

    for path in paths {
        let f = BufReader::new(File::open(path)?);
        for line in f.split(b'\n') {
            lines.push(line?);
        }
    }
    Ok(lines)
}

fn to_lowercase(vector: &Vec<u8>) -> Vec<u8> {
    vector.iter().map(|c| 0x20 | c).collect::<Vec<_>>()
}

fn eq_strings(left: &Vec<u8>, right: &Vec<u8>, ignore_case: bool) -> bool {
    if ignore_case {
        to_lowercase(left) == to_lowercase(right)
    } else {
        left == right
    }
}

fn get_squashed_lines(lines: &Vec<Vec<u8>>, ignore_case: bool) -> Vec<(usize, &Vec<u8>)> {
    let mut squashed =  Vec::new();
    let llen = lines.len();

    let mut r: usize = 0;

    while r < llen {
        let mut rnext: usize = r + 1;
        let mut count: usize = 1;

        while rnext < llen && eq_strings(&lines[r], &lines[rnext], ignore_case) {
            count += 1;
            rnext += 1;
        }

        squashed.push((count, &lines[r]));
        r += count;
    }

    squashed
}

fn unique_lines(lines: Vec<(usize, &Vec<u8>)>) -> Vec<(usize, &Vec<u8>)> {
   lines.into_iter()
       .filter(|&(k,_)| k == 1)
       .collect::<Vec<_>>()
}

fn repeated_lines(lines: Vec<(usize, &Vec<u8>)>) -> Vec<(usize, &Vec<u8>)> {
   lines.into_iter()
       .filter(|&(k,_)| k > 1)
       .collect::<Vec<_>>()
}

fn main() {

    let stdout = stdout();
    let mut stdout = BufWriter::with_capacity(8192, stdout.lock());
    let mut stderr = stderr();
    let mut parser = ArgParser::new(5)
        .add_flag(&["i", "ignore-case"])
        .add_flag(&["c", "count"])
        .add_flag(&["d", "repeated-lines"])
        .add_flag(&["u", "unique-lines"])
        .add_flag(&["h", "help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    let lines = match parser.args.is_empty() {
        true => lines_from_stdin(),
        false => {
            let paths = parser.args.iter().collect::<Vec<_>>();
            lines_from_files(&paths)
        }
    };

    match lines {
        Ok(ref l) => {
            let mut squashed = get_squashed_lines(&l, parser.found("ignore-case"));

            if parser.found("unique-lines") {
                squashed = unique_lines(squashed);
            } else if parser.found("repeated-lines") {
                squashed = repeated_lines(squashed);
            }

            if parser.found("count") {
                for (c, v) in squashed {
                    let line = str::from_utf8(&v[..]).expect("Unable to parse line");
                    stdout.write(&format!("{} {}\n", c, line).as_bytes()).unwrap();
                }
            } else {
                for (_, v) in squashed {
                    let line = str::from_utf8(&v[..]).expect("Unable to parse line");
                    stdout.write(&format!("{}\n", line).as_bytes()).unwrap();

                }
            }
        }
        Err(e) => {
            let _ = write!(stderr, "{}", e);
        }
    }
}
<commit_msg>Performance improvements for uniq<commit_after>#![deny(warnings)]

extern crate coreutils;
extern crate extra;

use std::env;
use std::str;
use std::fs::File;
use std::process::exit;
use std::io::{stdout, stderr, stdin, Error, Write, BufRead, BufReader, BufWriter};
use coreutils::ArgParser;
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = r#"
NAME
    uniq - report or omit repeated lines

SYNOPSIS
    uniq [ -h | --help | -d | -u | -i ] [FILE]...

DESCRIPTION
    Filter adjacent matching lines of FILE(s) to standard output.

    With no FILE(s), read standard input.

OPTIONS
    -h
    --help
        display this help and exit
    -c
    --count
        precede each output line with a count of the number of times the line occurred in the input
    -i
    --ignore-case
        compare lines case-insensitively
    -d
    --repeated-lines
        only print duplicate lines, one for each group
    -u
    --unique-lines
        only print unique lines
"#; /* @MANEND */

fn lines_from_stdin() -> Result<Vec<Vec<u8>>, Error> {
    let stdin = stdin();
    let mut lines = Vec::new();

    let f = BufReader::new(stdin.lock());
    for line in f.split(b'\n') {
        lines.push(line?);
    }
    Ok(lines)
}

fn lines_from_files(paths: &Vec<&String>) -> Result<Vec<Vec<u8>>, Error> {
    let mut lines = Vec::new();

    for path in paths {
        let f = BufReader::new(File::open(path)?);
        for line in f.split(b'\n') {
            lines.push(line?);
        }
    }
    Ok(lines)
}

fn eq_strings(left: &Vec<u8>, right: &Vec<u8>, ignore_case: bool) -> bool {
    if ignore_case {
        left.len() == right.len() &&
        left
            .iter()
            .zip(right.iter())
            .all(|(&l, &r)|  l | 0x20 == r | 0x20)

    } else {
        left == right
    }
}

fn get_squashed_lines(lines: &Vec<Vec<u8>>, ignore_case: bool) -> Vec<(usize, &Vec<u8>)> {
    let mut squashed =  Vec::new();
    let llen = lines.len();

    let mut r: usize = 0;

    while r < llen {
        let mut rnext: usize = r + 1;
        let mut count: usize = 1;

        while rnext < llen && eq_strings(&lines[r], &lines[rnext], ignore_case) {
            count += 1;
            rnext += 1;
        }

        squashed.push((count, &lines[r]));
        r += count;
    }

    squashed
}

fn unique_lines(lines: Vec<(usize, &Vec<u8>)>) -> Vec<(usize, &Vec<u8>)> {
   lines.into_iter()
       .filter(|&(k,_)| k == 1)
       .collect::<Vec<_>>()
}

fn repeated_lines(lines: Vec<(usize, &Vec<u8>)>) -> Vec<(usize, &Vec<u8>)> {
   lines.into_iter()
       .filter(|&(k,_)| k > 1)
       .collect::<Vec<_>>()
}

fn main() {

    let stdout = stdout();
    let mut stdout = BufWriter::with_capacity(8192, stdout.lock());
    let mut stderr = stderr();
    let mut parser = ArgParser::new(5)
        .add_flag(&["i", "ignore-case"])
        .add_flag(&["c", "count"])
        .add_flag(&["d", "repeated-lines"])
        .add_flag(&["u", "unique-lines"])
        .add_flag(&["h", "help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    let lines = match parser.args.is_empty() {
        true => lines_from_stdin(),
        false => {
            let paths = parser.args.iter().collect::<Vec<_>>();
            lines_from_files(&paths)
        }
    };

    match lines {
        Ok(ref l) => {
            let mut squashed = get_squashed_lines(&l, parser.found("ignore-case"));

            if parser.found("unique-lines") {
                squashed = unique_lines(squashed);
            } else if parser.found("repeated-lines") {
                squashed = repeated_lines(squashed);
            }

            if parser.found("count") {
                for (c, v) in squashed {
                    let _ = stdout.write_fmt(format_args!("{} ", c))
                        .and_then(|_| stdout.write_all(b" "))
                        .and_then(|_| stdout.write_all(v))
                        .and_then(|_| stdout.write_all(b"\n"));
                }
            } else {
                for (_, v) in squashed {
                    let _ = stdout.write_all(v)
                        .and_then(|_| stdout.write_all(b"\n"));
                }
            }
        }
        Err(e) => {
            let _ = write!(stderr, "{}", e);
        }
    }
}
<|endoftext|>


<commit_before>use std::f32;
use std::f64;

use protobuf::reflect::FieldDescriptor;
use protobuf::reflect::MessageDescriptor;
use protobuf::reflect::ReflectValueBox;
use protobuf::reflect::RuntimeFieldType;
use protobuf::reflect::RuntimeTypeBox;
use protobuf::well_known_types::value;
use protobuf::well_known_types::Value;
use protobuf::Message;
use protobuf::MessageDyn;

pub fn value_for_runtime_type(field_type: &RuntimeTypeBox) -> ReflectValueBox {
    match field_type {
        RuntimeTypeBox::U32 => ReflectValueBox::U32(11),
        RuntimeTypeBox::U64 => ReflectValueBox::U64(12),
        RuntimeTypeBox::I32 => ReflectValueBox::I32(13),
        RuntimeTypeBox::I64 => ReflectValueBox::I64(14),
        RuntimeTypeBox::F32 => ReflectValueBox::F32(15.5),
        RuntimeTypeBox::F64 => ReflectValueBox::F64(16.5),
        RuntimeTypeBox::Bool => ReflectValueBox::Bool(true),
        RuntimeTypeBox::String => ReflectValueBox::String("here".to_owned()),
        RuntimeTypeBox::VecU8 => ReflectValueBox::Bytes(b"there".as_ref().to_owned()),
        RuntimeTypeBox::Enum(e) => ReflectValueBox::from(e.first_value()),
        RuntimeTypeBox::Message(m) => ReflectValueBox::Message(m.new_instance()),
    }
}

fn values_for_message_type(descriptor: &MessageDescriptor) -> Vec<Box<dyn MessageDyn>> {
    if descriptor == &Value::descriptor_static() {
        // special handling because empty `Value` is not valid
        let mut value = Value::new();
        value.kind = Some(value::Kind::number_value(23.0));
        vec![Box::new(value)]
    } else {
        vec![
            // TODO: populated messages
            descriptor.new_instance(),
        ]
    }
}

pub fn values_for_runtime_type(field_type: &RuntimeTypeBox) -> Vec<ReflectValueBox> {
    match field_type {
        RuntimeTypeBox::U32 => vec![
            ReflectValueBox::U32(11),
            ReflectValueBox::U32(0),
            ReflectValueBox::U32(0x7fff_ffff),
            ReflectValueBox::U32(0x8000_0000),
            ReflectValueBox::U32(0xffff_ffff),
        ],
        RuntimeTypeBox::U64 => vec![
            ReflectValueBox::U64(12),
            ReflectValueBox::U64(0),
            ReflectValueBox::U64(0xffff_ffff),
            ReflectValueBox::U64(0xffff_ffff_ffff_ffff),
        ],
        RuntimeTypeBox::I32 => vec![
            ReflectValueBox::I32(13),
            ReflectValueBox::I32(0),
            ReflectValueBox::I32(-1),
            ReflectValueBox::I32(0x7fff_ffff),
            ReflectValueBox::I32(0x1000_0000),
        ],
        RuntimeTypeBox::I64 => vec![
            ReflectValueBox::I64(14),
            ReflectValueBox::I64(0),
            ReflectValueBox::I64(-1),
            ReflectValueBox::I64(0x7fff_ffff_ffff_ffff),
            ReflectValueBox::I64(0x1000_0000_0000_0000),
        ],
        RuntimeTypeBox::F32 => vec![
            ReflectValueBox::F32(15.5),
            ReflectValueBox::F32(0.0),
            ReflectValueBox::F32(-0.0),
            ReflectValueBox::F32(1. / 3.0),
            ReflectValueBox::F32(-1. / 3.0),
            ReflectValueBox::F32(f32::NAN),
            ReflectValueBox::F32(f32::INFINITY),
            ReflectValueBox::F32(-f32::INFINITY),
        ],
        RuntimeTypeBox::F64 => vec![
            ReflectValueBox::F64(16.5),
            ReflectValueBox::F64(0.0),
            ReflectValueBox::F64(-0.0),
            ReflectValueBox::F64(1.0 / 3.0),
            ReflectValueBox::F64(-1.0 / 3.0),
            ReflectValueBox::F64(f64::NAN),
            ReflectValueBox::F64(f64::INFINITY),
            ReflectValueBox::F64(-f64::INFINITY),
        ],
        RuntimeTypeBox::Bool => vec![ReflectValueBox::Bool(true), ReflectValueBox::Bool(false)],
        RuntimeTypeBox::String => vec![
            ReflectValueBox::String("here".to_owned()),
            ReflectValueBox::String("".to_owned()),
            ReflectValueBox::String(" \t\n".to_owned()),
            ReflectValueBox::String("\0".to_owned()),
        ],
        RuntimeTypeBox::VecU8 => vec![
            ReflectValueBox::Bytes(b"there".as_ref().to_owned()),
            ReflectValueBox::Bytes(b"".as_ref().to_owned()),
        ],
        RuntimeTypeBox::Enum(e) => vec![
            ReflectValueBox::from(e.values().next().unwrap()),
            ReflectValueBox::from(e.values().last().unwrap()),
        ],
        RuntimeTypeBox::Message(m) => values_for_message_type(&m)
            .into_iter()
            .map(ReflectValueBox::from)
            .collect(),
    }
}

pub fn special_values_for_field(
    f: &FieldDescriptor,
    d: &MessageDescriptor,
) -> Vec<Box<dyn MessageDyn>> {
    let mut r = Vec::new();
    match f.runtime_field_type() {
        RuntimeFieldType::Singular(t) => {
            for v in values_for_runtime_type(&t) {
                let mut m = d.new_instance();
                f.set_singular_field(&mut *m, v);
                r.push(m);
            }
        }
        RuntimeFieldType::Repeated(t) => {
            // TODO: empty repeated
            // TODO: repeated of more than one element
            let mut m = d.new_instance();
            f.mut_repeated(&mut *m).push(value_for_runtime_type(&t));
            r.push(m);
        }
        RuntimeFieldType::Map(k, v) => {
            // TODO: empty map
            // TODO: map of more than one element
            let mut m = d.new_instance();
            let k = value_for_runtime_type(&k);
            let v = value_for_runtime_type(&v);
            f.mut_map(&mut *m).insert(k, v);
            r.push(m);
        }
    }
    r
}

pub fn special_messages(d: &MessageDescriptor) -> Vec<Box<dyn MessageDyn>> {
    let mut r = Vec::new();
    for f in d.fields() {
        r.extend(special_values_for_field(&f, d));
    }
    r
}

pub fn special_messages_typed<M: Message>() -> Vec<M> {
    let mut r = Vec::new();
    for m in special_messages(&M::descriptor_static()) {
        r.push(*m.downcast_box().unwrap());
    }
    r
}
<commit_msg>Remove unused module imports, use associated constants<commit_after>use protobuf::reflect::FieldDescriptor;
use protobuf::reflect::MessageDescriptor;
use protobuf::reflect::ReflectValueBox;
use protobuf::reflect::RuntimeFieldType;
use protobuf::reflect::RuntimeTypeBox;
use protobuf::well_known_types::value;
use protobuf::well_known_types::Value;
use protobuf::Message;
use protobuf::MessageDyn;

pub fn value_for_runtime_type(field_type: &RuntimeTypeBox) -> ReflectValueBox {
    match field_type {
        RuntimeTypeBox::U32 => ReflectValueBox::U32(11),
        RuntimeTypeBox::U64 => ReflectValueBox::U64(12),
        RuntimeTypeBox::I32 => ReflectValueBox::I32(13),
        RuntimeTypeBox::I64 => ReflectValueBox::I64(14),
        RuntimeTypeBox::F32 => ReflectValueBox::F32(15.5),
        RuntimeTypeBox::F64 => ReflectValueBox::F64(16.5),
        RuntimeTypeBox::Bool => ReflectValueBox::Bool(true),
        RuntimeTypeBox::String => ReflectValueBox::String("here".to_owned()),
        RuntimeTypeBox::VecU8 => ReflectValueBox::Bytes(b"there".as_ref().to_owned()),
        RuntimeTypeBox::Enum(e) => ReflectValueBox::from(e.first_value()),
        RuntimeTypeBox::Message(m) => ReflectValueBox::Message(m.new_instance()),
    }
}

fn values_for_message_type(descriptor: &MessageDescriptor) -> Vec<Box<dyn MessageDyn>> {
    if descriptor == &Value::descriptor_static() {
        // special handling because empty `Value` is not valid
        let mut value = Value::new();
        value.kind = Some(value::Kind::number_value(23.0));
        vec![Box::new(value)]
    } else {
        vec![
            // TODO: populated messages
            descriptor.new_instance(),
        ]
    }
}

pub fn values_for_runtime_type(field_type: &RuntimeTypeBox) -> Vec<ReflectValueBox> {
    match field_type {
        RuntimeTypeBox::U32 => vec![
            ReflectValueBox::U32(11),
            ReflectValueBox::U32(0),
            ReflectValueBox::U32(0x7fff_ffff),
            ReflectValueBox::U32(0x8000_0000),
            ReflectValueBox::U32(0xffff_ffff),
        ],
        RuntimeTypeBox::U64 => vec![
            ReflectValueBox::U64(12),
            ReflectValueBox::U64(0),
            ReflectValueBox::U64(0xffff_ffff),
            ReflectValueBox::U64(0xffff_ffff_ffff_ffff),
        ],
        RuntimeTypeBox::I32 => vec![
            ReflectValueBox::I32(13),
            ReflectValueBox::I32(0),
            ReflectValueBox::I32(-1),
            ReflectValueBox::I32(0x7fff_ffff),
            ReflectValueBox::I32(0x1000_0000),
        ],
        RuntimeTypeBox::I64 => vec![
            ReflectValueBox::I64(14),
            ReflectValueBox::I64(0),
            ReflectValueBox::I64(-1),
            ReflectValueBox::I64(0x7fff_ffff_ffff_ffff),
            ReflectValueBox::I64(0x1000_0000_0000_0000),
        ],
        RuntimeTypeBox::F32 => vec![
            ReflectValueBox::F32(15.5),
            ReflectValueBox::F32(0.0),
            ReflectValueBox::F32(-0.0),
            ReflectValueBox::F32(1. / 3.0),
            ReflectValueBox::F32(-1. / 3.0),
            ReflectValueBox::F32(f32::NAN),
            ReflectValueBox::F32(f32::INFINITY),
            ReflectValueBox::F32(-f32::INFINITY),
        ],
        RuntimeTypeBox::F64 => vec![
            ReflectValueBox::F64(16.5),
            ReflectValueBox::F64(0.0),
            ReflectValueBox::F64(-0.0),
            ReflectValueBox::F64(1.0 / 3.0),
            ReflectValueBox::F64(-1.0 / 3.0),
            ReflectValueBox::F64(f64::NAN),
            ReflectValueBox::F64(f64::INFINITY),
            ReflectValueBox::F64(-f64::INFINITY),
        ],
        RuntimeTypeBox::Bool => vec![ReflectValueBox::Bool(true), ReflectValueBox::Bool(false)],
        RuntimeTypeBox::String => vec![
            ReflectValueBox::String("here".to_owned()),
            ReflectValueBox::String("".to_owned()),
            ReflectValueBox::String(" \t\n".to_owned()),
            ReflectValueBox::String("\0".to_owned()),
        ],
        RuntimeTypeBox::VecU8 => vec![
            ReflectValueBox::Bytes(b"there".as_ref().to_owned()),
            ReflectValueBox::Bytes(b"".as_ref().to_owned()),
        ],
        RuntimeTypeBox::Enum(e) => vec![
            ReflectValueBox::from(e.values().next().unwrap()),
            ReflectValueBox::from(e.values().last().unwrap()),
        ],
        RuntimeTypeBox::Message(m) => values_for_message_type(&m)
            .into_iter()
            .map(ReflectValueBox::from)
            .collect(),
    }
}

pub fn special_values_for_field(
    f: &FieldDescriptor,
    d: &MessageDescriptor,
) -> Vec<Box<dyn MessageDyn>> {
    let mut r = Vec::new();
    match f.runtime_field_type() {
        RuntimeFieldType::Singular(t) => {
            for v in values_for_runtime_type(&t) {
                let mut m = d.new_instance();
                f.set_singular_field(&mut *m, v);
                r.push(m);
            }
        }
        RuntimeFieldType::Repeated(t) => {
            // TODO: empty repeated
            // TODO: repeated of more than one element
            let mut m = d.new_instance();
            f.mut_repeated(&mut *m).push(value_for_runtime_type(&t));
            r.push(m);
        }
        RuntimeFieldType::Map(k, v) => {
            // TODO: empty map
            // TODO: map of more than one element
            let mut m = d.new_instance();
            let k = value_for_runtime_type(&k);
            let v = value_for_runtime_type(&v);
            f.mut_map(&mut *m).insert(k, v);
            r.push(m);
        }
    }
    r
}

pub fn special_messages(d: &MessageDescriptor) -> Vec<Box<dyn MessageDyn>> {
    let mut r = Vec::new();
    for f in d.fields() {
        r.extend(special_values_for_field(&f, d));
    }
    r
}

pub fn special_messages_typed<M: Message>() -> Vec<M> {
    let mut r = Vec::new();
    for m in special_messages(&M::descriptor_static()) {
        r.push(*m.downcast_box().unwrap());
    }
    r
}
<|endoftext|>


<commit_before>use std::fmt;
use std::string::FromUtf8Error;

use super::lexer_impl::Lexer;
use super::lexer_impl::LexerError;
use crate::text_format::lexer::ParserLanguage;

#[derive(Debug)]
pub enum StrLitDecodeError {
    FromUtf8Error(FromUtf8Error),
    // TODO: be more specific
    OtherError,
}

impl fmt::Display for StrLitDecodeError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            StrLitDecodeError::FromUtf8Error(e) => write!(f, "{}", e),
            StrLitDecodeError::OtherError => write!(f, "String literal decode error"),
        }
    }
}

impl std::error::Error for StrLitDecodeError {}

impl From<LexerError> for StrLitDecodeError {
    fn from(_: LexerError) -> Self {
        StrLitDecodeError::OtherError
    }
}

impl From<FromUtf8Error> for StrLitDecodeError {
    fn from(e: FromUtf8Error) -> Self {
        StrLitDecodeError::FromUtf8Error(e)
    }
}

pub type StrLitDecodeResult<T> = Result<T, StrLitDecodeError>;

/// String literal, both `string` and `bytes`.
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct StrLit {
    pub escaped: String,
}

impl fmt::Display for StrLit {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "\"{}\"", &self.escaped)
    }
}

impl StrLit {
    /// May fail if not valid UTF8
    pub fn decode_utf8(&self) -> StrLitDecodeResult<String> {
        let mut lexer = Lexer::new(&self.escaped, ParserLanguage::Json);
        let mut r = Vec::new();
        while !lexer.eof() {
            r.push(lexer.next_byte_value()?);
        }
        Ok(String::from_utf8(r)?)
    }

    pub fn decode_bytes(&self) -> StrLitDecodeResult<Vec<u8>> {
        let mut lexer = Lexer::new(&self.escaped, ParserLanguage::Json);
        let mut r = Vec::new();
        while !lexer.eof() {
            r.push(lexer.next_byte_value()?);
        }
        Ok(r)
    }

    pub fn quoted(&self) -> String {
        format!("\"{}\"", self.escaped)
    }
}

#[cfg(test)]
mod test {
    use crate::text_format::lexer::StrLit;

    #[test]
    fn decode_utf8() {
        assert_eq!(
            "\u{1234}".to_owned(),
            StrLit {
                escaped: "\\341\\210\\264".to_owned()
            }
            .decode_utf8()
            .unwrap()
        )
    }
}
<commit_msg>Use thiserror for StrLitDecodeError<commit_after>use std::fmt;
use std::string::FromUtf8Error;

use super::lexer_impl::Lexer;
use super::lexer_impl::LexerError;
use crate::text_format::lexer::ParserLanguage;

#[derive(Debug, thiserror::Error)]
pub enum StrLitDecodeError {
    #[error(transparent)]
    FromUtf8Error(#[from] FromUtf8Error),
    // TODO: be more specific
    #[error("String literal decode error")]
    OtherError,
}

impl From<LexerError> for StrLitDecodeError {
    fn from(_: LexerError) -> Self {
        StrLitDecodeError::OtherError
    }
}

pub type StrLitDecodeResult<T> = Result<T, StrLitDecodeError>;

/// String literal, both `string` and `bytes`.
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct StrLit {
    pub escaped: String,
}

impl fmt::Display for StrLit {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "\"{}\"", &self.escaped)
    }
}

impl StrLit {
    /// May fail if not valid UTF8
    pub fn decode_utf8(&self) -> StrLitDecodeResult<String> {
        let mut lexer = Lexer::new(&self.escaped, ParserLanguage::Json);
        let mut r = Vec::new();
        while !lexer.eof() {
            r.push(lexer.next_byte_value()?);
        }
        Ok(String::from_utf8(r)?)
    }

    pub fn decode_bytes(&self) -> StrLitDecodeResult<Vec<u8>> {
        let mut lexer = Lexer::new(&self.escaped, ParserLanguage::Json);
        let mut r = Vec::new();
        while !lexer.eof() {
            r.push(lexer.next_byte_value()?);
        }
        Ok(r)
    }

    pub fn quoted(&self) -> String {
        format!("\"{}\"", self.escaped)
    }
}

#[cfg(test)]
mod test {
    use crate::text_format::lexer::StrLit;

    #[test]
    fn decode_utf8() {
        assert_eq!(
            "\u{1234}".to_owned(),
            StrLit {
                escaped: "\\341\\210\\264".to_owned()
            }
            .decode_utf8()
            .unwrap()
        )
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017 the original author or authors.
 *
 * 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.
 */

pub struct AgentController<'a> {
    #[allow(dead_code)] // TODO: revisit this once port is complete
    jvmti: ::env::JvmTiEnv,
    heuristic: Box<super::Heuristic + 'a>,
    actions: Vec<Box<super::Action>>
}

impl<'a> AgentController<'a> {
    pub fn new(ti: ::env::JvmTiEnv, options: *mut ::std::os::raw::c_char) -> Result<Self, ::jvmti::jint> {
        let parms = super::parms::AgentParameters::parseParameters(options);
        super::heaphistogram::HeapHistogram::new(ti, parms.heap_histogram_max_entries).map(|action| {
            Self {
                jvmti: ti,
                heuristic: Box::new(super::threshold::Threshold::new(parms.count_threshold, parms.time_threshold)),
                actions: vec![Box::new(action), Box::new(super::kill::Kill::new())],
            }
        })
    }

    #[cfg(test)]
    fn test_new(ti: ::env::JvmTiEnv, heuristic: Box<super::Heuristic + 'a>, actions: Vec<Box<super::Action>>) -> Self {
        Self {
            jvmti: ti,
            heuristic: heuristic,
            actions: actions,
        }
    }
}

impl<'a> super::MutAction for AgentController<'a> {
    fn on_oom(&mut self, jni_env: ::env::JniEnv, resource_exhaustion_flags: ::jvmti::jint) {
        const heap_exhausted: ::jvmti::jint = ::jvmti::JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP as ::jvmti::jint;
        const threads_exhausted: ::jvmti::jint = ::jvmti::JVMTI_RESOURCE_EXHAUSTED_THREADS as ::jvmti::jint;
        const oom_error: ::jvmti::jint = ::jvmti::JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR as ::jvmti::jint;

        if resource_exhaustion_flags & heap_exhausted == heap_exhausted {
            eprintln!("\nResource exhaustion event: the JVM was unable to allocate memory from the heap.");
        }
        if resource_exhaustion_flags & threads_exhausted == threads_exhausted {
            eprintln!("\nResource exhaustion event: the JVM was unable to create a thread.");
        }

        if self.heuristic.on_oom() {
            for action in &self.actions {
                action.on_oom(jni_env, resource_exhaustion_flags);
            }
        } else if resource_exhaustion_flags & oom_error == oom_error {
            eprintln!("\nThe JVM is about to throw a java.lang.OutOfMemoryError.");
        }
    }
}

unsafe impl<'a> Send for AgentController<'a> {}

unsafe impl<'a> Sync for AgentController<'a> {}

#[cfg(test)]
mod tests {
    use agentcontroller::MutAction;

    pub struct TestHeuristic {
        call_count: u32
    }

    impl TestHeuristic {
        pub fn new() -> Self {
            Self {
                call_count: 0,
            }
        }
    }

    impl super::super::Heuristic for TestHeuristic {
        fn on_oom(&mut self) -> bool {
            self.call_count += 1;
            self.call_count >= 2
        }
    }

    pub struct TestAction {}

    impl TestAction {
        pub fn new() -> Self {
            Self {}
        }
    }

    impl super::super::Action for TestAction {
        fn on_oom(&self, _: ::env::JniEnv, _: ::jvmti::jint) {
            panic!("TestAction.on_oom")
        }
    }

    #[test]
    fn does_not_call_action_when_heuristic_returns_false() {
        let heuristic = Box::new(TestHeuristic::new());
        let mut ac = super::AgentController::test_new(::env::JvmTiEnv::new(dummy_jni()).unwrap(),
                                                      heuristic,
                                                      vec![Box::new(TestAction::new())]);
        ac.on_oom(dummy_jni_env(), 0);
    }

    #[test]
    #[should_panic(expected = "TestAction.on_oom")]
    fn calls_action_when_heuristic_returns_true() {
        let heuristic = Box::new(TestHeuristic::new());
        let mut ac = super::AgentController::test_new(::env::JvmTiEnv::new(dummy_jni()).unwrap(),
                                                      heuristic,
                                                      vec![Box::new(TestAction::new())]);
        ac.on_oom(dummy_jni_env(), 0);
        ac.on_oom(dummy_jni_env(), 0);
    }

    unsafe extern "C" fn test_get_env(_: *mut ::jvmti::JavaVM,
                                      _: *mut *mut ::std::os::raw::c_void,
                                      _: ::jvmti::jint)
                                      -> ::jvmti::jint {
        0
    }

    fn dummy_jni_env() -> ::env::JniEnv {
        ::env::JniEnv::new(::std::ptr::null_mut())
    }

    fn dummy_jni() -> *mut ::jvmti::JavaVM {
        &mut (&::jvmti::JNIInvokeInterface_ {
            reserved0: ::std::ptr::null_mut(),
            reserved1: ::std::ptr::null_mut(),
            reserved2: ::std::ptr::null_mut(),
            DestroyJavaVM: None,
            AttachCurrentThread: None,
            DetachCurrentThread: None,
            GetEnv: Some(test_get_env),
            AttachCurrentThreadAsDaemon: None,
        } as *const ::jvmti::JNIInvokeInterface_) as *mut *const ::jvmti::JNIInvokeInterface_
    }
}
<commit_msg>Only print heap histogram if specified in parameters<commit_after>/*
 * Copyright (c) 2017 the original author or authors.
 *
 * 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.
 */

pub struct AgentController<'a> {
    #[allow(dead_code)] // TODO: revisit this once port is complete
    jvmti: ::env::JvmTiEnv,
    heuristic: Box<super::Heuristic + 'a>,
    actions: Vec<Box<super::Action>>
}

impl<'a> AgentController<'a> {
    pub fn new(ti: ::env::JvmTiEnv, options: *mut ::std::os::raw::c_char) -> Result<Self, ::jvmti::jint> {
        let parms = super::parms::AgentParameters::parseParameters(options);

        let mut ac = Self {
            jvmti: ti,
            heuristic: Box::new(super::threshold::Threshold::new(parms.count_threshold, parms.time_threshold)),
            actions: Vec::new(),
        };

        if parms.print_heap_histogram {
            ac.actions.push(Box::new(super::heaphistogram::HeapHistogram::new(ti, parms.heap_histogram_max_entries)?));
        }

        ac.actions.push(Box::new(super::kill::Kill::new()));

        Ok(ac)
    }

    #[cfg(test)]
    fn test_new(ti: ::env::JvmTiEnv, heuristic: Box<super::Heuristic + 'a>, actions: Vec<Box<super::Action>>) -> Self {
        Self {
            jvmti: ti,
            heuristic: heuristic,
            actions: actions,
        }
    }
}

impl<'a> super::MutAction for AgentController<'a> {
    fn on_oom(&mut self, jni_env: ::env::JniEnv, resource_exhaustion_flags: ::jvmti::jint) {
        const heap_exhausted: ::jvmti::jint = ::jvmti::JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP as ::jvmti::jint;
        const threads_exhausted: ::jvmti::jint = ::jvmti::JVMTI_RESOURCE_EXHAUSTED_THREADS as ::jvmti::jint;
        const oom_error: ::jvmti::jint = ::jvmti::JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR as ::jvmti::jint;

        if resource_exhaustion_flags & heap_exhausted == heap_exhausted {
            eprintln!("\nResource exhaustion event: the JVM was unable to allocate memory from the heap.");
        }
        if resource_exhaustion_flags & threads_exhausted == threads_exhausted {
            eprintln!("\nResource exhaustion event: the JVM was unable to create a thread.");
        }

        if self.heuristic.on_oom() {
            for action in &self.actions {
                action.on_oom(jni_env, resource_exhaustion_flags);
            }
        } else if resource_exhaustion_flags & oom_error == oom_error {
            eprintln!("\nThe JVM is about to throw a java.lang.OutOfMemoryError.");
        }
    }
}

unsafe impl<'a> Send for AgentController<'a> {}

unsafe impl<'a> Sync for AgentController<'a> {}

#[cfg(test)]
mod tests {
    use agentcontroller::MutAction;

    pub struct TestHeuristic {
        call_count: u32
    }

    impl TestHeuristic {
        pub fn new() -> Self {
            Self {
                call_count: 0,
            }
        }
    }

    impl super::super::Heuristic for TestHeuristic {
        fn on_oom(&mut self) -> bool {
            self.call_count += 1;
            self.call_count >= 2
        }
    }

    pub struct TestAction {}

    impl TestAction {
        pub fn new() -> Self {
            Self {}
        }
    }

    impl super::super::Action for TestAction {
        fn on_oom(&self, _: ::env::JniEnv, _: ::jvmti::jint) {
            panic!("TestAction.on_oom")
        }
    }

    #[test]
    fn does_not_call_action_when_heuristic_returns_false() {
        let heuristic = Box::new(TestHeuristic::new());
        let mut ac = super::AgentController::test_new(::env::JvmTiEnv::new(dummy_jni()).unwrap(),
                                                      heuristic,
                                                      vec![Box::new(TestAction::new())]);
        ac.on_oom(dummy_jni_env(), 0);
    }

    #[test]
    #[should_panic(expected = "TestAction.on_oom")]
    fn calls_action_when_heuristic_returns_true() {
        let heuristic = Box::new(TestHeuristic::new());
        let mut ac = super::AgentController::test_new(::env::JvmTiEnv::new(dummy_jni()).unwrap(),
                                                      heuristic,
                                                      vec![Box::new(TestAction::new())]);
        ac.on_oom(dummy_jni_env(), 0);
        ac.on_oom(dummy_jni_env(), 0);
    }

    unsafe extern "C" fn test_get_env(_: *mut ::jvmti::JavaVM,
                                      _: *mut *mut ::std::os::raw::c_void,
                                      _: ::jvmti::jint)
                                      -> ::jvmti::jint {
        0
    }

    fn dummy_jni_env() -> ::env::JniEnv {
        ::env::JniEnv::new(::std::ptr::null_mut())
    }

    fn dummy_jni() -> *mut ::jvmti::JavaVM {
        &mut (&::jvmti::JNIInvokeInterface_ {
            reserved0: ::std::ptr::null_mut(),
            reserved1: ::std::ptr::null_mut(),
            reserved2: ::std::ptr::null_mut(),
            DestroyJavaVM: None,
            AttachCurrentThread: None,
            DetachCurrentThread: None,
            GetEnv: Some(test_get_env),
            AttachCurrentThreadAsDaemon: None,
        } as *const ::jvmti::JNIInvokeInterface_) as *mut *const ::jvmti::JNIInvokeInterface_
    }
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::fs::File;
use std::string::String;
use std::path::Path;
use std::vec::Vec;
use std::io::BufReader;
use json;
use game::constants::{CHARACTER_JSON_PATH, CHARACTER_BUF_LENGTH, ZOMBIE_JSON_PATH};
use tiled::Map;
use tiled;
use critter::CritterData;

pub fn load_map_file(filename: &str) -> Map {
  let file = match File::open(&Path::new(&filename)) {
    Ok(f) => f,
    Err(e) => panic!("File {} not found: {}", filename, e),
  };
  let reader = BufReader::new(file);
  match tiled::parse(reader) {
    Ok(m) => m,
    Err(e) => panic!("Map parse error {:?}", e)
  }
}

pub fn get_map_tile(map: &Map, layer_index: usize, x: usize, y: usize) -> u32 {
  let layer = match map.layers.get(layer_index) {
    None => panic!("Layer_index value out of index {:?}", map.layers),
    Some(l) => l
  };
  let y_index = match layer.tiles.iter().rev().nth(y) {
    None => panic!("X value out of index {:?}", map.layers[0]),
    Some(x) => x
  };
  match y_index.get(x) {
    None => panic!("Y value out of index {:?}", layer.tiles[y]),
    Some(val) => *val
  }
}

fn read_sprite_file(filename: &str) -> String {
  let path = Path::new(&filename);
  let mut file = match File::open(&path) {
    Ok(f) => f,
    Err(e) => panic!("File {} not found: {}", filename, e),
  };
  let mut buf = String::new();
  match file.read_to_string(&mut buf) {
    Ok(_) => buf,
    Err(_) => panic!("Couldn't read file {}", filename),
  }
}

pub fn load_character() -> Vec<CritterData> {
  let mut sprites = Vec::with_capacity(CHARACTER_BUF_LENGTH + 64);
  let character_json = read_sprite_file(CHARACTER_JSON_PATH);
  let character = match json::parse(&character_json) {
    Ok(res) => res,
    Err(e) => panic!("Character JSON parse error {:?}", e),
  };
  for x in 0..16 {
    for y in 0..14 {
      let key = &format!("run_{}_{}", x, y);
      sprites.push(CritterData::new([
        character["frames"][key]["frame"]["x"].as_f32().unwrap(),
        character["frames"][key]["frame"]["y"].as_f32().unwrap(),
        character["frames"][key]["frame"]["w"].as_f32().unwrap(),
        character["frames"][key]["frame"]["h"].as_f32().unwrap(),
      ]));
    }
  }

  for x in 0..15 {
    for y in 0..4 {
      let key = &format!("fire_{}_{}", x, y);
      sprites.push(CritterData::new([
        character["frames"][key]["frame"]["x"].as_f32().unwrap(),
        character["frames"][key]["frame"]["y"].as_f32().unwrap(),
        character["frames"][key]["frame"]["w"].as_f32().unwrap(),
        character["frames"][key]["frame"]["h"].as_f32().unwrap(),
      ]));
    }
  }

  sprites
}

pub fn load_zombie() -> Vec<CritterData> {
  let mut sprites = Vec::with_capacity(128);
  let character_json = read_sprite_file(ZOMBIE_JSON_PATH);
  let zombie = match json::parse(&character_json) {
    Ok(res) => res,
    Err(e) => panic!("Character JSON parse error {:?}", e),
  };

  for x in 0..7 {
    for y in 0..7 {
      let key = &format!("walk_{}_{}", x, y);
      sprites.push(CritterData::new([
        zombie["frames"][key]["frame"]["x"].as_f32().unwrap(),
        zombie["frames"][key]["frame"]["y"].as_f32().unwrap(),
        zombie["frames"][key]["frame"]["w"].as_f32().unwrap(),
        zombie["frames"][key]["frame"]["h"].as_f32().unwrap()
      ]));
    }
  }

  sprites
}
<commit_msg>Fix zombie.json parsing<commit_after>use std::io::prelude::*;
use std::fs::File;
use std::string::String;
use std::path::Path;
use std::vec::Vec;
use std::io::BufReader;
use json;
use game::constants::{CHARACTER_JSON_PATH, CHARACTER_BUF_LENGTH, ZOMBIE_JSON_PATH};
use tiled::Map;
use tiled;
use critter::CritterData;

pub fn load_map_file(filename: &str) -> Map {
  let file = match File::open(&Path::new(&filename)) {
    Ok(f) => f,
    Err(e) => panic!("File {} not found: {}", filename, e),
  };
  let reader = BufReader::new(file);
  match tiled::parse(reader) {
    Ok(m) => m,
    Err(e) => panic!("Map parse error {:?}", e)
  }
}

pub fn get_map_tile(map: &Map, layer_index: usize, x: usize, y: usize) -> u32 {
  let layer = match map.layers.get(layer_index) {
    None => panic!("Layer_index value out of index {:?}", map.layers),
    Some(l) => l
  };
  let y_index = match layer.tiles.iter().rev().nth(y) {
    None => panic!("X value out of index {:?}", map.layers[0]),
    Some(x) => x
  };
  match y_index.get(x) {
    None => panic!("Y value out of index {:?}", layer.tiles[y]),
    Some(val) => *val
  }
}

fn read_sprite_file(filename: &str) -> String {
  let path = Path::new(&filename);
  let mut file = match File::open(&path) {
    Ok(f) => f,
    Err(e) => panic!("File {} not found: {}", filename, e),
  };
  let mut buf = String::new();
  match file.read_to_string(&mut buf) {
    Ok(_) => buf,
    Err(_) => panic!("Couldn't read file {}", filename),
  }
}

pub fn load_character() -> Vec<CritterData> {
  let mut sprites = Vec::with_capacity(CHARACTER_BUF_LENGTH + 64);
  let character_json = read_sprite_file(CHARACTER_JSON_PATH);
  let character = match json::parse(&character_json) {
    Ok(res) => res,
    Err(e) => panic!("Character JSON parse error {:?}", e),
  };
  for x in 0..16 {
    for y in 0..14 {
      let key = &format!("run_{}_{}", x, y);
      sprites.push(CritterData::new([
        character["frames"][key]["frame"]["x"].as_f32().unwrap(),
        character["frames"][key]["frame"]["y"].as_f32().unwrap(),
        character["frames"][key]["frame"]["w"].as_f32().unwrap(),
        character["frames"][key]["frame"]["h"].as_f32().unwrap(),
      ]));
    }
  }

  for x in 0..15 {
    for y in 0..4 {
      let key = &format!("fire_{}_{}", x, y);
      sprites.push(CritterData::new([
        character["frames"][key]["frame"]["x"].as_f32().unwrap(),
        character["frames"][key]["frame"]["y"].as_f32().unwrap(),
        character["frames"][key]["frame"]["w"].as_f32().unwrap(),
        character["frames"][key]["frame"]["h"].as_f32().unwrap(),
      ]));
    }
  }

  sprites
}

pub fn load_zombie() -> Vec<CritterData> {
  let mut sprites = Vec::with_capacity(128);
  let character_json = read_sprite_file(ZOMBIE_JSON_PATH);
  let zombie = match json::parse(&character_json) {
    Ok(res) => res,
    Err(e) => panic!("Character JSON parse error {:?}", e),
  };

  for x in 0..7 {
    for y in 0..7 {
      let key = &format!("zombie_{}_{}", x, y);
      sprites.push(CritterData::new([
        zombie["frames"][key]["frame"]["x"].as_f32().unwrap(),
        zombie["frames"][key]["frame"]["y"].as_f32().unwrap(),
        zombie["frames"][key]["frame"]["w"].as_f32().unwrap(),
        zombie["frames"][key]["frame"]["h"].as_f32().unwrap()
      ]));
    }
  }

  sprites
}
<|endoftext|>


<commit_before>//! Receive incoming Iridium messages through their Direct IP service.
//!
//! Iridium DirectIP is a service provided by the Iridium company. New Mobile Originated messages
//! are forwarded from the Iridium servers to a configured IP address. The Iridum service attempts
//! to initate a TCP connection to port 10800 at the specified IP. IF the connection is successful,
//! the MO message is transmitted, then the connection is closed.
//!
//! This module provides a `Server` structure, which can be created to run forever and receive
//! those incoming MO messages.

use std::io;
use std::net::{TcpListener, TcpStream, ToSocketAddrs};
use std::path::Path;
use std::sync::Arc;
use std::thread;

use super::filesystem::Storage;
use super::message::Message;

/// A Iridium DirectIP server.
pub struct Server<A: ToSocketAddrs + Sync> {
    addr: A,
    listener: Option<TcpListener>,
    storage: Arc<Storage>,
}

impl<A: ToSocketAddrs + Sync> Server<A> {
    /// Creates a new server.
    ///
    /// This function does not bind to the address or do anything with the root directory.
    pub fn new<P: AsRef<Path>>(addr: A, root: P) -> Server<A> {
        Server {
            addr: addr,
            listener: None,
            storage: Arc::new(Storage::new(root)),
        }
    }

    /// Binds this server to its tcp socket.
    ///
    /// This is a seperate operation from `serve_forever` so that we can capture any errors
    /// associated with the underlying `TcpListener::bind`.
    pub fn bind(&mut self) -> io::Result<()> {
        self.listener = Some(try!(self.create_listener()));
        Ok(())
    }

    /// Starts the DirectIP server and serve forever.
    ///
    /// # Panics
    ///
    /// This method panics if it has a problem binding to the tcp socket address. To avoid a panic,
    /// use `Server::bind` before calling `Server::serve_forever`.
    pub fn serve_forever(&mut self) {
        let listener = match self.listener {
            Some(ref listener) => listener,
            None => {
                self.listener = Some(self.create_listener().unwrap());
                self.listener.as_ref().unwrap()
            },
        };
        for stream in listener.incoming() {
            match stream {
                Ok(stream) => {
                    let storage = self.storage.clone();
                    thread::spawn(move || {
                        handle_stream(stream, storage)
                    });
                }
                Err(err) => {
                    thread::spawn(move || {
                        handle_error(err)
                    });
                }
            }
        }
    }

    fn create_listener(&self) -> io::Result<TcpListener> {
        TcpListener::bind(&self.addr)
    }
}

/// Handles an incoming DirectIP stream.
///
/// # Panics
///
/// Panics if the tcp stream can't produce a peer address.
fn handle_stream(stream: TcpStream, storage: Arc<Storage>) {
    debug!("Handling TcpStream from {}", stream.peer_addr().unwrap());
    let ref message = match Message::read_from(stream) {
        Ok(message) => {
            info!("Recieved message with {} byte payload", message.payload_ref().len());
            message
        },
        Err(err) => {
            error!("Error when reading message: {:?}", err);
            return;
        },
    };
    match storage.store(message) {
        Ok(path) => info!("Stored message to {:?}", path),
        Err(err) => error!("Problem storing message: {:?}", err),
    };
}

/// Handles an error when handling a connection.
fn handle_error(err: io::Error) {
    error!("Error when receiving tcp communication: {:?}", err);
}
<commit_msg>Document the directip module<commit_after>//! Receive incoming Iridium messages through their Direct IP service.
//!
//! Iridium DirectIP is a service provided by the Iridium company. New Mobile
//! Originated messages are forwarded from the Iridium servers to a configured
//! IP address. The Iridum service attempts to initate a TCP connection to port
//! 10800 at the specified IP. IF the connection is successful, the MO message
//! is transmitted, then the connection is closed.
//!
//! This module provides a `Server` structure, which can be created to run
//! forever and receive those incoming MO messages.

use std::io;
use std::net::{TcpListener, TcpStream, ToSocketAddrs};
use std::path::Path;
use std::sync::Arc;
use std::thread;

use super::filesystem::Storage;
use super::message::Message;

/// A Iridium DirectIP server.
///
/// The server will listen on a socket address for incoming Iridium SBD Mobile Originated
/// messages. Incoming messages will be stored using `sbd::filesystem::Storage`. Errors are logged
/// using the logging framework.
pub struct Server<A: ToSocketAddrs + Sync> {
    addr: A,
    listener: Option<TcpListener>,
    storage: Arc<Storage>,
}

impl<A: ToSocketAddrs + Sync> Server<A> {
    /// Creates a new server that will listen on `addr` and write messages to `root`.
    ///
    /// This method does not actually bind to the socket address or do anything with the root
    /// directory. Use `bind` and `serve_forever` to actually do stuff.
    ///
    /// The `root` parameters is used to create a new `sbd::filesystem::Storage`, and the server
    /// will store all incoming messages under `root`.
    ///
    /// # Examples
    ///
    /// ```
    /// let server = sbd::directip::Server::new("0.0.0.0:10800", "/var/iridium");
    /// ```
    pub fn new<P: AsRef<Path>>(addr: A, root: P) -> Server<A> {
        Server {
            addr: addr,
            listener: None,
            storage: Arc::new(Storage::new(root)),
        }
    }

    /// Binds this server to its tcp socket.
    ///
    /// This is a seperate operation from `serve_forever` so that we can capture any errors
    /// associated with the underlying `TcpListener::bind`.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut server = sbd::directip::Server::new("0.0.0.0:10800", "/var/iridium");
    /// server.bind().unwrap();
    /// ```
    pub fn bind(&mut self) -> io::Result<()> {
        self.listener = Some(try!(self.create_listener()));
        Ok(())
    }

    /// Starts the DirectIP server and serves forever.
    ///
    /// # Panics
    ///
    /// This method panics if it has a problem binding to the tcp socket address. To avoid a panic,
    /// use `Server::bind` before calling `Server::serve_forever`.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// let mut server = sbd::directip::Server::new("0.0.0.0:10800", "/var/iridium");
    /// server.bind().unwrap();
    /// server.serve_forever();
    /// ```
    pub fn serve_forever(&mut self) {
        let listener = match self.listener {
            Some(ref listener) => listener,
            None => {
                self.listener = Some(self.create_listener().unwrap());
                self.listener.as_ref().unwrap()
            }
        };
        for stream in listener.incoming() {
            match stream {
                Ok(stream) => {
                    let storage = self.storage.clone();
                    thread::spawn(move || handle_stream(stream, storage));
                }
                Err(err) => {
                    thread::spawn(move || handle_error(err));
                }
            }
        }
    }

    fn create_listener(&self) -> io::Result<TcpListener> {
        TcpListener::bind(&self.addr)
    }
}

/// Handles an incoming DirectIP stream.
fn handle_stream(stream: TcpStream, storage: Arc<Storage>) {
    match stream.peer_addr() {
        Ok(addr) => {
            debug!("Handling TcpStream from {}", addr);
        }
        Err(err) => {
            warn!("Problem when extracting peer address from TcpStream, but we'll press on: {:?}",
                  err);
        }
    }
    let ref message = match Message::read_from(stream) {
        Ok(message) => {
            info!("Recieved message with {} byte payload",
                  message.payload_ref().len());
            message
        }
        Err(err) => {
            error!("Error when reading message: {:?}", err);
            return;
        }
    };
    match storage.store(message) {
        Ok(path) => info!("Stored message to {:?}", path),
        Err(err) => error!("Problem storing message: {:?}", err),
    }
}

/// Handles an error when handling a connection.
fn handle_error(err: io::Error) {
    error!("Error when receiving tcp communication: {:?}", err);
}
<|endoftext|>


<commit_before>mod day_01 {
    use std::fs::File;
    use std::io::{BufRead, BufReader};

    pub fn first() {
        let filename = "day01-01.txt";
        let file = File::open(filename).unwrap();
        let reader = BufReader::new(file);

        let fuel_for_modules: i32 = reader
            .lines()
            .map(|s| s.unwrap().parse::<i32>().unwrap())
            .map(|i| weigth(i))
            .sum();
        println!("Day 1 - 1: {}", fuel_for_modules);
    }

    pub fn second() {
        let filename = "day01-01.txt";
        let file = File::open(filename).unwrap();
        let reader = BufReader::new(file);

        let fuel_for_modules: i32 = reader
            .lines()
            .map(|s| s.unwrap().parse::<i32>().unwrap())
            .map(|i| total_fuel(i))
            .sum();
        println!("Day 1 - 2: {}", fuel_for_modules);
    }

    fn total_fuel(mass: i32) -> i32 {
        let initial_fuel = weigth(mass);

        let mut total = initial_fuel;
        let mut current_fuel = total;

        while current_fuel > 0 {
            let new_fuel = weigth(current_fuel);
            if new_fuel > 0 {
                total += new_fuel
            }
            current_fuel = new_fuel;
        }
        total
    }

    fn weigth(mass: i32) -> i32 {
        mass / 3 - 2
    }
}

fn main() {
    day_01::first();
    day_01::second();
}
<commit_msg>Extract function to read_lines<commit_after>mod helpers {
    use std::fs::File;
    use std::io::{BufRead, BufReader};

    pub fn read_lines(filename: &str) -> std::io::Lines<std::io::BufReader<std::fs::File>> {
        let file = File::open(filename).unwrap();
        let reader = BufReader::new(file);
        reader.lines()
    }
}

mod day_01 {
    pub fn first() {
        let filename = "day01-01.txt";

        let fuel_for_modules: i32 = super::helpers::read_lines(filename)
            .map(|s| s.unwrap().parse::<i32>().unwrap())
            .map(|i| weigth(i))
            .sum();
        println!("Day 1 - 1: {}", fuel_for_modules);
    }

    pub fn second() {
        let filename = "day01-01.txt";

        let fuel_for_modules: i32 = super::helpers::read_lines(filename)
            .map(|s| s.unwrap().parse::<i32>().unwrap())
            .map(|i| total_fuel(i))
            .sum();
        println!("Day 1 - 2: {}", fuel_for_modules);
    }

    fn total_fuel(mass: i32) -> i32 {
        let initial_fuel = weigth(mass);

        let mut total = initial_fuel;
        let mut current_fuel = total;

        while current_fuel > 0 {
            let new_fuel = weigth(current_fuel);
            if new_fuel > 0 {
                total += new_fuel
            }
            current_fuel = new_fuel;
        }
        total
    }

    fn weigth(mass: i32) -> i32 {
        mass / 3 - 2
    }
}

fn main() {
    day_01::first();
    day_01::second();
}
<|endoftext|>


<commit_before>use crate::command_prelude::*;

use cargo::core::{GitReference, SourceId};
use cargo::ops;
use cargo::util::IntoUrl;

pub fn cli() -> App {
    subcommand("install")
        .about("Install a Rust binary. Default location is $HOME/.cargo/bin")
        .arg(opt("quiet", "No output printed to stdout").short("q"))
        .arg(Arg::with_name("crate").empty_values(false).multiple(true))
        .arg(
            opt("version", "Specify a version to install")
                .alias("vers")
                .value_name("VERSION")
                .requires("crate"),
        )
        .arg(
            opt("git", "Git URL to install the specified crate from")
                .value_name("URL")
                .conflicts_with_all(&["path", "registry"]),
        )
        .arg(
            opt("branch", "Branch to use when installing from git")
                .value_name("BRANCH")
                .requires("git"),
        )
        .arg(
            opt("tag", "Tag to use when installing from git")
                .value_name("TAG")
                .requires("git"),
        )
        .arg(
            opt("rev", "Specific commit to use when installing from git")
                .value_name("SHA")
                .requires("git"),
        )
        .arg(
            opt("path", "Filesystem path to local crate to install")
                .value_name("PATH")
                .conflicts_with_all(&["git", "registry"]),
        )
        .arg(opt(
            "list",
            "list all installed packages and their versions",
        ))
        .arg_jobs()
        .arg(opt("force", "Force overwriting existing crates or binaries").short("f"))
        .arg(opt(
            "no-track",
            "Do not save tracking information (unstable)",
        ))
        .arg_features()
        .arg_profile("Install artifacts with from the specified profile")
        .arg(opt("debug", "Build in debug mode instead of release mode"))
        .arg_targets_bins_examples(
            "Install only the specified binary",
            "Install all binaries",
            "Install only the specified example",
            "Install all examples",
        )
        .arg_target_triple("Build for the target triple")
        .arg(opt("root", "Directory to install packages into").value_name("DIR"))
        .arg(
            opt("registry", "Registry to use")
                .value_name("REGISTRY")
                .requires("crate")
                .conflicts_with_all(&["git", "path"]),
        )
        .after_help(
            "\
This command manages Cargo's local set of installed binary crates. Only
packages which have executable [[bin]] or [[example]] targets can be
installed, and all executables are installed into the installation root's
`bin` folder. The installation root is determined, in order of precedence, by
`--root`, `$CARGO_INSTALL_ROOT`, the `install.root` configuration key, and
finally the home directory (which is either `$CARGO_HOME` if set or
`$HOME/.cargo` by default).

There are multiple sources from which a crate can be installed. The default
location is crates.io but the `--git`, `--path`, and `--registry` flags can
change this source. If the source contains more than one package (such as
crates.io or a git repository with multiple crates) the `<crate>` argument is
required to indicate which crate should be installed.

Crates from crates.io can optionally specify the version they wish to install
via the `--version` flags, and similarly packages from git repositories can
optionally specify the branch, tag, or revision that should be installed. If a
crate has multiple binaries, the `--bin` argument can selectively install only
one of them, and if you'd rather install examples the `--example` argument can
be used as well.

By default cargo will refuse to overwrite existing binaries. The `--force` flag
enables overwriting existing binaries. Thus you can reinstall a crate with
`cargo install --force <crate>`.

Omitting the <crate> specification entirely will install the crate in the
current directory. This behaviour is deprecated, and it no longer works in the
Rust 2018 edition. Use the more explicit `install --path .` instead.

If the source is crates.io or `--git` then by default the crate will be built
in a temporary target directory. To avoid this, the target directory can be
specified by setting the `CARGO_TARGET_DIR` environment variable to a relative
path. In particular, this can be useful for caching build artifacts on
continuous integration systems.",
        )
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let registry = args.registry(config)?;

    if let Some(path) = args.value_of_path("path", config) {
        config.reload_rooted_at(path)?;
    } else {
        config.reload_rooted_at(config.home().clone().into_path_unlocked())?;
    }

    let workspace = args.workspace(config).ok();
    let mut compile_opts = args.compile_options(
        config,
        CompileMode::Build,
        workspace.as_ref(),
        ProfileChecking::Checked,
    )?;

    compile_opts.build_config.profile_kind =
        args.get_profile_kind(config, ProfileKind::Release, ProfileChecking::Checked)?;

    let krates = args
        .values_of("crate")
        .unwrap_or_default()
        .collect::<Vec<_>>();

    let mut from_cwd = false;

    let source = if let Some(url) = args.value_of("git") {
        let url = url.into_url()?;
        let gitref = if let Some(branch) = args.value_of("branch") {
            GitReference::Branch(branch.to_string())
        } else if let Some(tag) = args.value_of("tag") {
            GitReference::Tag(tag.to_string())
        } else if let Some(rev) = args.value_of("rev") {
            GitReference::Rev(rev.to_string())
        } else {
            GitReference::Branch("master".to_string())
        };
        SourceId::for_git(&url, gitref)?
    } else if let Some(path) = args.value_of_path("path", config) {
        SourceId::for_path(&path)?
    } else if krates.is_empty() {
        from_cwd = true;
        SourceId::for_path(config.cwd())?
    } else if let Some(registry) = registry {
        SourceId::alt_registry(config, &registry)?
    } else {
        SourceId::crates_io(config)?
    };

    let version = args.value_of("version");
    let root = args.value_of("root");

    if args.is_present("no-track") && !config.cli_unstable().install_upgrade {
        return Err(failure::format_err!(
            "`--no-track` flag is unstable, pass `-Z install-upgrade` to enable it"
        )
        .into());
    };

    if args.is_present("list") {
        ops::install_list(root, config)?;
    } else {
        ops::install(
            root,
            krates,
            source,
            from_cwd,
            version,
            &compile_opts,
            args.is_present("force"),
            args.is_present("no-track"),
        )?;
    }
    Ok(())
}
<commit_msg>Auto merge of #7532 - dario23:install-cmd-help-typo, r=alexcrichton<commit_after>use crate::command_prelude::*;

use cargo::core::{GitReference, SourceId};
use cargo::ops;
use cargo::util::IntoUrl;

pub fn cli() -> App {
    subcommand("install")
        .about("Install a Rust binary. Default location is $HOME/.cargo/bin")
        .arg(opt("quiet", "No output printed to stdout").short("q"))
        .arg(Arg::with_name("crate").empty_values(false).multiple(true))
        .arg(
            opt("version", "Specify a version to install")
                .alias("vers")
                .value_name("VERSION")
                .requires("crate"),
        )
        .arg(
            opt("git", "Git URL to install the specified crate from")
                .value_name("URL")
                .conflicts_with_all(&["path", "registry"]),
        )
        .arg(
            opt("branch", "Branch to use when installing from git")
                .value_name("BRANCH")
                .requires("git"),
        )
        .arg(
            opt("tag", "Tag to use when installing from git")
                .value_name("TAG")
                .requires("git"),
        )
        .arg(
            opt("rev", "Specific commit to use when installing from git")
                .value_name("SHA")
                .requires("git"),
        )
        .arg(
            opt("path", "Filesystem path to local crate to install")
                .value_name("PATH")
                .conflicts_with_all(&["git", "registry"]),
        )
        .arg(opt(
            "list",
            "list all installed packages and their versions",
        ))
        .arg_jobs()
        .arg(opt("force", "Force overwriting existing crates or binaries").short("f"))
        .arg(opt(
            "no-track",
            "Do not save tracking information (unstable)",
        ))
        .arg_features()
        .arg_profile("Install artifacts with the specified profile")
        .arg(opt("debug", "Build in debug mode instead of release mode"))
        .arg_targets_bins_examples(
            "Install only the specified binary",
            "Install all binaries",
            "Install only the specified example",
            "Install all examples",
        )
        .arg_target_triple("Build for the target triple")
        .arg(opt("root", "Directory to install packages into").value_name("DIR"))
        .arg(
            opt("registry", "Registry to use")
                .value_name("REGISTRY")
                .requires("crate")
                .conflicts_with_all(&["git", "path"]),
        )
        .after_help(
            "\
This command manages Cargo's local set of installed binary crates. Only
packages which have executable [[bin]] or [[example]] targets can be
installed, and all executables are installed into the installation root's
`bin` folder. The installation root is determined, in order of precedence, by
`--root`, `$CARGO_INSTALL_ROOT`, the `install.root` configuration key, and
finally the home directory (which is either `$CARGO_HOME` if set or
`$HOME/.cargo` by default).

There are multiple sources from which a crate can be installed. The default
location is crates.io but the `--git`, `--path`, and `--registry` flags can
change this source. If the source contains more than one package (such as
crates.io or a git repository with multiple crates) the `<crate>` argument is
required to indicate which crate should be installed.

Crates from crates.io can optionally specify the version they wish to install
via the `--version` flags, and similarly packages from git repositories can
optionally specify the branch, tag, or revision that should be installed. If a
crate has multiple binaries, the `--bin` argument can selectively install only
one of them, and if you'd rather install examples the `--example` argument can
be used as well.

By default cargo will refuse to overwrite existing binaries. The `--force` flag
enables overwriting existing binaries. Thus you can reinstall a crate with
`cargo install --force <crate>`.

Omitting the <crate> specification entirely will install the crate in the
current directory. This behaviour is deprecated, and it no longer works in the
Rust 2018 edition. Use the more explicit `install --path .` instead.

If the source is crates.io or `--git` then by default the crate will be built
in a temporary target directory. To avoid this, the target directory can be
specified by setting the `CARGO_TARGET_DIR` environment variable to a relative
path. In particular, this can be useful for caching build artifacts on
continuous integration systems.",
        )
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let registry = args.registry(config)?;

    if let Some(path) = args.value_of_path("path", config) {
        config.reload_rooted_at(path)?;
    } else {
        config.reload_rooted_at(config.home().clone().into_path_unlocked())?;
    }

    let workspace = args.workspace(config).ok();
    let mut compile_opts = args.compile_options(
        config,
        CompileMode::Build,
        workspace.as_ref(),
        ProfileChecking::Checked,
    )?;

    compile_opts.build_config.profile_kind =
        args.get_profile_kind(config, ProfileKind::Release, ProfileChecking::Checked)?;

    let krates = args
        .values_of("crate")
        .unwrap_or_default()
        .collect::<Vec<_>>();

    let mut from_cwd = false;

    let source = if let Some(url) = args.value_of("git") {
        let url = url.into_url()?;
        let gitref = if let Some(branch) = args.value_of("branch") {
            GitReference::Branch(branch.to_string())
        } else if let Some(tag) = args.value_of("tag") {
            GitReference::Tag(tag.to_string())
        } else if let Some(rev) = args.value_of("rev") {
            GitReference::Rev(rev.to_string())
        } else {
            GitReference::Branch("master".to_string())
        };
        SourceId::for_git(&url, gitref)?
    } else if let Some(path) = args.value_of_path("path", config) {
        SourceId::for_path(&path)?
    } else if krates.is_empty() {
        from_cwd = true;
        SourceId::for_path(config.cwd())?
    } else if let Some(registry) = registry {
        SourceId::alt_registry(config, &registry)?
    } else {
        SourceId::crates_io(config)?
    };

    let version = args.value_of("version");
    let root = args.value_of("root");

    if args.is_present("no-track") && !config.cli_unstable().install_upgrade {
        return Err(failure::format_err!(
            "`--no-track` flag is unstable, pass `-Z install-upgrade` to enable it"
        )
        .into());
    };

    if args.is_present("list") {
        ops::install_list(root, config)?;
    } else {
        ops::install(
            root,
            krates,
            source,
            from_cwd,
            version,
            &compile_opts,
            args.is_present("force"),
            args.is_present("no-track"),
        )?;
    }
    Ok(())
}
<|endoftext|>


<commit_before>#![feature(path_ext)]

extern crate bindgen;
extern crate pkg_config;

use std::env;
use std::fs::PathExt;
use std::path::Path;
use std::process::Command;

static VERSION: &'static str = "1.1.10"; // Should be the same as the version in the manifest

fn main() {
    let out_dir_var = env::var("OUT_DIR").unwrap();
    let out_dir = format!("{}/{}", out_dir_var, VERSION);
    let current_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let driver_src_path = format!("mongo-c-driver-{}", VERSION);

    let libmongoc_path = Path::new(&out_dir).join("lib/libmongoc-1.0.a");
    if !libmongoc_path.exists() {
        // Download and extract driver archive
        let url = format!(
            "https://github.com/mongodb/mongo-c-driver/releases/download/{}/mongo-c-driver-{}.tar.gz",
            VERSION,
            VERSION
        );
        assert!(Command::new("curl").arg("-O") // Save to disk
                                    .arg("-L") // Follow redirects
                                    .arg(url)
                                    .status()
                                    .unwrap()
                                    .success());

        let archive_name = format!(
            "mongo-c-driver-{}.tar.gz",
            VERSION
        );
        assert!(Command::new("tar").arg("xzf")
                                   .arg(&archive_name)
                                   .status()
                                   .unwrap()
                                   .success());

        // Configure and install
        let mut command = Command::new("sh");
        command.arg("configure");
        command.arg("--enable-ssl=yes");
        command.arg("--enable-sasl=no");
        command.arg("--enable-static=yes");
        command.arg("--enable-shared=no");
        command.arg("--enable-shm-counters=no");
        command.arg("--with-libbson=bundled");
        command.arg("--with-pic=yes");
        command.arg(format!("--prefix={}", &out_dir));
        command.current_dir(&driver_src_path);

        // Enable debug symbols if configured for this profile
        if env::var("DEBUG") == Ok("true".to_string()) {
            command.arg("--enable-debug-symbols=yes");
        }

        // Use target that Cargo sets
        if let Ok(target) = env::var("TARGET") {
            command.arg(format!("--build={}", target));
        }

        assert!(command.status().unwrap().success());
        assert!(Command::new("make").
                         current_dir(&driver_src_path).
                         status().
                         unwrap().
                         success());
        assert!(Command::new("make").arg("install").current_dir(&driver_src_path).status().unwrap().success());

        // Generate bindings
        let bindings_rs_path = Path::new(&current_dir).join("src/bindings.rs");
        let mongo_h_path     = Path::new(&current_dir).join(&driver_src_path).join("src/mongoc/mongoc.h");
        let bson_path        = Path::new(&current_dir).join(&driver_src_path).join("src/libbson/src/bson");
        let mongo_h_path_arg = mongo_h_path.to_str().unwrap();
        let bson_path_arg    = bson_path.to_str().unwrap();

        let mut builder = bindgen::builder();
        builder.emit_builtins();
        builder.header(mongo_h_path_arg);
        builder.clang_arg("-I".to_owned());
        builder.clang_arg(bson_path_arg);

        // Add clang include dir if it's detected by bindgen.
        if let Some(path) = bindgen::get_include_dir() {
            builder.clang_arg("-I".to_owned());
            builder.clang_arg(path);
        }

        // Add clang include dir from env var, use as a last resort
        // if include cannot be detected normally.
        if let Ok(path) = env::var("CLANG_INCLUDE_DIR") {
            builder.clang_arg("-I".to_owned());
            builder.clang_arg(path);
        }

        let binding = builder.generate().unwrap();
        binding.write_to_file(&bindings_rs_path).unwrap();
    }

    // Output to Cargo
    println!("cargo:root={}", &out_dir);
    println!("cargo:libdir={}/lib", &out_dir);
    println!("cargo:include={}/include", &out_dir);
    println!("cargo:rustc-link-search={}/lib", &out_dir);
    println!("cargo:rustc-link-lib=static=bson-1.0");
    println!("cargo:rustc-link-lib=static=mongoc-1.0");

    for link_path in pkg_config::find_library("openssl").unwrap().link_paths.iter(){
        println!("cargo:rustc-link-search=framework={}", &link_path.display());
    }
}
<commit_msg>Whitespace fix<commit_after>#![feature(path_ext)]

extern crate bindgen;
extern crate pkg_config;

use std::env;
use std::fs::PathExt;
use std::path::Path;
use std::process::Command;

static VERSION: &'static str = "1.1.10"; // Should be the same as the version in the manifest

fn main() {
    let out_dir_var = env::var("OUT_DIR").unwrap();
    let out_dir = format!("{}/{}", out_dir_var, VERSION);
    let current_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let driver_src_path = format!("mongo-c-driver-{}", VERSION);

    let libmongoc_path = Path::new(&out_dir).join("lib/libmongoc-1.0.a");
    if !libmongoc_path.exists() {
        // Download and extract driver archive
        let url = format!(
            "https://github.com/mongodb/mongo-c-driver/releases/download/{}/mongo-c-driver-{}.tar.gz",
            VERSION,
            VERSION
        );
        assert!(Command::new("curl").arg("-O") // Save to disk
                                    .arg("-L") // Follow redirects
                                    .arg(url)
                                    .status()
                                    .unwrap()
                                    .success());

        let archive_name = format!(
            "mongo-c-driver-{}.tar.gz",
            VERSION
        );
        assert!(Command::new("tar").arg("xzf")
                                   .arg(&archive_name)
                                   .status()
                                   .unwrap()
                                   .success());

        // Configure and install
        let mut command = Command::new("sh");
        command.arg("configure");
        command.arg("--enable-ssl=yes");
        command.arg("--enable-sasl=no");
        command.arg("--enable-static=yes");
        command.arg("--enable-shared=no");
        command.arg("--enable-shm-counters=no");
        command.arg("--with-libbson=bundled");
        command.arg("--with-pic=yes");
        command.arg(format!("--prefix={}", &out_dir));
        command.current_dir(&driver_src_path);

        // Enable debug symbols if configured for this profile
        if env::var("DEBUG") == Ok("true".to_string()) {
            command.arg("--enable-debug-symbols=yes");
        }

        // Use target that Cargo sets
        if let Ok(target) = env::var("TARGET") {
            command.arg(format!("--build={}", target));
        }

        assert!(command.status().unwrap().success());
        assert!(Command::new("make").
                         current_dir(&driver_src_path).
                         status().
                         unwrap().
                         success());
        assert!(Command::new("make").
                         arg("install").
                         current_dir(&driver_src_path).
                         status().
                         unwrap().
                         success());

        // Generate bindings
        let bindings_rs_path = Path::new(&current_dir).join("src/bindings.rs");
        let mongo_h_path     = Path::new(&current_dir).join(&driver_src_path).join("src/mongoc/mongoc.h");
        let bson_path        = Path::new(&current_dir).join(&driver_src_path).join("src/libbson/src/bson");
        let mongo_h_path_arg = mongo_h_path.to_str().unwrap();
        let bson_path_arg    = bson_path.to_str().unwrap();

        let mut builder = bindgen::builder();
        builder.emit_builtins();
        builder.header(mongo_h_path_arg);
        builder.clang_arg("-I".to_owned());
        builder.clang_arg(bson_path_arg);

        // Add clang include dir if it's detected by bindgen.
        if let Some(path) = bindgen::get_include_dir() {
            builder.clang_arg("-I".to_owned());
            builder.clang_arg(path);
        }

        // Add clang include dir from env var, use as a last resort
        // if include cannot be detected normally.
        if let Ok(path) = env::var("CLANG_INCLUDE_DIR") {
            builder.clang_arg("-I".to_owned());
            builder.clang_arg(path);
        }

        let binding = builder.generate().unwrap();
        binding.write_to_file(&bindings_rs_path).unwrap();
    }

    // Output to Cargo
    println!("cargo:root={}", &out_dir);
    println!("cargo:libdir={}/lib", &out_dir);
    println!("cargo:include={}/include", &out_dir);
    println!("cargo:rustc-link-search={}/lib", &out_dir);
    println!("cargo:rustc-link-lib=static=bson-1.0");
    println!("cargo:rustc-link-lib=static=mongoc-1.0");

    for link_path in pkg_config::find_library("openssl").unwrap().link_paths.iter(){
        println!("cargo:rustc-link-search=framework={}", &link_path.display());
    }
}
<|endoftext|>


<commit_before>use fasteval::{ez_eval, Error};
use kernel::{
    async_trait::async_trait,
    eyre::{bail, Result},
    serde::Serialize,
    stencila_schema::{CodeError, Node},
    Kernel, KernelStatus, KernelTrait, KernelType, Task, TaskResult,
};
use once_cell::sync::Lazy;
use regex::Regex;
use std::collections::BTreeMap;

/// A kernel that evaluates simple calculator like numerical expressions
///
/// Based on [`fasteval`](https://github.com/likebike/fasteval). See the
/// `fasteval` docs for more on the syntax and functions supported.
#[derive(Debug, Clone, Default, Serialize)]
#[serde(crate = "kernel::serde")]
pub struct CalcKernel {
    symbols: BTreeMap<String, f64>,
}

impl CalcKernel {
    pub fn new() -> Self {
        Self::default()
    }
}

#[async_trait]
impl KernelTrait for CalcKernel {
    fn spec(&self) -> Kernel {
        Kernel::new("calc", KernelType::Builtin, &["calc"], true)
    }

    async fn status(&self) -> Result<KernelStatus> {
        Ok(KernelStatus::Idle)
    }

    async fn get(&mut self, name: &str) -> Result<Node> {
        match self.symbols.get(name) {
            Some(number) => Ok(Node::Number(*number)),
            None => bail!("Symbol `{}` does not exist in this kernel", name),
        }
    }

    async fn set(&mut self, name: &str, value: Node) -> Result<()> {
        let value = match value {
            Node::Integer(integer) => integer as f64,
            Node::Number(number) => number,
            _ => bail!("Unable to convert node to a number"),
        };
        self.symbols.insert(name.to_string(), value);
        Ok(())
    }

    async fn exec_sync(&mut self, code: &str) -> Result<Task> {
        static STATEMENTS_REGEX: Lazy<Regex> =
            Lazy::new(|| Regex::new(r"\r?\n|;").expect("Unable to create regex"));
        static ASSIGN_REGEX: Lazy<Regex> = Lazy::new(|| {
            Regex::new(r"\s*([a-zA-Z_][a-zA-Z_0-9]*)\s*=(.*)").expect("Unable to create regex")
        });

        let mut task = Task::start_sync();
        let mut outputs = Vec::new();
        let mut messages = Vec::new();
        for statement in STATEMENTS_REGEX.split(code) {
            let statement = statement.trim();

            // Skip the statement if it is blank or is a comment
            if statement.is_empty() || statement.starts_with('#') {
                continue;
            }

            // Get the name of any assigned variable, and the expression to be evaluated
            let (symbol, expr) = if let Some(captures) = ASSIGN_REGEX.captures(statement) {
                let symbol = captures.get(1).expect("Should always have group 1");
                let expr = captures.get(2).expect("Should always have group 2");
                (Some(symbol.as_str()), expr.as_str())
            } else {
                (None, statement)
            };

            // Evaluate the expression
            match ez_eval(expr, &mut self.symbols) {
                Ok(num) => {
                    // Either assign the result, or add it to outputs
                    if let Some(symbol) = symbol {
                        self.symbols.insert(symbol.to_string(), num);
                    } else {
                        outputs.push(Node::Number(num))
                    }
                }
                Err(error) => {
                    let error_message = match error {
                        // Custom error strings for common errors
                        Error::EOF | Error::EofWhileParsing(..) => {
                            "Unexpected end of Calc expression".to_string()
                        }
                        Error::Undefined(name) => {
                            format!("Undefined variable or function: {}", name)
                        }
                        Error::WrongArgs(msg) => {
                            format!("Function called with wrong number of arguments: {}", msg)
                        }
                        Error::InvalidValue => "Unexpected value in expression".to_string(),
                        Error::TooLong => "Calc expression was too long".to_string(),
                        Error::TooDeep => "Calc expression was too recursive".to_string(),
                        // Use the debug string for others
                        _ => format!("Could not execute Calc expression: {:?}", error),
                    };
                    messages.push(CodeError {
                        error_message,
                        ..Default::default()
                    });
                }
            }
        }
        task.finished(TaskResult::new(outputs, messages));
        Ok(task)
    }

    async fn exec_fork(&mut self, code: &str) -> Result<Task> {
        let mut fork = self.clone();
        fork.exec_async(code).await
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use kernel::{KernelStatus, KernelTrait};
    use test_utils::{assert_json_eq, serde_json::json};

    #[tokio::test]
    async fn status() -> Result<()> {
        let kernel = CalcKernel::new();

        assert_eq!(kernel.status().await?, KernelStatus::Idle);

        Ok(())
    }

    #[tokio::test]
    async fn get_set_exec() -> Result<()> {
        let mut kernel = CalcKernel::new();

        match kernel.get("a").await {
            Ok(..) => bail!("Expected an error"),
            Err(error) => assert!(error.to_string().contains("does not exist")),
        };

        match kernel.set("a", Node::String("A".to_string())).await {
            Ok(..) => bail!("Expected an error"),
            Err(error) => assert!(error
                .to_string()
                .contains("Unable to convert node to a number")),
        };

        kernel.set("a", Node::Number(1.23)).await?;

        let a = kernel.get("a").await?;
        assert!(matches!(a, Node::Number(..)));
        assert_json_eq!(a, json!(1.23));

        let (outputs, errors) = kernel.exec("a * 2").await?;
        assert_json_eq!(outputs, json!([2.46]));
        assert_eq!(errors.len(), 0);

        let (outputs, errors) = kernel.exec("x * 2").await?;
        assert_eq!(outputs.len(), 0);
        assert_json_eq!(
            errors,
            json!([{"type": "CodeError", "errorMessage": "Undefined variable or function: x"}])
        );

        Ok(())
    }
}
<commit_msg>feat(Calc kernel): Add `now` function<commit_after>use fasteval::{ez_eval, Error};
use kernel::{
    async_trait::async_trait,
    eyre::{bail, Result},
    serde::Serialize,
    stencila_schema::{CodeError, Node},
    Kernel, KernelStatus, KernelTrait, KernelType, Task, TaskResult,
};
use once_cell::sync::Lazy;
use regex::Regex;
use std::collections::BTreeMap;

/// A kernel that evaluates simple calculator like numerical expressions
///
/// Based on [`fasteval`](https://github.com/likebike/fasteval). See the
/// `fasteval` docs for more on the syntax and functions supported.
#[derive(Debug, Clone, Default, Serialize)]
#[serde(crate = "kernel::serde")]
pub struct CalcKernel {
    symbols: BTreeMap<String, f64>,
}

impl CalcKernel {
    pub fn new() -> Self {
        Self::default()
    }
}

#[async_trait]
impl KernelTrait for CalcKernel {
    fn spec(&self) -> Kernel {
        Kernel::new("calc", KernelType::Builtin, &["calc"], true)
    }

    async fn status(&self) -> Result<KernelStatus> {
        Ok(KernelStatus::Idle)
    }

    async fn get(&mut self, name: &str) -> Result<Node> {
        match self.symbols.get(name) {
            Some(number) => Ok(Node::Number(*number)),
            None => bail!("Symbol `{}` does not exist in this kernel", name),
        }
    }

    async fn set(&mut self, name: &str, value: Node) -> Result<()> {
        let value = match value {
            Node::Integer(integer) => integer as f64,
            Node::Number(number) => number,
            _ => bail!("Unable to convert node to a number"),
        };
        self.symbols.insert(name.to_string(), value);
        Ok(())
    }

    async fn exec_sync(&mut self, code: &str) -> Result<Task> {
        static STATEMENTS_REGEX: Lazy<Regex> =
            Lazy::new(|| Regex::new(r"\r?\n|;").expect("Unable to create regex"));
        static ASSIGN_REGEX: Lazy<Regex> = Lazy::new(|| {
            Regex::new(r"\s*([a-zA-Z_][a-zA-Z_0-9]*)\s*=(.*)").expect("Unable to create regex")
        });

        let mut task = Task::start_sync();
        let mut outputs = Vec::new();
        let mut messages = Vec::new();
        for statement in STATEMENTS_REGEX.split(code) {
            let statement = statement.trim();

            // Skip the statement if it is blank or is a comment
            if statement.is_empty() || statement.starts_with('#') {
                continue;
            }

            // Get the name of any assigned variable, and the expression to be evaluated
            let (symbol, expr) = if let Some(captures) = ASSIGN_REGEX.captures(statement) {
                let symbol = captures.get(1).expect("Should always have group 1");
                let expr = captures.get(2).expect("Should always have group 2");
                (Some(symbol.as_str()), expr.as_str())
            } else {
                (None, statement)
            };

            // A fasteval callback function that defines some custom functions
            let mut cb = |name: &str, _args: Vec<f64>| -> Option<f64> {
                match name {
                    "now" => now(),
                    _ => self.symbols.get(name).copied(),
                }
            };

            // Evaluate the expression
            match ez_eval(expr, &mut cb) {
                Ok(num) => {
                    // Either assign the result, or add it to outputs
                    if let Some(symbol) = symbol {
                        self.symbols.insert(symbol.to_string(), num);
                    } else {
                        outputs.push(Node::Number(num))
                    }
                }
                Err(error) => {
                    let error_message = match error {
                        // Custom error strings for common errors
                        Error::EOF | Error::EofWhileParsing(..) => {
                            "Unexpected end of Calc expression".to_string()
                        }
                        Error::Undefined(name) => {
                            format!("Undefined variable or function: {}", name)
                        }
                        Error::WrongArgs(msg) => {
                            format!("Function called with wrong number of arguments: {}", msg)
                        }
                        Error::InvalidValue => "Unexpected value in expression".to_string(),
                        Error::TooLong => "Calc expression was too long".to_string(),
                        Error::TooDeep => "Calc expression was too recursive".to_string(),
                        // Use the debug string for others
                        _ => format!("Could not execute Calc expression: {:?}", error),
                    };
                    messages.push(CodeError {
                        error_message,
                        ..Default::default()
                    });
                }
            }
        }
        task.finished(TaskResult::new(outputs, messages));
        Ok(task)
    }

    async fn exec_fork(&mut self, code: &str) -> Result<Task> {
        let mut fork = self.clone();
        fork.exec_async(code).await
    }
}

// Custom functions

/// The current system time as seconds (to millisecond resolution) since the Unix epoch
fn now() -> Option<f64> {
    use std::time::{SystemTime, UNIX_EPOCH};

    SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .ok()
        .map(|duration| duration.as_millis() as f64 / 1000.0)
}

#[cfg(test)]
mod tests {
    use super::*;
    use kernel::{KernelStatus, KernelTrait};
    use test_utils::{assert_json_eq, serde_json::json};

    #[tokio::test]
    async fn status() -> Result<()> {
        let kernel = CalcKernel::new();

        assert_eq!(kernel.status().await?, KernelStatus::Idle);

        Ok(())
    }

    #[tokio::test]
    async fn get_set_exec() -> Result<()> {
        let mut kernel = CalcKernel::new();

        match kernel.get("a").await {
            Ok(..) => bail!("Expected an error"),
            Err(error) => assert!(error.to_string().contains("does not exist")),
        };

        match kernel.set("a", Node::String("A".to_string())).await {
            Ok(..) => bail!("Expected an error"),
            Err(error) => assert!(error
                .to_string()
                .contains("Unable to convert node to a number")),
        };

        kernel.set("a", Node::Number(1.23)).await?;

        let a = kernel.get("a").await?;
        assert!(matches!(a, Node::Number(..)));
        assert_json_eq!(a, json!(1.23));

        let (outputs, errors) = kernel.exec("a * 2").await?;
        assert_json_eq!(outputs, json!([2.46]));
        assert_eq!(errors.len(), 0);

        let (outputs, errors) = kernel.exec("x * 2").await?;
        assert_eq!(outputs.len(), 0);
        assert_json_eq!(
            errors,
            json!([{"type": "CodeError", "errorMessage": "Undefined variable or function: x"}])
        );

        Ok(())
    }
}
<|endoftext|>


<commit_before>#[link(name = "fuse",
vers = "0.0.0",
uuid = "d37c5c30-fdcd-459d-bfca-ebb8da04b2a0",
url = "https://github.com/MicahChalmer/rust-fuse")];

#[comment = "FUSE bindings"];
#[license = "MIT"];
#[crate_type = "lib"];

#[link_args = "-lfuse"]

use std::libc::{c_int, c_char, c_void, size_t};

// A cfuncptr is used here to stand in for a C function pointer.
// For this struct, see fuse.h
type cfuncptr = *u8;
struct c_fuse_operations {
    getattr: cfuncptr,
    readlink: cfuncptr,
    getdir: cfuncptr,
    mknod: cfuncptr,
    mkdir: cfuncptr,
    unlink: cfuncptr,
    rmdir: cfuncptr,
    symlink: cfuncptr,
    rename: cfuncptr,
    link: cfuncptr,
    chmod: cfuncptr,
    chown: cfuncptr,
    truncate: cfuncptr,
    utime: cfuncptr,
    open: cfuncptr,
    read: cfuncptr,
    write: cfuncptr,
    statfs: cfuncptr,
    flush: cfuncptr,
    release: cfuncptr,
    fsync: cfuncptr,
    setxattr: cfuncptr,
    getxattr: cfuncptr,
    listxattr: cfuncptr,
    removexattr: cfuncptr,
    opendir: cfuncptr,
    readdir: cfuncptr,
    releasedir: cfuncptr,
    fsyncdir: cfuncptr,
    init: cfuncptr,
    destroy: cfuncptr,
    access: cfuncptr,
    create: cfuncptr,
    ftruncate: cfuncptr,
    fgetattr: cfuncptr,
    lock: cfuncptr,
    utimens: cfuncptr,
    bmap: cfuncptr,

    flag_nullpath_ok: uint,
    flag_nopath: uint,
    flag_utime_omit_ok: uint,
    flag_reserved: uint,

    ioctl: cfuncptr,
    poll: cfuncptr,
    write_buf: cfuncptr,
    read_buf: cfuncptr,
    flock: cfuncptr
}

extern {
    fn fuse_main_real(argc:c_int, argv:**c_char,
                      op:*c_fuse_operations, op_size: size_t,
                      user_data: *c_void);
}

<commit_msg>More WIP stuff<commit_after>#[link(name = "fuse",
vers = "0.0.0",
uuid = "d37c5c30-fdcd-459d-bfca-ebb8da04b2a0",
url = "https://github.com/MicahChalmer/rust-fuse")];

#[comment = "FUSE bindings"];
#[license = "MIT"];
#[crate_type = "lib"];

#[link_args = "-lfuse"]

use std::libc::{
    c_char,
    c_int,
    c_uint,
    c_ulong,
    c_void,
    off_t,
    size_t,
    stat
};

// A cfuncptr is used here to stand in for a C function pointer.
// For this struct, see fuse.h
type cfuncptr = *u8;
struct c_fuse_operations {
    getattr: cfuncptr,
    readlink: cfuncptr,
    getdir: cfuncptr,
    mknod: cfuncptr,
    mkdir: cfuncptr,
    unlink: cfuncptr,
    rmdir: cfuncptr,
    symlink: cfuncptr,
    rename: cfuncptr,
    link: cfuncptr,
    chmod: cfuncptr,
    chown: cfuncptr,
    truncate: cfuncptr,
    utime: cfuncptr,
    open: cfuncptr,
    read: cfuncptr,
    write: cfuncptr,
    statfs: cfuncptr,
    flush: cfuncptr,
    release: cfuncptr,
    fsync: cfuncptr,
    setxattr: cfuncptr,
    getxattr: cfuncptr,
    listxattr: cfuncptr,
    removexattr: cfuncptr,
    opendir: cfuncptr,
    readdir: cfuncptr,
    releasedir: cfuncptr,
    fsyncdir: cfuncptr,
    init: cfuncptr,
    destroy: cfuncptr,
    access: cfuncptr,
    create: cfuncptr,
    ftruncate: cfuncptr,
    fgetattr: cfuncptr,
    lock: cfuncptr,
    utimens: cfuncptr,
    bmap: cfuncptr,

    flag_nullpath_ok: uint,
    flag_nopath: uint,
    flag_utime_omit_ok: uint,
    flag_reserved: uint,

    ioctl: cfuncptr,
    poll: cfuncptr,
    write_buf: cfuncptr,
    read_buf: cfuncptr,
    flock: cfuncptr
}

pub struct fuse_file_info {
    flags: c_int,
    fh_old: c_ulong, // Old file handle, don't use
    writepage: c_int,
    direct_io: c_uint,
    keep_cache: c_uint,
    flush: c_uint,
    nonseekable: c_uint,
    flock_release: c_uint,
    padding: c_uint, // Padding.  Do not use
    fh: u64,
    lock_owner: u64
}

extern {
    fn fuse_main_real(argc:c_int, argv:**c_char,
                      op:*c_fuse_operations, op_size: size_t,
                      user_data: *c_void);
}

// Used for return values from FS operations
type errno = int;

pub struct dir_entry {
    name: ~str,
    stat: Option<stat>,
    off: off_t
}

pub trait FuseOperations {
    fn getattr(path:&str) -> Either<stat, errno>;
    fn readdir(path:&str, info: &fuse_file_info) -> (errno, ~[~dir_entry]);
    fn open(path:&str, info: &mut fuse_file_info) -> errno;  // TODO: don't allow mutation of the whole fuse_file_info
    fn read(path:&str, buf:&mut [u8], size: size_t, offset: off_t, info: &fuse_file_info) -> (errno, size_t);
}

pub fn fuse_main<T: FuseOperations>(args: ~[~str], ops: ~T) {

}
<|endoftext|>


<commit_before>extern crate find_folder;

use screen::{self, Screen, MainMenu};
use context::{Context, GameState};

use piston_window::{self, PistonWindow, WindowSettings};

type Screens = Vec<Box<Screen>>;

pub struct Game {
    window: PistonWindow,
    context: Context,
    screens: Screens,
}

impl Game {
    pub fn new() -> Self {
        let window: PistonWindow = WindowSettings::new("rrthozopsi", [600, 600])
                                       .build()
                                       .unwrap();
        let mut context = Context {
            assets_path: find_folder::Search::KidsThenParents(3, 5).for_folder("assets").unwrap(),
            game_state: GameState::NotStarted,
        };
        let screens: Screens = vec![Box::new(MainMenu::new(&window, &mut context))];
        Game {
            window: window,
            screens: screens,
            context: context,
        }
    }

    pub fn run(&mut self) {
        use piston_window::Event;

        let screens = &mut self.screens;

        for window in &mut self.window {
            match window.event {
                Some(Event::Update(ref args)) => {
                    last(screens).on_update(&args);
                }
                Some(Event::Render(ref args)) => {
                    last(screens).on_draw(&args, &window);
                }
                Some(Event::Input(ref input)) => {
                    handle_input(screens, &input, &window, &mut self.context);
                    assert!(screens.is_empty());
                    if screens.is_empty() {
                        // No screens - exit game.
                        return;
                    }
                }
                _ => {}
            }
        }
    }
}

fn last<'a>(vec: &'a mut Screens) -> &'a mut Box<Screen> {
    vec.last_mut().unwrap()
}

fn handle_input(screens: &mut Screens, input: &piston_window::Input, window: &PistonWindow, context: &mut Context) -> bool {
    use screen::InputResult;

    for action in last(screens).on_input(&input, &window, context) {
        match action {
            InputResult::PushScreen(new_screen) => {
                screens.push(new_screen);
            }
            InputResult::PopScreen => {
                screens.pop();
            }
            // TODO: Handle event correctly.
            // TODO: Use screen::InputResult.
            InputResult::Exit => { return true }
        }
    }

    false
}
<commit_msg>screens.is_empty() check has been removed<commit_after>extern crate find_folder;

use screen::{self, Screen, MainMenu};
use context::{Context, GameState};

use piston_window::{self, PistonWindow, WindowSettings};

type Screens = Vec<Box<Screen>>;

pub struct Game {
    window: PistonWindow,
    context: Context,
    screens: Screens,
}

impl Game {
    pub fn new() -> Self {
        let window: PistonWindow = WindowSettings::new("rrthozopsi", [600, 600])
                                       .build()
                                       .unwrap();
        let mut context = Context {
            assets_path: find_folder::Search::KidsThenParents(3, 5).for_folder("assets").unwrap(),
            game_state: GameState::NotStarted,
        };
        let screens: Screens = vec![Box::new(MainMenu::new(&window, &mut context))];
        Game {
            window: window,
            screens: screens,
            context: context,
        }
    }

    pub fn run(&mut self) {
        use piston_window::Event;

        let screens = &mut self.screens;

        for window in &mut self.window {
            match window.event {
                Some(Event::Update(ref args)) => {
                    last(screens).on_update(&args);
                }
                Some(Event::Render(ref args)) => {
                    last(screens).on_draw(&args, &window);
                }
                Some(Event::Input(ref input)) => {
                    if handle_input(screens, &input, &window, &mut self.context) {
                        // Exit game.
                        return;
                    }
                }
                _ => {}
            }
        }
    }
}

fn last<'a>(vec: &'a mut Screens) -> &'a mut Box<Screen> {
    vec.last_mut().unwrap()
}

fn handle_input(screens: &mut Screens, input: &piston_window::Input, window: &PistonWindow, context: &mut Context) -> bool {
    use screen::InputResult;

    for action in last(screens).on_input(&input, &window, context) {
        match action {
            InputResult::PushScreen(new_screen) => {
                screens.push(new_screen);
            }
            InputResult::PopScreen => {
                screens.pop();
            }
            // TODO: Handle event correctly.
            // TODO: Use screen::InputResult.
            InputResult::Exit => { return true }
        }
    }

    false
}
<|endoftext|>