<commit_before>use std::iter::Peekable;
use { Token, TokenValue };
use environment::ParsingEnvironment;
use Result;
use error::{ Error, ErrorMessage };
use operator::{ OperatorOptions, OperatorKind };
use lexer::iter::TokenIter;

pub mod body;
pub mod module;
pub mod expr;

pub trait Parse<'c> {
    type Output;

    fn parse<'p>(parser: &mut Context<'p, 'c>)
        -> Result<Self::Output>;
}

/// Helpers for manipulating and inspecting token iterators when creating AST.
///
/// Has methods to inspect state, like "current" token, and advance to next.
///
/// Current token is actually implemented as "peekable" next token. However,
/// in all parsing code this "peekable" becomes "current".
pub struct Context<'p, 'c: 'p>
{
    pub env: &'p ParsingEnvironment,
    pub tokens: Peekable<&'p mut TokenIter<'p, 'c>>,
}

impl<'p, 'c: 'p> Context<'p, 'c>
{
    pub fn new<'r, 'z>(
        env: &'r ParsingEnvironment,
        tokens: &'r mut TokenIter<'r, 'z>
    ) -> Context<'r, 'z>
    {
        Context {
            env: env,
            tokens: tokens.peekable(),
        }
    }

    /// Get current token or fail.
    ///
    /// Returns current token, does not modify iterator position.
    /// Expects current token to exist, and if it is not (the end of file), returns
    /// UnexpectedEndOfTemplate error.
    pub fn current<'r>(&'r mut self) -> Result<Token<'c>>
    {
        Ok(match self.tokens.peek() {
            Some(&Ok(ref t)) => t.clone(),
            None => return Err(Error::new(ErrorMessage::UnexpectedEndOfTemplate)),
            Some(&Err(ref e)) => return Err(e.clone()),
        })
    }

    /// Get current token or the end of stream.
    ///
    /// Returns current token, does not modify iterator position.
    /// If the end of stream, returns None.
    pub fn maybe_current<'r>(&'r mut self) -> Result<Option<Token<'c>>>
    {
        Ok(match self.tokens.peek() {
            Some(&Ok(ref t)) => Some(t.clone()),
            None => None,
            Some(&Err(ref e)) => return Err(e.clone()),
        })
    }

    /// Advances to the next token and returns previous.
    ///
    /// Expects the next token to exist. If it does not exist (the end of file), returns
    /// UnexpectedEndOfTemplate error.
    pub fn next<'r>(&'r mut self) -> Result<Token<'c>>
    {
        let token = match self.tokens.peek() {
            Some(&Ok(ref t)) => t.clone(),
            None => return Err(Error::new(ErrorMessage::UnexpectedEndOfTemplate)),
            Some(&Err(ref e)) => return Err(e.clone()),
        };

        match self.tokens.next() {
            None => return Err(Error::new(ErrorMessage::UnexpectedEndOfTemplate)),
            Some(Err(e)) => return Err(e),
            _ => (),
        };

        Ok(token)
    }

    /// Advances to the next token if expected token value is the same as current and
    /// returns current.
    ///
    /// Expects these tokens to exist. If they do not exist (the end of file), returns
    /// UnexpectedEndOfTemplate error.
    pub fn skip_to_next_if<'r>(&'r mut self, expected: TokenValue<'c>) -> Result<bool>
    {
        let skip = match self.tokens.peek() {
            Some(&Ok(ref token)) if token.value == expected => true,
            _ => false,
        };
        if skip {
            match self.tokens.next() {
                Some(Ok(_)) => Ok(true),
                None => return Err(Error::new(ErrorMessage::UnexpectedEndOfTemplate)),
                Some(Err(e)) => return Err(e),
            }
        } else {
            Ok(false)
        }
    }

    /// Expects the current token to match value and advances to next token.
    ///
    /// Expects these tokens to exist. If they do not exist (the end of file), returns
    /// UnexpectedEndOfTemplate error.
    pub fn expect<'r>(&'r mut self, expected: TokenValue<'c>) -> Result<Token<'c>>
    {
        let token = match self.tokens.peek() {
            Some(&Ok(ref t)) => {
                if t.value == expected {
                    t.clone()
                } else {
                    return Err(Error::new_at(
                        ErrorMessage::ExpectedOtherTokenValue((t.value.into(), expected.into())),
                        t.line
                    ))
                }
            },
            None => return Err(Error::new(ErrorMessage::UnexpectedEndOfTemplate)),
            Some(&Err(ref e)) => return Err(e.clone()),
        };
        try!(self.next());

        Ok(token)
    }

    /// Expects the current token to match value and advances to next token.
    ///
    /// Expects these tokens to exist. If they do not exist (the end of file), returns
    /// UnexpectedEndOfTemplate error.
    pub fn expect_or_error<'r>(&'r mut self, expected: TokenValue<'c>, error_message: ErrorMessage) -> Result<Token<'c>>
    {
        let token = match self.tokens.peek() {
            Some(&Ok(ref t)) => {
                if t.value == expected {
                    t.clone()
                } else {
                    return Err(Error::new_at(
                        error_message,
                        t.line
                    ))
                }
            },
            None => return Err(Error::new(ErrorMessage::UnexpectedEndOfTemplate)),
            Some(&Err(ref e)) => return Err(e.clone()),
        };
        try!(self.next());

        Ok(token)
    }

    /// Test the current token to match value.
    ///
    /// Expects these token to exist. If it does not exist (the end of file), returns
    /// UnexpectedEndOfTemplate error.
    pub fn test<'r>(&'r mut self, expected: TokenValue<'c>) -> Result<bool>
    {
        match self.tokens.peek() {
            Some(&Ok(ref t)) => {
                if t.value == expected {
                    Ok(true)
                } else {
                    Ok(false)
                }
            },
            None => Err(Error::new(ErrorMessage::UnexpectedEndOfTemplate)),
            Some(&Err(ref e)) => Err(e.clone()),
        }
    }

    /// Returns options structure for specified operator.
    ///
    /// Operator must exist in environment, otherwise panics.
    pub fn get_operator_options<'r>(&'r self, op_str: &'c str) -> OperatorOptions {
        self.env.operators
            .get(op_str)
            .cloned()
            .unwrap_or(OperatorOptions { precedence: None, kind: OperatorKind::Other })
    }
}
<commit_msg>DRY expect code.<commit_after>use std::iter::Peekable;
use { Token, TokenValue };
use environment::ParsingEnvironment;
use Result;
use error::{ Error, ErrorMessage };
use operator::{ OperatorOptions, OperatorKind };
use lexer::iter::TokenIter;

pub mod body;
pub mod module;
pub mod expr;

pub trait Parse<'c> {
    type Output;

    fn parse<'p>(parser: &mut Context<'p, 'c>)
        -> Result<Self::Output>;
}

/// Helpers for manipulating and inspecting token iterators when creating AST.
///
/// Has methods to inspect state, like "current" token, and advance to next.
///
/// Current token is actually implemented as "peekable" next token. However,
/// in all parsing code this "peekable" becomes "current".
pub struct Context<'p, 'c: 'p>
{
    pub env: &'p ParsingEnvironment,
    pub tokens: Peekable<&'p mut TokenIter<'p, 'c>>,
}

impl<'p, 'c: 'p> Context<'p, 'c>
{
    pub fn new<'r, 'z>(
        env: &'r ParsingEnvironment,
        tokens: &'r mut TokenIter<'r, 'z>
    ) -> Context<'r, 'z>
    {
        Context {
            env: env,
            tokens: tokens.peekable(),
        }
    }

    /// Get current token or fail.
    ///
    /// Returns current token, does not modify iterator position.
    /// Expects current token to exist, and if it is not (the end of file), returns
    /// UnexpectedEndOfTemplate error.
    pub fn current<'r>(&'r mut self) -> Result<Token<'c>>
    {
        Ok(match self.tokens.peek() {
            Some(&Ok(ref t)) => t.clone(),
            None => return Err(Error::new(ErrorMessage::UnexpectedEndOfTemplate)),
            Some(&Err(ref e)) => return Err(e.clone()),
        })
    }

    /// Get current token or the end of stream.
    ///
    /// Returns current token, does not modify iterator position.
    /// If the end of stream, returns None.
    pub fn maybe_current<'r>(&'r mut self) -> Result<Option<Token<'c>>>
    {
        Ok(match self.tokens.peek() {
            Some(&Ok(ref t)) => Some(t.clone()),
            None => None,
            Some(&Err(ref e)) => return Err(e.clone()),
        })
    }

    /// Advances to the next token and returns previous.
    ///
    /// Expects the next token to exist. If it does not exist (the end of file), returns
    /// UnexpectedEndOfTemplate error.
    pub fn next<'r>(&'r mut self) -> Result<Token<'c>>
    {
        let token = match self.tokens.peek() {
            Some(&Ok(ref t)) => t.clone(),
            None => return Err(Error::new(ErrorMessage::UnexpectedEndOfTemplate)),
            Some(&Err(ref e)) => return Err(e.clone()),
        };

        match self.tokens.next() {
            None => return Err(Error::new(ErrorMessage::UnexpectedEndOfTemplate)),
            Some(Err(e)) => return Err(e),
            _ => (),
        };

        Ok(token)
    }

    /// Advances to the next token if expected token value is the same as current and
    /// returns current.
    ///
    /// Expects these tokens to exist. If they do not exist (the end of file), returns
    /// UnexpectedEndOfTemplate error.
    pub fn skip_to_next_if<'r>(&'r mut self, expected: TokenValue<'c>) -> Result<bool>
    {
        let skip = match self.tokens.peek() {
            Some(&Ok(ref token)) if token.value == expected => true,
            _ => false,
        };
        if skip {
            match self.tokens.next() {
                Some(Ok(_)) => Ok(true),
                None => return Err(Error::new(ErrorMessage::UnexpectedEndOfTemplate)),
                Some(Err(e)) => return Err(e),
            }
        } else {
            Ok(false)
        }
    }

    /// Expects the current token to match value and advances to next token.
    ///
    /// Error condition same as `expect_match_or`.
    pub fn expect<'r>(&'r mut self, expected: TokenValue<'c>) -> Result<Token<'c>>
    {
        self.expect_match_or(
            |value| value == &expected,
            move |token| Err(Error::new_at(
                ErrorMessage::ExpectedOtherTokenValue((token.value.into(), expected.into())),
                token.line
            ))
        )
    }

    /// Expects the current token to match value and advances to the next token.
    ///
    /// Error condition same as `expect_match_or`.
    pub fn expect_or_error<'r>(&'r mut self, expected: TokenValue<'c>, error_message: ErrorMessage) -> Result<Token<'c>>
    {
        self.expect_match_or(
            |value| value == &expected,
            move |token| Err(Error::new_at(
                error_message,
                token.line
            ))
        )
    }

    /// Expects the current token to pass `check` and advances to next token.
    ///
    /// Returns result produced by `result` if check fails.
    ///
    /// Expects these tokens (current and next) to exist. If they do not exist (the end of file),
    /// returns `UnexpectedEndOfTemplate` error.
    pub fn expect_match_or<'r, C, R>(&'r mut self, check: C, result: R) -> Result<Token<'c>>
        where
            C: for<'a> FnOnce(&'a TokenValue<'c>) -> bool,
            R: for<'a> FnOnce(&'a Token<'c>) -> Result<Token<'c>>
    {
        let token = match self.tokens.peek() {
            Some(&Ok(ref t)) => {
                if check(&t.value) {
                    t.clone()
                } else {
                    return result(&t);
                }
            },
            None => return Err(Error::new(ErrorMessage::UnexpectedEndOfTemplate)),
            Some(&Err(ref e)) => return Err(e.clone()),
        };
        try!(self.next());

        Ok(token)
    }

    /// Test the current token to match value.
    ///
    /// Expects these token to exist. If it does not exist (the end of file), returns
    /// UnexpectedEndOfTemplate error.
    pub fn test<'r>(&'r mut self, expected: TokenValue<'c>) -> Result<bool>
    {
        match self.tokens.peek() {
            Some(&Ok(ref t)) => {
                if t.value == expected {
                    Ok(true)
                } else {
                    Ok(false)
                }
            },
            None => Err(Error::new(ErrorMessage::UnexpectedEndOfTemplate)),
            Some(&Err(ref e)) => Err(e.clone()),
        }
    }

    /// Returns options structure for specified operator.
    ///
    /// Operator must exist in environment, otherwise panics.
    pub fn get_operator_options<'r>(&'r self, op_str: &'c str) -> OperatorOptions {
        self.env.operators
            .get(op_str)
            .cloned()
            .unwrap_or(OperatorOptions { precedence: None, kind: OperatorKind::Other })
    }
}
<|endoftext|>


