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

use super::lexer::{Lexer, LexError};
use super::token::{TokenSpan, Token, Lit};
use super::exec::*; // TODO: remove * import

pub struct Parser<'a> {
    lexer: Lexer<'a>,

    curr: Option<TokenSpan>,
    last: Option<TokenSpan>,
    peek: Option<TokenSpan>,
}

impl<'a> Parser<'a> {
    pub fn from_query(q: &'a str) -> Parser<'a> {
        let lex = Lexer::from_query(q);
        Parser {
            lexer: lex,
            curr: None,
            last: None,
            peek: None,
        }
    }

    pub fn parse(&mut self) -> Result<Query, ParserError> {
        // TODO: handle this with a better error message
        try!(self.bump());
        try!(self.bump());

        self.parse_commands()
    }

    fn bump(&mut self) -> Result<(), ParserError> {
        // do stuff. Mainly swap last = curr, curr = peek, then peek = next_real
        mem::swap(&mut self.last, &mut self.curr);
        mem::swap(&mut self.curr, &mut self.peek);
        self.peek = try!(self.lexer.next_real());
        Ok(())
    }

    // SQL Commands

    fn parse_commands(&mut self) -> Result<Query, ParserError> {
        let curr = self.curr.clone();

        // Parse first word that
        match curr.unwrap().token {
            Token::Word(val) => self.run_major_command(val),
            _ => Err(ParserError::FirstCmdNotWord),
        }
    }

    fn run_major_command(&mut self, cmd: String) -> Result<Query, ParserError> {
        match Keyword::from_str(&*cmd).unwrap() { // TODO: clean up unwrap
            Keyword::Select => self.parse_select(),
            Keyword::Insert => self.parse_insert(),

            _ => Err(ParserError::FirstCmdNotMajor),
        }
    }

    fn parse_select(&mut self) -> Result<Query, ParserError> {
        // TODO: impl parse_select

        Ok(Query::Table(TableStmt::Select(SelectStmt {
            cols: vec![Col { name: "id".to_owned() }],
            table: Table {
                name: "user_v1".to_owned(),
                alias: None,
            },
        })))
    }

    fn parse_insert(&mut self) -> Result<Query, ParserError> {
        // TODO: impl parse_insert
        try!(self.expect_keyword(Keyword::Into));

        //try!();

        try!(self.expect_token(Token::ParentOP));

        let mut cols = Vec::new();

        loop {
            match self.expect_word() {
                Ok(ref word) => {
                    cols.push(word.to_owned());
                    try!(self.expect_token(Token::Comma));
                },
                Err(ParserError::ExpectedToken(_, _)) => {
                    let curr = self.curr.clone().unwrap().token;
                    println!("blah {:?}", curr);

                    match curr {
                        Token::Comma => try!(self.bump()),
                        Token::ParentCL => {
                            try!(self.bump());
                            break;
                        },
                        token => return Err(ParserError::ExpectedToken(Token::Comma, format!("{:?}", token))),
                    }
                },
                Err(err) => return Err(err),
            }
        }

        Ok(Query::Table(TableStmt::Insert(InsertStmt {
            table: Table {
                name: "user_v1".to_owned(),
                alias: None,
            },
            cols: HashMap::new(),
        })))
    }
}

// Helper function
impl<'a> Parser<'a> {
    fn expect_keyword(&mut self, exp: Keyword) -> Result<Keyword, ParserError> {
        // TODO: clean up unwrap but they should be safe for the moment

        try!(self.bump());
        let curr = {
            let token = &self.curr.clone().unwrap();

            match &token.token {
                &Token::Word(ref word) => word.clone(),
                t => return Err(ParserError::ExpectedKeyword(exp, format!("{:?}", t))),
            }
        };

        let actual = try!(Keyword::from_str(&curr));

        if actual == exp {
            Ok(actual)
        } else {
            Err(ParserError::ExpectedKeyword(exp, curr))
        }
    }

    fn expect_token(&mut self, exp: Token)  -> Result<Token, ParserError> {
        try!(self.bump());

        let token = self.curr.clone().unwrap();
        let actual = token.token.clone();

        if actual == exp {
            Ok(actual)
        } else {
            Err(ParserError::ExpectedToken(exp, format!("{:?}", actual)))
        }
    }

    // expect word case insensitive.
    fn expect_word(&mut self) -> Result<String, ParserError> {
        try!(self.bump());

        let token = match self.curr.clone() {
            Some(t) => t,
            None => return Err(ParserError::ExpectedTokenButGotNone),
        };
        let actual = token.token.clone();

        let word = match actual {
            Token::Word(ref word) => word.to_lowercase(), // always lowercase
            t => return Err(ParserError::ExpectedToken(Token::Word(String::new()), format!("{:?}", t))),
        };

        Ok(word)
    }

    fn expect_lit(&mut self) -> Result<Lit, ParserError> {
        try!(self.bump());

        let token = self.curr.clone().unwrap();
        let actual = token.token.clone();

        match actual {
            Token::Literal(lit) => Ok(lit),
            t => Err(ParserError::ExpectedToken(Token::Literal(Lit::String(String::new())), format!("{:?}", t))),
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum Keyword {
    // Major
    Select,
    Insert,

    // Minor
    From,
    Into,
}

impl Keyword {
    pub fn from_str(k: &str) -> Result<Keyword, ParserError> {
        let keyword = match &*k.to_lowercase() {
            "select" => Keyword::Select,
            "insert" => Keyword::Insert,

            "from" => Keyword::From,
            "into" => Keyword::Into,

            // Keyword not found
            keyword => return Err(ParserError::UnexpectedKeyword(keyword.to_owned())), // TODO: clean up panic
        };

        Ok(keyword)
    }
}

#[derive(Debug)]
pub enum ParserError {
    InvalidCommand,
    LexerError(LexError),

    FirstCmdNotWord,
    FirstCmdNotMajor,

    ExpectedKeyword(Keyword, String), // exp, actual
    ExpectedToken(Token, String), // exp, actual
    ExpectedTokenButGotNone,

    UnexpectedKeyword(String),
}

impl From<LexError> for ParserError {
    fn from(e: LexError) -> ParserError {
        ParserError::LexerError(e)
    }
}

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

    #[test]
    fn select() {
        let mut p = Parser::from_query("select");
        p.parse().unwrap();
    }

    #[test]
    fn insert() {
        let mut p = Parser::from_query("insert into (name)");
        let q = p.parse().unwrap();

    }

    #[test]
    #[should_panic]
    fn insert_panic() {
        Parser::from_query("insert into (asdf aslkdfhjahh dsfkjals)").parse().unwrap();
    }

    #[test]
    #[should_panic]
    fn first_non_major() {
        let err = Parser::from_query("alskdfj").parse();
        assert!(err.is_err());
    }
}
<commit_msg>added some more to parser<commit_after>use std::mem;
use std::collections::HashMap;

use super::lexer::{Lexer, LexError};
use super::token::{TokenSpan, Token, Lit};
use super::exec::*; // TODO: remove * import

pub struct Parser<'a> {
    lexer: Lexer<'a>,

    curr: Option<TokenSpan>,
    last: Option<TokenSpan>,
    peek: Option<TokenSpan>,
}

impl<'a> Parser<'a> {
    pub fn from_query(q: &'a str) -> Parser<'a> {
        let lex = Lexer::from_query(q);
        Parser {
            lexer: lex,
            curr: None,
            last: None,
            peek: None,
        }
    }

    pub fn parse(&mut self) -> Result<Query, ParserError> {
        // TODO: handle this with a better error message
        try!(self.bump());
        try!(self.bump());

        self.parse_commands()
    }

    fn bump(&mut self) -> Result<(), ParserError> {
        // do stuff. Mainly swap last = curr, curr = peek, then peek = next_real
        mem::swap(&mut self.last, &mut self.curr);
        mem::swap(&mut self.curr, &mut self.peek);
        self.peek = try!(self.lexer.next_real());
        Ok(())
    }

    // SQL Commands

    fn parse_commands(&mut self) -> Result<Query, ParserError> {
        let curr = self.curr.clone();

        // Parse first word that
        match curr.unwrap().token {
            Token::Word(val) => self.run_major_command(val),
            _ => Err(ParserError::FirstCmdNotWord),
        }
    }

    fn run_major_command(&mut self, cmd: String) -> Result<Query, ParserError> {
        match Keyword::from_str(&*cmd).unwrap() { // TODO: clean up unwrap
            Keyword::Select => self.parse_select(),
            Keyword::Insert => self.parse_insert(),

            _ => Err(ParserError::FirstCmdNotMajor),
        }
    }

    fn parse_select(&mut self) -> Result<Query, ParserError> {
        // TODO: impl parse_select

        Ok(Query::Table(TableStmt::Select(SelectStmt {
            cols: vec![Col { name: "id".to_owned() }],
            table: Table {
                name: "user_v1".to_owned(),
                alias: None,
            },
        })))
    }

    fn parse_insert(&mut self) -> Result<Query, ParserError> {
        // TODO: impl parse_insert
        try!(self.expect_keyword(Keyword::Into));

        //try!();

        try!(self.expect_token(Token::ParentOP));

        let cols = try!(self.expect_comma_dil_word());

        Ok(Query::Table(TableStmt::Insert(InsertStmt {
            table: Table {
                name: "user_v1".to_owned(),
                alias: None,
            },
            cols: HashMap::new(),
        })))
    }
}

// Helper function
impl<'a> Parser<'a> {
    fn expect_keyword(&mut self, exp: Keyword) -> Result<Keyword, ParserError> {
        // TODO: clean up unwrap but they should be safe for the moment

        try!(self.bump());
        let curr = {
            let token = &self.curr.clone().unwrap();

            match &token.token {
                &Token::Word(ref word) => word.clone(),
                t => return Err(ParserError::ExpectedKeyword(exp, format!("{:?}", t))),
            }
        };

        let actual = try!(Keyword::from_str(&curr));

        if actual == exp {
            Ok(actual)
        } else {
            Err(ParserError::ExpectedKeyword(exp, curr))
        }
    }

