<commit_before>use byteorder::{BigEndian, ByteOrder};
use bytes::{BufMut, Bytes, BytesMut};
use shannon::Shannon;
use std::io;
use tokio_io::codec::{Decoder, Encoder};

const HEADER_SIZE: usize = 3;
const MAC_SIZE: usize = 4;

#[derive(Debug)]
enum DecodeState {
    Header,
    Payload(u8, usize),
}

pub struct APCodec {
    encode_nonce: u32,
    encode_cipher: Shannon,

    decode_nonce: u32,
    decode_cipher: Shannon,
    decode_state: DecodeState,
}

impl APCodec {
    pub fn new(send_key: &[u8], recv_key: &[u8]) -> APCodec {
        APCodec {
            encode_nonce: 0,
            encode_cipher: Shannon::new(send_key),

            decode_nonce: 0,
            decode_cipher: Shannon::new(recv_key),
            decode_state: DecodeState::Header,
        }
    }
}

impl Encoder for APCodec {
    type Item = (u8, Vec<u8>);
    type Error = io::Error;

    fn encode(&mut self, item: (u8, Vec<u8>), buf: &mut BytesMut) -> io::Result<()> {
        let (cmd, payload) = item;
        let offset = buf.len();

        buf.reserve(3 + payload.len());
        buf.put_u8(cmd);
        buf.put_u16::<BigEndian>(payload.len() as u16);
        buf.extend_from_slice(&payload);

        self.encode_cipher.nonce_u32(self.encode_nonce);
        self.encode_nonce += 1;

        self.encode_cipher.encrypt(&mut buf[offset..]);

        let mut mac = [0u8; MAC_SIZE];
        self.encode_cipher.finish(&mut mac);
        buf.extend_from_slice(&mac);

        Ok(())
    }
}

impl Decoder for APCodec {
    type Item = (u8, Bytes);
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<(u8, Bytes)>> {
        if let DecodeState::Header = self.decode_state {
            if buf.len() >= HEADER_SIZE {
                let mut header = [0u8; HEADER_SIZE];
                header.copy_from_slice(buf.split_to(HEADER_SIZE).as_ref());

                self.decode_cipher.nonce_u32(self.decode_nonce);
                self.decode_nonce += 1;

                self.decode_cipher.decrypt(&mut header);

                let cmd = header[0];
                let size = BigEndian::read_u16(&header[1..]) as usize;
                self.decode_state = DecodeState::Payload(cmd, size);
            }
        }

        if let DecodeState::Payload(cmd, size) = self.decode_state {
            if buf.len() >= size + MAC_SIZE {
                self.decode_state = DecodeState::Header;

                let mut payload = buf.split_to(size + MAC_SIZE);

                self.decode_cipher.decrypt(&mut payload.get_mut(..size).unwrap());
                let mac = payload.split_off(size);
                self.decode_cipher.check_mac(mac.as_ref())?;

                return Ok(Some((cmd, payload.freeze())));
            }
        }

        Ok(None)
    }
}
<commit_msg>fix deprecation warning for bytes<commit_after>use byteorder::{BigEndian, ByteOrder};
use bytes::{BufMut, Bytes, BytesMut};
use shannon::Shannon;
use std::io;
use tokio_io::codec::{Decoder, Encoder};

const HEADER_SIZE: usize = 3;
const MAC_SIZE: usize = 4;

#[derive(Debug)]
enum DecodeState {
    Header,
    Payload(u8, usize),
}

pub struct APCodec {
    encode_nonce: u32,
    encode_cipher: Shannon,

    decode_nonce: u32,
    decode_cipher: Shannon,
    decode_state: DecodeState,
}

impl APCodec {
    pub fn new(send_key: &[u8], recv_key: &[u8]) -> APCodec {
        APCodec {
            encode_nonce: 0,
            encode_cipher: Shannon::new(send_key),

            decode_nonce: 0,
            decode_cipher: Shannon::new(recv_key),
            decode_state: DecodeState::Header,
        }
    }
}

impl Encoder for APCodec {
    type Item = (u8, Vec<u8>);
    type Error = io::Error;

    fn encode(&mut self, item: (u8, Vec<u8>), buf: &mut BytesMut) -> io::Result<()> {
        let (cmd, payload) = item;
        let offset = buf.len();

        buf.reserve(3 + payload.len());
        buf.put_u8(cmd);
        buf.put_u16_be(payload.len() as u16);
        buf.extend_from_slice(&payload);

        self.encode_cipher.nonce_u32(self.encode_nonce);
        self.encode_nonce += 1;

        self.encode_cipher.encrypt(&mut buf[offset..]);

        let mut mac = [0u8; MAC_SIZE];
        self.encode_cipher.finish(&mut mac);
        buf.extend_from_slice(&mac);

        Ok(())
    }
}

impl Decoder for APCodec {
    type Item = (u8, Bytes);
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<(u8, Bytes)>> {
        if let DecodeState::Header = self.decode_state {
            if buf.len() >= HEADER_SIZE {
                let mut header = [0u8; HEADER_SIZE];
                header.copy_from_slice(buf.split_to(HEADER_SIZE).as_ref());

                self.decode_cipher.nonce_u32(self.decode_nonce);
                self.decode_nonce += 1;

                self.decode_cipher.decrypt(&mut header);

                let cmd = header[0];
                let size = BigEndian::read_u16(&header[1..]) as usize;
                self.decode_state = DecodeState::Payload(cmd, size);
            }
        }

        if let DecodeState::Payload(cmd, size) = self.decode_state {
            if buf.len() >= size + MAC_SIZE {
                self.decode_state = DecodeState::Header;

                let mut payload = buf.split_to(size + MAC_SIZE);

                self.decode_cipher.decrypt(&mut payload.get_mut(..size).unwrap());
                let mac = payload.split_off(size);
                self.decode_cipher.check_mac(mac.as_ref())?;

                return Ok(Some((cmd, payload.freeze())));
            }
        }

        Ok(None)
    }
}
<|endoftext|>


<commit_before>//! A parser for lambda expressions

use term::*;
use term::Term::*;
use term::Notation::*;
use self::Token::*;
use self::CToken::*;
use self::Error::*;
use self::Expression::*;

/// A type to represent a parsing error.
#[derive(Debug, PartialEq)]
pub enum Error {
    InvalidCharacter((usize, char)),
    InvalidExpression,
    EmptyExpression
}

#[derive(Debug, PartialEq)]
enum Token {
    Lambda,
    Lparen,
    Rparen,
    Number(usize)
}

#[derive(Debug, PartialEq)]
enum CToken {
    CLambda(String),
    CLparen,
    CRparen,
    CName(String)
}

fn tokenize(input: &str) -> Result<Vec<Token>, Error> {
    let mut chars = input.chars();
    let mut tokens = Vec::new();
    let mut position = 0;

    while let Some(c) = chars.next() {
        match c {
     '\\' | 'λ' => { tokens.push(Lambda) },
            '(' => { tokens.push(Lparen) },
            ')' => { tokens.push(Rparen) },
             x  => {
                if let Some(n) = x.to_digit(16) {
                    tokens.push(Number(n as usize))
                } else if x.is_whitespace() {
                    ()
                } else {
                    return Err(InvalidCharacter((position, x)))
                }
            }
        }
        position += if c == 'λ' { 2 } else { 1 };
    }

    Ok(tokens)
}

fn tokenize_classic(input: &str) -> Result<Vec<CToken>, Error> {
    let mut chars = input.chars().peekable();
    let mut tokens = Vec::new();
    let mut position = 0;

    while let Some(c) = chars.next() {
        match c {
            '\\' | 'λ' => {
                let mut name = String::new();
                while let Some(c) = chars.next() {
                    if c == '.' {
                        break
                    } else if "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".contains(c) {
                        name.push(c)
                    } else {
                        return Err(InvalidCharacter((position, c)))
                    }
                    position += 1;
                }
                tokens.push(CLambda(name))
            },
            '(' => { tokens.push(CLparen) },
            ')' => { tokens.push(CRparen) },
             x  => {
                if x.is_whitespace() {
                    ()
                } else if "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".contains(x) {
                    let mut name = x.to_string();
                    while let Some(&c) = chars.peek() {
                        if c.is_whitespace() || c == '(' || c == ')' {
                            break
                        } else {
                            name.push(c);
                            chars.next();
                        }
                        position += 1;
                    }
                    tokens.push(CName(name))
                } else {
                    return Err(InvalidCharacter((position, x)))
                }
            }
        }
        position += if c == 'λ' { 2 } else { 1 };
    }

    Ok(tokens)
}

fn convert_classic_tokens(tokens: &[CToken]) -> Vec<Token> {
    let mut stack = Vec::new();
    let mut pos = 0;

    _convert_classic_tokens(tokens, &mut stack, &mut pos)
}

fn _convert_classic_tokens(tokens: &[CToken], stack: &mut Vec<String>, pos: &mut usize) -> Vec<Token>
{
    let mut output = Vec::new();
    let mut inner_stack_count = 0;

    while *pos < tokens.len() {
        match tokens[*pos] {
            CLambda(ref name) => {
                output.push(Lambda);
                stack.push(name.clone());
                inner_stack_count += 1;
            },
            CLparen => {
                output.push(Lparen);
                *pos += 1;
                output.append(&mut _convert_classic_tokens(tokens, stack, pos));
            },
            CRparen => {
                output.push(Rparen);
                for _ in 0..inner_stack_count { stack.pop(); }
                return output
            },
            CName(ref name) => {
                let number = if stack.contains(name) {
                    stack.iter().rev().position(|t| t == name).unwrap() + 1
                } else {
                    stack.len() + 1
                };
                output.push(Number(number));
            }
        }
        *pos += 1;
    }

    output
}

#[derive(Debug, PartialEq)]
enum Expression {
    Abstraction,
    Sequence(Vec<Expression>),
    Variable(usize)
}

fn _get_ast(tokens: &[Token], pos: &mut usize) -> Result<Expression, Error> {
    let mut expr = Vec::new();

    if tokens.is_empty() { return Err(EmptyExpression) }

    while *pos < tokens.len() {
        match tokens[*pos] {
            Lambda => {
                expr.push(Abstraction)
            },
            Number(i) => {
                expr.push(Variable(i))
            },
            Lparen => {
                *pos += 1;
                let subtree = try!(_get_ast(&tokens, pos));
                expr.push(subtree);
            },
            Rparen => {
                return Ok(Sequence(expr))
            }
        }
        *pos += 1;
    }

    Ok(Sequence(expr))
}

fn get_ast(tokens: &[Token]) -> Result<Expression, Error> {
    let mut pos = 0;

    _get_ast(tokens, &mut pos)
}

/// Parses the input `&str` as a lambda `Term`.
///
/// - lambdas can be represented either with the greek letter (λ) or a backslash (\\ -
/// less aesthetic, but only one byte in size)
/// - the identifiers in `Classic` mode are `String`s of ASCII alphabetic characters
/// - `Classic` mode ignores whitespaces where unambiguous
/// - `DeBruijn` mode ignores all whitespaces (since indices > 15 are very unlikely)
/// - the indices in the `DeBruijn` notation mode start with 1 and are hexadecimal digits
///
/// # Example
/// ```
/// use lambda_calculus::parser::parse;
/// use lambda_calculus::term::Notation::*;
/// use lambda_calculus::arithmetic::{succ, pred};
///
/// assert_eq!(parse(&"λn. λf. λx. n (λg. λh. h (g f)) (λu. x) (λu. u)", Classic), Ok(pred()));
/// assert_eq!(parse(&"λn.λf.λx.n(λg.λh.h(g f))(λu.x)(λu.u)", Classic), Ok(pred()));
///
/// assert_eq!(parse(  &"λλλ2(321)",  DeBruijn), Ok(succ()));
/// assert_eq!(parse(&r#"\\\2(321)"#, DeBruijn), Ok(succ()));
/// ```
pub fn parse(input: &str, notation: Notation) -> Result<Term, Error> {
    let tokens = if notation == DeBruijn {
        try!(tokenize(input))
    } else {
        convert_classic_tokens(&try!(tokenize_classic(input)))
    };
    let ast = try!(get_ast(&tokens));

    let exprs = try!(if let Sequence(exprs) = ast { Ok(exprs) } else { Err(InvalidExpression) });

    let mut stack = Vec::new();
    let mut output = Vec::new();
    let term = fold_exprs(&exprs, &mut stack, &mut output);

    term
}