<commit_before>use iron::{Request, Response, Middleware, Alloy};
use iron::middleware::{Status, Continue};
use std::sync::{Arc, RWLock};

pub struct Persistent<Data, Phantom> {
    pub data: Arc<RWLock<Data>>
}

impl<D: Send + Share, P> Clone for Persistent<D, P> {
    fn clone(&self) -> Persistent<D, P> {
        Persistent {
            data: self.data.clone()
        }
    }
}

impl<D: Send + Share, P> Middleware for Persistent<D, P> {
    fn enter(&mut self, _: &mut Request,
             _: &mut Response, alloy: &mut Alloy) -> Status {
        alloy.insert::<Persistent<D, P>>(self.clone());
        Continue
    }
}

impl<D: Send + Share, P> Persistent<D, P> {
    pub fn new(data: D) -> Persistent<D, P> {
        Persistent { data: Arc::new(RWLock::new(data)) }
    }
}

impl<D: Send + Share, P> Persistent<D, P> {
    pub fn new(data: D) -> Persistent<D, P> {
        return Persistent { data: Arc::new(RWLock::new(data)) };
    }
}

<commit_msg>(fix) Removed duplicate definition of new.<commit_after>use iron::{Request, Response, Middleware, Alloy};
use iron::middleware::{Status, Continue};
use std::sync::{Arc, RWLock};

pub struct Persistent<Data, Phantom> {
    pub data: Arc<RWLock<Data>>
}

impl<D: Send + Share, P> Clone for Persistent<D, P> {
    fn clone(&self) -> Persistent<D, P> {
        Persistent {
            data: self.data.clone()
        }
    }
}

impl<D: Send + Share, P> Middleware for Persistent<D, P> {
    fn enter(&mut self, _: &mut Request,
             _: &mut Response, alloy: &mut Alloy) -> Status {
        alloy.insert::<Persistent<D, P>>(self.clone());
        Continue
    }
}

impl<D: Send + Share, P> Persistent<D, P> {
    pub fn new(data: D) -> Persistent<D, P> {
        Persistent { data: Arc::new(RWLock::new(data)) }
    }
}

<|endoftext|>


<commit_before>//  * This file is part of the uutils coreutils package.
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore (ToDO) allocs bset dflag cflag sflag tflag

extern crate nom;

mod convert;
mod operation;
mod unicode_table;

use clap::{crate_version, Arg, Command};
use nom::AsBytes;
use operation::{translate_input, Sequence, SqueezeOperation, TranslateOperation};
use std::io::{stdin, stdout, BufReader, BufWriter};
use uucore::{format_usage, show};

use crate::operation::DeleteOperation;
use uucore::error::{UResult, USimpleError, UUsageError};
use uucore::{display::Quotable, InvalidEncodingHandling};

static ABOUT: &str = "translate or delete characters";
const USAGE: &str = "{} [OPTION]... SET1 [SET2]";

mod options {
    pub const COMPLEMENT: &str = "complement";
    pub const DELETE: &str = "delete";
    pub const SQUEEZE: &str = "squeeze-repeats";
    pub const TRUNCATE_SET1: &str = "truncate-set1";
    pub const SETS: &str = "sets";
}

fn get_long_usage() -> String {
    "Translate, squeeze, and/or delete characters from standard input, \
     writing to standard output."
        .to_string()
}

#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
    let args = args
        .collect_str(InvalidEncodingHandling::ConvertLossy)
        .accept_any();

    let after_help = get_long_usage();

    let matches = uu_app().after_help(&after_help[..]).get_matches_from(args);

    let delete_flag = matches.is_present(options::DELETE);
    let complement_flag = matches.is_present(options::COMPLEMENT);
    let squeeze_flag = matches.is_present(options::SQUEEZE);
    let truncate_set1_flag = matches.is_present(options::TRUNCATE_SET1);

    let sets = matches
        .values_of(options::SETS)
        .map(|v| {
            v.map(ToString::to_string)
                .map(|input| convert::reduce_octal_to_char(&input))
                .collect::<Vec<_>>()
        })
        .unwrap_or_default();
    let sets_len = sets.len();

    if sets.is_empty() {
        return Err(UUsageError::new(1, "missing operand"));
    }

    if !(delete_flag || squeeze_flag) && sets_len < 2 {
        return Err(UUsageError::new(
            1,
            format!("missing operand after {}", sets[0].quote()),
        ));
    }

    if let Some(first) = sets.get(0) {
        if first.ends_with('\\') {
            show!(USimpleError::new(
                0,
                "warning: an unescaped backslash at end of string is not portable"
            ));
        }
    }

    let stdin = stdin();
    let mut locked_stdin = stdin.lock();
    let stdout = stdout();
    let locked_stdout = stdout.lock();
    let mut buffered_stdout = BufWriter::new(locked_stdout);

    let mut sets_iter = sets.iter().map(|c| c.as_str());
    let (set1, set2) = Sequence::solve_set_characters(
        sets_iter.next().unwrap_or_default(),
        sets_iter.next().unwrap_or_default(),
        truncate_set1_flag,
    )?;

    if delete_flag {
        if squeeze_flag {
            let mut delete_buffer = vec![];
            {
                let mut delete_writer = BufWriter::new(&mut delete_buffer);
                let delete_op = DeleteOperation::new(set1, complement_flag);
                translate_input(&mut locked_stdin, &mut delete_writer, delete_op);
            }
            {
                let mut squeeze_reader = BufReader::new(delete_buffer.as_bytes());
                let op = SqueezeOperation::new(set2, complement_flag);
                translate_input(&mut squeeze_reader, &mut buffered_stdout, op);
            }
        } else {
            let op = DeleteOperation::new(set1, complement_flag);
            translate_input(&mut locked_stdin, &mut buffered_stdout, op);
        }
    } else if squeeze_flag {
        if sets_len < 2 {
            let op = SqueezeOperation::new(set1, complement_flag);
            translate_input(&mut locked_stdin, &mut buffered_stdout, op);
        } else {
            let mut translate_buffer = vec![];
            {
                let mut writer = BufWriter::new(&mut translate_buffer);
                let op = TranslateOperation::new(set1, set2.clone(), complement_flag)?;
                translate_input(&mut locked_stdin, &mut writer, op);
            }
            {
                let mut reader = BufReader::new(translate_buffer.as_bytes());
                let squeeze_op = SqueezeOperation::new(set2, false);
                translate_input(&mut reader, &mut buffered_stdout, squeeze_op);
            }
        }
    } else {
        let op = TranslateOperation::new(set1, set2, complement_flag)?;
        translate_input(&mut locked_stdin, &mut buffered_stdout, op);
    }
    Ok(())
}

pub fn uu_app<'a>() -> Command<'a> {
    Command::new(uucore::util_name())
        .version(crate_version!())
        .about(ABOUT)
        .override_usage(format_usage(USAGE))
        .infer_long_args(true)
        .infer_long_args(true)
        .arg(
            Arg::new(options::COMPLEMENT)
                .visible_short_alias('C')
                .short('c')
                .long(options::COMPLEMENT)
                .help("use the complement of SET1"),
        )
        .arg(
            Arg::new(options::DELETE)
                .short('d')
                .long(options::DELETE)
                .help("delete characters in SET1, do not translate"),
        )
        .arg(
            Arg::new(options::SQUEEZE)
                .long(options::SQUEEZE)
                .short('s')
                .help(
                    "replace each sequence of a repeated character that is \
                     listed in the last specified SET, with a single occurrence \
                     of that character",
                ),
        )
        .arg(
            Arg::new(options::TRUNCATE_SET1)
                .long(options::TRUNCATE_SET1)
                .short('t')
                .help("first truncate SET1 to length of SET2"),
        )
        .arg(
            Arg::new(options::SETS)
                .multiple_occurrences(true)
                .takes_value(true)
                .min_values(1)
                .max_values(2),
        )
}
<commit_msg>tr: remove duplicate line from clap::Command<commit_after>//  * This file is part of the uutils coreutils package.
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore (ToDO) allocs bset dflag cflag sflag tflag

extern crate nom;

mod convert;
mod operation;
mod unicode_table;

use clap::{crate_version, Arg, Command};
use nom::AsBytes;
use operation::{translate_input, Sequence, SqueezeOperation, TranslateOperation};
use std::io::{stdin, stdout, BufReader, BufWriter};
use uucore::{format_usage, show};

use crate::operation::DeleteOperation;
use uucore::error::{UResult, USimpleError, UUsageError};
use uucore::{display::Quotable, InvalidEncodingHandling};

static ABOUT: &str = "translate or delete characters";
const USAGE: &str = "{} [OPTION]... SET1 [SET2]";

mod options {
    pub const COMPLEMENT: &str = "complement";
    pub const DELETE: &str = "delete";
    pub const SQUEEZE: &str = "squeeze-repeats";
    pub const TRUNCATE_SET1: &str = "truncate-set1";
    pub const SETS: &str = "sets";
}

fn get_long_usage() -> String {
    "Translate, squeeze, and/or delete characters from standard input, \
     writing to standard output."
        .to_string()
}

#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
    let args = args
        .collect_str(InvalidEncodingHandling::ConvertLossy)
        .accept_any();

    let after_help = get_long_usage();

    let matches = uu_app().after_help(&after_help[..]).get_matches_from(args);

    let delete_flag = matches.is_present(options::DELETE);
    let complement_flag = matches.is_present(options::COMPLEMENT);
    let squeeze_flag = matches.is_present(options::SQUEEZE);
    let truncate_set1_flag = matches.is_present(options::TRUNCATE_SET1);

    let sets = matches
        .values_of(options::SETS)
        .map(|v| {
            v.map(ToString::to_string)
                .map(|input| convert::reduce_octal_to_char(&input))
                .collect::<Vec<_>>()
        })
        .unwrap_or_default();
    let sets_len = sets.len();

    if sets.is_empty() {
        return Err(UUsageError::new(1, "missing operand"));
    }

    if !(delete_flag || squeeze_flag) && sets_len < 2 {
        return Err(UUsageError::new(
            1,
            format!("missing operand after {}", sets[0].quote()),
        ));
    }

    if let Some(first) = sets.get(0) {
        if first.ends_with('\\') {
            show!(USimpleError::new(
                0,
                "warning: an unescaped backslash at end of string is not portable"
            ));
        }
    }

    let stdin = stdin();
    let mut locked_stdin = stdin.lock();
    let stdout = stdout();
    let locked_stdout = stdout.lock();
    let mut buffered_stdout = BufWriter::new(locked_stdout);

    let mut sets_iter = sets.iter().map(|c| c.as_str());
    let (set1, set2) = Sequence::solve_set_characters(
        sets_iter.next().unwrap_or_default(),
        sets_iter.next().unwrap_or_default(),
        truncate_set1_flag,
    )?;

    if delete_flag {
        if squeeze_flag {
            let mut delete_buffer = vec![];
            {
                let mut delete_writer = BufWriter::new(&mut delete_buffer);
                let delete_op = DeleteOperation::new(set1, complement_flag);
                translate_input(&mut locked_stdin, &mut delete_writer, delete_op);
            }
            {
                let mut squeeze_reader = BufReader::new(delete_buffer.as_bytes());
                let op = SqueezeOperation::new(set2, complement_flag);
                translate_input(&mut squeeze_reader, &mut buffered_stdout, op);
            }
        } else {
            let op = DeleteOperation::new(set1, complement_flag);
            translate_input(&mut locked_stdin, &mut buffered_stdout, op);
        }
    } else if squeeze_flag {
        if sets_len < 2 {
            let op = SqueezeOperation::new(set1, complement_flag);
            translate_input(&mut locked_stdin, &mut buffered_stdout, op);
        } else {
            let mut translate_buffer = vec![];
            {
                let mut writer = BufWriter::new(&mut translate_buffer);
                let op = TranslateOperation::new(set1, set2.clone(), complement_flag)?;
                translate_input(&mut locked_stdin, &mut writer, op);
            }
            {
                let mut reader = BufReader::new(translate_buffer.as_bytes());
                let squeeze_op = SqueezeOperation::new(set2, false);
                translate_input(&mut reader, &mut buffered_stdout, squeeze_op);
            }
        }
    } else {
        let op = TranslateOperation::new(set1, set2, complement_flag)?;
        translate_input(&mut locked_stdin, &mut buffered_stdout, op);
    }
    Ok(())
}