    fn expect_token(&mut self, exp: Token)  -> Result<Token, ParserError> {
        try!(self.bump());

        let token = self.curr.clone().unwrap();
        let actual = token.token.clone();

        if actual == exp {
            Ok(actual)
        } else {
            Err(ParserError::ExpectedToken(exp, format!("{:?}", actual)))
        }
    }

    // expect word case insensitive.
    fn expect_word(&mut self) -> Result<String, ParserError> {
        try!(self.bump());

        let token = match self.curr.clone() {
            Some(t) => t,
            None => return Err(ParserError::ExpectedTokenButGotNone),
        };
        let actual = token.token.clone();

        let word = match actual {
            Token::Word(ref word) => word.to_lowercase(), // always lowercase
            t => return Err(ParserError::ExpectedToken(Token::Word(String::new()), format!("{:?}", t))),
        };

        Ok(word)
    }

    fn expect_lit(&mut self) -> Result<Lit, ParserError> {
        try!(self.bump());

        let token = self.curr.clone().unwrap();
        let actual = token.token.clone();

        match actual {
            Token::Literal(lit) => Ok(lit),
            t => Err(ParserError::ExpectedToken(Token::Literal(Lit::String(String::new())), format!("{:?}", t))),
        }
    }

    fn expect_comma_dil_word(&mut self) -> Result<Vec<String>, ParserError> {
        let mut cols = Vec::new();

        loop {
            match self.expect_word() {
                Ok(ref word) => {
                    cols.push(word.to_owned());
                    match try!(self.peek_clone()) {
                        Token::Comma => try!(self.bump()),
                        Token::ParentCL => {
                            try!(self.bump());
                            break;
                        },
                        _ => (),
                    }
                },
                Err(ParserError::ExpectedToken(_, _)) => {
                    let curr = self.curr.clone().unwrap().token;

                    match curr {
                        Token::Comma => try!(self.bump()),
                        Token::ParentCL => {
                            try!(self.bump());
                            break;
                        },
                        token => return Err(ParserError::ExpectedToken(Token::Comma, format!("{:?}", token))),
                    }
                },
                Err(err) => return Err(err),
            }
        }

        Ok(cols)
    }

    fn peek_clone(&mut self) -> Result<Token, ParserError> {
        let peek = try!(Self::unwrap_tokenspan(self.peek.clone()));

        Ok(peek.token)
    }