fn fold_exprs(exprs: &[Expression], stack: &mut Vec<Expression>, output: &mut Vec<Term>)
    -> Result<Term, Error>
{
    let mut iter = exprs.into_iter();

    while let Some(ref expr) = iter.next() {
        match **expr {
            Variable(i) => output.push(Var(i)),
            Abstraction => stack.push(Abstraction),
            Sequence(ref exprs) => {
                let mut stack2 = Vec::new();
                let mut output2 = Vec::new();
                let subexpr = try!(fold_exprs(&exprs, &mut stack2, &mut output2));
                output.push(subexpr)
            }
        }
    }

    let mut ret = try!(fold_terms(output.drain(..).collect()));

    while let Some(Abstraction) = stack.pop() {
        ret = abs(ret);
    }

    Ok(ret)
}

fn fold_terms(mut terms: Vec<Term>) -> Result<Term, Error> {
    if terms.len() > 1 {
        let fst = terms.remove(0);
        Ok( terms.into_iter().fold(fst, |acc, t| app(acc, t)) )
    } else if terms.len() == 1 {
        Ok( terms.pop().unwrap() )
    } else {
        Err(EmptyExpression)
    }
}

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

    #[test]
    fn tokenization_error() {
        assert_eq!(tokenize(&"λλx2"), Err(InvalidCharacter((4, 'x'))))
    }

    #[test]
    fn tokenization_success() {
        let quine = "λ 1 ( (λ 1 1) (λ λ λ λ λ 1 4 (3 (5 5) 2) ) ) 1";
        let tokens = tokenize(&quine);

        assert!(tokens.is_ok());
        assert_eq!(tokens.unwrap(), vec![Lambda, Number(1), Lparen, Lparen, Lambda, Number(1),
            Number(1), Rparen, Lparen, Lambda, Lambda, Lambda, Lambda, Lambda, Number(1),
            Number(4), Lparen, Number(3), Lparen, Number(5), Number(5), Rparen, Number(2),
            Rparen, Rparen, Rparen, Number(1)]);
    }

    #[test]
    fn tokenization_success_classic() {
        let blc_dbr = "(λ11)(λλλ1(λλλλ3(λ5(3(λ2(3(λλ3(λ123)))(4(λ4(λ31(21))))))(1(2(λ12))\
            (λ4(λ4(λ2(14)))5))))(33)2)(λ1((λ11)(λ11)))";
        let blc_cla = format!("{}", parse(&blc_dbr, DeBruijn).unwrap());

        let tokens_cla = tokenize_classic(&blc_cla);
        let tokens_dbr = tokenize(&blc_dbr);

        assert!(tokens_cla.is_ok());
        assert!(tokens_dbr.is_ok());

        assert_eq!(convert_classic_tokens(&tokens_cla.unwrap()), tokens_dbr.unwrap());
    }

    #[test]
    fn alternative_lambda_parsing() {
        assert_eq!(parse(&"\\\\\\2(321)", DeBruijn), parse(&"λλλ2(321)", DeBruijn))
    }

    #[test]
    fn succ_ast() {
        let tokens = tokenize(&"λλλ2(321)").unwrap();
        let ast = get_ast(&tokens);

        assert_eq!(ast,
            Ok(Sequence(vec![
                Abstraction,
                Abstraction,
                Abstraction,
                Variable(2),
                Sequence(vec![
                    Variable(3),
                    Variable(2),
                    Variable(1)
                ])
            ])
        ));
    }

    #[test]
    fn parse_y() {
        let y = "λ(λ2(11))(λ2(11))";
        assert_eq!(parse(&y, DeBruijn).expect("parsing Y failed!"),
            abs(
                app(
                    abs(
                        app(
                            Var(2),
                            app(Var(1), Var(1))
                        )
                    ),
                    abs(
                        app(
                            Var(2),
                            app(Var(1), Var(1))
                        )
                    )
                )
            )
        );
    }

    #[test]
    fn parse_quine() {
        let quine = "λ1((λ11)(λλλλλ14(3(55)2)))1";
        assert_eq!(parse(&quine, DeBruijn).expect("parsing QUINE failed!"),
            abs(app(app(Var(1), app(abs(app(Var(1), Var(1))), abs(abs(abs(abs(abs(app(app(Var(1),
            Var(4)), app(app(Var(3), app(Var(5), Var(5))), Var(2)))))))))), Var(1)))
        );
    }

    #[test]
    fn parse_blc() {
        let blc = "(λ11)(λλλ1(λλλλ3(λ5(3(λ2(3(λλ3(λ123)))(4(λ4(λ31(21))))))(1(2(λ12))\
                   (λ4(λ4(λ2(14)))5))))(33)2)(λ1((λ11)(λ11)))";
        assert_eq!(parse(&blc, DeBruijn).expect("parsing BLC failed!"),
            app(app(abs(app(Var(1), Var(1))), abs(abs(abs(app(app(app(Var(1),
            abs(abs(abs(abs(app(Var(3), abs(app(app(Var(5), app(Var(3), abs(app(app(Var(2),
            app(Var(3), abs(abs(app(Var(3), abs(app(app(Var(1), Var(2)), Var(3)))))))), app(Var(4),
            abs(app(Var(4), abs(app(app(Var(3), Var(1)), app(Var(2), Var(1))))))))))),
            app(app(Var(1), app(Var(2), abs(app(Var(1), Var(2))))), abs(app(app(Var(4),
            abs(app(Var(4), abs(app(Var(2), app(Var(1), Var(4))))))), Var(5)))))))))))),
            app(Var(3), Var(3))), Var(2)))))), abs(app(Var(1), app(abs(app(Var(1), Var(1))),
            abs(app(Var(1), Var(1)))))))
        );
    }
}
<commit_msg>alter tokenizing functions' names; follow character (not byte) position<commit_after>//! A parser for lambda expressions

use term::*;
use term::Term::*;
use term::Notation::*;
use self::Token::*;
use self::CToken::*;
use self::Error::*;
use self::Expression::*;

/// A type to represent a parsing error.
#[derive(Debug, PartialEq)]
pub enum Error {
    InvalidCharacter((usize, char)),
    InvalidExpression,
    EmptyExpression
}

#[derive(Debug, PartialEq)]
enum Token {
    Lambda,
    Lparen,
    Rparen,
    Number(usize)
}

#[derive(Debug, PartialEq)]
enum CToken {
    CLambda(String),
    CLparen,
    CRparen,
    CName(String)
}

fn tokenize_dbr(input: &str) -> Result<Vec<Token>, Error> {
    let mut chars = input.chars();
    let mut tokens = Vec::new();
    let mut position = 1;

    while let Some(c) = chars.next() {
        match c {
     '\\' | 'λ' => { tokens.push(Lambda) },
            '(' => { tokens.push(Lparen) },
            ')' => { tokens.push(Rparen) },
             x  => {
                if let Some(n) = x.to_digit(16) {
                    tokens.push(Number(n as usize))
                } else if x.is_whitespace() {
                    ()
                } else {
                    return Err(InvalidCharacter((position, x)))
                }
            }
        }
        position += 1;
    }

    Ok(tokens)
}

fn tokenize_cla(input: &str) -> Result<Vec<CToken>, Error> {
    let mut chars = input.chars().peekable();
    let mut tokens = Vec::new();
    let mut position = 1;

    while let Some(c) = chars.next() {
        match c {
            '\\' | 'λ' => {
                let mut name = String::new();
                while let Some(c) = chars.next() {
                    position += 1;
                    if c == '.' {
                        break
                    } else if "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".contains(c) {
                        name.push(c)
                    } else {
                        return Err(InvalidCharacter((position, c)))
                    }
                }
                tokens.push(CLambda(name))
            },
            '(' => { tokens.push(CLparen) },
            ')' => { tokens.push(CRparen) },
             x  => {
                if x.is_whitespace() {
                    ()
                } else if "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".contains(x) {
                    let mut name = x.to_string();
                    while let Some(&c) = chars.peek() {
                        if c.is_whitespace() || c == '(' || c == ')' {
                            break
                        } else {
                            name.push(c);
                            chars.next();
                            position += 1;
                        }
                    }
                    tokens.push(CName(name))
                } else {
                    return Err(InvalidCharacter((position, x)))
                }
            }
        }
        position += 1;
    }

    Ok(tokens)
}

fn convert_classic_tokens(tokens: &[CToken]) -> Vec<Token> {
    let mut stack = Vec::new();
    let mut pos = 0;

    _convert_classic_tokens(tokens, &mut stack, &mut pos)
}

fn _convert_classic_tokens(tokens: &[CToken], stack: &mut Vec<String>, pos: &mut usize) -> Vec<Token>
{
    let mut output = Vec::new();
    let mut inner_stack_count = 0;

    while *pos < tokens.len() {
        match tokens[*pos] {
            CLambda(ref name) => {
                output.push(Lambda);
                stack.push(name.clone());
                inner_stack_count += 1;
            },
            CLparen => {
                output.push(Lparen);
                *pos += 1;
                output.append(&mut _convert_classic_tokens(tokens, stack, pos));
            },
            CRparen => {
                output.push(Rparen);
                for _ in 0..inner_stack_count { stack.pop(); }
                return output
            },
            CName(ref name) => {
                let number = if stack.contains(name) {
                    stack.iter().rev().position(|t| t == name).unwrap() + 1
                } else {
                    stack.len() + 1
                };
                output.push(Number(number));
            }
        }
        *pos += 1;
    }

    output
}

#[derive(Debug, PartialEq)]
enum Expression {
    Abstraction,
    Sequence(Vec<Expression>),
    Variable(usize)
}

fn _get_ast(tokens: &[Token], pos: &mut usize) -> Result<Expression, Error> {
    let mut expr = Vec::new();

    if tokens.is_empty() { return Err(EmptyExpression) }

    while *pos < tokens.len() {
        match tokens[*pos] {
            Lambda => {
                expr.push(Abstraction)
            },
            Number(i) => {
                expr.push(Variable(i))
            },
            Lparen => {
                *pos += 1;
                let subtree = try!(_get_ast(&tokens, pos));
                expr.push(subtree);
            },
            Rparen => {
                return Ok(Sequence(expr))
            }
        }
        *pos += 1;
    }

    Ok(Sequence(expr))
}

fn get_ast(tokens: &[Token]) -> Result<Expression, Error> {
    let mut pos = 0;

    _get_ast(tokens, &mut pos)
}

/// Parses the input `&str` as a lambda `Term`.
///
/// - lambdas can be represented either with the greek letter (λ) or a backslash (\\ -
/// less aesthetic, but only one byte in size)
/// - the identifiers in `Classic` mode are `String`s of ASCII alphabetic characters
/// - `Classic` mode ignores whitespaces where unambiguous
/// - `DeBruijn` mode ignores all whitespaces (since indices > 15 are very unlikely)
/// - the indices in the `DeBruijn` notation mode start with 1 and are hexadecimal digits
///
/// # Example
/// ```
/// use lambda_calculus::parser::parse;
/// use lambda_calculus::term::Notation::*;
/// use lambda_calculus::arithmetic::{succ, pred};
///
/// assert_eq!(parse(&"λn. λf. λx. n (λg. λh. h (g f)) (λu. x) (λu. u)", Classic), Ok(pred()));
/// assert_eq!(parse(&"λn.λf.λx.n(λg.λh.h(g f))(λu.x)(λu.u)", Classic), Ok(pred()));
///
/// assert_eq!(parse(  &"λλλ2(321)",  DeBruijn), Ok(succ()));
/// assert_eq!(parse(&r#"\\\2(321)"#, DeBruijn), Ok(succ()));
/// ```
pub fn parse(input: &str, notation: Notation) -> Result<Term, Error> {
    let tokens = if notation == DeBruijn {
        try!(tokenize_dbr(input))
    } else {
        convert_classic_tokens(&try!(tokenize_cla(input)))
    };
    let ast = try!(get_ast(&tokens));

    let exprs = try!(if let Sequence(exprs) = ast { Ok(exprs) } else { Err(InvalidExpression) });

    let mut stack = Vec::new();
    let mut output = Vec::new();
    let term = fold_exprs(&exprs, &mut stack, &mut output);

    term
}

fn fold_exprs(exprs: &[Expression], stack: &mut Vec<Expression>, output: &mut Vec<Term>)
    -> Result<Term, Error>
{
    let mut iter = exprs.into_iter();

    while let Some(ref expr) = iter.next() {
        match **expr {
            Variable(i) => output.push(Var(i)),
            Abstraction => stack.push(Abstraction),
            Sequence(ref exprs) => {
                let mut stack2 = Vec::new();
                let mut output2 = Vec::new();
                let subexpr = try!(fold_exprs(&exprs, &mut stack2, &mut output2));
                output.push(subexpr)
            }
        }
    }

    let mut ret = try!(fold_terms(output.drain(..).collect()));

    while let Some(Abstraction) = stack.pop() {
        ret = abs(ret);
    }

    Ok(ret)
}