pub fn uu_app<'a>() -> Command<'a> {
    Command::new(uucore::util_name())
        .version(crate_version!())
        .about(ABOUT)
        .override_usage(format_usage(USAGE))
        .infer_long_args(true)
        .arg(
            Arg::new(options::COMPLEMENT)
                .visible_short_alias('C')
                .short('c')
                .long(options::COMPLEMENT)
                .help("use the complement of SET1"),
        )
        .arg(
            Arg::new(options::DELETE)
                .short('d')
                .long(options::DELETE)
                .help("delete characters in SET1, do not translate"),
        )
        .arg(
            Arg::new(options::SQUEEZE)
                .long(options::SQUEEZE)
                .short('s')
                .help(
                    "replace each sequence of a repeated character that is \
                     listed in the last specified SET, with a single occurrence \
                     of that character",
                ),
        )
        .arg(
            Arg::new(options::TRUNCATE_SET1)
                .long(options::TRUNCATE_SET1)
                .short('t')
                .help("first truncate SET1 to length of SET2"),
        )
        .arg(
            Arg::new(options::SETS)
                .multiple_occurrences(true)
                .takes_value(true)
                .min_values(1)
                .max_values(2),
        )
}
<|endoftext|>


<commit_before>#![allow(clippy::single_match_else)]
use rustc_tools_util::VersionInfo;

#[test]
fn check_that_clippy_lints_and_clippy_utils_have_the_same_version_as_clippy() {
    let clippy_meta = cargo_metadata::MetadataCommand::new()
        .no_deps()
        .exec()
        .expect("could not obtain cargo metadata");

    for krate in &["clippy_lints", "clippy_utils"] {
        let krate_meta = cargo_metadata::MetadataCommand::new()
            .current_dir(std::env::current_dir().unwrap().join(krate))
            .no_deps()
            .exec()
            .expect("could not obtain cargo metadata");
        assert_eq!(krate_meta.packages[0].version, clippy_meta.packages[0].version);
        for package in &clippy_meta.packages[0].dependencies {
            if package.name == *krate {
                assert!(package.req.matches(&krate_meta.packages[0].version));
                break;
            }
        }
    }
}

#[test]
fn check_that_clippy_has_the_same_major_version_as_rustc() {
    // do not run this test inside the upstream rustc repo:
    // https://github.com/rust-lang/rust-clippy/issues/6683
    if option_env!("RUSTC_TEST_SUITE").is_some() {
        return;
    }

    let clippy_version = rustc_tools_util::get_version_info!();
    let clippy_major = clippy_version.major;
    let clippy_minor = clippy_version.minor;
    let clippy_patch = clippy_version.patch;

    // get the rustc version either from the rustc installed with the toolchain file or from
    // `RUSTC_REAL` if Clippy is build in the Rust repo with `./x.py`.
    let rustc = std::env::var("RUSTC_REAL").unwrap_or_else(|_| "rustc".to_string());
    let rustc_version = String::from_utf8(
        std::process::Command::new(&rustc)
            .arg("--version")
            .output()
            .expect("failed to run `rustc --version`")
            .stdout,
    )
    .unwrap();
    // extract "1 XX 0" from "rustc 1.XX.0-nightly (<commit> <date>)"
    let vsplit: Vec<&str> = rustc_version
        .split(' ')
        .nth(1)
        .unwrap()
        .split('-')
        .next()
        .unwrap()
        .split('.')
        .collect();
    match vsplit.as_slice() {
        [rustc_major, rustc_minor, _rustc_patch] => {
            // clippy 0.1.XX should correspond to rustc 1.XX.0
            assert_eq!(clippy_major, 0); // this will probably stay the same for a long time
            assert_eq!(
                clippy_minor.to_string(),
                *rustc_major,
                "clippy minor version does not equal rustc major version"
            );
            assert_eq!(
                clippy_patch.to_string(),
                *rustc_minor,
                "clippy patch version does not equal rustc minor version"
            );
            // do not check rustc_patch because when a stable-patch-release is made (like 1.50.2),
            // we don't want our tests failing suddenly
        },
        _ => {
            panic!("Failed to parse rustc version: {:?}", vsplit);
        },
    };
}
<commit_msg>Fix versioncheck test<commit_after>#![allow(clippy::single_match_else)]
use rustc_tools_util::VersionInfo;

#[test]
fn check_that_clippy_lints_and_clippy_utils_have_the_same_version_as_clippy() {
    let clippy_meta = cargo_metadata::MetadataCommand::new()
        .no_deps()
        .exec()
        .expect("could not obtain cargo metadata");

    for krate in &["clippy_lints", "clippy_utils"] {
        let krate_meta = clippy_meta
            .packages
            .iter()
            .find(|package| package.name == *krate)
            .expect("could not obtain cargo metadata");
        assert_eq!(krate_meta.version, clippy_meta.packages[0].version);
        for package in &clippy_meta.packages[0].dependencies {
            if package.name == *krate {
                assert!(package.req.matches(&krate_meta.version));
                break;
            }
        }
    }
}

#[test]
fn check_that_clippy_has_the_same_major_version_as_rustc() {
    // do not run this test inside the upstream rustc repo:
    // https://github.com/rust-lang/rust-clippy/issues/6683
    if option_env!("RUSTC_TEST_SUITE").is_some() {
        return;
    }

    let clippy_version = rustc_tools_util::get_version_info!();
    let clippy_major = clippy_version.major;
    let clippy_minor = clippy_version.minor;
    let clippy_patch = clippy_version.patch;

    // get the rustc version either from the rustc installed with the toolchain file or from
    // `RUSTC_REAL` if Clippy is build in the Rust repo with `./x.py`.
    let rustc = std::env::var("RUSTC_REAL").unwrap_or_else(|_| "rustc".to_string());
    let rustc_version = String::from_utf8(
        std::process::Command::new(&rustc)
            .arg("--version")
            .output()
            .expect("failed to run `rustc --version`")
            .stdout,
    )
    .unwrap();
    // extract "1 XX 0" from "rustc 1.XX.0-nightly (<commit> <date>)"
    let vsplit: Vec<&str> = rustc_version
        .split(' ')
        .nth(1)
        .unwrap()
        .split('-')
        .next()
        .unwrap()
        .split('.')
        .collect();
    match vsplit.as_slice() {
        [rustc_major, rustc_minor, _rustc_patch] => {
            // clippy 0.1.XX should correspond to rustc 1.XX.0
            assert_eq!(clippy_major, 0); // this will probably stay the same for a long time
            assert_eq!(
                clippy_minor.to_string(),
                *rustc_major,
                "clippy minor version does not equal rustc major version"
            );
            assert_eq!(
                clippy_patch.to_string(),
                *rustc_minor,
                "clippy patch version does not equal rustc minor version"
            );
            // do not check rustc_patch because when a stable-patch-release is made (like 1.50.2),
            // we don't want our tests failing suddenly
        },
        _ => {
            panic!("Failed to parse rustc version: {:?}", vsplit);
        },
    };
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;

/// The dominance relation.

pub trait Dominate {

    /// If `self` dominates `other`, return `Less`.
    /// If `other` dominates `self`, return `Greater`.
    /// If neither `self` nor `other` dominates the other, `Equal`.

    fn dominate(&self, other: &Self) -> Ordering {
        if self.dominates(other) {
            Ordering::Less
        } else if other.dominates(self) {
            Ordering::Greater
        } else {
            Ordering::Equal
        }
    }

    /// Returns true if `self` dominates `other`.

    fn dominates(&self, other: &Self) -> bool {
        match self.dominate(other) {
            Ordering::Less => true,
            _ => false
        }
    }
}

/// Perform a non dominated sort of the `solutions`.
///
/// Stop after we have found `n` solutions. As we include the whole pareto front, there are
/// probably more solutions returned.

pub fn fast_non_dominated_sort<P: Dominate>(solutions: &[P], n: usize) -> Vec<Vec<usize>> {
    let mut fronts: Vec<Vec<usize>> = Vec::new();
    let mut current_front = Vec::new();

    let mut domination_count: Vec<usize> = (0..solutions.len()).map(|_| 0).collect();
    let mut dominated_solutions: Vec<Vec<usize>> = (0..solutions.len())
                                                       .map(|_| Vec::new())
                                                       .collect();
    let mut found_solutions: usize = 0;

    for (i, p) in solutions.iter().enumerate() {
        for (j, q) in solutions.iter().enumerate() {
            if i == j {
                continue;
            }
            match p.dominate(q) {
                Ordering::Less => {
                    // p dominates q
                    // Add `q` to the set of solutions dominated by `p`.
                    dominated_solutions[i].push(j);
                }
                Ordering::Greater => {
                    // q dominates p
                    // Increment domination counter of `p`.
                    domination_count[i] += 1;
                }
                _ => {}
            }
        }

        if domination_count[i] == 0 {
            // `p` belongs to the first front as it is not dominated by any
            // other solution.
            current_front.push(i);
        }
    }

    while !current_front.is_empty() {
        found_solutions += current_front.len();
        if found_solutions >= n {
            fronts.push(current_front);
            break;
        } else {
            // we haven't found enough solutions yet.
            let mut next_front = Vec::new();
            for &p_i in current_front.iter() {
                for &q_i in dominated_solutions[p_i].iter() {
                    domination_count[q_i] -= 1;
                    if domination_count[q_i] == 0 {
                        // q belongs to the next front
                        next_front.push(q_i);
                    }
                }
            }
            fronts.push(current_front);
            current_front = next_front;
        }
    }

    return fronts;
}

#[cfg(test)]
mod tests {
    use super::{fast_non_dominated_sort, Dominate};
    use std::cmp::Ordering;

    struct T(u32, u32);

    impl Dominate for T {
        fn dominate(&self, other: &Self) -> Ordering {
            if self.0 < other.0 && self.1 <= other.1 {
                return Ordering::Less;
            }
            if self.0 <= other.0 && self.1 < other.1 {
                return Ordering::Less;
            }

            if self.0 > other.0 && self.1 >= other.1 {
                return Ordering::Greater;
            }
            if self.0 >= other.0 && self.1 > other.1 {
                return Ordering::Greater;
            }

            return Ordering::Equal;
        }
    }

    #[test]
    fn test_dominate() {
        assert_eq!(Ordering::Equal, T(1, 2).dominate(&T(1, 2)));
        assert_eq!(Ordering::Equal, T(1, 2).dominate(&T(2, 1)));
        assert_eq!(Ordering::Less, T(1, 2).dominate(&T(1, 3)));
        assert_eq!(Ordering::Less, T(0, 2).dominate(&T(1, 2)));
        assert_eq!(Ordering::Greater, T(1, 3).dominate(&T(1, 2)));
        assert_eq!(Ordering::Greater, T(1,2).dominate(&T(0, 2)));
    }

    #[test]
    fn test_non_dominated_sort() {
        let solutions = vec![T(1, 2), T(1, 2), T(2, 1), T(1, 3), T(0, 2)];
        let fronts = fast_non_dominated_sort(&solutions, solutions.len());

        assert_eq!(3, fronts.len());
        assert_eq!(&vec![2, 4], &fronts[0]);
        assert_eq!(&vec![0, 1], &fronts[1]);
        assert_eq!(&vec![3], &fronts[2]);
    }
}
<commit_msg>Half the total number of iterations by using symmetry<commit_after>use std::cmp::Ordering;

/// The dominance relation.

pub trait Dominate {

    /// If `self` dominates `other`, return `Less`.
    /// If `other` dominates `self`, return `Greater`.
    /// If neither `self` nor `other` dominates the other, `Equal`.

    fn dominate(&self, other: &Self) -> Ordering {
        if self.dominates(other) {
            Ordering::Less
        } else if other.dominates(self) {
            Ordering::Greater
        } else {
            Ordering::Equal
        }
    }

    /// Returns true if `self` dominates `other`.

    fn dominates(&self, other: &Self) -> bool {
        match self.dominate(other) {
            Ordering::Less => true,
            _ => false
        }
    }
}

/// Perform a non dominated sort of the `solutions`.
///
/// Stop after we have found `n` solutions. As we include the whole pareto front, there are
/// probably more solutions returned.

pub fn fast_non_dominated_sort<P: Dominate>(solutions: &[P], n: usize) -> Vec<Vec<usize>> {
    let mut fronts: Vec<Vec<usize>> = Vec::new();
    let mut current_front = Vec::new();

    let mut domination_count: Vec<usize> = (0..solutions.len()).map(|_| 0).collect();
    let mut dominated_solutions: Vec<Vec<usize>> = (0..solutions.len())
                                                       .map(|_| Vec::new())
                                                       .collect();
    let mut found_solutions: usize = 0;

    for i in 0 .. solutions.len() {
        for j in i+1 .. solutions.len() {
            let p = &solutions[i];
            let q = &solutions[j];

            match p.dominate(q) {
                Ordering::Less => {
                    // p dominates q
                    // Add `q` to the set of solutions dominated by `p`.
                    dominated_solutions[i].push(j);
                    // q is dominated by p
                    domination_count[j] += 1;
                }
                Ordering::Greater => {
                    // p is dominated by q
                    // Add `p` to the set of solutions dominated by `q`.
                    dominated_solutions[j].push(i);
                    // q dominates p
                    // Increment domination counter of `p`.
                    domination_count[i] += 1;
                }
                _ => {}
            }
        }

        if domination_count[i] == 0 {
            // `p` belongs to the first front as it is not dominated by any
            // other solution.
            current_front.push(i);
        }
    }

    while !current_front.is_empty() {
        found_solutions += current_front.len();
        if found_solutions >= n {
            fronts.push(current_front);
            break;
        } else {
            // we haven't found enough solutions yet.
            let mut next_front = Vec::new();
            for &p_i in current_front.iter() {
                for &q_i in dominated_solutions[p_i].iter() {
                    domination_count[q_i] -= 1;
                    if domination_count[q_i] == 0 {
                        // q belongs to the next front
                        next_front.push(q_i);
                    }
                }
            }
            fronts.push(current_front);
            current_front = next_front;
        }
    }

    return fronts;
}

#[cfg(test)]
mod tests {
    use super::{fast_non_dominated_sort, Dominate};
    use std::cmp::Ordering;

    struct T(u32, u32);

    impl Dominate for T {
        fn dominate(&self, other: &Self) -> Ordering {
            if self.0 < other.0 && self.1 <= other.1 {
                return Ordering::Less;
            }
            if self.0 <= other.0 && self.1 < other.1 {
                return Ordering::Less;
            }

            if self.0 > other.0 && self.1 >= other.1 {
                return Ordering::Greater;
            }
            if self.0 >= other.0 && self.1 > other.1 {
                return Ordering::Greater;
            }

            return Ordering::Equal;
        }
    }

    #[test]
    fn test_dominate() {
        assert_eq!(Ordering::Equal, T(1, 2).dominate(&T(1, 2)));
        assert_eq!(Ordering::Equal, T(1, 2).dominate(&T(2, 1)));
        assert_eq!(Ordering::Less, T(1, 2).dominate(&T(1, 3)));
        assert_eq!(Ordering::Less, T(0, 2).dominate(&T(1, 2)));
        assert_eq!(Ordering::Greater, T(1, 3).dominate(&T(1, 2)));
        assert_eq!(Ordering::Greater, T(1,2).dominate(&T(0, 2)));
    }

    #[test]
    fn test_non_dominated_sort() {
        let solutions = vec![T(1, 2), T(1, 2), T(2, 1), T(1, 3), T(0, 2)];
        let fronts = fast_non_dominated_sort(&solutions, solutions.len());

        assert_eq!(3, fronts.len());
        assert_eq!(&vec![2, 4], &fronts[0]);
        assert_eq!(&vec![0, 1], &fronts[1]);
        assert_eq!(&vec![3], &fronts[2]);
    }
}
<|endoftext|>


<commit_before>use std::cmp;
use std::io;
use std::ops::Deref;

pub use self::Doc::{
    Nil,
    Append,
    Group,
    Nest,
    Newline,
    Text,
};

#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
enum Mode {
    Break,
    Flat,
}

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum Doc<'a, B> {
    Nil,
    Append(B, B),
    Group(B),
    Nest(usize, B),
    Newline,
    Text(::std::borrow::Cow<'a, str>),
}

impl<'a, B> Doc<'a, B> {
    #[inline]
    pub fn render<'b, W: io::Write>(&'b self, width: usize, out: &mut W) -> io::Result<()>
    where B: Deref<Target = Doc<'b, B>>
    {
        best(self, width, out).and_then(|()| out.write_all(b"\n"))
    }
}