    fn unwrap_tokenspan(t: Option<TokenSpan>) -> Result<TokenSpan, ParserError> {
        match t {
            Some(val) =>  Ok(val),
            None => Err(ParserError::ExpectedTokenButGotNone),
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum Keyword {
    // Major
    Select,
    Insert,

    // Minor
    From,
    Into,
}

impl Keyword {
    pub fn from_str(k: &str) -> Result<Keyword, ParserError> {
        let keyword = match &*k.to_lowercase() {
            "select" => Keyword::Select,
            "insert" => Keyword::Insert,

            "from" => Keyword::From,
            "into" => Keyword::Into,

            // Keyword not found
            keyword => return Err(ParserError::UnexpectedKeyword(keyword.to_owned())), // TODO: clean up panic
        };

        Ok(keyword)
    }
}

#[derive(Debug)]
pub enum ParserError {
    InvalidCommand,
    LexerError(LexError),

    FirstCmdNotWord,
    FirstCmdNotMajor,

    ExpectedKeyword(Keyword, String), // exp, actual
    ExpectedToken(Token, String), // exp, actual
    ExpectedTokenButGotNone,

    UnexpectedKeyword(String),
}

impl From<LexError> for ParserError {
    fn from(e: LexError) -> ParserError {
        ParserError::LexerError(e)
    }
}

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

    #[test]
    fn select() {
        let mut p = Parser::from_query("select");
        p.parse().unwrap();
    }

    #[test]
    fn insert() {
        let mut p = Parser::from_query("insert into (name, email)");
        let q = p.parse().unwrap();

    }

    #[test]
    #[should_panic]
    #[ignore]
    fn insert_panic() {
        Parser::from_query("insert into (asdf aslkdfhjahh dsfkjals)").parse().unwrap();
    }

    #[test]
    #[should_panic]
    fn first_non_major() {
        let err = Parser::from_query("alskdfj").parse();
        assert!(err.is_err());
    }
}
<|endoftext|>


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

#[allow(dead_code,non_camel_case_types,non_snake_case)]
mod ffi;

use libc::{c_ulong};

pub struct Demux {
    device: DeviceFileDescriptor
}

use super::device::{DeviceFileDescriptor,BlockMode,ReadWriteMode,DeviceResult,DeviceError};

impl Demux {
    pub fn open(file: &Path, rw_mode: ReadWriteMode, block_mode: BlockMode) -> DeviceResult<Frontend> {
        let device = try!(DeviceFileDescriptor::open(file, rw_mode, block_mode));
        Ok(Demux { device: device })
    }

    pub fn read(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    // Should this even exist here?
    pub fn write(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn start(&self) -> DeviceResult<()> {
        self.device.ioctl_argumentless(ffi::DMX_START as c_ulong)
    }

    pub fn stop(&self) -> DeviceResult<()> {
        self.device.ioctl_argumentless(ffi::DMX_STOP as c_ulong)
    }

    pub fn set_filter(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn set_pes_filter(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn set_buffer_size(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn get_system_time_counter(&self) -> DeviceResult<SystemTimeCounter> {
        unimplemented!();
    }

    pub fn get_pes_pids(&self) -> DeviceResult<[u16; 5]> {
        unimplemented!();
    }

    pub fn get_caps(&self) -> DeviceResult<DemuxCaps> {
        unimplemented!();
    }

    pub fn set_source(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn add_pid(&self, pid: u16) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn remove_pid(&selfm, pid: u16) -> DeviceResult<()> {
        unimplemented!();
    }
}<commit_msg>Implement demux device's set_buffer_size().<commit_after>// Copyright 2015 Ilkka Rauta
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[allow(dead_code,non_camel_case_types,non_snake_case)]
mod ffi;

use libc::{c_ulong};

pub struct Demux {
    device: DeviceFileDescriptor
}

use super::device::{DeviceFileDescriptor,BlockMode,ReadWriteMode,DeviceResult,DeviceError};

impl Demux {
    pub fn open(file: &Path, rw_mode: ReadWriteMode, block_mode: BlockMode) -> DeviceResult<Frontend> {
        let device = try!(DeviceFileDescriptor::open(file, rw_mode, block_mode));
        Ok(Demux { device: device })
    }

    pub fn read(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    // Should this even exist here?
    pub fn write(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn start(&self) -> DeviceResult<()> {
        self.device.ioctl_argumentless(ffi::DMX_START as c_ulong)
    }

    pub fn stop(&self) -> DeviceResult<()> {
        self.device.ioctl_argumentless(ffi::DMX_STOP as c_ulong)
    }

    pub fn set_filter(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn set_pes_filter(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn set_buffer_size(&self, buffer_size: u32) -> DeviceResult<()> {
        self.device.ioctl_pointer(ffi::DMX_SET_BUFFER_SIZE, &(buffer_size as c_ulong))
    }

    pub fn get_system_time_counter(&self) -> DeviceResult<SystemTimeCounter> {
        unimplemented!();
    }

    pub fn get_pes_pids(&self) -> DeviceResult<[u16; 5]> {
        unimplemented!();
    }

    pub fn get_caps(&self) -> DeviceResult<DemuxCaps> {
        unimplemented!();
    }

    pub fn set_source(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn add_pid(&self, pid: u16) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn remove_pid(&selfm, pid: u16) -> DeviceResult<()> {
        unimplemented!();
    }
}<|endoftext|>


<commit_before>use ast::Expr;
use ast::Function;
use ast::Statement;
use ast::StatementType::*;
use ast::visit::Visitor;

use error::ErrorCode;
use error::ParseError;

use lexer::position::Position;

pub struct ReturnCheck {
    errors: Vec<ParseError>,
}

impl ReturnCheck {
    pub fn new() -> ReturnCheck {
        ReturnCheck { errors: Vec::new() }
    }

    pub fn errors(self) -> Vec<ParseError> {
        self.errors
    }

    fn check_block(self: &mut ReturnCheck, stmts: &mut Vec<Box<Statement>>) -> bool {
        if stmts.len() == 0 {
            return false;
        }

        let mut return_occured = false;

        for stmt in stmts {
            if return_occured {
                self.errors.push(ParseError {
                    position: stmt.position,
                    code: ErrorCode::UnreachableCode,
                    message: format!("statement unreachable")
                });

                return true;
            }

            return_occured = self.visit_stmt(stmt);
        }

        return_occured
    }
}

fn end_position(s: &Statement) -> Position {
    match s.stmt {
        Block(ref stmts) if stmts.len() > 0 => {
            stmts[stmts.len()-1].position
        }

        _ => s.position
    }
}

impl Visitor for ReturnCheck {
    type Returns = bool;

    fn visit_fct(self: &mut ReturnCheck, fct: &mut Function) -> bool {
        let return_occured = if fct.return_type.is_unit() {
            true
        } else {
            self.visit_stmt(&mut fct.block)
        };

        if !return_occured {
            self.errors.push(ParseError {
                position: end_position(&fct.block),
                code: ErrorCode::NoReturnValue,
                message: format!("function `{}` does not return a value in all code paths", fct.name)
            })
        }

        return_occured
    }

    fn visit_stmt(self: &mut ReturnCheck, s: &mut Statement) -> bool {
        match s.stmt {
            If(_, ref mut tblock, ref mut eblock) => {
                let eblock = if eblock.is_some() {
                    self.visit_stmt(eblock.as_mut().unwrap())
                } else {
                    false
                };

                eblock && self.visit_stmt(tblock)
            }

            Block(ref mut stmts) => {
                self.check_block(stmts)
            }

            While(_, ref mut block) => {
                self.visit_stmt(block)
            }

            Loop(ref mut block) => {
                self.visit_stmt(block)
            }

            Return(_) => true,

            _ => false
        }
    }

    fn visit_expr(self: &mut ReturnCheck, _: &mut Expr) -> bool {
        false
    }
}

#[cfg(test)]
mod tests {
    use ast::Function;

    use error::ErrorCode;
    use parser::Parser;

    fn parse(code: &'static str) -> Function {
        let mut prog = Parser::from_str(code).parse().unwrap();

        prog.functions.swap_remove(0)
    }

    fn err(code: &'static str, error_code: ErrorCode, line: u32, col: u32) {
        let err = Parser::from_str(code).parse().unwrap_err();

        assert_eq!(error_code, err.code);
        assert_eq!(line, err.position.line);
        assert_eq!(col, err.position.column);
    }

    #[test]
    fn check_block() {
        err("fn f->int {1;}", ErrorCode::NoReturnValue, 1, 12);
        err("fn f->int {}", ErrorCode::NoReturnValue, 1, 11);
        err("fn f->int {return 1;1;}", ErrorCode::UnreachableCode, 1, 21);
        parse("fn f->int {return 1;}");
    }

    #[test]
    fn check_if() {
        parse("fn f->int {if true {return 1;} else {return 2;}}");
        err("fn f->int {if true {return 1;}}", ErrorCode::NoReturnValue, 1, 12);
        err("fn f->int {if true {return 1;} else {}}", ErrorCode::NoReturnValue, 1, 12);
        err("fn f->int {if true {return 1;} else {return 2;} return 3;}",
           ErrorCode::UnreachableCode, 1, 49);
    }
}
<commit_msg>used backslash to split code<commit_after>use ast::Expr;
use ast::Function;
use ast::Statement;
use ast::StatementType::*;
use ast::visit::Visitor;

use error::ErrorCode;
use error::ParseError;

use lexer::position::Position;

pub struct ReturnCheck {
    errors: Vec<ParseError>,
}

impl ReturnCheck {
    pub fn new() -> ReturnCheck {
        ReturnCheck { errors: Vec::new() }
    }

    pub fn errors(self) -> Vec<ParseError> {
        self.errors
    }

    fn check_block(self: &mut ReturnCheck, stmts: &mut Vec<Box<Statement>>) -> bool {
        if stmts.len() == 0 {
            return false;
        }

        let mut return_occured = false;

        for stmt in stmts {
            if return_occured {
                self.errors.push(ParseError {
                    position: stmt.position,
                    code: ErrorCode::UnreachableCode,
                    message: format!("statement unreachable")
                });

                return true;
            }

            return_occured = self.visit_stmt(stmt);
        }

        return_occured
    }
}

fn end_position(s: &Statement) -> Position {
    match s.stmt {
        Block(ref stmts) if stmts.len() > 0 => {
            stmts[stmts.len()-1].position
        }

        _ => s.position
    }
}

impl Visitor for ReturnCheck {
    type Returns = bool;

    fn visit_fct(self: &mut ReturnCheck, fct: &mut Function) -> bool {
        let return_occured = if fct.return_type.is_unit() {
            true
        } else {
            self.visit_stmt(&mut fct.block)
        };

        if !return_occured {
            self.errors.push(ParseError {
                position: end_position(&fct.block),
                code: ErrorCode::NoReturnValue,
                message: format!("function `{}` does not return a value in all code paths", fct.name)
            })
        }

        return_occured
    }

    fn visit_stmt(self: &mut ReturnCheck, s: &mut Statement) -> bool {
        match s.stmt {
            If(_, ref mut tblock, ref mut eblock) => {
                let eblock = if eblock.is_some() {
                    self.visit_stmt(eblock.as_mut().unwrap())
                } else {
                    false
                };

                eblock && self.visit_stmt(tblock)
            }

            Block(ref mut stmts) => {
                self.check_block(stmts)
            }

            While(_, ref mut block) => {
                self.visit_stmt(block)
            }

            Loop(ref mut block) => {
                self.visit_stmt(block)
            }

            Return(_) => true,

            _ => false
        }
    }

    fn visit_expr(self: &mut ReturnCheck, _: &mut Expr) -> bool {
        false
    }
}

#[cfg(test)]
mod tests {
    use ast::Function;

    use error::ErrorCode;
    use parser::Parser;

    fn parse(code: &'static str) -> Function {
        let mut prog = Parser::from_str(code).parse().unwrap();

        prog.functions.swap_remove(0)
    }

    fn err(code: &'static str, error_code: ErrorCode, line: u32, col: u32) {
        let err = Parser::from_str(code).parse().unwrap_err();

        assert_eq!(error_code, err.code);
        assert_eq!(line, err.position.line);
        assert_eq!(col, err.position.column);
    }

    #[test]
    fn check_block() {
        err("fn f->int {1;}", ErrorCode::NoReturnValue, 1, 12);
        err("fn f->int {}", ErrorCode::NoReturnValue, 1, 11);
        err("fn f->int {return 1;1;}", ErrorCode::UnreachableCode, 1, 21);
        parse("fn f->int {return 1;}");
    }

    #[test]
    fn check_if() {
        parse("fn f->int {\
               if true { return 1; }\
               else { return 2; } }");
        err("fn f->int {\
             if true { return 1; } }", ErrorCode::NoReturnValue, 1, 12);
        err("fn f->int {\
             if true { return 1; } else { } }", ErrorCode::NoReturnValue, 1, 12);
        err("fn f->int {\
             if true { return 1; } else { return 2; }\
             return 3; }",
           ErrorCode::UnreachableCode, 1, 52);
    }
}
<|endoftext|>


<commit_before>use super::response::Response;
use super::request::Request;
use super::alloy::Alloy;

pub enum Status {
    Continue, Unwind
}

pub trait Ingot<Rq: Request, Rs: Response>: Send + Clone {
    fn enter(&mut self, _request: &mut Rq, _response: &mut Rs, _alloy: &mut Alloy) -> Status {
        Continue
    }
    fn exit(&mut self, _request: &mut Rq, _response: &mut Rs, _alloy: &mut Alloy) -> Status {
        Continue
    }
    fn clone_box(&self) -> Box<Ingot<Rq, Rs>> { box self.clone() as Box<Ingot<Rq, Rs>> }
}

impl<Rq: Request, Rs: Response> Clone for Box<Ingot<Rq, Rs>> {
    fn clone(&self) -> Box<Ingot<Rq, Rs>> { self.clone_box() }
}
<commit_msg>(doc) Documented ingot::Status<commit_after>use super::response::Response;
use super::request::Request;
use super::alloy::Alloy;

/// The Status returned by `Ingot's` `enter` and `exit` methods. This indicates
/// to the `Furnace` whether this is a terminal `Ingot` or whether to continue
/// passing the `Request` and `Response` down the `Furnace's` stack.
///
/// Most `Furnaces` will ignore the returned `Status` from the `exit` method of
/// `Ingots`.
pub enum Status {
    /// `Continue` indicates that this is an intermediate `Ingot` in the stack
    /// and the `Furnace` should continue passing requests down the `Furnace's`
    /// stack.
    ///
    /// Most `Ingots` will return `Continue` from both `enter` and `exit`.
    Continue,

    /// `Unwind` indicates that this is a terminal `Ingot` or something went
    /// wrong. It can be used to immediately stop passing requests down the
    /// `Furnace's` stack and start calling `exit` of all previous `Ingots`.
    ///
    /// For instance, an authorization `Ingot` might return `Unwind` if the
    /// request fails an authentication check, and `Continue` otherwise.
    Unwind
}

pub trait Ingot<Rq: Request, Rs: Response>: Send + Clone {
    fn enter(&mut self, _request: &mut Rq, _response: &mut Rs, _alloy: &mut Alloy) -> Status {
        Continue
    }
    fn exit(&mut self, _request: &mut Rq, _response: &mut Rs, _alloy: &mut Alloy) -> Status {
        Continue
    }
    fn clone_box(&self) -> Box<Ingot<Rq, Rs>> { box self.clone() as Box<Ingot<Rq, Rs>> }
}

impl<Rq: Request, Rs: Response> Clone for Box<Ingot<Rq, Rs>> {
    fn clone(&self) -> Box<Ingot<Rq, Rs>> { self.clone_box() }
}
<|endoftext|>


<commit_before>//! Utilities for generalized iterators over trees of arbitrary types.

use super::iter::*;
pub use self::action::Action;

/// Descriptions of actions that may be taken on a given node when traversing
/// a pattern tree.
pub mod action {
    use super::WalkType;

    enum Flag {
        /// Terminate iteration after performing other specified actions.
        TERMINATE = 1,
    }

    pub use self::Flag::*;

    pub struct Action<Type> where Type: WalkType {
        pub yield_value: Option<<Type as WalkType>::Yield>,
        pub recurse: bool,
        pub flags: u8
    }

    impl<'a,Type> Action<Type> where Type: WalkType, <Type as WalkType>::Item: super::Walkable<'a,Type> {
        pub fn new(y: Option<<Type as WalkType>::Yield>, r: bool, f: u8) -> Action<Type> {
            Action{yield_value: y, recurse: r, flags: f}
        }
    }

}

/// Defines a particular kind of walk.
pub trait WalkType {
    /// Type yielded by iterators for this trait.
    type Yield;

    /// Value produced by base iterators for the container being walked.
    /// This should generally *not* include a reference!
    type Item;
}

/// Interface for patterns whose elements may be visited in
/// a runtime-specified manner.
///
/// @tparam Type Walk type this trait works with.
pub trait Walkable<'a,Type: WalkType>: Iterable<'a,Box<Iterator<Item=&'a <Type as WalkType>::Item>>> {
    /// Determine the action to take for a given node in the implementor's
    /// element tree.
    ///
    /// @param element Pattern element to process.
    ///
    /// @return Structure describing the action to be performed for the
    ///     given element.
    fn action(&'a self, element: &'a <Type as WalkType>::Item)
                  -> Action<Type>;
}

/// Provides additional helper methods for implementers of a particular walk type.
pub trait WalkableExt {
    fn walk<'a,W>(&'a self) -> Walker<'a,W>
        where Self: Sized + Walkable<'a,W>,
              W: WalkType,
              <W as WalkType>::Item: 'a {
        Walker::new(self)
    }
}

/// Iterator used to perform a particular walk on a particular type.
///
/// @tparam Tag Walk-type tag.
///
/// @tparam Yield `Item` type for the iterator implementation of
///     the structure.
///
/// @tparam T Top-level Walkable type for which this structure is an iterator.
pub struct Walker<'a,Type>
    where Type: WalkType,
          <Type as WalkType>::Item: 'a {

    walkable: &'a Walkable<'a,Type>,
    base_iterator: Option<Box<Iterator<Item=&'a <Type as WalkType>::Item> + 'a>>,
    sub_iterator: Option<Box<Iterator<Item=<Type as WalkType>::Yield> + 'a>>
}

impl<'a,Type> Walker<'a,Type>
    where Type: WalkType,
          <Type as WalkType>::Item: 'a {
    /// Create a new walker iterator from the given base iterator.
    pub fn new(base: &'a Walkable<'a,Type>) -> Walker<'a,Type> {
        Walker{walkable: base,
               base_iterator: Some(base.iter()),
               sub_iterator: None}
    }
}

impl<'a,Type> Iterator for Walker<'a,Type>
where Type: 'a + WalkType,
      <Type as WalkType>::Yield: 'a,
      <Type as WalkType>::Item: 'a + WalkableExt + Walkable<'a,Type>,
{
    type Item = <Type as WalkType>::Yield;

    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
        let mut terminate: bool = false;
        loop {
            if terminate { self.base_iterator = None;
                           break; }

            // If the sub-iterator exists and isn't exhausted, return its
            // yielded value...
            if let Some(ref mut iter) = self.sub_iterator {
                let yielded_opt = iter.next();
                if yielded_opt.is_some() {
                    return yielded_opt }
            }
            // ...otherwise clear it and check if the base iterator exists
            self.sub_iterator = None;
            if let Some(ref mut iter) = self.base_iterator {
                if let Some(ref element) = iter.next() {
                    let action = self.walkable.action(*element);

                    // FIXME: need to provide a way to specify order in which
                    // to recurse vs. yield.  The solution should allow for
                    // selection of different traversal methods -- need to come
                    // up with an API for that.
                    if action.recurse {
                        self.sub_iterator = Some(Box::new(element.walk::<Type>()));

                        // Recurse immediately if we have no value to yield.
                        if ! action.yield_value.is_some() {
                            continue;
                        }
                    }

                    // For now we'll just do depth-first, since it's simplest.
                    if action.yield_value.is_some() {
                        return action.yield_value;
                    }

                    // Clear the base iterator if we were asked to terminate
                    // the walk.  Note that any recursive walks on
                    // `self.sub_iterator` will continue until that iterator
                    // is exhausted.
                    if (action.flags & action::TERMINATE as u8) != 0 {
                        terminate = true; }
                } else {
                    // Base iterator is exhausted; clear it.
                    terminate = true;
                }
            }
        }
        if terminate { self.base_iterator = None; }
        return None;
    }

    /// We implement `size_hint` as the sum of the hints for the current base-
    /// and sub-iterators, if they're not `None`.  We return an upper bound
    /// only if both iterators are `None`.
    fn size_hint(&self) -> (usize, Option<usize>) {
        let mut min = 0;
        if let Some(ref iter) = self.sub_iterator { min += iter.size_hint().0 }
        if let Some(ref iter) = self.base_iterator { min += iter.size_hint().0 }

        (min, if self.sub_iterator.is_none() && self.base_iterator.is_none() { Some(0) } else { None })
    }
}
<commit_msg>WIP on rework of pattern::walk module<commit_after>//! Utilities for generalized iterators over trees of arbitrary types.

use std;
use std::iter::IntoIterator;

use util::flex_box::*;
pub use self::action::Action;

/// Descriptions of actions that may be taken on a given node when traversing
/// a pattern tree.
pub mod action {
    use super::WalkType;

    enum Flag {
        /// Terminate iteration after performing other specified actions.
        TERMINATE = 1,
    }

    pub use self::Flag::*;

    pub struct Action<Type> where Type: WalkType {
        pub yield_value: Option<<Type as WalkType>::Yield>,
        pub recurse: bool,
        pub flags: u8
    }

    impl<'a,Type> Action<Type> where Type: WalkType, <Type as WalkType>::Item: super::Walkable<Type> {
        #[inline]
        pub fn new(y: Option<<Type as WalkType>::Yield>, r: bool, f: u8) -> Action<Type> {
            Action{yield_value: y, recurse: r, flags: f}
        }
    }

}

/// Defines a particular kind of walk.
pub trait WalkType {
    /// Type yielded by iterators for this trait.
    type Yield;

    /// Value produced by base iterators for the container being walked.
    /// This should generally *not* include a reference!
    type Item;
}

/// Interface for patterns whose elements may be visited in
/// a runtime-specified manner.
///
/// @tparam Type Walk type this trait works with.
pub trait Walkable<Type: WalkType>
{
    /// Determine the action to take for a given node in the implementor's
    /// element tree.
    ///
    /// @param element Pattern element to process.
    ///
    /// @return Structure describing the action to be performed for the
    ///     given element.
    fn action<'a>(&'a self, element: &'a <Type as WalkType>::Item)
                  -> Action<Type>;
}

/// Provides additional helper methods for implementers of a particular walk type.
pub trait WalkableExt {
    #[inline(always)]
    fn walk<'a,'b,W>(&'a self) -> Walker<'b,W,Self>
    where 'a: 'b,
          Self: 'b + Sized + Walkable<W>,
          W: 'b + WalkType,
          <W as WalkType>::Yield: 'b,
          <W as WalkType>::Item: 'b
          //,<Self as Iterable<<W as WalkType>::Item>>::Iterator: 'b
{
        Walker::new(self)
    }
}

/// Iterator used to perform a particular walk on a particular type.
///
/// @tparam Walk Walk type
/// @tparam T Type of the value being walked.
pub struct Walker<'a, Walk, T>
    where Walk: 'a + WalkType,
          <Walk as WalkType>::Yield: 'a,
          <Walk as WalkType>::Item: 'a,
          T: 'a + Walkable<Walk>,
          &'a T: IntoIterator,
          <&'a T as IntoIterator>::Item: 'a,
          <&'a T as IntoIterator>::IntoIter: 'a
{
    walkable: &'a T,
    base_iterator: Option<Ref<'a,Iterator<Item=<Walk as WalkType>::Item>>>,
    sub_iterator_box: FlexBox,
    sub_iterator: Option<Ref<'a,Walker<'a,Walk,T>>>
}

impl<'a,Walk,T> Walker<'a,Walk,T>
    where Walk: 'a + WalkType,
          <Walk as WalkType>::Yield: 'a,
          <Walk as WalkType>::Item: 'a,
          T: 'a + Walkable<Walk>,
          &'a T: IntoIterator,
          <&'a T as IntoIterator>::Item: 'a
          //,<T as Iterable<<Walk as WalkType>::Item>>::Iterator: 'a

{
    /// Create a new walker iterator from the given base iterator.
    pub fn new(base: &'a T) -> Walker<'a,Walk,T> {
        Walker{walkable: base,
               base_iterator: Some(base.into_iter()),
               sub_iterator_box: FlexBox::new(),
               sub_iterator: None}
    }
}

impl<'a,Type,T> std::iter::Iterator for Walker<'a,Type,T>
where Type: 'a + WalkType,
      <Type as WalkType>::Yield: 'a,
      <Type as WalkType>::Item: 'a + Walkable<Type>,
      &'a T: IntoIterator,
      <&'a T as IntoIterator>::Item: 'a,
      T: 'a + Walkable<Type>,
{
    type Item = <Type as WalkType>::Yield;

    fn next(&mut self) -> Option<<Type as WalkType>::Yield> {
        let mut terminate: bool = false;
        loop {
            if terminate { self.base_iterator = None;
                           break; }

            // If the sub-iterator exists and isn't exhausted, return its
            // yielded value...
            if let Some(ref mut iter) = self.sub_iterator {
                let yielded_opt = iter.next();
                if yielded_opt.is_some() {
                    return yielded_opt }
            }
            // ...otherwise clear it and check if the base iterator exists
            self.sub_iterator = None;
            if let Some(ref mut iter) = self.base_iterator {
                if let Some(ref element) = iter.next() {
                    let action = self.walkable.action(element);

                    // FIXME: need to provide a way to specify order in which
                    // to recurse vs. yield.  The solution should allow for
                    // selection of different traversal methods -- need to come
                    // up with an API for that.
                    if action.recurse {
                        self.sub_iterator = Some(self.sub_iterator_box.store(element.walk::<Type>()));

                        // Recurse immediately if we have no value to yield.
                        if ! action.yield_value.is_some() {
                            continue;
                        }
                    }

                    // For now we'll just do depth-first, since it's simplest.
                    if action.yield_value.is_some() {
                        return action.yield_value;
                    }

                    // Clear the base iterator if we were asked to terminate
                    // the walk.  Note that any recursive walks on
                    // `self.sub_iterator` will continue until that iterator
                    // is exhausted.
                    if (action.flags & action::TERMINATE as u8) != 0 {
                        terminate = true; }
                } else {
                    // Base iterator is exhausted; clear it.
                    terminate = true;
                }
            }
        }
        if terminate { self.base_iterator = None; }
        return None;
    }

    /// We implement `size_hint` as the sum of the hints for the current base-
    /// and sub-iterators, if they're not `None`.  We return an upper bound
    /// only if both iterators are `None`.
    fn size_hint(&self) -> (usize, Option<usize>) {
        let mut min = 0;
        if let Some(ref iter) = self.sub_iterator { min += iter.size_hint().0 }
        if let Some(ref iter) = self.base_iterator { min += iter.size_hint().0 }

        (min, if self.sub_iterator.is_none() && self.base_iterator.is_none() { Some(0) } else { None })
    }
}
<|endoftext|>


<commit_before>#[link(name = "protobuf", vers = "0.1.0")];
#[crate_type = "lib"];
#[feature(globs)];
#[feature(managed_boxes)];

#[desc = "protobuf implementation for rust"];
#[license = "BSD"];
#[author = "Stepan Koltsov"];

pub use core::*;

mod core;
pub mod descriptor;
pub mod codegen;
pub mod rt;
mod misc;
mod zigzag;
mod hex;

#[cfg(test)]
mod shrug;
#[cfg(test)]
mod test;

// so `use protobuf::*` could work in descriptor mod
pub mod protobuf {
    pub use descriptor;
    pub use codegen;
    pub use core::*;
    pub use rt;
}
<commit_msg>Remove testing imports temporarily<commit_after>#[link(name = "protobuf", vers = "0.1.0")];
#[crate_type = "lib"];
#[feature(globs)];
#[feature(managed_boxes)];

#[desc = "protobuf implementation for rust"];
#[license = "BSD"];
#[author = "Stepan Koltsov"];

pub use core::*;

mod core;
pub mod descriptor;
pub mod codegen;
pub mod rt;
mod misc;
mod zigzag;
mod hex;

// so `use protobuf::*` could work in descriptor mod
pub mod protobuf {
    pub use descriptor;
    pub use codegen;
    pub use core::*;
    pub use rt;
}
<|endoftext|>


<commit_before>// Bloom
//
// HTTP REST API caching middleware
// Copyright: 2017, Valerian Saliou <valerian@valeriansaliou.name>
// License: Mozilla Public License v2.0 (MPL v2.0)

use futures::{future, Future};
use hyper::client::{HttpConnector, Response};
use hyper::{Body, Client, Error, Headers, Method, Request, Uri};
use std::time::Duration;

use crate::server::listen::LISTEN_REMOTE;
use crate::APP_CONF;

const MAX_SHARDS: u8 = 16;
const CLIENT_KEEP_ALIVE_TIMEOUT_SECONDS: u64 = 30;

lazy_static! {
    static ref SHARD_REGISTER: [Option<Uri>; MAX_SHARDS as usize] = map_shards();
}

thread_local! {
    static TUNNEL_CLIENT: Client<HttpConnector> = make_client();
}

pub struct ProxyTunnel;

pub type ProxyTunnelFuture = Box<Future<Item = Response, Error = Error>>;

fn make_client() -> Client<HttpConnector> {
    Client::configure()
        .keep_alive(true)
        .keep_alive_timeout(Some(Duration::from_secs(CLIENT_KEEP_ALIVE_TIMEOUT_SECONDS)))
        .build(
            &LISTEN_REMOTE
                .lock()
                .unwrap()
                .get_mut()
                .to_owned()
                .unwrap()
                .handle()
                .unwrap(),
        )
}

fn map_shards() -> [Option<Uri>; MAX_SHARDS as usize] {
    // Notice: this array cannot be initialized using the short format, as hyper::Uri doesnt \
    //   implement the Copy trait, hence the ugly hardcoded initialization vector w/ Nones.
    let mut shards = [
        None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
        None,
    ];

    for shard in &APP_CONF.proxy.shard {
        // Shard number overflows?
        if shard.shard >= MAX_SHARDS {
            panic!("shard number overflows maximum of {} shards", MAX_SHARDS);
        }

        // Store this shard
        shards[shard.shard as usize] = Some(
            format!(
                "http://{}:{}",
                APP_CONF.proxy.shard[0].host, APP_CONF.proxy.shard[0].port
            )
            .parse()
            .expect("could not build shard uri"),
        );
    }

    shards
}

impl ProxyTunnel {
    pub fn run(
        method: &Method,
        uri: &Uri,
        headers: &Headers,
        body: Body,
        shard: u8,
    ) -> ProxyTunnelFuture {
        if shard < MAX_SHARDS {
            // Route to target shard
            match SHARD_REGISTER[shard as usize] {
                Some(ref shard_uri) => {
                    let mut tunnel_uri = format!("{}{}", shard_uri, uri.path());

                    if let Some(query) = uri.query() {
                        tunnel_uri.push_str("?");
                        tunnel_uri.push_str(query);
                    }

                    match tunnel_uri.parse() {
                        Ok(tunnel_uri) => {
                            let mut tunnel_req = Request::new(method.to_owned(), tunnel_uri);

                            // Forward headers
                            {
                                let tunnel_headers = tunnel_req.headers_mut();

                                tunnel_headers.clone_from(headers);
                            }

                            // Forward body?
                            // Notice: HTTP DELETE is not forbidden per-spec to hold a request \
                            //   body, even if it is not commonly used. Hence why we forward it.
                            match method {
                                &Method::Post | &Method::Patch | &Method::Put | &Method::Delete => {
                                    tunnel_req.set_body(body);
                                }
                                _ => {}
                            }

                            TUNNEL_CLIENT.with(|client| Box::new(client.request(tunnel_req)))
                        }
                        Err(err) => Box::new(future::err(Error::Uri(err))),
                    }
                }
                None => Box::new(future::err(Error::Header)),
            }
        } else {
            // Shard out of bounds
            Box::new(future::err(Error::Header))
        }
    }
}
<commit_msg>Fix “//“ in proxied URIs<commit_after>// Bloom
//
// HTTP REST API caching middleware
// Copyright: 2017, Valerian Saliou <valerian@valeriansaliou.name>
// License: Mozilla Public License v2.0 (MPL v2.0)

use futures::{future, Future};
use hyper::client::{HttpConnector, Response};
use hyper::{Body, Client, Error, Headers, Method, Request, Uri};
use std::time::Duration;

use crate::server::listen::LISTEN_REMOTE;
use crate::APP_CONF;

const MAX_SHARDS: u8 = 16;
const CLIENT_KEEP_ALIVE_TIMEOUT_SECONDS: u64 = 30;

lazy_static! {
    static ref SHARD_REGISTER: [Option<Uri>; MAX_SHARDS as usize] = map_shards();
}

thread_local! {
    static TUNNEL_CLIENT: Client<HttpConnector> = make_client();
}

pub struct ProxyTunnel;

pub type ProxyTunnelFuture = Box<Future<Item = Response, Error = Error>>;

fn make_client() -> Client<HttpConnector> {
    Client::configure()
        .keep_alive(true)
        .keep_alive_timeout(Some(Duration::from_secs(CLIENT_KEEP_ALIVE_TIMEOUT_SECONDS)))
        .build(
            &LISTEN_REMOTE
                .lock()
                .unwrap()
                .get_mut()
                .to_owned()
                .unwrap()
                .handle()
                .unwrap(),
        )
}

fn map_shards() -> [Option<Uri>; MAX_SHARDS as usize] {
    // Notice: this array cannot be initialized using the short format, as hyper::Uri doesnt \
    //   implement the Copy trait, hence the ugly hardcoded initialization vector w/ Nones.
    let mut shards = [
        None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
        None,
    ];

    for shard in &APP_CONF.proxy.shard {
        // Shard number overflows?
        if shard.shard >= MAX_SHARDS {
            panic!("shard number overflows maximum of {} shards", MAX_SHARDS);
        }

        // Store this shard
        shards[shard.shard as usize] = Some(
            format!(
                "http://{}:{}",
                APP_CONF.proxy.shard[0].host, APP_CONF.proxy.shard[0].port
            )
            .parse()
            .expect("could not build shard uri"),
        );
    }

    shards
}

impl ProxyTunnel {
    pub fn run(
        method: &Method,
        uri: &Uri,
        headers: &Headers,
        body: Body,
        shard: u8,
    ) -> ProxyTunnelFuture {
        if shard < MAX_SHARDS {
            // Route to target shard
            match SHARD_REGISTER[shard as usize] {
                Some(ref shard_uri) => {
                    let mut tunnel_uri = format!(
                        "{}://{}{}",
                        shard_uri.scheme().unwrap_or(""),
                        shard_uri.authority().unwrap_or(""),
                        uri.path()
                    );

                    if let Some(query) = uri.query() {
                        tunnel_uri.push_str("?");
                        tunnel_uri.push_str(query);
                    }

                    match tunnel_uri.parse() {
                        Ok(tunnel_uri) => {
                            let mut tunnel_req = Request::new(method.to_owned(), tunnel_uri);

                            // Forward headers
                            {
                                let tunnel_headers = tunnel_req.headers_mut();

                                tunnel_headers.clone_from(headers);
                            }

                            // Forward body?
                            // Notice: HTTP DELETE is not forbidden per-spec to hold a request \
                            //   body, even if it is not commonly used. Hence why we forward it.
                            match method {
                                &Method::Post | &Method::Patch | &Method::Put | &Method::Delete => {
                                    tunnel_req.set_body(body);
                                }
                                _ => {}
                            }

                            TUNNEL_CLIENT.with(|client| Box::new(client.request(tunnel_req)))
                        }
                        Err(err) => Box::new(future::err(Error::Uri(err))),
                    }
                }
                None => Box::new(future::err(Error::Header)),
            }
        } else {
            // Shard out of bounds
            Box::new(future::err(Error::Header))
        }
    }
}
<|endoftext|>


<commit_before>use expression::{Expression, AsExpression, nullable};
use expression::aliased::Aliased;
use expression::array_comparison::{In, AsInExpression};
use expression::predicates::*;

pub trait ExpressionMethods: Expression + Sized {
    /// Alias an expression for use alongside
    /// [`with`](../../../trait.WithDsl.html).
    ///
    /// While you will need to give it a name to alias as, you should not need
    /// to reference the alias elsewhere. You can pass the returned expression
    /// anywhere you want to reference the alias.
    ///
    /// # Example
    ///
    /// ```ignore
    /// let query = plain_to_tsquery(search_text).aliased("q");
    /// let rank = ts_rank(query, indexed_search_column).aliased("rank");
    /// crates.with(query).with(rank)
    ///     .filter(query.matches(indexed_search_column))
    ///     .order(rank.desc())
    /// ```
    fn aliased<'a>(self, alias: &'a str) -> Aliased<'a, Self> {
        Aliased::new(self, alias)
    }

    /// Creates a SQL `=` expression.
    ///
    /// # Example
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("src/doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users {
    /// #         id -> Integer,
    /// #         name -> VarChar,
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     let connection = establish_connection();
    /// let data = users.select(id).filter(name.eq("Sean"));
    /// assert_eq!(Ok(1), data.first(&connection));
    /// # }
    /// ```
    fn eq<T: AsExpression<Self::SqlType>>(self, other: T) -> Eq<Self, T::Expression> {
        Eq::new(self, other.as_expression())
    }

    /// Creates a SQL `!=` expression.
    ///
    /// # Example
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("src/doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users {
    /// #         id -> Integer,
    /// #         name -> VarChar,
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     let connection = establish_connection();
    /// let data = users.select(id).filter(name.ne("Sean"));
    /// assert_eq!(Ok(2), data.first(&connection));
    /// # }
    /// ```
    fn ne<T: AsExpression<Self::SqlType>>(self, other: T) -> NotEq<Self, T::Expression> {
        NotEq::new(self, other.as_expression())
    }

    /// Creates a SQL `IN` statement. Queries using this method will not be
    /// placed in the prepared statement cache. On PostgreSQL, you should use
    /// `eq(any())` instead. This method may change in the future to
    /// automatically perform `= ANY` on PostgreSQL.
    ///
    /// # Example
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("src/doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users {
    /// #         id -> Integer,
    /// #         name -> VarChar,
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     let connection = establish_connection();
    /// #     connection.execute("INSERT INTO users (name) VALUES
    /// #         ('Jim')").unwrap();
    /// let data = users.select(id).filter(name.eq_any(vec!["Sean", "Jim"]));
    /// assert_eq!(Ok(vec![1, 3]), data.load(&connection));
    /// # }
    /// ```
    fn eq_any<T>(self, values: T) -> In<Self, T::InExpression> where
        T: AsInExpression<Self::SqlType>,
    {
        In::new(self, values.as_in_expression())
    }

    /// Creates a SQL `IS NULL` expression.
    fn is_null(self) -> IsNull<Self> {
       IsNull::new(self)
    }

    /// Creates a SQL `IS NOT NULL` expression.
    fn is_not_null(self) -> IsNotNull<Self> {
       IsNotNull::new(self)
    }

    /// Creates a SQL `>` expression.
    ///
    /// # Example
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("src/doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users {
    /// #         id -> Integer,
    /// #         name -> VarChar,
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     let connection = establish_connection();
    /// let data = users.select(name).filter(id.gt(1));
    /// assert_eq!(Ok("Tess".to_string()), data.first(&connection));
    /// # }
    /// ```
    fn gt<T: AsExpression<Self::SqlType>>(self, other: T) -> Gt<Self, T::Expression> {
        Gt::new(self, other.as_expression())
    }

    /// Creates a SQL `>=` expression.
    ///
    /// # Example
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("src/doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users {
    /// #         id -> Integer,
    /// #         name -> VarChar,
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     let connection = establish_connection();
    /// let data = users.select(name).filter(id.ge(2));
    /// assert_eq!(Ok("Tess".to_string()), data.first(&connection));
    /// # }
    /// ```
    fn ge<T: AsExpression<Self::SqlType>>(self, other: T) -> GtEq<Self, T::Expression> {
        GtEq::new(self, other.as_expression())
    }

    /// Creates a SQL `<` expression.
    ///
    /// # Example
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("src/doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users {
    /// #         id -> Integer,
    /// #         name -> VarChar,
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     let connection = establish_connection();
    /// let data = users.select(name).filter(id.lt(2));
    /// assert_eq!(Ok("Sean".to_string()), data.first(&connection));
    /// # }
    /// ```
    fn lt<T: AsExpression<Self::SqlType>>(self, other: T) -> Lt<Self, T::Expression> {
        Lt::new(self, other.as_expression())
    }

    /// Creates a SQL `<=` expression.
    ///
    /// # Example
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("src/doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users {
    /// #         id -> Integer,
    /// #         name -> VarChar,
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     let connection = establish_connection();
    /// let data = users.select(name).filter(id.le(2));
    /// assert_eq!(Ok("Sean".to_string()), data.first(&connection));
    /// # }
    fn le<T: AsExpression<Self::SqlType>>(self, other: T) -> LtEq<Self, T::Expression> {
        LtEq::new(self, other.as_expression())
    }

    /// Creates a SQL `BETWEEN` expression using the given range.
    fn between<T: AsExpression<Self::SqlType>>(self, other: ::std::ops::Range<T>)
    -> Between<Self, And<T::Expression, T::Expression>> {
        Between::new(self, And::new(other.start.as_expression(), other.end.as_expression()))
    }

    /// Creates a SQL `NOT BETWEEN` expression using the given range.
    fn not_between<T: AsExpression<Self::SqlType>>(self, other: ::std::ops::Range<T>)
    -> NotBetween<Self, And<T::Expression, T::Expression>> {
        NotBetween::new(self, And::new(other.start.as_expression(), other.end.as_expression()))
    }

    /// Creates a SQL `DESC` expression, representing this expression in
    /// descending order.
    fn desc(self) -> Desc<Self> {
        Desc::new(self)
    }

    /// Creates a SQL `ASC` expression, representing this expression in
    /// descending order.
    ///
    /// This is the same as leaving the direction unspecified. It is useful if
    /// you need to provide an unknown ordering, and need to box the return
    /// value of a function.
    ///
    /// # Example
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("src/doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users {
    /// #         id -> Integer,
    /// #         name -> VarChar,
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     let order = "name";
    /// let ordering: Box<BoxableExpression<users, (), DB, SqlType=()>> =
    ///     if order == "name" {
    ///         Box::new(name.desc())
    ///     } else {
    ///         Box::new(id.asc())
    ///     };
    /// # }
    /// ```
    fn asc(self) -> Asc<Self> {
        Asc::new(self)
    }

    /// Converts this potentially non-null expression into one which is treated
    /// as nullable. This method has no impact on the generated SQL, and is only
    /// used to allow certain comparisons that would otherwise fail to compile.
    ///
    /// # Example
    /// ```no_run
    /// # #![allow(dead_code)]
    /// # #[macro_use] extern crate diesel;
    /// # include!("src/doctest_setup.rs");
    /// # use self::diesel::types::*;
    /// #
    /// table! {
    ///     users {
    ///         id -> Integer,
    ///         name -> VarChar,
    ///     }
    /// }
    ///
    /// table! {
    ///     posts {
    ///         id -> Integer,
    ///         user_id -> Integer,
    ///         author_name -> Nullable<VarChar>,
    ///     }
    /// }
    /// #
    /// #  pub struct User {
    /// #      id: i32,
    /// #      name: VarChar,
    /// #  }
    /// #
    /// #  pub struct Post {
    /// #      id: i32,
    /// #      user_id: i32,
    /// #      author_name: Option<VarChar>,
    /// #  }
    /// #
    /// #  joinable!(posts -> users (user_id));
    /// #  select_column_workaround!(posts -> users (id, user_id, author_name));
    /// #  select_column_workaround!(users -> posts (id, name));
    ///
    /// fn main() {
    ///     use self::users::dsl::*;
    ///     use self::posts::dsl::{posts, author_name};
    ///     let connection = establish_connection();
    ///
    ///     let data = users.inner_join(posts)
    ///         .filter(name.nullable().eq(author_name))
    ///         .select(name)
    ///         .load::<String>(&connection);
    ///     println!("{:?}", data);
    /// }
    fn nullable(self) -> nullable::Nullable<Self> {
        nullable::Nullable::new(self)
    }
}

impl<T: Expression> ExpressionMethods for T {}
<commit_msg>Fixed typo in doc: global_expression_methods.rs<commit_after>use expression::{Expression, AsExpression, nullable};
use expression::aliased::Aliased;
use expression::array_comparison::{In, AsInExpression};
use expression::predicates::*;

pub trait ExpressionMethods: Expression + Sized {
    /// Alias an expression for use alongside
    /// [`with`](../../../trait.WithDsl.html).
    ///
    /// While you will need to give it a name to alias as, you should not need
    /// to reference the alias elsewhere. You can pass the returned expression
    /// anywhere you want to reference the alias.
    ///
    /// # Example
    ///
    /// ```ignore
    /// let query = plain_to_tsquery(search_text).aliased("q");
    /// let rank = ts_rank(query, indexed_search_column).aliased("rank");
    /// crates.with(query).with(rank)
    ///     .filter(query.matches(indexed_search_column))
    ///     .order(rank.desc())
    /// ```
    fn aliased<'a>(self, alias: &'a str) -> Aliased<'a, Self> {
        Aliased::new(self, alias)
    }

    /// Creates a SQL `=` expression.
    ///
    /// # Example
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("src/doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users {
    /// #         id -> Integer,
    /// #         name -> VarChar,
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     let connection = establish_connection();
    /// let data = users.select(id).filter(name.eq("Sean"));
    /// assert_eq!(Ok(1), data.first(&connection));
    /// # }
    /// ```
    fn eq<T: AsExpression<Self::SqlType>>(self, other: T) -> Eq<Self, T::Expression> {
        Eq::new(self, other.as_expression())
    }

    /// Creates a SQL `!=` expression.
    ///
    /// # Example
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("src/doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users {
    /// #         id -> Integer,
    /// #         name -> VarChar,
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     let connection = establish_connection();
    /// let data = users.select(id).filter(name.ne("Sean"));
    /// assert_eq!(Ok(2), data.first(&connection));
    /// # }
    /// ```
    fn ne<T: AsExpression<Self::SqlType>>(self, other: T) -> NotEq<Self, T::Expression> {
        NotEq::new(self, other.as_expression())
    }

    /// Creates a SQL `IN` statement. Queries using this method will not be
    /// placed in the prepared statement cache. On PostgreSQL, you should use
    /// `eq(any())` instead. This method may change in the future to
    /// automatically perform `= ANY` on PostgreSQL.
    ///
    /// # Example
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("src/doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users {
    /// #         id -> Integer,
    /// #         name -> VarChar,
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     let connection = establish_connection();
    /// #     connection.execute("INSERT INTO users (name) VALUES
    /// #         ('Jim')").unwrap();
    /// let data = users.select(id).filter(name.eq_any(vec!["Sean", "Jim"]));
    /// assert_eq!(Ok(vec![1, 3]), data.load(&connection));
    /// # }
    /// ```
    fn eq_any<T>(self, values: T) -> In<Self, T::InExpression> where
        T: AsInExpression<Self::SqlType>,
    {
        In::new(self, values.as_in_expression())
    }

    /// Creates a SQL `IS NULL` expression.
    fn is_null(self) -> IsNull<Self> {
       IsNull::new(self)
    }

    /// Creates a SQL `IS NOT NULL` expression.
    fn is_not_null(self) -> IsNotNull<Self> {
       IsNotNull::new(self)
    }

    /// Creates a SQL `>` expression.
    ///
    /// # Example
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("src/doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users {
    /// #         id -> Integer,
    /// #         name -> VarChar,
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     let connection = establish_connection();
    /// let data = users.select(name).filter(id.gt(1));
    /// assert_eq!(Ok("Tess".to_string()), data.first(&connection));
    /// # }
    /// ```
    fn gt<T: AsExpression<Self::SqlType>>(self, other: T) -> Gt<Self, T::Expression> {
        Gt::new(self, other.as_expression())
    }

    /// Creates a SQL `>=` expression.
    ///
    /// # Example
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("src/doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users {
    /// #         id -> Integer,
    /// #         name -> VarChar,
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     let connection = establish_connection();
    /// let data = users.select(name).filter(id.ge(2));
    /// assert_eq!(Ok("Tess".to_string()), data.first(&connection));
    /// # }
    /// ```
    fn ge<T: AsExpression<Self::SqlType>>(self, other: T) -> GtEq<Self, T::Expression> {
        GtEq::new(self, other.as_expression())
    }

    /// Creates a SQL `<` expression.
    ///
    /// # Example
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("src/doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users {
    /// #         id -> Integer,
    /// #         name -> VarChar,
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     let connection = establish_connection();
    /// let data = users.select(name).filter(id.lt(2));
    /// assert_eq!(Ok("Sean".to_string()), data.first(&connection));
    /// # }
    /// ```
    fn lt<T: AsExpression<Self::SqlType>>(self, other: T) -> Lt<Self, T::Expression> {
        Lt::new(self, other.as_expression())
    }

    /// Creates a SQL `<=` expression.
    ///
    /// # Example
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("src/doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users {
    /// #         id -> Integer,
    /// #         name -> VarChar,
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     let connection = establish_connection();
    /// let data = users.select(name).filter(id.le(2));
    /// assert_eq!(Ok("Sean".to_string()), data.first(&connection));
    /// # }
    fn le<T: AsExpression<Self::SqlType>>(self, other: T) -> LtEq<Self, T::Expression> {
        LtEq::new(self, other.as_expression())
    }

    /// Creates a SQL `BETWEEN` expression using the given range.
    fn between<T: AsExpression<Self::SqlType>>(self, other: ::std::ops::Range<T>)
    -> Between<Self, And<T::Expression, T::Expression>> {
        Between::new(self, And::new(other.start.as_expression(), other.end.as_expression()))
    }

    /// Creates a SQL `NOT BETWEEN` expression using the given range.
    fn not_between<T: AsExpression<Self::SqlType>>(self, other: ::std::ops::Range<T>)
    -> NotBetween<Self, And<T::Expression, T::Expression>> {
        NotBetween::new(self, And::new(other.start.as_expression(), other.end.as_expression()))
    }

    /// Creates a SQL `DESC` expression, representing this expression in
    /// descending order.
    fn desc(self) -> Desc<Self> {
        Desc::new(self)
    }

    /// Creates a SQL `ASC` expression, representing this expression in
    /// ascending order.
    ///
    /// This is the same as leaving the direction unspecified. It is useful if
    /// you need to provide an unknown ordering, and need to box the return
    /// value of a function.
    ///
    /// # Example
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("src/doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users {
    /// #         id -> Integer,
    /// #         name -> VarChar,
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     let order = "name";
    /// let ordering: Box<BoxableExpression<users, (), DB, SqlType=()>> =
    ///     if order == "name" {
    ///         Box::new(name.desc())
    ///     } else {
    ///         Box::new(id.asc())
    ///     };
    /// # }
    /// ```
    fn asc(self) -> Asc<Self> {
        Asc::new(self)
    }

    /// Converts this potentially non-null expression into one which is treated
    /// as nullable. This method has no impact on the generated SQL, and is only
    /// used to allow certain comparisons that would otherwise fail to compile.
    ///
    /// # Example
    /// ```no_run
    /// # #![allow(dead_code)]
    /// # #[macro_use] extern crate diesel;
    /// # include!("src/doctest_setup.rs");
    /// # use self::diesel::types::*;
    /// #
    /// table! {
    ///     users {
    ///         id -> Integer,
    ///         name -> VarChar,
    ///     }
    /// }
    ///
    /// table! {
    ///     posts {
    ///         id -> Integer,
    ///         user_id -> Integer,
    ///         author_name -> Nullable<VarChar>,
    ///     }
    /// }
    /// #
    /// #  pub struct User {
    /// #      id: i32,
    /// #      name: VarChar,
    /// #  }
    /// #
    /// #  pub struct Post {
    /// #      id: i32,
    /// #      user_id: i32,
    /// #      author_name: Option<VarChar>,
    /// #  }
    /// #
    /// #  joinable!(posts -> users (user_id));
    /// #  select_column_workaround!(posts -> users (id, user_id, author_name));
    /// #  select_column_workaround!(users -> posts (id, name));
    ///
    /// fn main() {
    ///     use self::users::dsl::*;
    ///     use self::posts::dsl::{posts, author_name};
    ///     let connection = establish_connection();
    ///
    ///     let data = users.inner_join(posts)
    ///         .filter(name.nullable().eq(author_name))
    ///         .select(name)
    ///         .load::<String>(&connection);
    ///     println!("{:?}", data);
    /// }
    fn nullable(self) -> nullable::Nullable<Self> {
        nullable::Nullable::new(self)
    }
}

impl<T: Expression> ExpressionMethods for T {}
<|endoftext|>