fn fold_terms(mut terms: Vec<Term>) -> Result<Term, Error> {
    if terms.len() > 1 {
        let fst = terms.remove(0);
        Ok( terms.into_iter().fold(fst, |acc, t| app(acc, t)) )
    } else if terms.len() == 1 {
        Ok( terms.pop().unwrap() )
    } else {
        Err(EmptyExpression)
    }
}

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

    #[test]
    fn tokenization_error() {
        assert_eq!(tokenize_dbr(&"λλx2"),    Err(InvalidCharacter((3, 'x'))));
        assert_eq!(tokenize_cla(&"λa.λb a"), Err(InvalidCharacter((6, ' '))));
    }

    #[test]
    fn tokenization_success() {
        let quine = "λ 1 ( (λ 1 1) (λ λ λ λ λ 1 4 (3 (5 5) 2) ) ) 1";
        let tokens = tokenize_dbr(&quine);

        assert!(tokens.is_ok());
        assert_eq!(tokens.unwrap(), vec![Lambda, Number(1), Lparen, Lparen, Lambda, Number(1),
            Number(1), Rparen, Lparen, Lambda, Lambda, Lambda, Lambda, Lambda, Number(1),
            Number(4), Lparen, Number(3), Lparen, Number(5), Number(5), Rparen, Number(2),
            Rparen, Rparen, Rparen, Number(1)]);
    }

    #[test]
    fn tokenization_success_classic() {
        let blc_dbr = "(λ11)(λλλ1(λλλλ3(λ5(3(λ2(3(λλ3(λ123)))(4(λ4(λ31(21))))))(1(2(λ12))\
            (λ4(λ4(λ2(14)))5))))(33)2)(λ1((λ11)(λ11)))";
        let blc_cla = format!("{}", parse(&blc_dbr, DeBruijn).unwrap());

        let tokens_cla = tokenize_cla(&blc_cla);
        let tokens_dbr = tokenize_dbr(&blc_dbr);

        assert!(tokens_cla.is_ok());
        assert!(tokens_dbr.is_ok());

        assert_eq!(convert_classic_tokens(&tokens_cla.unwrap()), tokens_dbr.unwrap());
    }

    #[test]
    fn alternative_lambda_parsing() {
        assert_eq!(parse(&"\\\\\\2(321)", DeBruijn), parse(&"λλλ2(321)", DeBruijn))
    }

    #[test]
    fn succ_ast() {
        let tokens = tokenize_dbr(&"λλλ2(321)").unwrap();
        let ast = get_ast(&tokens);

        assert_eq!(ast,
            Ok(Sequence(vec![
                Abstraction,
                Abstraction,
                Abstraction,
                Variable(2),
                Sequence(vec![
                    Variable(3),
                    Variable(2),
                    Variable(1)
                ])
            ])
        ));
    }

    #[test]
    fn parse_y() {
        let y = "λ(λ2(11))(λ2(11))";
        assert_eq!(parse(&y, DeBruijn).expect("parsing Y failed!"),
            abs(
                app(
                    abs(
                        app(
                            Var(2),
                            app(Var(1), Var(1))
                        )
                    ),
                    abs(
                        app(
                            Var(2),
                            app(Var(1), Var(1))
                        )
                    )
                )
            )
        );
    }

    #[test]
    fn parse_quine() {
        let quine = "λ1((λ11)(λλλλλ14(3(55)2)))1";
        assert_eq!(parse(&quine, DeBruijn).expect("parsing QUINE failed!"),
            abs(app(app(Var(1), app(abs(app(Var(1), Var(1))), abs(abs(abs(abs(abs(app(app(Var(1),
            Var(4)), app(app(Var(3), app(Var(5), Var(5))), Var(2)))))))))), Var(1)))
        );
    }

    #[test]
    fn parse_blc() {
        let blc = "(λ11)(λλλ1(λλλλ3(λ5(3(λ2(3(λλ3(λ123)))(4(λ4(λ31(21))))))(1(2(λ12))\
                   (λ4(λ4(λ2(14)))5))))(33)2)(λ1((λ11)(λ11)))";
        assert_eq!(parse(&blc, DeBruijn).expect("parsing BLC failed!"),
            app(app(abs(app(Var(1), Var(1))), abs(abs(abs(app(app(app(Var(1),
            abs(abs(abs(abs(app(Var(3), abs(app(app(Var(5), app(Var(3), abs(app(app(Var(2),
            app(Var(3), abs(abs(app(Var(3), abs(app(app(Var(1), Var(2)), Var(3)))))))), app(Var(4),
            abs(app(Var(4), abs(app(app(Var(3), Var(1)), app(Var(2), Var(1))))))))))),
            app(app(Var(1), app(Var(2), abs(app(Var(1), Var(2))))), abs(app(app(Var(4),
            abs(app(Var(4), abs(app(Var(2), app(Var(1), Var(4))))))), Var(5)))))))))))),
            app(Var(3), Var(3))), Var(2)))))), abs(app(Var(1), app(abs(app(Var(1), Var(1))),
            abs(app(Var(1), Var(1)))))))
        );
    }
}
<|endoftext|>


<commit_before>use token::{Token, Kind, Tokenizer};
use ast;

// # Parser
//
// Represents the parser that is responsible for parsing a stream of tokens
// from a given Tokenizer into an Abstracted Sintax Tree
pub struct Parser {
    tokenizer: Tokenizer,
    current: Option<Token>
}

impl Parser {
    pub fn new(text: Tokenizer) -> Self {
        Parser {
            tokenizer: text,
            current: None
        }
    }

    // next
    //
    // It store the next token from Tokenizer and return itself for
    // chaining porpouses
    fn next(&mut self) -> &mut Self {
        if self.current.is_none() { self.current = self.tokenizer.next() }
        self
    }

    // get
    //
    // It gets the current token without consuming it
    fn get(&mut self) -> Option<Token> {
        self.current.clone()
    }

    // consume
    //
    // It is responsible for consume the current Token validating the expected
    // token for the expression sintax
    fn consume(&mut self, expected_kind: Kind) -> Token {
        if let Some(token) = self.current.clone() {
            self.current = None;
            if token.kind != expected_kind {
                panic!(
                    "Sintax error: expected token kind {:?} found {:?} at position {}",
                    expected_kind,
                    token,
                    self.tokenizer.position
                    )
            }
            return token;
        } else {
            panic!("Interpreter error: unexpected end of file");
        }
    }

    // compound
    //
    // compound is a BEGIN followed by statement_list followed by END
    // Represented as context free grammar:
    // ```
    //   compound: BEGIN statement_list END
    // ```
    fn compound(&mut self) -> ast::Node {
        self.consume(Kind::Begin);
        let statement_list = self.statement_list();
        self.consume(Kind::End);
        ast::Node::compound(statement_list)
    }

    // statement_list
    //
    // statement_list can be a single statement or single statement followed by
    // STATEMENT_END followed by statement_list recursively
    // Represented as context free grammar:
    // ```
    //   statement_list: statement
    //   statement_list: statement STATEMENT_END statement_list
    // ```
    fn statement_list(&mut self) -> Vec<ast::Node> {
        let mut statements = vec![self.statement()];
        if let Some(Token{kind: Kind::StatementEnd, ..}) = self.next().get() {
            self.consume(Kind::StatementEnd);
            statements.extend(self.statement_list())
        }
        return statements
    }

    // statement
    //
    // statement can be a compoud, assign or empty statement.
    // Represented as context free grammar:
    // ```
    //   statement: compoud_statement
    //   statement: assign_statement
    //   statement: empty_statement
    // ```
    fn statement(&mut self) -> ast::Node {
        match self.next().get() {
            Some(Token{ kind: Kind::ID, ..}) => self.assign_statement(),
            Some(Token{ kind: Kind::Begin, ..}) => self.compound(),
            _ => ast::Node::empty()
        }
    }

    // assign_statement
    //
    // assign_statement is an variable followed by an assign token followed by
    // an expression (expr). Represented as context free grammar:
    // ```
    //   assign_statement: variable ASSIGN expr
    // ```
    fn assign_statement(&mut self) -> ast::Node {
        ast::Node::new(self.variable(),
                       self.next().consume(Kind::Assign),
                       self.expr())
    }

    // variable
    //
    // variable is an ID. Represented as context free grammar:
    // ```
    //   variable: ID
    // ```
    fn variable(&mut self) -> ast::Node {
        let token = self.consume(Kind::ID);
        ast::Node::leaf(token)
    }

    // factor
    //
    // factor can be a terminal Integer, result of a grouped expr,
    // unary result of a factor or a var. Represented as context free grammar:
    // ```
    //  factor:: (-|+) factor
    //  factor:: Integer
    //  factor:: ( expr )
    //  factor:: variable
    // ```
    fn factor(&mut self) -> ast::Node {
        match self.next().get() {
            Some(Token{ kind: Kind::Operator, .. }) => {
                ast::Node::unary(self.consume(Kind::Operator), self.factor())
            },

            Some(Token{ kind: Kind::GroupBegin , .. }) => {
                self.consume(Kind::GroupBegin);
                let result = self.expr();
                self.consume(Kind::GroupEnd);
                result
            },

            Some(Token{ kind: Kind::Integer, .. }) => {
                ast::Node::leaf(self.next().consume(Kind::Integer))
            },

            Some(Token{ kind: Kind::ID, .. }) => {
                self.variable()
            },

            other =>
            panic!("Factor error: exptected Operator|GroupBegin|Integer|ID
                   found {:?}", other)
        }
    }

    // term
    //
    // One term can be a `factor` or result of `factor * factor`
    // or `factor / factor`. Represented in context free grammar:
    // ```
    // term:: factor
    // term:: factor (*|/) factor
    // ```
    fn term(&mut self) -> ast::Node {
        let result = self.factor();

        if let Some(token) = self.next().get() {
            match token.value.as_ref() {
                "*" | "/" => {
                    return ast::Node::new(result.clone(),
                                          self.consume(Kind::Operator),
                                          self.factor());
                },
                _ => ()
            };
        }
        return result
    }

    // # expr
    //
    // One expr can be a `term` or result of `term + term` or `term - term`
    // Represented in context free grammar:
    // ```
    //   expr:: term
    //   expr:: term (+|-) term
    // ```
    pub fn expr(&mut self) -> ast::Node {
        let mut result = self.term();
        while let Some(token) = self.next().get() {
            if token.kind == Kind::EOF { break }
            match token.value.as_ref() {
                "+" | "-" => {
                    result = ast::Node::new(result.clone(),
                                            self.consume(Kind::Operator),
                                            self.term())
                },
                _ => break
            };
        }
        result
    }

    pub fn parse(&mut self) -> ast::Node {
        self.expr()
    }
}

fn test_node_builder(left: String, operator: String, right: String) -> ast::Node {
    let lnode = ast::Node::leaf(Token::build(Kind::Integer, left));
    let token = Token::build(Kind::Operator, operator);
    let rnode = ast::Node::leaf(Token::build(Kind::Integer, right));
    ast::Node::new(lnode, token, rnode)
}

#[test]
fn it_parses_sum_as_node() {
    let text = "5+1";
    let tokenizer = Tokenizer::new(String::from(text));
    let mut parser = Parser::new(tokenizer);
    let expected = test_node_builder(String::from("5"),
                                     String::from("+"),
                                     String::from("1"));

    assert_eq!(expected, parser.parse());
}

#[test]
fn it_parses_multiples_operation() {
    let text = "10+5-4";
    let tokenizer = Tokenizer::new(String::from(text));
    let mut parser = Parser::new(tokenizer);

    let firstsum = test_node_builder(String::from("10"),
                                     String::from("+"),
                                     String::from("5"));

    let token = Token::build(Kind::Operator, String::from("-"));
    let rnode = ast::Node::leaf(Token::build(Kind::Integer, String::from("4")));

    let expected = ast::Node::new(firstsum, token, rnode);
    assert_eq!(expected, parser.parse());
}

#[test]
fn it_parses_respecting_precedence() {
    let text = "10+5*4";
    let tokenizer = Tokenizer::new(String::from(text));
    let mut parser = Parser::new(tokenizer);

    let plusnode = test_node_builder(String::from("5"),
                                     String::from("*"),
                                     String::from("4"));

    let token = Token::build(Kind::Operator, String::from("+"));
    let rnode = ast::Node::leaf(Token::build(Kind::Integer, String::from("10")));

    let expected = ast::Node::new(rnode, token, plusnode);
    assert_eq!(expected, parser.parse());
}

#[test]
fn it_parses_respecting_parentesis_precedence() {
    let text = "(10+5)*4";
    let tokenizer = Tokenizer::new(String::from(text));
    let mut parser = Parser::new(tokenizer);

    let plusnode = test_node_builder(String::from("10"),
                                     String::from("+"),
                                     String::from("5"));

    let token = Token::build(Kind::Operator, String::from("*"));
    let rnode = ast::Node::leaf(Token::build(Kind::Integer, String::from("4")));

    let expected = ast::Node::new(plusnode, token, rnode);
    assert_eq!(expected, parser.parse());
}
<commit_msg>tests: for block parsing<commit_after>use token::{Token, Kind, Tokenizer};
use ast;

// # Parser
//
// Represents the parser that is responsible for parsing a stream of tokens
// from a given Tokenizer into an Abstracted Sintax Tree
pub struct Parser {
    tokenizer: Tokenizer,
    current: Option<Token>
}

impl Parser {
    pub fn new(text: Tokenizer) -> Self {
        Parser {
            tokenizer: text,
            current: None
        }
    }