type Cmd<'a, B> = (usize, Mode, &'a Doc<'a, B>);

#[inline]
fn fitting<'a, B>(
    next: Cmd<'a, B>,
    bcmds: &Vec<Cmd<'a, B>>,
    fcmds: &mut Vec<Cmd<'a, B>>,
    mut rem: isize,
) -> bool
where B: Deref<Target = Doc<'a, B>>
{
    let mut bidx = bcmds.len();
    let mut fits = true;
    fcmds.clear(); // clear from previous calls from best
    fcmds.push(next);
    loop {
        if rem < 0 {
            fits = false;
            break;
        }
        match fcmds.pop() {
            None => {
                if bidx == 0 {
                    break;
                } else {
                    fcmds.push(bcmds[ bidx - 1 ]);
                    bidx -= 1;
                }
            },
            Some((ind, mode, doc)) => match doc {
                &Nil => {
                },
                &Append(ref ldoc, ref rdoc) => {
                    fcmds.push((ind, mode, rdoc));
                    fcmds.push((ind, mode, ldoc));
                },
                &Group(ref doc) => {
                    fcmds.push((ind, mode, doc));
                },
                &Nest(off, ref doc) => {
                    fcmds.push((ind + off, mode, doc));
                },
                &Newline => {
                    fits = true;
                },
                &Text(ref str) => {
                    rem -= str.len() as isize;
                },
            }
        }
    }
    fits
}

#[inline]
pub fn best<'a, W: io::Write, B>(
    doc: &'a Doc<'a, B>,
    width: usize,
    out: &mut W,
) -> io::Result<()>
where B: Deref<Target = Doc<'a, B>>
{
    let mut pos = 0usize;
    let mut bcmds = vec![(0usize, Mode::Break, doc)];
    let mut fcmds = vec![];
    loop {
        match bcmds.pop() {
            None => {
                break;
            },
            Some((ind, mode, doc)) => match doc {
                &Nil => {
                },
                &Append(ref ldoc, ref rdoc) => {
                    bcmds.push((ind, mode, rdoc));
                    bcmds.push((ind, mode, ldoc));
                },
                &Group(ref doc) => match mode {
                    Mode::Flat => {
                        bcmds.push((ind, Mode::Flat, doc));
                    },
                    Mode::Break => {
                        let next = (ind, Mode::Flat, &**doc);
                        let rem = width as isize - pos as isize;
                        if fitting(next, &bcmds, &mut fcmds, rem) {
                            bcmds.push(next);
                        } else {
                            bcmds.push((ind, Mode::Break, doc));
                        }
                    }
                },
                &Nest(off, ref doc) => {
                    bcmds.push((ind + off, mode, doc));
                },
                &Newline => {
                    const SPACES: [u8; 100] = [b' '; 100];
                    try!(out.write_all(b"\n"));
                    let mut inserted = 0;
                    while inserted < ind {
                        let insert = cmp::min(100, ind - inserted);
                        inserted += insert;
                        try!(out.write_all(&SPACES[..insert]));
                    }
                    pos = ind;
                },
                &Text(ref s) => {
                    try!(out.write_all(&s.as_bytes()));
                    pos += s.len();
                },
            }
        }
    }
    Ok(())
}
<commit_msg>Use while let instead of loop + match<commit_after>use std::cmp;
use std::io;
use std::ops::Deref;

pub use self::Doc::{
    Nil,
    Append,
    Group,
    Nest,
    Newline,
    Text,
};

#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
enum Mode {
    Break,
    Flat,
}

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum Doc<'a, B> {
    Nil,
    Append(B, B),
    Group(B),
    Nest(usize, B),
    Newline,
    Text(::std::borrow::Cow<'a, str>),
}

impl<'a, B> Doc<'a, B> {
    #[inline]
    pub fn render<'b, W: io::Write>(&'b self, width: usize, out: &mut W) -> io::Result<()>
    where B: Deref<Target = Doc<'b, B>>
    {
        best(self, width, out).and_then(|()| out.write_all(b"\n"))
    }
}

type Cmd<'a, B> = (usize, Mode, &'a Doc<'a, B>);

#[inline]
fn fitting<'a, B>(
    next: Cmd<'a, B>,
    bcmds: &Vec<Cmd<'a, B>>,
    fcmds: &mut Vec<Cmd<'a, B>>,
    mut rem: isize,
) -> bool
where B: Deref<Target = Doc<'a, B>>
{
    let mut bidx = bcmds.len();
    let mut fits = true;
    fcmds.clear(); // clear from previous calls from best
    fcmds.push(next);
    loop {
        if rem < 0 {
            fits = false;
            break;
        }
        match fcmds.pop() {
            None => {
                if bidx == 0 {
                    break;
                } else {
                    fcmds.push(bcmds[ bidx - 1 ]);
                    bidx -= 1;
                }
            },
            Some((ind, mode, doc)) => match doc {
                &Nil => {
                },
                &Append(ref ldoc, ref rdoc) => {
                    fcmds.push((ind, mode, rdoc));
                    fcmds.push((ind, mode, ldoc));
                },
                &Group(ref doc) => {
                    fcmds.push((ind, mode, doc));
                },
                &Nest(off, ref doc) => {
                    fcmds.push((ind + off, mode, doc));
                },
                &Newline => {
                    fits = true;
                },
                &Text(ref str) => {
                    rem -= str.len() as isize;
                },
            }
        }
    }
    fits
}

#[inline]
pub fn best<'a, W: io::Write, B>(
    doc: &'a Doc<'a, B>,
    width: usize,
    out: &mut W,
) -> io::Result<()>
where B: Deref<Target = Doc<'a, B>>
{
    let mut pos = 0usize;
    let mut bcmds = vec![(0usize, Mode::Break, doc)];
    let mut fcmds = vec![];
    while let Some((ind, mode, doc)) = bcmds.pop() {
        match doc {
            &Nil => {
            },
            &Append(ref ldoc, ref rdoc) => {
                bcmds.push((ind, mode, rdoc));
                bcmds.push((ind, mode, ldoc));
            },
            &Group(ref doc) => match mode {
                Mode::Flat => {
                    bcmds.push((ind, Mode::Flat, doc));
                },
                Mode::Break => {
                    let next = (ind, Mode::Flat, &**doc);
                    let rem = width as isize - pos as isize;
                    if fitting(next, &bcmds, &mut fcmds, rem) {
                        bcmds.push(next);
                    } else {
                        bcmds.push((ind, Mode::Break, doc));
                    }
                }
            },
            &Nest(off, ref doc) => {
                bcmds.push((ind + off, mode, doc));
            },
            &Newline => {
                const SPACES: [u8; 100] = [b' '; 100];
                try!(out.write_all(b"\n"));
                let mut inserted = 0;
                while inserted < ind {
                    let insert = cmp::min(100, ind - inserted);
                    inserted += insert;
                    try!(out.write_all(&SPACES[..insert]));
                }
                pos = ind;
            },
            &Text(ref s) => {
                try!(out.write_all(&s.as_bytes()));
                pos += s.len();
            },
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>//! This crate defines a
//! [Wadler-style](http://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf)
//! pretty-printing API.
extern crate typed_arena;

use doc::Doc::{
    Append,
    Group,
    Nest,
    Newline,
    Nil,
    Text,
};
use std::borrow::Cow;
use std::ops::Deref;

mod doc;

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct BoxDoc<'a>(Box<doc::Doc<'a, BoxDoc<'a>>>);

impl<'a> BoxDoc<'a> {
    fn new(doc: doc::Doc<'a, BoxDoc<'a>>) -> BoxDoc<'a> {
        BoxDoc(Box::new(doc))
    }
}

impl<'a> Deref for BoxDoc<'a> {
    type Target = doc::Doc<'a, BoxDoc<'a>>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

pub struct DocBuilder<'a, A: ?Sized>(pub &'a A, pub doc::Doc<'a, A::Doc>)
    where A: Allocator<'a> + 'a;

impl <'a, A> Into<doc::Doc<'a, A::Doc>> for DocBuilder<'a, A>
    where A: Allocator<'a>
{
    fn into(self) -> doc::Doc<'a, A::Doc> {
        self.1
    }
}

pub trait Allocator<'a> {
    type Doc: Deref<Target = doc::Doc<'a, Self::Doc>> + Clone;
    fn alloc(&'a self, doc::Doc<'a, Self::Doc>) -> Self::Doc;

    #[inline]
    fn nil(&'a self) -> DocBuilder<'a, Self> {
        DocBuilder(self, Nil)
    }

    #[inline]
    fn newline(&'a self) -> DocBuilder<'a, Self> {
        DocBuilder(self, Newline)
    }

    #[inline]
    fn as_string<T: ToString>(&'a self, t: T) -> DocBuilder<'a, Self> {
        self.text(t.to_string())
    }

    #[inline]
    fn text<T: Into<Cow<'a, str>>>(&'a self, data: T) -> DocBuilder<'a, Self> {
        DocBuilder(self, Text(data.into()))
    }

    #[inline]
    fn concat<I>(&'a self, docs: I) -> DocBuilder<'a, Self>
    where I: IntoIterator<Item = doc::Doc<'a, Self::Doc>>
    {
        docs.into_iter().fold(self.nil(), |a, b| a.append(b))
    }
}

impl<'a, 's, A: ?Sized> DocBuilder<'a, A> where A: Allocator<'a> {
    #[inline]
    pub fn append<B>(self, that: B) -> DocBuilder<'a, A>
    where B: Into<doc::Doc<'a, A::Doc>>,
    {
        let DocBuilder(allocator, this) = self;
        let that = that.into();
        let doc = match this {
            Nil  => that,
            _ => match that {
                Nil  => this,
                _ => Append(allocator.alloc(this), allocator.alloc(that)),
            }
        };
        DocBuilder(allocator, doc)
    }

    #[inline]
    pub fn group(self) -> DocBuilder<'a, A>
    {
        let DocBuilder(allocator, this) = self;
        DocBuilder(allocator, Group(allocator.alloc(this)))
    }

    #[inline]
    pub fn nest(self, offset: usize) -> DocBuilder<'a, A>
    {
        let DocBuilder(allocator, this) = self;
        DocBuilder(allocator, Nest(offset, allocator.alloc(this)))
    }
}

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct RefDoc<'a>(&'a doc::Doc<'a, RefDoc<'a>>);

impl<'a> Deref for RefDoc<'a> {
    type Target = doc::Doc<'a, RefDoc<'a>>;

    fn deref(&self) -> &doc::Doc<'a, RefDoc<'a>> {
        &self.0
    }
}

pub type Arena<'a> = typed_arena::Arena<doc::Doc<'a, RefDoc<'a>>>;

impl<'a> Allocator<'a> for Arena<'a> {
    type Doc = RefDoc<'a>;

    fn alloc(&'a self, doc: doc::Doc<'a, Self::Doc>) -> Self::Doc {
        RefDoc(Arena::alloc(self, doc))
    }
}

pub struct BoxAllocator;

static BOX_ALLOCATOR: BoxAllocator = BoxAllocator;

impl<'a> Allocator<'a> for BoxAllocator {
    type Doc = BoxDoc<'a>;

    fn alloc(&'a self, doc: doc::Doc<'a, Self::Doc>) -> Self::Doc {
        BoxDoc::new(doc)
    }
}

pub type Doc<'a> = doc::Doc<'a, BoxDoc<'a>>;

impl<'a> Doc<'a> {
    #[inline]
    pub fn nil() -> Doc<'a> {
        Nil
    }

    #[inline]
    pub fn append(self, that: Doc<'a>) -> Doc<'a> {
        DocBuilder(&BOX_ALLOCATOR, self).append(that).into()
    }

    #[inline]
    pub fn as_string<T: ToString>(t: T) -> Doc<'a> {
        Doc::text(t.to_string())
    }

    #[inline]
    pub fn concat<I>(&'a self, docs: I) -> Doc<'a>
    where I: IntoIterator<Item = Doc<'a>>
    {
        docs.into_iter().fold(Doc::nil(), |a, b| a.append(b))
    }

    #[inline]
    pub fn group(self) -> Doc<'a> {
        DocBuilder(&BOX_ALLOCATOR, self).group().into()
    }

    #[inline]
    pub fn nest(self, offset: usize) -> Doc<'a> {
        DocBuilder(&BOX_ALLOCATOR, self).nest(offset).into()
    }

    #[inline]
    pub fn newline() -> Doc<'a> {
        Newline
    }

    #[inline]
    pub fn text<T: Into<Cow<'a, str>>>(data: T) -> Doc<'a> {
        Text(data.into())
    }
}
<commit_msg>Add clearer std::fmt::Debug for RefDoc and BoxDoc<commit_after>//! This crate defines a
//! [Wadler-style](http://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf)
//! pretty-printing API.
extern crate typed_arena;

use doc::Doc::{
    Append,
    Group,
    Nest,
    Newline,
    Nil,
    Text,
};
use std::borrow::Cow;
use std::fmt;
use std::ops::Deref;

mod doc;

#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct BoxDoc<'a>(Box<doc::Doc<'a, BoxDoc<'a>>>);

impl<'a> fmt::Debug for BoxDoc<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<'a> BoxDoc<'a> {
    fn new(doc: doc::Doc<'a, BoxDoc<'a>>) -> BoxDoc<'a> {
        BoxDoc(Box::new(doc))
    }
}

impl<'a> Deref for BoxDoc<'a> {
    type Target = doc::Doc<'a, BoxDoc<'a>>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

pub struct DocBuilder<'a, A: ?Sized>(pub &'a A, pub doc::Doc<'a, A::Doc>)
    where A: Allocator<'a> + 'a;

impl <'a, A> Into<doc::Doc<'a, A::Doc>> for DocBuilder<'a, A>
    where A: Allocator<'a>
{
    fn into(self) -> doc::Doc<'a, A::Doc> {
        self.1
    }
}

pub trait Allocator<'a> {
    type Doc: Deref<Target = doc::Doc<'a, Self::Doc>> + Clone;
    fn alloc(&'a self, doc::Doc<'a, Self::Doc>) -> Self::Doc;

    #[inline]
    fn nil(&'a self) -> DocBuilder<'a, Self> {
        DocBuilder(self, Nil)
    }

    #[inline]
    fn newline(&'a self) -> DocBuilder<'a, Self> {
        DocBuilder(self, Newline)
    }

    #[inline]
    fn as_string<T: ToString>(&'a self, t: T) -> DocBuilder<'a, Self> {
        self.text(t.to_string())
    }

    #[inline]
    fn text<T: Into<Cow<'a, str>>>(&'a self, data: T) -> DocBuilder<'a, Self> {
        DocBuilder(self, Text(data.into()))
    }

    #[inline]
    fn concat<I>(&'a self, docs: I) -> DocBuilder<'a, Self>
    where I: IntoIterator<Item = doc::Doc<'a, Self::Doc>>
    {
        docs.into_iter().fold(self.nil(), |a, b| a.append(b))
    }
}

impl<'a, 's, A: ?Sized> DocBuilder<'a, A> where A: Allocator<'a> {
    #[inline]
    pub fn append<B>(self, that: B) -> DocBuilder<'a, A>
    where B: Into<doc::Doc<'a, A::Doc>>,
    {
        let DocBuilder(allocator, this) = self;
        let that = that.into();
        let doc = match this {
            Nil  => that,
            _ => match that {
                Nil  => this,
                _ => Append(allocator.alloc(this), allocator.alloc(that)),
            }
        };
        DocBuilder(allocator, doc)
    }

    #[inline]
    pub fn group(self) -> DocBuilder<'a, A>
    {
        let DocBuilder(allocator, this) = self;
        DocBuilder(allocator, Group(allocator.alloc(this)))
    }

    #[inline]
    pub fn nest(self, offset: usize) -> DocBuilder<'a, A>
    {
        let DocBuilder(allocator, this) = self;
        DocBuilder(allocator, Nest(offset, allocator.alloc(this)))
    }
}

#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct RefDoc<'a>(&'a doc::Doc<'a, RefDoc<'a>>);

impl<'a> fmt::Debug for RefDoc<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<'a> Deref for RefDoc<'a> {
    type Target = doc::Doc<'a, RefDoc<'a>>;

    fn deref(&self) -> &doc::Doc<'a, RefDoc<'a>> {
        &self.0
    }
}

pub type Arena<'a> = typed_arena::Arena<doc::Doc<'a, RefDoc<'a>>>;

impl<'a> Allocator<'a> for Arena<'a> {
    type Doc = RefDoc<'a>;

    fn alloc(&'a self, doc: doc::Doc<'a, Self::Doc>) -> Self::Doc {
        RefDoc(Arena::alloc(self, doc))
    }
}

pub struct BoxAllocator;

static BOX_ALLOCATOR: BoxAllocator = BoxAllocator;

impl<'a> Allocator<'a> for BoxAllocator {
    type Doc = BoxDoc<'a>;

    fn alloc(&'a self, doc: doc::Doc<'a, Self::Doc>) -> Self::Doc {
        BoxDoc::new(doc)
    }
}

pub type Doc<'a> = doc::Doc<'a, BoxDoc<'a>>;

impl<'a> Doc<'a> {
    #[inline]
    pub fn nil() -> Doc<'a> {
        Nil
    }

    #[inline]
    pub fn append(self, that: Doc<'a>) -> Doc<'a> {
        DocBuilder(&BOX_ALLOCATOR, self).append(that).into()
    }

    #[inline]
    pub fn as_string<T: ToString>(t: T) -> Doc<'a> {
        Doc::text(t.to_string())
    }

    #[inline]
    pub fn concat<I>(&'a self, docs: I) -> Doc<'a>
    where I: IntoIterator<Item = Doc<'a>>
    {
        docs.into_iter().fold(Doc::nil(), |a, b| a.append(b))
    }

    #[inline]
    pub fn group(self) -> Doc<'a> {
        DocBuilder(&BOX_ALLOCATOR, self).group().into()
    }

    #[inline]
    pub fn nest(self, offset: usize) -> Doc<'a> {
        DocBuilder(&BOX_ALLOCATOR, self).nest(offset).into()
    }

    #[inline]
    pub fn newline() -> Doc<'a> {
        Newline
    }

    #[inline]
    pub fn text<T: Into<Cow<'a, str>>>(data: T) -> Doc<'a> {
        Text(data.into())
    }
}
<|endoftext|>