    // next
    //
    // It store the next token from Tokenizer and return itself for
    // chaining porpouses
    fn next(&mut self) -> &mut Self {
        if self.current.is_none() { self.current = self.tokenizer.next() }
        self
    }

    // get
    //
    // It gets the current token without consuming it
    fn get(&mut self) -> Option<Token> {
        self.current.clone()
    }

    // consume
    //
    // It is responsible for consume the current Token validating the expected
    // token for the expression sintax
    fn consume(&mut self, expected_kind: Kind) -> Token {
        if let Some(token) = self.current.clone() {
            self.current = None;
            if token.kind != expected_kind {
                panic!(
                    "Sintax error: expected token kind {:?} found {:?} at position {}",
                    expected_kind,
                    token,
                    self.tokenizer.position
                    )
            }
            return token;
        } else {
            panic!("Interpreter error: unexpected end of file");
        }
    }

    // compound
    //
    // compound is a BEGIN followed by statement_list followed by END
    // Represented as context free grammar:
    // ```
    //   compound: BEGIN statement_list END
    // ```
    fn compound(&mut self) -> ast::Node {
        self.consume(Kind::Begin);
        let statement_list = self.statement_list();
        self.consume(Kind::End);
        ast::Node::compound(statement_list)
    }

    // statement_list
    //
    // statement_list can be a single statement or single statement followed by
    // STATEMENT_END followed by statement_list recursively
    // Represented as context free grammar:
    // ```
    //   statement_list: statement
    //   statement_list: statement STATEMENT_END statement_list
    // ```
    fn statement_list(&mut self) -> Vec<ast::Node> {
        let mut statements = vec![self.statement()];
        if let Some(Token{kind: Kind::StatementEnd, ..}) = self.next().get() {
            self.consume(Kind::StatementEnd);
            statements.extend(self.statement_list())
        }
        return statements
    }

    // statement
    //
    // statement can be a compoud, assign or empty statement.
    // Represented as context free grammar:
    // ```
    //   statement: compoud_statement
    //   statement: assign_statement
    //   statement: empty_statement
    // ```
    fn statement(&mut self) -> ast::Node {
        match self.next().get() {
            Some(Token{ kind: Kind::ID, ..}) => self.assign_statement(),
            Some(Token{ kind: Kind::Begin, ..}) => self.compound(),
            _ => ast::Node::empty()
        }
    }

    // assign_statement
    //
    // assign_statement is an variable followed by an assign token followed by
    // an expression (expr). Represented as context free grammar:
    // ```
    //   assign_statement: variable ASSIGN expr
    // ```
    fn assign_statement(&mut self) -> ast::Node {
        println!("assign_statement: {:?}", self.next().get());
        ast::Node::new(self.variable(),
                       self.next().consume(Kind::Assign),
                       self.expr())
    }

    // variable
    //
    // variable is an ID. Represented as context free grammar:
    // ```
    //   variable: ID
    // ```
    fn variable(&mut self) -> ast::Node {
        let token = self.consume(Kind::ID);
        ast::Node::leaf(token)
    }