<commit_before>use engine::{IntoMap, Tile};
use util::units::{Point, Size};

use std::path::AsPath;
use std::fs::File;
use std::io::Read;

/// A map.
pub struct Map {
    pub tiles: Vec<Vec<Tile>>,
    pub size: Size,
}

impl Map {

    /// Creates a new map.
    ///
    /// This method takes a type which implements the `IntoMap` trait to create
    /// the new map.
    ///
    /// # Examples
    ///
    /// From a 2D vector of Tiles:
    ///
    /// ```
    /// use rslike::engine::Map;
    ///
    /// let tiles = vec![vec![]];
    /// let map = Map::new(tiles);
    /// ```
    ///
    /// From a String:
    ///
    /// ```
    /// use rslike::engine::Map;
    ///
    /// let mapstr = "###\n# #\n###".to_string();
    /// let map = Map::new(mapstr);
    /// ```
    pub fn new<T>(maplike: T) -> Map where T: IntoMap {
        maplike.as_map().unwrap()
    }

    pub fn from_file<T>(path: T) -> Map where T: AsPath {
        let mut level_file = File::open(&path).ok().expect("Could not find level file");

        let mut level_string = String::new();
        level_file.read_to_string(&mut level_string).ok().expect("Could not read from level file");

        Map::new(level_string)
    }

    pub fn at(&self, loc: Point) -> Tile {
        self.tiles[loc.y as usize][loc.x as usize]
    }

    pub fn is_walkable(&self, loc: Point) -> bool {
        self.at(loc).is_walkable()
    }

    pub fn set_tile(&mut self, loc: Point, tile: Tile) {
        self.tiles[loc.y as usize][loc.x as usize] = tile;
    }

    pub fn height(&self) -> i32 {
        self.tiles.len() as i32
    }

    pub fn width(&self) -> i32 {
        self.tiles[0].len() as i32
    }

}
<commit_msg>Update to the latest version of Rust<commit_after>use engine::{IntoMap, Tile};
use util::units::{Point, Size};

use std::path::AsPath;
use std::fs::File;
use std::io::Read;

/// A map.
pub struct Map {
    pub tiles: Vec<Vec<Tile>>,
    pub size: Size,
}

impl Map {

    /// Creates a new map.
    ///
    /// This method takes a type which implements the `IntoMap` trait to create
    /// the new map.
    ///
    /// # Examples
    ///
    /// From a 2D vector of Tiles:
    ///
    /// ```
    /// use rslike::engine::Map;
    ///
    /// let tiles = vec![vec![]];
    /// let map = Map::new(tiles);
    /// ```
    ///
    /// From a String:
    ///
    /// ```
    /// use rslike::engine::Map;
    ///
    /// let mapstr = "###\n# #\n###".to_string();
    /// let map = Map::new(mapstr);
    /// ```
    pub fn new<T>(maplike: T) -> Map where T: IntoMap {
        maplike.as_map().unwrap()
    }

    pub fn from_file<T>(path: T) -> Map where T: AsPath {
        let mut level_file = File::open(path).ok().expect("Could not find level file");

        let mut level_string = String::new();
        level_file.read_to_string(&mut level_string).ok().expect("Could not read from level file");

        Map::new(level_string)
    }

    pub fn at(&self, loc: Point) -> Tile {
        self.tiles[loc.y as usize][loc.x as usize]
    }

    pub fn is_walkable(&self, loc: Point) -> bool {
        self.at(loc).is_walkable()
    }

    pub fn set_tile(&mut self, loc: Point, tile: Tile) {
        self.tiles[loc.y as usize][loc.x as usize] = tile;
    }

    pub fn height(&self) -> i32 {
        self.tiles.len() as i32
    }

    pub fn width(&self) -> i32 {
        self.tiles[0].len() as i32
    }

}
<|endoftext|>


<commit_before>/// MidlevelEvents -> MatroskaEvents

extern crate bytes;

use super::elements::midlevel::{MidlevelEventHandler,WhatToDo,MidlevelEvent};
use super::elements::database::Class;
use super::elements::parser::{SimpleContent,BinaryChunkStatus};

use bytes::{Buf,IntoBuf,BigEndian};

/// TODO: revise this Vec<Vec<u8>>
#[derive(Debug, Eq, PartialEq, Hash)]
pub struct MatroskaFrame {
    pub timecode_nanoseconds: u64,
    pub track_number: usize,
    /// outer vec - lacing, inner vec - byte buffer
    pub buffers: Vec<Vec<u8>>,
}

/// TODO: more functions (or rewrite the whole thing)
pub trait MatroskaEventHandler {
    fn frame_encountered(&mut self, f: MatroskaFrame);
    fn segment_tracks(&mut self, e: &std::rc::Rc<super::elements::Element>);
    fn segment_info(&mut self, e: &std::rc::Rc<super::elements::Element>) { }
}

enum WhatToAwait {
    Block,
    TimecodeScale,
    ClusterTimecode,
    Nothing,
}

pub struct MatroskaDemuxer<H: MatroskaEventHandler> {
    h: H,
    timecode_scale: u64,
    last_cluster_timecode: u64,
    a: WhatToAwait,
    b: Vec<u8>,
}

impl<H: MatroskaEventHandler> MidlevelEventHandler for MatroskaDemuxer<H> {
  fn event(&mut self, e: MidlevelEvent) -> () {
    match e {
        MidlevelEvent::EnterElement(c) => {
            self.b.clear();
            match c {
                Class::SimpleBlock => self.a = WhatToAwait::Block,
                Class::Block => self.a = WhatToAwait::Block,
                Class::TimecodeScale => self.a = WhatToAwait::TimecodeScale,
                Class::Timecode => self.a = WhatToAwait::ClusterTimecode,
                _ => {self.a = WhatToAwait::Nothing},
            }
        },
        MidlevelEvent::Content(x) => {
            match self.a {
                WhatToAwait::TimecodeScale => {
                    match x {
                        SimpleContent::Unsigned(xx) => {
                            self.timecode_scale = xx;
                            info!("Got timecode scale: {}", xx);
                        }
                        _ => { error!("Unexpected type"); }
                    }
                }
                WhatToAwait::ClusterTimecode => {
                    match x {
                        SimpleContent::Unsigned(xx) => {
                            self.last_cluster_timecode = xx;
                            info!("Got cluster timecode: {}", xx);
                        }
                        _ => { error!("Unexpected type"); }
                    }
                }
                WhatToAwait::Block => {
                    match x {
                        SimpleContent::Binary(xx, status) => {
                            self.b.extend(xx);
                            match status {
                                BinaryChunkStatus::Last | BinaryChunkStatus::Full => {
                                    self.process_frame();
                                }
                                _ => {},
                            }
                        }
                        _ => { error!("Unexpected type"); }
                    }
                }
                _ => {},
            }
        },
        MidlevelEvent::LeaveElement(_) => {},
        MidlevelEvent::Element(e) => {
            match e.class {
                Class::Info => self.h.segment_info(&e),
                Class::Tracks => self.h.segment_tracks(&e),
                _ => warn!("This code line should not be reachable"),
            }
        },
        MidlevelEvent::Resync => {
            warn!("Resynging matroska parser")
            // TODO: report to user
        },
    }
  }
  fn how_to_handle(&mut self, c: Class) -> WhatToDo {
    match c {
        Class::Info => WhatToDo::Build,
        Class::Tracks => WhatToDo::Build,
        _ => WhatToDo::GoOn,
    }
  }
}

impl<H: MatroskaEventHandler> MatroskaDemuxer<H> {
    pub fn new(h: H) -> Self {
        MatroskaDemuxer {
            h,
            timecode_scale: 1000_000,
            last_cluster_timecode: 0,
            a: WhatToAwait::Nothing,
            b: vec![],
        }
    }

    fn process_frame(&mut self) {
        let mut b  = (&self.b).into_buf();

        let tn_ = b.get_u8();
        if tn_ & 0x80 != 0x80 {
            error!("large track numbers not supported");
            return;
        }
        let tn = tn_ & 0x7F;

        let ts = b.get_i16::<BigEndian>();

        let flags = b.get_u8();

        if flags&0x06 != 0x00 {
            error!("lacing not supported yet");
        }

        // TODO: extract more info from flags and report it to user

        // TODO: to it properly
        let mut ts_nano = ((self.last_cluster_timecode as i64) + (ts as i64)) as u64;
        ts_nano = ((ts_nano as f64) * (self.timecode_scale as f64)) as u64;

        let remaining: Vec<u8> = b.collect();

        let f = MatroskaFrame {
            timecode_nanoseconds : ts_nano,
            track_number: tn as usize,
            buffers: vec![remaining],
        };

        self.h.frame_encountered(f);
    }
}
<commit_msg>Fix the warning<commit_after>/// MidlevelEvents -> MatroskaEvents

extern crate bytes;

use super::elements::midlevel::{MidlevelEventHandler,WhatToDo,MidlevelEvent};
use super::elements::database::Class;
use super::elements::parser::{SimpleContent,BinaryChunkStatus};

use bytes::{Buf,IntoBuf,BigEndian};

/// TODO: revise this Vec<Vec<u8>>
#[derive(Debug, Eq, PartialEq, Hash)]
pub struct MatroskaFrame {
    pub timecode_nanoseconds: u64,
    pub track_number: usize,
    /// outer vec - lacing, inner vec - byte buffer
    pub buffers: Vec<Vec<u8>>,
}

/// TODO: more functions (or rewrite the whole thing)
pub trait MatroskaEventHandler {
    fn frame_encountered(&mut self, f: MatroskaFrame);
    fn segment_tracks(&mut self, e: &std::rc::Rc<super::elements::Element>);
    fn segment_info(&mut self, e: &std::rc::Rc<super::elements::Element>) { }
}

enum WhatToAwait {
    Block,
    TimecodeScale,
    ClusterTimecode,
    Nothing,
}

pub struct MatroskaDemuxer<H: MatroskaEventHandler> {
    h: H,
    timecode_scale: u64,
    last_cluster_timecode: u64,
    a: WhatToAwait,
    b: Vec<u8>,
}

impl<H: MatroskaEventHandler> MidlevelEventHandler for MatroskaDemuxer<H> {
  fn event(&mut self, e: MidlevelEvent) -> () {
    match e {
        MidlevelEvent::EnterElement(c) => {
            self.b.clear();
            match c {
                Class::SimpleBlock => self.a = WhatToAwait::Block,
                Class::Block => self.a = WhatToAwait::Block,
                Class::TimecodeScale => self.a = WhatToAwait::TimecodeScale,
                Class::Timecode => self.a = WhatToAwait::ClusterTimecode,
                _ => {self.a = WhatToAwait::Nothing},
            }
        },
        MidlevelEvent::Content(x) => {
            match self.a {
                WhatToAwait::TimecodeScale => {
                    match x {
                        SimpleContent::Unsigned(xx) => {
                            self.timecode_scale = xx;
                            info!("Got timecode scale: {}", xx);
                        }
                        _ => { error!("Unexpected type"); }
                    }
                }
                WhatToAwait::ClusterTimecode => {
                    match x {
                        SimpleContent::Unsigned(xx) => {
                            self.last_cluster_timecode = xx;
                            info!("Got cluster timecode: {}", xx);
                        }
                        _ => { error!("Unexpected type"); }
                    }
                }
                WhatToAwait::Block => {
                    match x {
                        SimpleContent::Binary(xx, status) => {
                            self.b.extend(xx);
                            match status {
                                BinaryChunkStatus::Last | BinaryChunkStatus::Full => {
                                    self.process_frame();
                                }
                                _ => {},
                            }
                        }
                        _ => { error!("Unexpected type"); }
                    }
                }
                _ => {},
            }
        },
        MidlevelEvent::LeaveElement(_) => {},
        MidlevelEvent::Element(e) => {
            match e.class {
                Class::Info => self.h.segment_info(&e),
                Class::Tracks => self.h.segment_tracks(&e),
                _ => warn!("This code line should not be reachable"),
            }
        },
        MidlevelEvent::Resync => {
            warn!("Resynging matroska parser")
            // TODO: report to user
        },
    }
  }
  fn how_to_handle(&mut self, c: Class) -> WhatToDo {
    match c {
        Class::Info => WhatToDo::Build,
        Class::Tracks => WhatToDo::Build,
        _ => WhatToDo::GoOn,
    }
  }
}