    // factor
    //
    // factor can be a terminal Integer, result of a grouped expr,
    // unary result of a factor or a var. Represented as context free grammar:
    // ```
    //  factor:: (-|+) factor
    //  factor:: Integer
    //  factor:: ( expr )
    //  factor:: variable
    // ```
    fn factor(&mut self) -> ast::Node {
        match self.next().get() {
            Some(Token{ kind: Kind::Operator, .. }) => {
                ast::Node::unary(self.consume(Kind::Operator), self.factor())
            },

            Some(Token{ kind: Kind::GroupBegin , .. }) => {
                self.consume(Kind::GroupBegin);
                let result = self.expr();
                self.consume(Kind::GroupEnd);
                result
            },

            Some(Token{ kind: Kind::Integer, .. }) => {
                ast::Node::leaf(self.next().consume(Kind::Integer))
            },

            Some(Token{ kind: Kind::ID, .. }) => {
                self.variable()
            },

            other =>
            panic!("Factor error: exptected Operator|GroupBegin|Integer|ID
                   found {:?}", other)
        }
    }

    // term
    //
    // One term can be a `factor` or result of `factor * factor`
    // or `factor / factor`. Represented in context free grammar:
    // ```
    // term:: factor
    // term:: factor (*|/) factor
    // ```
    fn term(&mut self) -> ast::Node {
        let result = self.factor();

        if let Some(token) = self.next().get() {
            match token.value.as_ref() {
                "*" | "/" => {
                    return ast::Node::new(result.clone(),
                                          self.consume(Kind::Operator),
                                          self.factor());
                },
                _ => ()
            };
        }
        return result
    }

    // # expr
    //
    // One expr can be a `term` or result of `term + term` or `term - term`
    // Represented in context free grammar:
    // ```
    //   expr:: term
    //   expr:: term (+|-) term
    // ```
    pub fn expr(&mut self) -> ast::Node {
        let mut result = self.term();
        while let Some(token) = self.next().get() {
            if token.kind == Kind::EOF { break }
            match token.value.as_ref() {
                "+" | "-" => {
                    result = ast::Node::new(result.clone(),
                                            self.consume(Kind::Operator),
                                            self.term())
                },
                _ => break
            };
        }
        result
    }

    pub fn parse(&mut self) -> ast::Node {
        match self.next().get() {
            Some(Token{kind: Kind::Begin, ..}) => self.compound(),
            _ => self.expr()
        }
    }
}

fn test_node_builder(left: String, operator: String, right: String) -> ast::Node {
    let lnode = ast::Node::leaf(Token::build(Kind::Integer, left));
    let token = Token::build(Kind::Operator, operator);
    let rnode = ast::Node::leaf(Token::build(Kind::Integer, right));
    ast::Node::new(lnode, token, rnode)
}

#[test]
fn it_parses_sum_as_node() {
    let text = "5+1";
    let tokenizer = Tokenizer::new(String::from(text));
    let mut parser = Parser::new(tokenizer);
    let expected = test_node_builder(String::from("5"),
                                     String::from("+"),
                                     String::from("1"));

    assert_eq!(expected, parser.parse());
}

#[test]
fn it_parses_multiples_operation() {
    let text = "10+5-4";
    let tokenizer = Tokenizer::new(String::from(text));
    let mut parser = Parser::new(tokenizer);

    let firstsum = test_node_builder(String::from("10"),
                                     String::from("+"),
                                     String::from("5"));

    let token = Token::build(Kind::Operator, String::from("-"));
    let rnode = ast::Node::leaf(Token::build(Kind::Integer, String::from("4")));

    let expected = ast::Node::new(firstsum, token, rnode);
    assert_eq!(expected, parser.parse());
}

#[test]
fn it_parses_respecting_precedence() {
    let text = "10+5*4";
    let tokenizer = Tokenizer::new(String::from(text));
    let mut parser = Parser::new(tokenizer);

    let plusnode = test_node_builder(String::from("5"),
                                     String::from("*"),
                                     String::from("4"));

    let token = Token::build(Kind::Operator, String::from("+"));
    let rnode = ast::Node::leaf(Token::build(Kind::Integer, String::from("10")));

    let expected = ast::Node::new(rnode, token, plusnode);
    assert_eq!(expected, parser.parse());
}

#[test]
fn it_parses_respecting_parentesis_precedence() {
    let text = "(10+5)*4";
    let tokenizer = Tokenizer::new(String::from(text));
    let mut parser = Parser::new(tokenizer);

    let plusnode = test_node_builder(String::from("10"),
                                     String::from("+"),
                                     String::from("5"));

    let token = Token::build(Kind::Operator, String::from("*"));
    let rnode = ast::Node::leaf(Token::build(Kind::Integer, String::from("4")));

    let expected = ast::Node::new(plusnode, token, rnode);
    assert_eq!(expected, parser.parse());
}

#[test]
fn it_parses_simple_block() {
    let text = "BEGIN x := 10+5 END";
    let tokenizer = Tokenizer::new(String::from(text));
    let mut parser = Parser::new(tokenizer);

    let expr = test_node_builder(String::from("10"),
                                 String::from("+"),
                                 String::from("5"));

    let var = ast::Node::leaf(Token{ kind: Kind::ID, value: String::from("x")});
    let assign_token = Token{ kind: Kind::Assign, value: String::from(":=")};
    let assign = ast::Node::new(var, assign_token, expr);

    let comp = ast::Node::compound(vec![assign]);
    assert_eq!(comp, parser.parse());
}

#[test]
fn it_parses_multiple_statements() {
    let text = "BEGIN x := 10+5; y := 100 END";
    let tokenizer = Tokenizer::new(String::from(text));
    let mut parser = Parser::new(tokenizer);
    let assign_token = Token{ kind: Kind::Assign, value: String::from(":=")};

    let expr = test_node_builder(String::from("10"),
                                 String::from("+"),
                                 String::from("5"));

    let yvar = ast::Node::leaf(Token{ kind: Kind::ID, value: String::from("y")});
    let yvalue = ast::Node::leaf(Token{ kind: Kind::Integer, value: String::from("100")});
    let yassign = ast::Node::new(yvar, assign_token.clone(), yvalue);

    let xvar = ast::Node::leaf(Token{ kind: Kind::ID, value: String::from("x")});
    let xassign_token = Token{ kind: Kind::Assign, value: String::from(":=")};
    let xassign = ast::Node::new(xvar, assign_token, expr);

    let comp = ast::Node::compound(vec![xassign, yassign]);
    assert_eq!(comp, parser.parse());
}
<|endoftext|>


<commit_before>use common::{Atom, Sexp};

#[derive(Debug, PartialEq)]
enum ParserState {
    StartRead,
    OpenList,
    AtomRead(Atom),
    CloseList,
    EndRead,
}

#[derive(Debug, PartialEq)]
enum ParserError {
}

fn parse(tokens: Vec<String>) -> Result<Vec<Sexp>, ParserError> {
    let mut state = ParserState::StartRead;
    let mut iter = tokens.iter();
    let mut result = vec![];
    loop {
        match state {
            ParserState::StartRead => {
                match iter.next() {
                    Some(s) if *s == "(" => {
                        state = ParserState::OpenList;
                        result.push(Sexp::List(vec![]));
                    },
                    _ => {
                        state = ParserState::EndRead;
                    }
                }
            },
            ParserState::OpenList => {
                match iter.next() {
                    Some(s) if *s == ")" => {
                        state = ParserState::CloseList;
                    },
                    Some(s) => {
                        state = ParserState::AtomRead(s.parse::<Atom>().ok().unwrap());
                    },
                    _ => {
                        state = ParserState::EndRead;
                    }
                }
            },
            ParserState::CloseList => {
                match iter.next() {
                    Some(s) if *s == "(" => {
                        state = ParserState::OpenList;
                        result.push(Sexp::List(vec![]));
                    },
                    _ => {
                        state = ParserState::EndRead;
                    }
                }
            },
            ParserState::AtomRead(atom) => {
                if let Some(Sexp::List(mut current_list)) = result.pop() {
                    current_list.push(Sexp::Atom(atom));
                    result.push(Sexp::List(current_list));
                }
                match iter.next() {
                    Some(s) if *s == ")" => {
                        state = ParserState::CloseList;
                    },
                    Some(s) => {
                        state = ParserState::AtomRead(s.parse::<Atom>().ok().unwrap());
                    },
                    _ => {
                        state = ParserState::EndRead;
                    }
                }
            },
            ParserState::EndRead => {
                return Ok(result)
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use common::Atom::{Number, Symbol};
    use common::Sexp::{List, Atom};
    use super::parse;

    #[test]
    fn test_parse_empty() {
        let expected_result = vec![];
        assert_eq!(expected_result, parse(vec![]).ok().unwrap())
    }

    #[test]
    fn test_parse_single_expression() {
        let expected_result =  vec![List(vec![Atom(Symbol("def".to_string())),
                                              Atom(Symbol("a".to_string())),
                                              Atom(Number(1f64))])];
        let actual_input = ["(", "def", "a", "1", ")"]
                                .iter()
                                .map(|s| { s.to_string() })
                                .collect();
        let actual_result = parse(actual_input).ok().unwrap();
        assert_eq!(expected_result, actual_result);
    }

    #[test]
    fn test_parse_multiple_expression() {
        let expected_result =  vec![List(vec![Atom(Symbol("def".to_string())),
                                              Atom(Symbol("a".to_string())),
                                              Atom(Number(1f64))]),
                                    List(vec![Atom(Symbol("def".to_string())),
                                              Atom(Symbol("b".to_string())),
                                              Atom(Number(2f64))]),
                                    List(vec![Atom(Symbol("+".to_string())),
                                              Atom(Symbol("a".to_string())),
                                              Atom(Symbol("b".to_string()))])];
        let actual_input = ["(", "def", "a", "1", ")",
                            "(", "def", "b", "2", ")",
                            "(", "+", "a", "b", ")"]
                                .iter()
                                .map(|s| { s.to_string() })
                                .collect();
        let actual_result = parse(actual_input).ok().unwrap();
        assert_eq!(expected_result, actual_result);
    }
}
<commit_msg>Borrow vector with tokens instead of moving<commit_after>use common::{Atom, Sexp};

#[derive(Debug, PartialEq)]
enum ParserState {
    StartRead,
    OpenList,
    AtomRead(Atom),
    CloseList,
    EndRead,
}

#[derive(Debug, PartialEq)]
enum ParserError {
}

fn parse(tokens: &Vec<String>) -> Result<Vec<Sexp>, ParserError> {
    let mut state = ParserState::StartRead;
    let mut iter = tokens.iter();
    let mut result = vec![];
    loop {
        match state {
            ParserState::StartRead => {
                match iter.next() {
                    Some(s) if *s == "(" => {
                        state = ParserState::OpenList;
                        result.push(Sexp::List(vec![]));
                    },
                    _ => {
                        state = ParserState::EndRead;
                    }
                }
            },
            ParserState::OpenList => {
                match iter.next() {
                    Some(s) if *s == ")" => {
                        state = ParserState::CloseList;
                    },
                    Some(s) => {
                        state = ParserState::AtomRead(s.parse::<Atom>().ok().unwrap());
                    },
                    _ => {
                        state = ParserState::EndRead;
                    }
                }
            },
            ParserState::CloseList => {
                match iter.next() {
                    Some(s) if *s == "(" => {
                        state = ParserState::OpenList;
                        result.push(Sexp::List(vec![]));
                    },
                    _ => {
                        state = ParserState::EndRead;
                    }
                }
            },
            ParserState::AtomRead(atom) => {
                if let Some(Sexp::List(mut current_list)) = result.pop() {
                    current_list.push(Sexp::Atom(atom));
                    result.push(Sexp::List(current_list));
                }
                match iter.next() {
                    Some(s) if *s == ")" => {
                        state = ParserState::CloseList;
                    },
                    Some(s) => {
                        state = ParserState::AtomRead(s.parse::<Atom>().ok().unwrap());
                    },
                    _ => {
                        state = ParserState::EndRead;
                    }
                }
            },
            ParserState::EndRead => {
                return Ok(result)
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use common::Atom::{Number, Symbol};
    use common::Sexp::{List, Atom};
    use super::parse;

    #[test]
    fn test_parse_empty() {
        assert_eq!(vec![], parse(&vec![]).ok().unwrap())
    }

    #[test]
    fn test_parse_single_expression() {
        let expected_result =  vec![List(vec![Atom(Symbol("def".to_string())),
                                              Atom(Symbol("a".to_string())),
                                              Atom(Number(1f64))])];
        let actual_input = ["(", "def", "a", "1", ")"]
                                .iter()
                                .map(|s| { s.to_string() })
                                .collect();
        let actual_result = parse(&actual_input).ok().unwrap();
        assert_eq!(expected_result, actual_result);
    }

    #[test]
    fn test_parse_multiple_expression() {
        let expected_result =  vec![List(vec![Atom(Symbol("def".to_string())),
                                              Atom(Symbol("a".to_string())),
                                              Atom(Number(1f64))]),
                                    List(vec![Atom(Symbol("def".to_string())),
                                              Atom(Symbol("b".to_string())),
                                              Atom(Number(2f64))]),
                                    List(vec![Atom(Symbol("+".to_string())),
                                              Atom(Symbol("a".to_string())),
                                              Atom(Symbol("b".to_string()))])];
        let actual_input = ["(", "def", "a", "1", ")",
                            "(", "def", "b", "2", ")",
                            "(", "+", "a", "b", ")"]
                                .iter()
                                .map(|s| { s.to_string() })
                                .collect();
        let actual_result = parse(&actual_input).ok().unwrap();
        assert_eq!(expected_result, actual_result);
    }
}
<|endoftext|>


<commit_before>use std::io::{Read, BufReader};

use types::{RedisResult, Value, ErrorKind, make_extension_error};

/// The internal redis response parser.
pub struct Parser<T> {
    reader: T,
}

/// The parser can be used to parse redis responses into values.  Generally
/// you normally do not use this directly as it's already done for you by
/// the client but in some more complex situations it might be useful to be
/// able to parse the redis responses.
impl<'a, T: Read> Parser<T> {
    /// Creates a new parser that parses the data behind the reader.  More
    /// than one value can be behind the reader in which case the parser can
    /// be invoked multiple times.  In other words: the stream does not have
    /// to be terminated.
    pub fn new(reader: T) -> Parser<T> {
        Parser { reader: reader }
    }

    // public api

    /// parses a single value out of the stream.  If there are multiple
    /// values you can call this multiple times.  If the reader is not yet
    /// ready this will block.
    pub fn parse_value(&mut self) -> RedisResult<Value> {
        let b = try!(self.read_byte());
        match b as char {
            '+' => self.parse_status(),
            ':' => self.parse_int(),
            '$' => self.parse_data(),
            '*' => self.parse_bulk(),
            '-' => self.parse_error(),
            _ => fail!((ErrorKind::ResponseError, "Invalid response when parsing value")),
        }
    }

    // internal helpers

    #[inline]
    fn expect_char(&mut self, refchar: char) -> RedisResult<()> {
        if try!(self.read_byte()) as char == refchar {
            Ok(())
        } else {
            fail!((ErrorKind::ResponseError, "Invalid byte in response"));
        }
    }

    #[inline]
    fn expect_newline(&mut self) -> RedisResult<()> {
        match try!(self.read_byte()) as char {
            '\n' => Ok(()),
            '\r' => self.expect_char('\n'),
            _ => fail!((ErrorKind::ResponseError, "Invalid byte in response")),
        }
    }

    fn read_line(&mut self) -> RedisResult<Vec<u8>> {
        let mut rv = vec![];

        loop {
            let b = try!(self.read_byte());
            match b as char {
                '\n' => {
                    break;
                }
                '\r' => {
                    try!(self.expect_char('\n'));
                    break;
                }
                _ => rv.push(b),
            };
        }

        Ok(rv)
    }

    fn read_string_line(&mut self) -> RedisResult<String> {
        match String::from_utf8(try!(self.read_line())) {
            Err(_) => fail!((ErrorKind::ResponseError, "Expected valid string, got garbage")),
            Ok(value) => Ok(value),
        }
    }

    fn read_byte(&mut self) -> RedisResult<u8> {
        let buf: &mut [u8; 1] = &mut [0];
        let nread = try!(self.reader.read(buf));

        if nread < 1 {
            fail!((ErrorKind::ResponseError, "Could not read enough bytes"))
        } else {
            Ok(buf[0])
        }
    }

    fn read(&mut self, bytes: usize) -> RedisResult<Vec<u8>> {
        let mut rv = vec![0; bytes];
        let mut i = 0;
        while i < bytes {
            let res_nread = {
                let ref mut buf = &mut rv[i..];
                self.reader.read(buf)
            };
            match res_nread {
                Ok(nread) if nread > 0 => i += nread,
                Ok(_) => return fail!((ErrorKind::ResponseError, "Could not read enough bytes")),
                Err(e) => return Err(From::from(e)),
            }
        }
        Ok(rv)
    }

    fn read_int_line(&mut self) -> RedisResult<i64> {
        let line = try!(self.read_string_line());
        match line.trim().parse::<i64>() {
            Err(_) => fail!((ErrorKind::ResponseError, "Expected integer, got garbage")),
            Ok(value) => Ok(value),
        }
    }

    fn parse_status(&mut self) -> RedisResult<Value> {
        let line = try!(self.read_string_line());
        if line == "OK" {
            Ok(Value::Okay)
        } else {
            Ok(Value::Status(line))
        }
    }

    fn parse_int(&mut self) -> RedisResult<Value> {
        Ok(Value::Int(try!(self.read_int_line())))
    }

    fn parse_data(&mut self) -> RedisResult<Value> {
        let length = try!(self.read_int_line());
        if length < 0 {
            Ok(Value::Nil)
        } else {
            let data = try!(self.read(length as usize));
            try!(self.expect_newline());
            Ok(Value::Data(data))
        }
    }

    fn parse_bulk(&mut self) -> RedisResult<Value> {
        let length = try!(self.read_int_line());
        if length < 0 {
            Ok(Value::Nil)
        } else {
            let mut rv = vec![];
            rv.reserve(length as usize);
            for _ in 0..length {
                rv.push(try!(self.parse_value()));
            }
            Ok(Value::Bulk(rv))
        }
    }

    fn parse_error(&mut self) -> RedisResult<Value> {
        let desc = "An error was signalled by the server";
        let line = try!(self.read_string_line());
        let mut pieces = line.splitn(2, ' ');
        let kind = match pieces.next().unwrap() {
            "ERR" => ErrorKind::ResponseError,
            "EXECABORT" => ErrorKind::ExecAbortError,
            "LOADING" => ErrorKind::BusyLoadingError,
            "NOSCRIPT" => ErrorKind::NoScriptError,
            code => {
                fail!(make_extension_error(code, pieces.next()));
            }
        };
        match pieces.next() {
            Some(detail) => fail!((kind, desc, detail.to_string())),
            None => fail!((kind, desc)),
        }
    }
}

/// Parses bytes into a redis value.
///
/// This is the most straightforward way to parse something into a low
/// level redis value instead of having to use a whole parser.
pub fn parse_redis_value(bytes: &[u8]) -> RedisResult<Value> {
    let mut parser = Parser::new(BufReader::new(bytes));
    parser.parse_value()
}
<commit_msg>Do not double-return<commit_after>use std::io::{Read, BufReader};

use types::{RedisResult, Value, ErrorKind, make_extension_error};

/// The internal redis response parser.
pub struct Parser<T> {
    reader: T,
}

/// The parser can be used to parse redis responses into values.  Generally
/// you normally do not use this directly as it's already done for you by
/// the client but in some more complex situations it might be useful to be
/// able to parse the redis responses.
impl<'a, T: Read> Parser<T> {
    /// Creates a new parser that parses the data behind the reader.  More
    /// than one value can be behind the reader in which case the parser can
    /// be invoked multiple times.  In other words: the stream does not have
    /// to be terminated.
    pub fn new(reader: T) -> Parser<T> {
        Parser { reader: reader }
    }

    // public api

    /// parses a single value out of the stream.  If there are multiple
    /// values you can call this multiple times.  If the reader is not yet
    /// ready this will block.
    pub fn parse_value(&mut self) -> RedisResult<Value> {
        let b = try!(self.read_byte());
        match b as char {
            '+' => self.parse_status(),
            ':' => self.parse_int(),
            '$' => self.parse_data(),
            '*' => self.parse_bulk(),
            '-' => self.parse_error(),
            _ => fail!((ErrorKind::ResponseError, "Invalid response when parsing value")),
        }
    }

    // internal helpers

    #[inline]
    fn expect_char(&mut self, refchar: char) -> RedisResult<()> {
        if try!(self.read_byte()) as char == refchar {
            Ok(())
        } else {
            fail!((ErrorKind::ResponseError, "Invalid byte in response"));
        }
    }

    #[inline]
    fn expect_newline(&mut self) -> RedisResult<()> {
        match try!(self.read_byte()) as char {
            '\n' => Ok(()),
            '\r' => self.expect_char('\n'),
            _ => fail!((ErrorKind::ResponseError, "Invalid byte in response")),
        }
    }

    fn read_line(&mut self) -> RedisResult<Vec<u8>> {
        let mut rv = vec![];

        loop {
            let b = try!(self.read_byte());
            match b as char {
                '\n' => {
                    break;
                }
                '\r' => {
                    try!(self.expect_char('\n'));
                    break;
                }
                _ => rv.push(b),
            };
        }

        Ok(rv)
    }

    fn read_string_line(&mut self) -> RedisResult<String> {
        match String::from_utf8(try!(self.read_line())) {
            Err(_) => fail!((ErrorKind::ResponseError, "Expected valid string, got garbage")),
            Ok(value) => Ok(value),
        }
    }

    fn read_byte(&mut self) -> RedisResult<u8> {
        let buf: &mut [u8; 1] = &mut [0];
        let nread = try!(self.reader.read(buf));

        if nread < 1 {
            fail!((ErrorKind::ResponseError, "Could not read enough bytes"))
        } else {
            Ok(buf[0])
        }
    }

    fn read(&mut self, bytes: usize) -> RedisResult<Vec<u8>> {
        let mut rv = vec![0; bytes];
        let mut i = 0;
        while i < bytes {
            let res_nread = {
                let ref mut buf = &mut rv[i..];
                self.reader.read(buf)
            };
            match res_nread {
                Ok(nread) if nread > 0 => i += nread,
                Ok(_) => fail!((ErrorKind::ResponseError, "Could not read enough bytes")),
                Err(e) => return Err(From::from(e)),
            }
        }
        Ok(rv)
    }

    fn read_int_line(&mut self) -> RedisResult<i64> {
        let line = try!(self.read_string_line());
        match line.trim().parse::<i64>() {
            Err(_) => fail!((ErrorKind::ResponseError, "Expected integer, got garbage")),
            Ok(value) => Ok(value),
        }
    }

    fn parse_status(&mut self) -> RedisResult<Value> {
        let line = try!(self.read_string_line());
        if line == "OK" {
            Ok(Value::Okay)
        } else {
            Ok(Value::Status(line))
        }
    }

    fn parse_int(&mut self) -> RedisResult<Value> {
        Ok(Value::Int(try!(self.read_int_line())))
    }

    fn parse_data(&mut self) -> RedisResult<Value> {
        let length = try!(self.read_int_line());
        if length < 0 {
            Ok(Value::Nil)
        } else {
            let data = try!(self.read(length as usize));
            try!(self.expect_newline());
            Ok(Value::Data(data))
        }
    }

    fn parse_bulk(&mut self) -> RedisResult<Value> {
        let length = try!(self.read_int_line());
        if length < 0 {
            Ok(Value::Nil)
        } else {
            let mut rv = vec![];
            rv.reserve(length as usize);
            for _ in 0..length {
                rv.push(try!(self.parse_value()));
            }
            Ok(Value::Bulk(rv))
        }
    }

    fn parse_error(&mut self) -> RedisResult<Value> {
        let desc = "An error was signalled by the server";
        let line = try!(self.read_string_line());
        let mut pieces = line.splitn(2, ' ');
        let kind = match pieces.next().unwrap() {
            "ERR" => ErrorKind::ResponseError,
            "EXECABORT" => ErrorKind::ExecAbortError,
            "LOADING" => ErrorKind::BusyLoadingError,
            "NOSCRIPT" => ErrorKind::NoScriptError,
            code => {
                fail!(make_extension_error(code, pieces.next()));
            }
        };
        match pieces.next() {
            Some(detail) => fail!((kind, desc, detail.to_string())),
            None => fail!((kind, desc)),
        }
    }
}

/// Parses bytes into a redis value.
///
/// This is the most straightforward way to parse something into a low
/// level redis value instead of having to use a whole parser.
pub fn parse_redis_value(bytes: &[u8]) -> RedisResult<Value> {
    let mut parser = Parser::new(BufReader::new(bytes));
    parser.parse_value()
}
<|endoftext|>


<commit_before>//! Basic types used by the library.

use std::{fmt, io};

pub use crate::errors::*;

/// Type of a model.
pub type Model<Ident, Type, Value> = Vec<(Ident, Vec<(Ident, Type)>, Type, Value)>;

/// A symbol printable in the SMT Lib 2 standard given some info.
pub trait Sym2Smt<Info> {
    /// Prints a symbol to a writer given some info.
    fn sym_to_smt2<Writer>(&self, w: &mut Writer, i: Info) -> SmtRes<()>
    where
        Writer: io::Write;
}

/// An expression printable in the SMT Lib 2 standard given some info.
pub trait Expr2Smt<Info> {
    /// Prints an expression to a writer given some info.
    fn expr_to_smt2<Writer>(&self, w: &mut Writer, i: Info) -> SmtRes<()>
    where
        Writer: io::Write;
}

/// A sort printable in the SMT Lib 2 standard.
pub trait Sort2Smt {
    /// Prints a sort to a writer info.
    fn sort_to_smt2<Writer>(&self, w: &mut Writer) -> SmtRes<()>
    where
        Writer: io::Write;
}

/// Writes a string.
#[inline(always)]
pub fn write_str<W: io::Write>(w: &mut W, s: &str) -> SmtRes<()> {
    w.write_all(s.as_bytes())?;
    Ok(())
}

impl<'a, T, Info> Sym2Smt<Info> for &'a T
where
    T: Sym2Smt<Info> + ?Sized,
{
    fn sym_to_smt2<Writer>(&self, writer: &mut Writer, info: Info) -> SmtRes<()>
    where
        Writer: io::Write,
    {
        (*self).sym_to_smt2(writer, info)
    }
}

impl<'a, T, Info> Expr2Smt<Info> for &'a T
where
    T: Expr2Smt<Info> + ?Sized,
{
    fn expr_to_smt2<Writer>(&self, writer: &mut Writer, info: Info) -> SmtRes<()>
    where
        Writer: io::Write,
    {
        (*self).expr_to_smt2(writer, info)
    }
}

impl<'a, T> Sort2Smt for &'a T
where
    T: Sort2Smt + ?Sized,
{
    fn sort_to_smt2<Writer>(&self, writer: &mut Writer) -> SmtRes<()>
    where
        Writer: io::Write,
    {
        (*self).sort_to_smt2(writer)
    }
}

impl<T> Sym2Smt<T> for str {
    fn sym_to_smt2<Writer>(&self, writer: &mut Writer, _: T) -> SmtRes<()>
    where
        Writer: io::Write,
    {
        write_str(writer, self)
    }
}
impl<T> Expr2Smt<T> for str {
    fn expr_to_smt2<Writer>(&self, writer: &mut Writer, _: T) -> SmtRes<()>
    where
        Writer: io::Write,
    {
        write_str(writer, self)
    }
}
impl Sort2Smt for str {
    fn sort_to_smt2<Writer>(&self, writer: &mut Writer) -> SmtRes<()>
    where
        Writer: io::Write,
    {
        write_str(writer, self)
    }
}

impl<T> Sym2Smt<T> for String {
    fn sym_to_smt2<Writer>(&self, writer: &mut Writer, _: T) -> SmtRes<()>
    where
        Writer: io::Write,
    {
        write_str(writer, self)
    }
}
impl<T> Expr2Smt<T> for String {
    fn expr_to_smt2<Writer>(&self, writer: &mut Writer, _: T) -> SmtRes<()>
    where
        Writer: io::Write,
    {
        write_str(writer, self)
    }
}
impl Sort2Smt for String {
    fn sort_to_smt2<Writer>(&self, writer: &mut Writer) -> SmtRes<()>
    where
        Writer: io::Write,
    {
        write_str(writer, self)
    }
}

/// SMT Lib 2 logics.
///
/// See [`Solver::set_logic`][logic].
///
/// [logic]: struct.Solver.html#method.set_logic
#[allow(non_camel_case_types)]
#[derive(Clone, Copy)]
pub enum Logic {
    /// Quantifier-free uninterpreted functions.
    QF_UF,
    /// Quantifier-free linear integer arithmetic.
    QF_LIA,
    /// Quantifier-free non-linear integer arithmetic.
    QF_NIA,
    /// Quantifier-free linear real arithmetic.
    QF_LRA,
    /** Quantifier-free arrays, uninterpreted functions, linear integer
    arithmetic. */
    QF_AUFLIA,
    /** Quantifier-free arrays, uninterpreted functions, linear integer
    arithmetic. */
    AUFLIA,
    /// Arrays, uninterpreted functions, linear integer/real arithmetic.
    AUFLIRA,
    /// arrays, uninterpreted functions, non-linear integer/real arithmetic.
    AUFNIRA,
    /// Linear real arithmetic.
    LRA,
}
impl fmt::Display for Logic {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        use self::Logic::*;
        match *self {
            QF_UF => write!(fmt, "QF_UF"),
            QF_LIA => write!(fmt, "QF_LIA"),
            QF_NIA => write!(fmt, "QF_NIA"),
            QF_LRA => write!(fmt, "QF_LRA"),
            QF_AUFLIA => write!(fmt, "QF_AUFLIA"),
            AUFLIA => write!(fmt, "AUFLIA"),
            AUFLIRA => write!(fmt, "AUFLIRA"),
            AUFNIRA => write!(fmt, "AUFNIRA"),
            LRA => write!(fmt, "LRA"),
        }
    }
}
impl Logic {
    /// Prints the logic in a writer in SMT Lib 2 format.
    pub fn to_smt2<W: io::Write>(self, writer: &mut W, _: ()) -> SmtRes<()> {
        write!(writer, "{}", self)?;
        Ok(())
    }
}
<commit_msg>Common: Add fixed-size bitvector logics<commit_after>//! Basic types used by the library.

use std::{fmt, io};

pub use crate::errors::*;

/// Type of a model.
pub type Model<Ident, Type, Value> = Vec<(Ident, Vec<(Ident, Type)>, Type, Value)>;

/// A symbol printable in the SMT Lib 2 standard given some info.
pub trait Sym2Smt<Info> {
    /// Prints a symbol to a writer given some info.
    fn sym_to_smt2<Writer>(&self, w: &mut Writer, i: Info) -> SmtRes<()>
    where
        Writer: io::Write;
}

/// An expression printable in the SMT Lib 2 standard given some info.
pub trait Expr2Smt<Info> {
    /// Prints an expression to a writer given some info.
    fn expr_to_smt2<Writer>(&self, w: &mut Writer, i: Info) -> SmtRes<()>
    where
        Writer: io::Write;
}

/// A sort printable in the SMT Lib 2 standard.
pub trait Sort2Smt {
    /// Prints a sort to a writer info.
    fn sort_to_smt2<Writer>(&self, w: &mut Writer) -> SmtRes<()>
    where
        Writer: io::Write;
}

/// Writes a string.
#[inline(always)]
pub fn write_str<W: io::Write>(w: &mut W, s: &str) -> SmtRes<()> {
    w.write_all(s.as_bytes())?;
    Ok(())
}

impl<'a, T, Info> Sym2Smt<Info> for &'a T
where
    T: Sym2Smt<Info> + ?Sized,
{
    fn sym_to_smt2<Writer>(&self, writer: &mut Writer, info: Info) -> SmtRes<()>
    where
        Writer: io::Write,
    {
        (*self).sym_to_smt2(writer, info)
    }
}

impl<'a, T, Info> Expr2Smt<Info> for &'a T
where
    T: Expr2Smt<Info> + ?Sized,
{
    fn expr_to_smt2<Writer>(&self, writer: &mut Writer, info: Info) -> SmtRes<()>
    where
        Writer: io::Write,
    {
        (*self).expr_to_smt2(writer, info)
    }
}

impl<'a, T> Sort2Smt for &'a T
where
    T: Sort2Smt + ?Sized,
{
    fn sort_to_smt2<Writer>(&self, writer: &mut Writer) -> SmtRes<()>
    where
        Writer: io::Write,
    {
        (*self).sort_to_smt2(writer)
    }
}

impl<T> Sym2Smt<T> for str {
    fn sym_to_smt2<Writer>(&self, writer: &mut Writer, _: T) -> SmtRes<()>
    where
        Writer: io::Write,
    {
        write_str(writer, self)
    }
}
impl<T> Expr2Smt<T> for str {
    fn expr_to_smt2<Writer>(&self, writer: &mut Writer, _: T) -> SmtRes<()>
    where
        Writer: io::Write,
    {
        write_str(writer, self)
    }
}
impl Sort2Smt for str {
    fn sort_to_smt2<Writer>(&self, writer: &mut Writer) -> SmtRes<()>
    where
        Writer: io::Write,
    {
        write_str(writer, self)
    }
}

impl<T> Sym2Smt<T> for String {
    fn sym_to_smt2<Writer>(&self, writer: &mut Writer, _: T) -> SmtRes<()>
    where
        Writer: io::Write,
    {
        write_str(writer, self)
    }
}
impl<T> Expr2Smt<T> for String {
    fn expr_to_smt2<Writer>(&self, writer: &mut Writer, _: T) -> SmtRes<()>
    where
        Writer: io::Write,
    {
        write_str(writer, self)
    }
}
impl Sort2Smt for String {
    fn sort_to_smt2<Writer>(&self, writer: &mut Writer) -> SmtRes<()>
    where
        Writer: io::Write,
    {
        write_str(writer, self)
    }
}

/// SMT Lib 2 logics.
///
/// See [`Solver::set_logic`][logic].
///
/// [logic]: struct.Solver.html#method.set_logic
#[allow(non_camel_case_types)]
#[derive(Clone, Copy)]
pub enum Logic {
    /// Quantifier-free uninterpreted functions.
    QF_UF,
    /// Quantifier-free linear integer arithmetic.
    QF_LIA,
    /// Quantifier-free non-linear integer arithmetic.
    QF_NIA,
    /// Quantifier-free linear real arithmetic.
    QF_LRA,
    /** Quantifier-free arrays, uninterpreted functions, linear integer
    arithmetic. */
    QF_AUFLIA,
    /** Quantifier-free arrays, uninterpreted functions, linear integer
    arithmetic. */
    AUFLIA,
    /// Arrays, uninterpreted functions, linear integer/real arithmetic.
    AUFLIRA,
    /// arrays, uninterpreted functions, non-linear integer/real arithmetic.
    AUFNIRA,
    /// Linear real arithmetic.
    LRA,
    /// Quantifier-free fixed-size bitvectors.
    QF_BV,
    /// Quantifier-free uninterpreted functions, fixed-size bitvectors.
    QF_UFBV,
    /// Quantifier-free arrays, fixed-size bitvectors.
    QF_ABV,
    /// Quantifier-free arrays, uninterpreted functions, fixed-size bitvectors.
    QF_AUFBV,
}
impl fmt::Display for Logic {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        use self::Logic::*;
        match *self {
            QF_UF => write!(fmt, "QF_UF"),
            QF_LIA => write!(fmt, "QF_LIA"),
            QF_NIA => write!(fmt, "QF_NIA"),
            QF_LRA => write!(fmt, "QF_LRA"),
            QF_AUFLIA => write!(fmt, "QF_AUFLIA"),
            AUFLIA => write!(fmt, "AUFLIA"),
            AUFLIRA => write!(fmt, "AUFLIRA"),
            AUFNIRA => write!(fmt, "AUFNIRA"),
            LRA => write!(fmt, "LRA"),
            QF_BV => write!(fmt, "QF_BV"),
            QF_UFBV => write!(fmt, "QF_UFBV"),
            QF_ABV => write!(fmt, "QF_ABV"),
            QF_AUFBV => write!(fmt, "QF_AUFBV"),
        }
    }
}
impl Logic {
    /// Prints the logic in a writer in SMT Lib 2 format.
    pub fn to_smt2<W: io::Write>(self, writer: &mut W, _: ()) -> SmtRes<()> {
        write!(writer, "{}", self)?;
        Ok(())
    }
}
<|endoftext|>


<commit_before>#![allow(deprecated)]

use crate::{Pinyin, ToPinyin, ToPinyinMulti};
use std::collections::hash_map::{Entry, HashMap};
use std::convert::identity;

/// 拼音风格
#[deprecated = "请使用 `Pinyin` 的方法代替"]
#[derive(Debug, PartialEq, Eq, Hash)]
pub enum Style {
    /// 普通风格，不带声调（默认风格）。如： `pin yin`
    Normal,
    /// 声调风格1，拼音声调在韵母第一个字母上。如： `pīn yīn`
    Tone,
    /// 声调风格2，即拼音声调在各个拼音之后，用数字 [0-4] 进行表示。如： `pi1n yi1n`
    Tone2,
    /// 声母风格，只返回各个拼音的声母部分。如： 中国 的拼音 `zh g`
    Initials,
    /// 首字母风格，只返回拼音的首字母部分。如： `p y`
    FirstLetter,
    /// 韵母风格1，只返回各个拼音的韵母部分，不带声调。如： `ong uo`
    Finals,
    /// 韵母风格2，带声调，声调在韵母第一个字母上。如： `ōng uó`
    FinalsTone,
    /// 韵母风格2，带声调，声调在各个拼音之后，用数字 [0-4] 进行表示。如： `o1ng uo2`
    FinalsTone2,
}

/// 参数
#[deprecated]
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct Args {
    /// 拼音风格
    pub style: Style,
    /// 是否启用多音字模式
    pub heteronym: bool,
}

impl Args {
    /// 返回一个默认参数
    ///
    /// ```ignore
    /// Args {
    ///    style: Style::Normal,
    ///    heteronym: false,
    /// }
    /// ```
    pub fn new() -> Args {
        Args {
            style: Style::Normal,
            heteronym: false,
        }
    }
}

impl Default for Args {
    fn default() -> Self {
        Self::new()
    }
}

fn apply_style(py: Pinyin, style: &Style) -> &'static str {
    match style {
        Style::Normal => py.plain(),
        Style::Tone => py.with_tone(),
        Style::Tone2 => py.with_tone_num(),
        Style::Initials => py.initials(),
        Style::FirstLetter => py.first_letter(),
        Style::Finals => py.finals_plain(),
        Style::FinalsTone => py.finals_with_tone(),
        Style::FinalsTone2 => py.finals_with_tone_num(),
    }
}

/// 汉字转拼音
///
/// ```
/// let hans = "中国人";
/// let args = pinyin::Args::new();
///
/// // 默认输出 [["zhong"] ["guo"] ["ren"]]
/// println!("{:?}",  pinyin::pinyin(hans, &args));
/// ```
#[deprecated = "请使用 `ToPinyin` 或 `ToPinyinMulti` 代替"]
pub fn pinyin(s: &str, a: &Args) -> Vec<Vec<String>> {
    if a.heteronym {
        s.to_pinyin_multi()
            .map(|multi| match multi {
                Some(multi) => {
                    let mut set = HashMap::new();
                    multi
                        .into_iter()
                        .filter_map(|pinyin| {
                            let s = apply_style(pinyin, &a.style);
                            match set.entry(s) {
                                Entry::Occupied(_) => None,
                                Entry::Vacant(entry) => {
                                    entry.insert(());
                                    Some(s.to_string())
                                }
                            }
                        })
                        .collect()
                }
                None => vec![],
            })
            .collect()
    } else {
        s.to_pinyin()
            .map(|pinyin| match pinyin {
                Some(pinyin) => vec![apply_style(pinyin, &a.style).to_string()],
                None => vec![],
            })
            .collect()
    }
}

/// 汉字转拼音, 与 ``pinyin`` 的区别是返回值不同，每个汉字只取一个音
///
/// ```
/// let hans = "中国人";
/// let args = pinyin::Args::new();
///
/// // 默认输出 ["zhong", "guo", "ren"]
/// println!("{:?}",  pinyin::lazy_pinyin(hans, &args));
/// ```
#[deprecated = "请使用 `ToPinyin` 代替"]
pub fn lazy_pinyin(s: &str, a: &Args) -> Vec<String> {
    s.to_pinyin()
        .filter_map(identity)
        .map(|pinyin| apply_style(pinyin, &a.style).to_string())
        .collect()
}
<commit_msg>简化compat中的去重代码<commit_after>#![allow(deprecated)]

use crate::{Pinyin, ToPinyin, ToPinyinMulti};
use std::collections::HashSet;
use std::convert::identity;

/// 拼音风格
#[deprecated = "请使用 `Pinyin` 的方法代替"]
#[derive(Debug, PartialEq, Eq, Hash)]
pub enum Style {
    /// 普通风格，不带声调（默认风格）。如： `pin yin`
    Normal,
    /// 声调风格1，拼音声调在韵母第一个字母上。如： `pīn yīn`
    Tone,
    /// 声调风格2，即拼音声调在各个拼音之后，用数字 [0-4] 进行表示。如： `pi1n yi1n`
    Tone2,
    /// 声母风格，只返回各个拼音的声母部分。如： 中国 的拼音 `zh g`
    Initials,
    /// 首字母风格，只返回拼音的首字母部分。如： `p y`
    FirstLetter,
    /// 韵母风格1，只返回各个拼音的韵母部分，不带声调。如： `ong uo`
    Finals,
    /// 韵母风格2，带声调，声调在韵母第一个字母上。如： `ōng uó`
    FinalsTone,
    /// 韵母风格2，带声调，声调在各个拼音之后，用数字 [0-4] 进行表示。如： `o1ng uo2`
    FinalsTone2,
}

/// 参数
#[deprecated]
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct Args {
    /// 拼音风格
    pub style: Style,
    /// 是否启用多音字模式
    pub heteronym: bool,
}

impl Args {
    /// 返回一个默认参数
    ///
    /// ```ignore
    /// Args {
    ///    style: Style::Normal,
    ///    heteronym: false,
    /// }
    /// ```
    pub fn new() -> Args {
        Args {
            style: Style::Normal,
            heteronym: false,
        }
    }
}

impl Default for Args {
    fn default() -> Self {
        Self::new()
    }
}

fn apply_style(py: Pinyin, style: &Style) -> &'static str {
    match style {
        Style::Normal => py.plain(),
        Style::Tone => py.with_tone(),
        Style::Tone2 => py.with_tone_num(),
        Style::Initials => py.initials(),
        Style::FirstLetter => py.first_letter(),
        Style::Finals => py.finals_plain(),
        Style::FinalsTone => py.finals_with_tone(),
        Style::FinalsTone2 => py.finals_with_tone_num(),
    }
}

/// 汉字转拼音
///
/// ```
/// let hans = "中国人";
/// let args = pinyin::Args::new();
///
/// // 默认输出 [["zhong"] ["guo"] ["ren"]]
/// println!("{:?}",  pinyin::pinyin(hans, &args));
/// ```
#[deprecated = "请使用 `ToPinyin` 或 `ToPinyinMulti` 代替"]
pub fn pinyin(s: &str, a: &Args) -> Vec<Vec<String>> {
    if a.heteronym {
        s.to_pinyin_multi()
            .map(|multi| match multi {
                Some(multi) => {
                    let mut set = HashSet::new();
                    multi
                        .into_iter()
                        .map(|pinyin| apply_style(pinyin, &a.style))
                        .filter(|s| set.insert(*s))
                        .map(str::to_string)
                        .collect()
                }
                None => vec![],
            })
            .collect()
    } else {
        s.to_pinyin()
            .map(|pinyin| match pinyin {
                Some(pinyin) => vec![apply_style(pinyin, &a.style).to_string()],
                None => vec![],
            })
            .collect()
    }
}

/// 汉字转拼音, 与 ``pinyin`` 的区别是返回值不同，每个汉字只取一个音
///
/// ```
/// let hans = "中国人";
/// let args = pinyin::Args::new();
///
/// // 默认输出 ["zhong", "guo", "ren"]
/// println!("{:?}",  pinyin::lazy_pinyin(hans, &args));
/// ```
#[deprecated = "请使用 `ToPinyin` 代替"]
pub fn lazy_pinyin(s: &str, a: &Args) -> Vec<String> {
    s.to_pinyin()
        .filter_map(identity)
        .map(|pinyin| apply_style(pinyin, &a.style).to_string())
        .collect()
}
<|endoftext|>


<commit_before>use super::*;

use std::{
    alloc::{alloc, dealloc, Layout},
    fmt,
    ops::Deref,
    sync::atomic::{AtomicUsize, Ordering},
};

const INLINE_LEN_MASK: u8 = 0b0000_1111;
const KIND_MASK: u8 = 0b1111_0000;
const KIND_INLINE: u8 = 0b1000_0000;
const KIND_REMOTE: u8 = 0b0100_0000;

const CUTOFF: usize = std::mem::size_of::<&[u8]>() - 1;
type Inner = [u8; std::mem::size_of::<&[u8]>()];
const ARC_SZ: usize = std::mem::size_of::<AtomicUsize>();

#[derive(Default, Ord, Eq, Serialize, Deserialize)]
pub(crate) struct IVec {
    #[serde(with = "ser")]
    data: Inner,
}

impl IVec {
    pub(crate) fn new(v: &[u8]) -> IVec {
        if v.len() <= CUTOFF {
            let sz = v.len() as u8;
            let tag = KIND_INLINE | sz;

            let mut data: Inner = [0; std::mem::size_of::<Inner>()];
            data[CUTOFF] = tag;

            unsafe {
                std::ptr::copy_nonoverlapping(
                    v.as_ptr(),
                    data.as_mut_ptr(),
                    v.len(),
                );
            }

            IVec { data }
        } else {
            let slice = unsafe {
                let layout = Layout::from_size_align_unchecked(
                    v.len() + ARC_SZ,
                    std::mem::size_of::<AtomicUsize>(),
                );
                let dst = alloc(layout);
                assert_ne!(dst, std::ptr::null_mut());

                // set arc
                let arc: &AtomicUsize = std::mem::transmute(dst);
                arc.store(1, Ordering::SeqCst);

                // copy source to destination
                std::ptr::copy_nonoverlapping(
                    v.as_ptr(),
                    dst.offset(ARC_SZ as isize),
                    v.len(),
                );

                std::slice::from_raw_parts(dst, v.len())
            };

            let mut data: Inner =
                unsafe { std::mem::transmute(slice) };

            assert_eq!(
                data[CUTOFF], 0,
                "we incorrectly assumed that we could use \
                 the highest bits in the length field. please \
                 report this bug ASAP!"
            );

            data[CUTOFF] = KIND_REMOTE;

            IVec { data }
        }
    }