impl<H: MatroskaEventHandler> MatroskaDemuxer<H> {
    pub fn new(h: H) -> Self {
        MatroskaDemuxer {
            h,
            timecode_scale: 1000_000,
            last_cluster_timecode: 0,
            a: WhatToAwait::Nothing,
            b: vec![],
        }
    }

    fn process_frame(&mut self) {
        let mut b  = (&self.b).into_buf();

        let tn_ = b.get_u8();
        if tn_ & 0x80 != 0x80 {
            error!("large track numbers not supported");
            return;
        }
        let tn = tn_ & 0x7F;

        let ts = b.get_i16_be();

        let flags = b.get_u8();

        if flags&0x06 != 0x00 {
            error!("lacing not supported yet");
        }

        // TODO: extract more info from flags and report it to user

        // TODO: to it properly
        let mut ts_nano = ((self.last_cluster_timecode as i64) + (ts as i64)) as u64;
        ts_nano = ((ts_nano as f64) * (self.timecode_scale as f64)) as u64;

        let remaining: Vec<u8> = b.collect();

        let f = MatroskaFrame {
            timecode_nanoseconds : ts_nano,
            track_number: tn as usize,
            buffers: vec![remaining],
        };

        self.h.frame_encountered(f);
    }
}
<|endoftext|>


<commit_before>extern crate tempfile;

use std::fmt::{ Display, Formatter, Error };
use std::iter::Iterator;
use std::collections::HashMap;
use std::collections::HashSet;
use std::vec::Vec;
use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;

use std::clone::Clone;

/**
 * test can be deleted.
 * clauses will house all clauses, key is int so that we can use occurrences
 * ID for simplifications later
 * occurrences tracks which clauses literals are used in
 */
#[derive(Debug)]
pub struct CNF {
    pub nvar        : i32,
    pub nclause     : i32,
    pub clauses     : HashMap<i32, Vec<i32>>,
    pub occurrences : HashMap<i32, Vec<i32>>,
    pub units       : HashSet<i32>
}

impl CNF {
    pub fn new(nvar: i32, nclause: i32) -> CNF {
        CNF {
            nvar        : nvar,
            nclause     : nclause,
            clauses     : HashMap::new(),
            occurrences : HashMap::new(),
            units       : HashSet::new(),
        }
    }

    // Add a clause, return the ID of the inserted clause
    fn add_clause(&mut self, clause : Vec<i32>) -> i32 {
        assert!(clause.len() > 0);
        let id : i32 = self.clauses.len() as i32;
        if clause.len() == 1 { self.units.insert(id); }
        for var in &clause {
            let occ = self.occurrences.entry(*var).or_insert(Vec::new());
            occ.push(id);
        }
        self.clauses.insert(id, clause);
        id
    }
}

impl Clone for CNF {
    fn clone(&self) -> CNF {
        CNF {
            nvar        : self.nvar,
            nclause     : self.nclause,
            clauses     : self.clauses.clone(),
            occurrences : self.occurrences.clone(),
            units        : self.units.clone()
        }
    }
}

impl Display for CNF {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        let formatted = format!("Nvar: {:?} Nclause: {:?}\nClauses: {:?}\nOccurrrences: {:?}",
                self.nvar, self.nclause,
                self.clauses, self.occurrences);
        write!(f, "{}", formatted)
    }
}

// End CNF

// Begin Assignemnts

pub type Assignment = Vec<bool>;

pub struct PartialAssignment {
    pub assignment : Vec<Option<bool>>,
    pub unassigned : HashSet<i32>,
}

impl PartialAssignment {
    pub fn new(n : usize) -> PartialAssignment {
        PartialAssignment {
            assignment : vec!(None; n),
            unassigned : (0..n as i32).collect(),
        }
    }

    pub fn assign(&mut self, v : usize, assn : bool) {
        // TODO: Error check
        self.assignment[v] = Some(assn);
    }

    pub fn unassign(&mut self, v : usize) {
        self.assignment[v] = None;
    }
}

// TODO: Implement Display
impl Display for PartialAssignment {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        let formatted = format!("Assignemnts: {:?}\nUnassigned: {:?}",
                self.assignment, self.unassigned);
        write!(f, "{}", formatted)
    }
}

// End Assignments

// Begin Parsing

// TODO: rename to from_dimacs or somehow isolate parsing
fn parse_dimacs(reader: &mut BufReader<File>) -> Result<CNF, &'static str> {
    let mut line_iterator = reader.lines();

    let mut nvar: i32 = -1;
    let mut nclause: i32 = -1;
    // DIMACS file must have a problem statement before other lines.
    // This first loop searches for the problem statement.
    for line in &mut line_iterator {
        let line = line.expect("could not read file");  // Unwrap result
        let words: Vec<&str> = line.split_whitespace().collect();
        if words.len() == 0 { continue; } // Ignore empty lines
        match words[0] {
            "c" => { }
            "p" => { // Problem statement
                // Must have format "p cnf nvar nclause"
                if words.len() != 4 || words[1] != "cnf" {
                    return Err("invalid problem statement");
                }
                nvar = words[2].parse()
                    .expect(&format!("invalid number of variables {}", words[2]));
                nclause = words[3].parse()
                    .expect(&format!("invalid number of clauses {}", words[3]));
                break;
            }
            // TODO: Add words[0] to this error message
            _ => { return Err("unknown statement beginning"); }
        }
    }
    // Then nvar, nclause were never initialized
    if nvar == -1 || nclause == -1 {
       return Err("no problem statement found");
    }
    // TODO: Different errors for different descriptions (hence why I've split up this if
    // statement)
    if nvar == 0 || nclause == 0 {
        return Err("invalid number of literals in problem")
    }

    // Initialize CNF and parse the rest of the file
    let mut cnf = CNF::new(nvar, nclause);
    let mut clauses_read: i32 = 0;
    for line in &mut line_iterator {
        let line = line.unwrap();
        let words: Vec<&str> = line.split_whitespace().collect();
        if words.len() == 0 { continue; }
        match words[0] {
            "c" => { }
            "p" => { return Err("duplicate problem statement"); }
            _   => {
                clauses_read = clauses_read + 1;
                if clauses_read > nclause { return Err("too many clauses in file"); }
                let tokens: Vec<i32> = words.iter()
                    .filter_map(|s| {
                        let n = s.parse::<i32>().unwrap();
                        // FIXME: This ignores zeros not just as line enders but in the formulas
                        // themselves. Split on zeros at the end here.
                        if n == 0 { return None; }
                        // FIXME: This should return an error instead of
                        // panicking, but I can't return an error
                        // in a closure
                        if n > nvar { panic!("variable out of range: {}", n); }
                        Some(if n < 0 { (-n) << 1 | 1 } else { n << 1 })
                    })
                    .collect();
                cnf.add_clause(tokens);
            }
        }
    }
    // Double check that the number of clauses read is equal
    if clauses_read != nclause { return Err("too few clauses in file"); }
    Ok(cnf)
}

pub fn parse_dimacs_file(f: File) -> Result<CNF, &'static str> {
    // Read the file
    let mut reader = BufReader::new(f);

    // TODO: This is definitely not the correct way to handle errors.
    // Should parse_dimacs have options for returning an error AND panicking?
    let line = parse_dimacs(&mut reader);
    line
}

#[cfg(test)]
mod tests {
    extern crate tempfile;
    use std::fs::File;
    use std::io::prelude::*;
    use std::io::SeekFrom;

    use super::parse_dimacs_file;

    macro_rules! create_tempfile {
        ($x: expr) => {{
            let mut tmpfile: File = tempfile::tempfile().unwrap();
            let _ = write!(tmpfile, $x);
            tmpfile.seek(SeekFrom::Start(0)).unwrap();

            tmpfile
        }};
    }