    #[inline]
    fn is_inline(&self) -> bool {
        self.data[CUTOFF] != KIND_REMOTE
    }

    #[inline]
    pub(crate) fn size_in_bytes(&self) -> u64 {
        if self.is_inline() {
            std::mem::size_of::<IVec>() as u64
        } else {
            let sz = std::mem::size_of::<IVec>() as u64;
            sz.saturating_add(self.len() as u64)
        }
    }
}

impl Drop for IVec {
    fn drop(&mut self) {
        if self.is_inline() {
            return;
        }
        let mut data = self.data.clone();
        data[CUTOFF] = 0;

        unsafe {
            // decrement arc
            let arc: &AtomicUsize =
                std::mem::transmute(data.as_ptr());
            if arc.fetch_sub(1, Ordering::SeqCst) != 1 {
                return;
            }

            // arc has hit 0, time to deallocate
            let slice: &mut [u8] = std::mem::transmute(data);
            let len = slice.len();
            let layout = Layout::from_size_align_unchecked(
                len,
                std::mem::size_of::<AtomicUsize>(),
            );

            dealloc(slice.as_mut_ptr(), layout);
        }
    }
}

impl Clone for IVec {
    fn clone(&self) -> IVec {
        if !self.is_inline() {
            // bump arc by 1
            let mut data = self.data.clone();
            data[CUTOFF] = 0;

            unsafe {
                let arc: &AtomicUsize =
                    std::mem::transmute(data.as_ptr());
                arc.fetch_add(1, Ordering::SeqCst);
            }
        }

        IVec { data: self.data }
    }
}

impl From<&[u8]> for IVec {
    fn from(v: &[u8]) -> IVec {
        IVec::new(v)
    }
}

impl From<Vec<u8>> for IVec {
    fn from(v: Vec<u8>) -> IVec {
        IVec::new(&v)
    }
}

impl Deref for IVec {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        if self.is_inline() {
            let base = self.data.as_ptr();
            let tag = self.data[CUTOFF];
            let len = (tag & INLINE_LEN_MASK) as usize;
            unsafe { std::slice::from_raw_parts(base, len) }
        } else {
            let mut data: Inner = self.data;
            data[CUTOFF] = 0;

            unsafe {
                let ptr: &[u8] = std::mem::transmute(data);
                &ptr[ARC_SZ..]
            }
        }
    }
}

impl PartialOrd for IVec {
    fn partial_cmp(
        &self,
        other: &IVec,
    ) -> Option<std::cmp::Ordering> {
        Some(self.deref().cmp(other.deref()))
    }
}

impl PartialEq for IVec {
    fn eq(&self, other: &IVec) -> bool {
        self.deref() == other.deref()
    }
}

impl<'a, T: AsRef<[u8]>> PartialEq<T> for IVec {
    fn eq(&self, other: &T) -> bool {
        self.deref() == other.as_ref()
    }
}