    #[test]
    #[should_panic(expected = "out of range")]
    fn variable_out_of_range() {
        let tmpfile = create_tempfile!("
            p cnf 2 3
            1 2 0
            4 1 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "invalid number")]
    fn invalid_nvar() {
        let tmpfile = create_tempfile!("
            p cnf gd 3
            1 2 0
            4 1 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "invalid number")]
    fn invalid_nclause() {
        let tmpfile = create_tempfile!("
            p cnf 2 gdd
            1 2 0
            4 1 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "too many")]
    fn too_many_clauses() {
        let tmpfile = create_tempfile!("
            p cnf 5 5
            1 2 0
            2 3 0
            3 4 0
            4 5 0
            1 3 0
            2 4 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "too few")]
    fn too_little_clauses() {
        let tmpfile = create_tempfile!("
            p cnf 5 5
            1 2 0
            2 3 0
            3 4 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    fn should_work() {
        let tmpfile = create_tempfile!("
            p cnf 3 3
            1 2 0
            2 3 0
            1 -3 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    fn should_ignore_comments() {
        let tmpfile = create_tempfile!("
            c comment
            p cnf 3 3
            c comment
            1 2 0
            2 3 0
            c comment
            1 -3 0
            c comment
            c comment
            c comment
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "duplicate problem")]
    fn duplicate_problem_statement() {
        let tmpfile = create_tempfile!("
            p cnf 3 3
            1 2 0
            p cnf 3 3
            2 3 0
            1 -3 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "duplicate problem")]
    fn duplicate_problem_statement_2() {
        let tmpfile = create_tempfile!("
            p cnf 3 3
            p cnf 3 3
            1 2 0
            2 3 0
            1 -3 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    fn adds_unit_clauses() {
        let tmpfile = create_tempfile!("
            p cnf 3 4
            1 0
            2 0
            3 0
            -1 -3 0
        ");
        let cnf = parse_dimacs_file(tmpfile).unwrap();
        assert_eq!(cnf.units.len(), 3);
    }
}
<commit_msg>Whoops<commit_after>extern crate tempfile;

use std::fmt::{ Display, Formatter, Error };
use std::iter::Iterator;
use std::collections::HashMap;
use std::collections::HashSet;
use std::vec::Vec;
use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;

use std::clone::Clone;

/**
 * test can be deleted.
 * clauses will house all clauses, key is int so that we can use occurrences
 * ID for simplifications later
 * occurrences tracks which clauses literals are used in
 */
#[derive(Debug)]
pub struct CNF {
    pub nvar        : i32,
    pub nclause     : i32,
    pub clauses     : HashMap<i32, Vec<i32>>,
    pub occurrences : HashMap<i32, Vec<i32>>,
    pub units       : HashSet<i32>
}

impl CNF {
    pub fn new(nvar: i32, nclause: i32) -> CNF {
        CNF {
            nvar        : nvar,
            nclause     : nclause,
            clauses     : HashMap::new(),
            occurrences : HashMap::new(),
            units       : HashSet::new(),
        }
    }

    // Add a clause, return the ID of the inserted clause
    fn add_clause(&mut self, clause : Vec<i32>) -> i32 {
        assert!(clause.len() > 0);
        let id : i32 = self.clauses.len() as i32;
        if clause.len() == 1 { self.units.insert(id); }
        for var in &clause {
            let occ = self.occurrences.entry(*var).or_insert(Vec::new());
            occ.push(id);
        }
        self.clauses.insert(id, clause);
        id
    }
}

impl Clone for CNF {
    fn clone(&self) -> CNF {
        CNF {
            nvar        : self.nvar,
            nclause     : self.nclause,
            clauses     : self.clauses.clone(),
            occurrences : self.occurrences.clone(),
            units       : self.units.clone()
        }
    }
}

impl Display for CNF {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        let formatted = format!("Nvar: {:?} Nclause: {:?}\nClauses: {:?}\nOccurrrences: {:?}",
                self.nvar, self.nclause,
                self.clauses, self.occurrences);
        write!(f, "{}", formatted)
    }
}

// End CNF

// Begin Assignemnts

pub type Assignment = Vec<bool>;

pub struct PartialAssignment {
    pub assignment : Vec<Option<bool>>,
    pub unassigned : HashSet<i32>,
}

impl PartialAssignment {
    pub fn new(n : usize) -> PartialAssignment {
        PartialAssignment {
            assignment : vec!(None; n),
            unassigned : (0..n as i32).collect(),
        }
    }

    pub fn assign(&mut self, v : usize, assn : bool) {
        // TODO: Error check
        self.assignment[v] = Some(assn);
    }

    pub fn unassign(&mut self, v : usize) {
        self.assignment[v] = None;
    }
}

// TODO: Implement Display
impl Display for PartialAssignment {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        let formatted = format!("Assignemnts: {:?}\nUnassigned: {:?}",
                self.assignment, self.unassigned);
        write!(f, "{}", formatted)
    }
}

// End Assignments

// Begin Parsing

// TODO: rename to from_dimacs or somehow isolate parsing
fn parse_dimacs(reader: &mut BufReader<File>) -> Result<CNF, &'static str> {
    let mut line_iterator = reader.lines();

    let mut nvar: i32 = -1;
    let mut nclause: i32 = -1;
    // DIMACS file must have a problem statement before other lines.
    // This first loop searches for the problem statement.
    for line in &mut line_iterator {
        let line = line.expect("could not read file");  // Unwrap result
        let words: Vec<&str> = line.split_whitespace().collect();
        if words.len() == 0 { continue; } // Ignore empty lines
        match words[0] {
            "c" => { }
            "p" => { // Problem statement
                // Must have format "p cnf nvar nclause"
                if words.len() != 4 || words[1] != "cnf" {
                    return Err("invalid problem statement");
                }
                nvar = words[2].parse()
                    .expect(&format!("invalid number of variables {}", words[2]));
                nclause = words[3].parse()
                    .expect(&format!("invalid number of clauses {}", words[3]));
                break;
            }
            // TODO: Add words[0] to this error message
            _ => { return Err("unknown statement beginning"); }
        }
    }
    // Then nvar, nclause were never initialized
    if nvar == -1 || nclause == -1 {
       return Err("no problem statement found");
    }
    // TODO: Different errors for different descriptions (hence why I've split up this if
    // statement)
    if nvar == 0 || nclause == 0 {
        return Err("invalid number of literals in problem")
    }

    // Initialize CNF and parse the rest of the file
    let mut cnf = CNF::new(nvar, nclause);
    let mut clauses_read: i32 = 0;
    for line in &mut line_iterator {
        let line = line.unwrap();
        let words: Vec<&str> = line.split_whitespace().collect();
        if words.len() == 0 { continue; }
        match words[0] {
            "c" => { }
            "p" => { return Err("duplicate problem statement"); }
            _   => {
                clauses_read = clauses_read + 1;
                if clauses_read > nclause { return Err("too many clauses in file"); }
                let tokens: Vec<i32> = words.iter()
                    .filter_map(|s| {
                        let n = s.parse::<i32>().unwrap();
                        // FIXME: This ignores zeros not just as line enders but in the formulas
                        // themselves. Split on zeros at the end here.
                        if n == 0 { return None; }
                        // FIXME: This should return an error instead of
                        // panicking, but I can't return an error
                        // in a closure
                        if n > nvar { panic!("variable out of range: {}", n); }
                        Some(if n < 0 { (-n) << 1 | 1 } else { n << 1 })
                    })
                    .collect();
                cnf.add_clause(tokens);
            }
        }
    }
    // Double check that the number of clauses read is equal
    if clauses_read != nclause { return Err("too few clauses in file"); }
    Ok(cnf)
}

pub fn parse_dimacs_file(f: File) -> Result<CNF, &'static str> {
    // Read the file
    let mut reader = BufReader::new(f);

    // TODO: This is definitely not the correct way to handle errors.
    // Should parse_dimacs have options for returning an error AND panicking?
    let line = parse_dimacs(&mut reader);
    line
}

#[cfg(test)]
mod tests {
    extern crate tempfile;
    use std::fs::File;
    use std::io::prelude::*;
    use std::io::SeekFrom;

    use super::parse_dimacs_file;

    macro_rules! create_tempfile {
        ($x: expr) => {{
            let mut tmpfile: File = tempfile::tempfile().unwrap();
            let _ = write!(tmpfile, $x);
            tmpfile.seek(SeekFrom::Start(0)).unwrap();

            tmpfile
        }};
    }

    #[test]
    #[should_panic(expected = "out of range")]
    fn variable_out_of_range() {
        let tmpfile = create_tempfile!("
            p cnf 2 3
            1 2 0
            4 1 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "invalid number")]
    fn invalid_nvar() {
        let tmpfile = create_tempfile!("
            p cnf gd 3
            1 2 0
            4 1 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "invalid number")]
    fn invalid_nclause() {
        let tmpfile = create_tempfile!("
            p cnf 2 gdd
            1 2 0
            4 1 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "too many")]
    fn too_many_clauses() {
        let tmpfile = create_tempfile!("
            p cnf 5 5
            1 2 0
            2 3 0
            3 4 0
            4 5 0
            1 3 0
            2 4 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "too few")]
    fn too_little_clauses() {
        let tmpfile = create_tempfile!("
            p cnf 5 5
            1 2 0
            2 3 0
            3 4 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    fn should_work() {
        let tmpfile = create_tempfile!("
            p cnf 3 3
            1 2 0
            2 3 0
            1 -3 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    fn should_ignore_comments() {
        let tmpfile = create_tempfile!("
            c comment
            p cnf 3 3
            c comment
            1 2 0
            2 3 0
            c comment
            1 -3 0
            c comment
            c comment
            c comment
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "duplicate problem")]
    fn duplicate_problem_statement() {
        let tmpfile = create_tempfile!("
            p cnf 3 3
            1 2 0
            p cnf 3 3
            2 3 0
            1 -3 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "duplicate problem")]
    fn duplicate_problem_statement_2() {
        let tmpfile = create_tempfile!("
            p cnf 3 3
            p cnf 3 3
            1 2 0
            2 3 0
            1 -3 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    fn adds_unit_clauses() {
        let tmpfile = create_tempfile!("
            p cnf 3 4
            1 0
            2 0
            3 0
            -1 -3 0
        ");
        let cnf = parse_dimacs_file(tmpfile).unwrap();
        assert_eq!(cnf.units.len(), 3);
    }
}
<|endoftext|>


<commit_before>use super::Encoder;
use flowgger::config::Config;
use flowgger::record::{Record, SDValue};
use serde_json;
use serde_json::builder::ObjectBuilder;
use serde_json::value::Value;

#[derive(Clone)]
pub struct GelfEncoder {
    extra: Vec<(String, String)>,
}

impl GelfEncoder {
    pub fn new(config: &Config) -> GelfEncoder {
        let extra = match config.lookup("output.gelf_extra") {
            None => Vec::new(),
            Some(extra) => extra
                .as_table()
                .expect("output.gelf_extra must be a list of key/value pairs")
                .into_iter()
                .map(|(k, v)| {
                    (
                        k.to_owned(),
                        v.as_str()
                            .expect("output.gelf_extra values must be strings")
                            .to_owned(),
                    )
                }).collect(),
        };
        GelfEncoder { extra: extra }
    }
}

impl Encoder for GelfEncoder {
    fn encode(&self, record: Record) -> Result<Vec<u8>, &'static str> {
        let mut map = ObjectBuilder::new()
            .insert("version".to_owned(), Value::String("1.1".to_owned()))
            .insert(
                "host".to_owned(),
                Value::String(record.hostname.unwrap_or_else(|| "unknown".to_owned())),
            ).insert(
                "short_message".to_owned(),
                Value::String(record.msg.unwrap_or_else(|| "-".to_owned())),
            ).insert("timestamp".to_owned(), Value::F64(record.ts));
        if let Some(severity) = record.severity {
            map = map.insert("level".to_owned(), Value::U64(u64::from(severity)));
        }
        if let Some(full_msg) = record.full_msg {
            map = map.insert("full_message".to_owned(), Value::String(full_msg));
        }
        if let Some(appname) = record.appname {
            map = map.insert("application_name".to_owned(), Value::String(appname));
        }
        if let Some(procid) = record.procid {
            map = map.insert("process_id".to_owned(), Value::String(procid));
        }
        for (name, value) in self.extra.iter().cloned() {
            map = map.insert(name, Value::String(value));
        }
        if let Some(sd) = record.sd {
            if let Some(sd_id) = sd.sd_id {
                map = map.insert("sd_id".to_owned(), Value::String(sd_id));
            }
            for (name, value) in sd.pairs {
                let value = match value {
                    SDValue::String(value) => Value::String(value),
                    SDValue::Bool(value) => Value::Bool(value),
                    SDValue::F64(value) => Value::F64(value),
                    SDValue::I64(value) => Value::I64(value),
                    SDValue::U64(value) => Value::U64(value),
                    SDValue::Null => Value::Null,
                };
                map = map.insert(name, value);
            }
        }
        let json = serde_json::to_vec(&map.build()).or(Err("Unable to serialize to JSON"))?;
        Ok(json)
    }
}
<commit_msg>unwrap_or_else() obviously won't work on a string<commit_after>use super::Encoder;
use flowgger::config::Config;
use flowgger::record::{Record, SDValue};
use serde_json;
use serde_json::builder::ObjectBuilder;
use serde_json::value::Value;

#[derive(Clone)]
pub struct GelfEncoder {
    extra: Vec<(String, String)>,
}

impl GelfEncoder {
    pub fn new(config: &Config) -> GelfEncoder {
        let extra = match config.lookup("output.gelf_extra") {
            None => Vec::new(),
            Some(extra) => extra
                .as_table()
                .expect("output.gelf_extra must be a list of key/value pairs")
                .into_iter()
                .map(|(k, v)| {
                    (
                        k.to_owned(),
                        v.as_str()
                            .expect("output.gelf_extra values must be strings")
                            .to_owned(),
                    )
                }).collect(),
        };
        GelfEncoder { extra: extra }
    }
}

impl Encoder for GelfEncoder {
    fn encode(&self, record: Record) -> Result<Vec<u8>, &'static str> {
        let mut map = ObjectBuilder::new()
            .insert("version".to_owned(), Value::String("1.1".to_owned()))
            .insert(
                "host".to_owned(),
                Value::String(if record.hostname.is_empty() {
                    "unknown".to_owned()
                } else {
                    record.hostname
                }),
            ).insert(
                "short_message".to_owned(),
                Value::String(record.msg.unwrap_or_else(|| "-".to_owned())),
            ).insert("timestamp".to_owned(), Value::F64(record.ts));
        if let Some(severity) = record.severity {
            map = map.insert("level".to_owned(), Value::U64(u64::from(severity)));
        }
        if let Some(full_msg) = record.full_msg {
            map = map.insert("full_message".to_owned(), Value::String(full_msg));
        }
        if let Some(appname) = record.appname {
            map = map.insert("application_name".to_owned(), Value::String(appname));
        }
        if let Some(procid) = record.procid {
            map = map.insert("process_id".to_owned(), Value::String(procid));
        }
        for (name, value) in self.extra.iter().cloned() {
            map = map.insert(name, Value::String(value));
        }
        if let Some(sd) = record.sd {
            if let Some(sd_id) = sd.sd_id {
                map = map.insert("sd_id".to_owned(), Value::String(sd_id));
            }
            for (name, value) in sd.pairs {
                let value = match value {
                    SDValue::String(value) => Value::String(value),
                    SDValue::Bool(value) => Value::Bool(value),
                    SDValue::F64(value) => Value::F64(value),
                    SDValue::I64(value) => Value::I64(value),
                    SDValue::U64(value) => Value::U64(value),
                    SDValue::Null => Value::Null,
                };
                map = map.insert(name, value);
            }
        }
        let json = serde_json::to_vec(&map.build()).or(Err("Unable to serialize to JSON"))?;
        Ok(json)
    }
}
<|endoftext|>