impl PartialEq<[u8]> for IVec {
    fn eq(&self, other: &[u8]) -> bool {
        self.deref() == other
    }
}

impl fmt::Debug for IVec {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "IVec( {:?} )", self.deref())
    }
}

pub(crate) mod ser {
    use super::{IVec, Inner};

    use std::ops::Deref;

    use serde::de::{Deserializer, Visitor};
    use serde::ser::Serializer;

    pub(crate) fn serialize<S>(
        data: &Inner,
        serializer: S,
    ) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let iv = IVec { data: *data };
        let ivr: &[u8] = iv.deref();

        serializer.serialize_bytes(ivr)
    }

    struct IVecVisitor;

    impl<'de> Visitor<'de> for IVecVisitor {
        type Value = IVec;

        fn expecting(
            &self,
            formatter: &mut std::fmt::Formatter,
        ) -> std::fmt::Result {
            formatter.write_str("a borrowed byte array")
        }

        #[inline]
        fn visit_borrowed_bytes<E>(
            self,
            v: &'de [u8],
        ) -> Result<IVec, E> {
            Ok(IVec::new(v))
        }
    }

    pub(crate) fn deserialize<'de, D>(
        deserializer: D,
    ) -> Result<Inner, D::Error>
    where
        D: Deserializer<'de>,
    {
        let iv = deserializer.deserialize_bytes(IVecVisitor)?;
        let data: Inner = iv.data;
        std::mem::forget(iv);
        Ok(data)
    }
}

#[test]
fn ivec_usage() {
    let iv1: IVec = vec![1, 2, 3].into();
    assert_eq!(iv1, vec![1, 2, 3]);
    let iv2 = IVec::new(&[4; 128]);
    assert_eq!(iv2, vec![4; 128]);
}
<commit_msg>Account for actual backing buffer size with Arc included during dealloc<commit_after>use super::*;

use std::{
    alloc::{alloc, dealloc, Layout},
    fmt,
    ops::Deref,
    sync::atomic::{AtomicUsize, Ordering},
};

const INLINE_LEN_MASK: u8 = 0b0000_1111;
const KIND_MASK: u8 = 0b1111_0000;
const KIND_INLINE: u8 = 0b1000_0000;
const KIND_REMOTE: u8 = 0b0100_0000;

const CUTOFF: usize = std::mem::size_of::<&[u8]>() - 1;
type Inner = [u8; std::mem::size_of::<&[u8]>()];
const ARC_SZ: usize = std::mem::size_of::<AtomicUsize>();

#[derive(Default, Ord, Eq, Serialize, Deserialize)]
pub(crate) struct IVec {
    #[serde(with = "ser")]
    data: Inner,
}

impl IVec {
    pub(crate) fn new(v: &[u8]) -> IVec {
        if v.len() <= CUTOFF {
            let sz = v.len() as u8;
            let tag = KIND_INLINE | sz;

            let mut data: Inner = [0; std::mem::size_of::<Inner>()];
            data[CUTOFF] = tag;

            unsafe {
                std::ptr::copy_nonoverlapping(
                    v.as_ptr(),
                    data.as_mut_ptr(),
                    v.len(),
                );
            }

            IVec { data }
        } else {
            let slice = unsafe {
                let layout = Layout::from_size_align_unchecked(
                    v.len() + ARC_SZ,
                    std::mem::size_of::<AtomicUsize>(),
                );
                let dst = alloc(layout);
                assert_ne!(dst, std::ptr::null_mut());

                // set arc
                let arc: &AtomicUsize = std::mem::transmute(dst);
                arc.store(1, Ordering::SeqCst);

                // copy source to destination
                std::ptr::copy_nonoverlapping(
                    v.as_ptr(),
                    dst.offset(ARC_SZ as isize),
                    v.len(),
                );

                std::slice::from_raw_parts(dst, v.len())
            };

            let mut data: Inner =
                unsafe { std::mem::transmute(slice) };

            assert_eq!(
                data[CUTOFF], 0,
                "we incorrectly assumed that we could use \
                 the highest bits in the length field. please \
                 report this bug ASAP!"
            );

            data[CUTOFF] = KIND_REMOTE;

            IVec { data }
        }
    }

    #[inline]
    fn is_inline(&self) -> bool {
        self.data[CUTOFF] != KIND_REMOTE
    }

    #[inline]
    pub(crate) fn size_in_bytes(&self) -> u64 {
        if self.is_inline() {
            std::mem::size_of::<IVec>() as u64
        } else {
            let sz = std::mem::size_of::<IVec>() as u64;
            sz.saturating_add(self.len() as u64)
        }
    }
}

impl Drop for IVec {
    fn drop(&mut self) {
        if self.is_inline() {
            return;
        }
        let mut data = self.data.clone();
        data[CUTOFF] = 0;

        unsafe {
            // decrement arc
            let arc: &AtomicUsize =
                std::mem::transmute(data.as_ptr());
            if arc.fetch_sub(1, Ordering::SeqCst) != 1 {
                return;
            }

            // arc has hit 0, time to deallocate
            let slice: &mut [u8] = std::mem::transmute(data);
            let len = slice.len();
            let layout = Layout::from_size_align_unchecked(
                len + ARC_SZ,
                std::mem::size_of::<AtomicUsize>(),
            );

            dealloc(slice.as_mut_ptr(), layout);
        }
    }
}

impl Clone for IVec {
    fn clone(&self) -> IVec {
        if !self.is_inline() {
            // bump arc by 1
            let mut data = self.data.clone();
            data[CUTOFF] = 0;

            unsafe {
                let arc: &AtomicUsize =
                    std::mem::transmute(data.as_ptr());
                arc.fetch_add(1, Ordering::SeqCst);
            }
        }

        IVec { data: self.data }
    }
}

impl From<&[u8]> for IVec {
    fn from(v: &[u8]) -> IVec {
        IVec::new(v)
    }
}

impl From<Vec<u8>> for IVec {
    fn from(v: Vec<u8>) -> IVec {
        IVec::new(&v)
    }
}

impl Deref for IVec {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        if self.is_inline() {
            let base = self.data.as_ptr();
            let tag = self.data[CUTOFF];
            let len = (tag & INLINE_LEN_MASK) as usize;
            unsafe { std::slice::from_raw_parts(base, len) }
        } else {
            let mut data: Inner = self.data;
            data[CUTOFF] = 0;

            unsafe {
                let ptr: &[u8] = std::mem::transmute(data);
                &ptr[ARC_SZ..]
            }
        }
    }
}

impl PartialOrd for IVec {
    fn partial_cmp(
        &self,
        other: &IVec,
    ) -> Option<std::cmp::Ordering> {
        Some(self.deref().cmp(other.deref()))
    }
}

impl PartialEq for IVec {
    fn eq(&self, other: &IVec) -> bool {
        self.deref() == other.deref()
    }
}

impl<'a, T: AsRef<[u8]>> PartialEq<T> for IVec {
    fn eq(&self, other: &T) -> bool {
        self.deref() == other.as_ref()
    }
}

impl PartialEq<[u8]> for IVec {
    fn eq(&self, other: &[u8]) -> bool {
        self.deref() == other
    }
}

impl fmt::Debug for IVec {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "IVec( {:?} )", self.deref())
    }
}

pub(crate) mod ser {
    use super::{IVec, Inner};

    use std::ops::Deref;

    use serde::de::{Deserializer, Visitor};
    use serde::ser::Serializer;

    pub(crate) fn serialize<S>(
        data: &Inner,
        serializer: S,
    ) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let iv = IVec { data: *data };
        let ivr: &[u8] = iv.deref();

        serializer.serialize_bytes(ivr)
    }

    struct IVecVisitor;

    impl<'de> Visitor<'de> for IVecVisitor {
        type Value = IVec;

        fn expecting(
            &self,
            formatter: &mut std::fmt::Formatter,
        ) -> std::fmt::Result {
            formatter.write_str("a borrowed byte array")
        }

        #[inline]
        fn visit_borrowed_bytes<E>(
            self,
            v: &'de [u8],
        ) -> Result<IVec, E> {
            Ok(IVec::new(v))
        }
    }

    pub(crate) fn deserialize<'de, D>(
        deserializer: D,
    ) -> Result<Inner, D::Error>
    where
        D: Deserializer<'de>,
    {
        let iv = deserializer.deserialize_bytes(IVecVisitor)?;
        let data: Inner = iv.data;
        std::mem::forget(iv);
        Ok(data)
    }
}

#[test]
fn ivec_usage() {
    let iv1: IVec = vec![1, 2, 3].into();
    assert_eq!(iv1, vec![1, 2, 3]);
    let iv2 = IVec::new(&[4; 128]);
    assert_eq!(iv2, vec![4; 128]);
}
<|endoftext|>