<commit_before>use backend;
use event::{Event, Key};
use theme::{Color, ColorStyle, Effect, BaseColor};
use utf8;

use ncurses;

pub struct NcursesBackend;

impl backend::Backend for NcursesBackend {
    fn init() {
        ::std::env::set_var("ESCDELAY", "25");
        ncurses::setlocale(ncurses::LcCategory::all, "");
        ncurses::initscr();
        ncurses::keypad(ncurses::stdscr, true);
        ncurses::noecho();
        ncurses::cbreak();
        ncurses::start_color();
        ncurses::curs_set(ncurses::CURSOR_VISIBILITY::CURSOR_INVISIBLE);
        ncurses::wbkgd(ncurses::stdscr,
                       ncurses::COLOR_PAIR(ColorStyle::Background.id()));
    }

    fn screen_size() -> (usize, usize) {
        let mut x: i32 = 0;
        let mut y: i32 = 0;
        ncurses::getmaxyx(ncurses::stdscr, &mut y, &mut x);
        (x as usize, y as usize)
    }

    fn has_colors() -> bool {
        ncurses::has_colors()
    }

    fn finish() {
        ncurses::endwin();
    }

    fn init_color_style(style: ColorStyle, foreground: &Color,
                        background: &Color) {
        // TODO: build the color on the spot

        ncurses::init_pair(style.id(),
                           find_closest(foreground) as i16,
                           find_closest(background) as i16);
    }

    fn with_color<F: FnOnce()>(color: ColorStyle, f: F) {
        let mut current_style: ncurses::attr_t = 0;
        let mut current_color: i16 = 0;
        ncurses::attr_get(&mut current_style, &mut current_color);

        let style = ncurses::COLOR_PAIR(color.id());
        ncurses::attron(style);
        f();
        // ncurses::attroff(style);
        ncurses::attron(current_style);
    }

    fn with_effect<F: FnOnce()>(effect: Effect, f: F) {
        let style = match effect {
            Effect::Reverse => ncurses::A_REVERSE(),
            Effect::Simple => ncurses::A_NORMAL(),
        };
        ncurses::attron(style);
        f();
        ncurses::attroff(style);
    }

    fn clear() {
        ncurses::clear();
    }

    fn refresh() {
        ncurses::refresh();
    }

    fn print_at((x, y): (usize, usize), text: &str) {
        ncurses::mvaddstr(y as i32, x as i32, text);
    }

    fn poll_event() -> Event {
        let ch: i32 = ncurses::getch();

        // Is it a UTF-8 starting point?
        if 32 <= ch && ch <= 255 && ch != 127 {
            Event::Char(utf8::read_char(ch as u8, || ncurses::getch() as u8)
                .unwrap())
        } else {
            parse_ncurses_char(ch)
        }
    }

    fn set_refresh_rate(fps: u32) {
        if fps == 0 {
            ncurses::timeout(-1);
        } else {
            ncurses::timeout(1000 / fps as i32);
        }
    }
}

/// Returns the Key enum corresponding to the given ncurses event.
fn parse_ncurses_char(ch: i32) -> Event {

    match ch {
        // Value sent by ncurses when nothing happens
        -1 => Event::Refresh,

        // Values under 256 are chars and control values
        //
        // Tab is '\t'
        9 => Event::Key(Key::Tab),
        // Treat '\n' and the numpad Enter the same
        10 |
        ncurses::KEY_ENTER => Event::Key(Key::Enter),
        // This is the escape key when pressed by itself.
        // When used for control sequences, it should have been caught earlier.
        27 => Event::Key(Key::Esc),
        // `Backspace` sends 127, but Ctrl-H sends `Backspace`
        127 |
        ncurses::KEY_BACKSPACE => Event::Key(Key::Backspace),

        410 => Event::WindowResize,

        // Values 512 and above are probably extensions
        // Those keys don't seem to be documented...
        519 => Event::Alt(Key::Del),
        520 => Event::AltShift(Key::Del),
        521 => Event::Ctrl(Key::Del),
        522 => Event::CtrlShift(Key::Del),
        // 523: CtrlAltDel?
        //
        // 524?
        525 => Event::Alt(Key::Down),
        526 => Event::AltShift(Key::Down),
        527 => Event::Ctrl(Key::Down),
        528 => Event::CtrlShift(Key::Down),
        529 => Event::CtrlAlt(Key::Down),

        530 => Event::Alt(Key::End),
        531 => Event::AltShift(Key::End),
        532 => Event::Ctrl(Key::End),
        533 => Event::CtrlShift(Key::End),
        534 => Event::CtrlAlt(Key::End),

        535 => Event::Alt(Key::Home),
        536 => Event::AltShift(Key::Home),
        537 => Event::Ctrl(Key::Home),
        538 => Event::CtrlShift(Key::Home),
        539 => Event::CtrlAlt(Key::Home),

        540 => Event::Alt(Key::Ins),
        // 541: AltShiftIns?
        542 => Event::Ctrl(Key::Ins),
        // 543: CtrlShiftIns?
        544 => Event::CtrlAlt(Key::Ins),

        545 => Event::Alt(Key::Left),
        546 => Event::AltShift(Key::Left),
        547 => Event::Ctrl(Key::Left),
        548 => Event::CtrlShift(Key::Left),
        549 => Event::CtrlAlt(Key::Left),

        550 => Event::Alt(Key::PageDown),
        551 => Event::AltShift(Key::PageDown),
        552 => Event::Ctrl(Key::PageDown),
        553 => Event::CtrlShift(Key::PageDown),
        554 => Event::CtrlAlt(Key::PageDown),

        555 => Event::Alt(Key::PageUp),
        556 => Event::AltShift(Key::PageUp),
        557 => Event::Ctrl(Key::PageUp),
        558 => Event::CtrlShift(Key::PageUp),
        559 => Event::CtrlAlt(Key::PageUp),

        560 => Event::Alt(Key::Right),
        561 => Event::AltShift(Key::Right),
        562 => Event::Ctrl(Key::Right),
        563 => Event::CtrlShift(Key::Right),
        564 => Event::CtrlAlt(Key::Right),
        // 565?
        566 => Event::Alt(Key::Up),
        567 => Event::AltShift(Key::Up),
        568 => Event::Ctrl(Key::Up),
        569 => Event::CtrlShift(Key::Up),
        570 => Event::CtrlAlt(Key::Up),

        ncurses::KEY_B2 => Event::Key(Key::NumpadCenter),
        ncurses::KEY_DC => Event::Key(Key::Del),
        ncurses::KEY_IC => Event::Key(Key::Ins),
        ncurses::KEY_BTAB => Event::Shift(Key::Tab),
        ncurses::KEY_SLEFT => Event::Shift(Key::Left),
        ncurses::KEY_SRIGHT => Event::Shift(Key::Right),
        ncurses::KEY_LEFT => Event::Key(Key::Left),
        ncurses::KEY_RIGHT => Event::Key(Key::Right),
        ncurses::KEY_UP => Event::Key(Key::Up),
        ncurses::KEY_DOWN => Event::Key(Key::Down),
        ncurses::KEY_SR => Event::Shift(Key::Up),
        ncurses::KEY_SF => Event::Shift(Key::Down),
        ncurses::KEY_PPAGE => Event::Key(Key::PageUp),
        ncurses::KEY_NPAGE => Event::Key(Key::PageDown),
        ncurses::KEY_HOME => Event::Key(Key::Home),
        ncurses::KEY_END => Event::Key(Key::End),
        ncurses::KEY_SHOME => Event::Shift(Key::Home),
        ncurses::KEY_SEND => Event::Shift(Key::End),
        ncurses::KEY_SDC => Event::Shift(Key::Del),
        ncurses::KEY_SNEXT => Event::Shift(Key::PageDown),
        ncurses::KEY_SPREVIOUS => Event::Shift(Key::PageUp),
        // All Fn keys use the same enum with associated number
        f @ ncurses::KEY_F1...ncurses::KEY_F12 => {
            Event::Key(Key::from_f((f - ncurses::KEY_F0) as u8))
        }
        f @ 277...288 => Event::Shift(Key::from_f((f - 276) as u8)),
        f @ 289...300 => Event::Ctrl(Key::from_f((f - 288) as u8)),
        f @ 301...312 => Event::CtrlShift(Key::from_f((f - 300) as u8)),
        f @ 313...324 => Event::Alt(Key::from_f((f - 312) as u8)),
        // Values 8-10 (H,I,J) are used by other commands,
        // so we probably won't receive them. Meh~
        c @ 1...25 => Event::CtrlChar((b'a' + (c - 1) as u8) as char),
        _ => Event::Unknown(ch),
    }
}

fn find_closest(color: &Color) -> u8 {
    match *color {
        Color::Dark(BaseColor::Black) => 0,
        Color::Dark(BaseColor::Red) => 1,
        Color::Dark(BaseColor::Green) => 2,
        Color::Dark(BaseColor::Yellow) => 3,
        Color::Dark(BaseColor::Blue) => 4,
        Color::Dark(BaseColor::Magenta) => 5,
        Color::Dark(BaseColor::Cyan) => 6,
        Color::Dark(BaseColor::White) => 7,
        Color::Light(BaseColor::Black) => 8,
        Color::Light(BaseColor::Red) => 9,
        Color::Light(BaseColor::Green) => 10,
        Color::Light(BaseColor::Yellow) => 11,
        Color::Light(BaseColor::Blue) => 12,
        Color::Light(BaseColor::Magenta) => 13,
        Color::Light(BaseColor::Cyan) => 14,
        Color::Light(BaseColor::White) => 15,
        Color::Rgb(r, g, b) => {
            let r = 6 * r as u16 / 256;
            let g = 6 * g as u16 / 256;
            let b = 6 * b as u16 / 256;
            (16 + 36 * r + 6 * g + b) as u8
        }
        Color::RgbLowRes(r, g, b) => (16 + 36 * r + 6 * g + b) as u8,
    }
}
<commit_msg>Add unsafe block around `ncurses::stdscr`<commit_after>use backend;
use event::{Event, Key};
use theme::{Color, ColorStyle, Effect, BaseColor};
use utf8;

use ncurses;

pub struct NcursesBackend;

impl backend::Backend for NcursesBackend {
    fn init() {
        ::std::env::set_var("ESCDELAY", "25");
        ncurses::setlocale(ncurses::LcCategory::all, "");
        ncurses::initscr();
        ncurses::keypad(unsafe { ncurses::stdscr }, true);
        ncurses::noecho();
        ncurses::cbreak();
        ncurses::start_color();
        ncurses::curs_set(ncurses::CURSOR_VISIBILITY::CURSOR_INVISIBLE);
        ncurses::wbkgd(unsafe { ncurses::stdscr },
                       ncurses::COLOR_PAIR(ColorStyle::Background.id()));
    }

    fn screen_size() -> (usize, usize) {
        let mut x: i32 = 0;
        let mut y: i32 = 0;
        ncurses::getmaxyx(unsafe { ncurses::stdscr }, &mut y, &mut x);
        (x as usize, y as usize)
    }

    fn has_colors() -> bool {
        ncurses::has_colors()
    }

    fn finish() {
        ncurses::endwin();
    }

    fn init_color_style(style: ColorStyle, foreground: &Color,
                        background: &Color) {
        // TODO: build the color on the spot

        ncurses::init_pair(style.id(),
                           find_closest(foreground) as i16,
                           find_closest(background) as i16);
    }

    fn with_color<F: FnOnce()>(color: ColorStyle, f: F) {
        let mut current_style: ncurses::attr_t = 0;
        let mut current_color: i16 = 0;
        ncurses::attr_get(&mut current_style, &mut current_color);

        let style = ncurses::COLOR_PAIR(color.id());
        ncurses::attron(style);
        f();
        // ncurses::attroff(style);
        ncurses::attron(current_style);
    }

    fn with_effect<F: FnOnce()>(effect: Effect, f: F) {
        let style = match effect {
            Effect::Reverse => ncurses::A_REVERSE(),
            Effect::Simple => ncurses::A_NORMAL(),
        };
        ncurses::attron(style);
        f();
        ncurses::attroff(style);
    }

    fn clear() {
        ncurses::clear();
    }

    fn refresh() {
        ncurses::refresh();
    }

    fn print_at((x, y): (usize, usize), text: &str) {
        ncurses::mvaddstr(y as i32, x as i32, text);
    }

    fn poll_event() -> Event {
        let ch: i32 = ncurses::getch();

        // Is it a UTF-8 starting point?
        if 32 <= ch && ch <= 255 && ch != 127 {
            Event::Char(utf8::read_char(ch as u8, || ncurses::getch() as u8)
                .unwrap())
        } else {
            parse_ncurses_char(ch)
        }
    }

    fn set_refresh_rate(fps: u32) {
        if fps == 0 {
            ncurses::timeout(-1);
        } else {
            ncurses::timeout(1000 / fps as i32);
        }
    }
}

/// Returns the Key enum corresponding to the given ncurses event.
fn parse_ncurses_char(ch: i32) -> Event {

    match ch {
        // Value sent by ncurses when nothing happens
        -1 => Event::Refresh,

        // Values under 256 are chars and control values
        //
        // Tab is '\t'
        9 => Event::Key(Key::Tab),
        // Treat '\n' and the numpad Enter the same
        10 |
        ncurses::KEY_ENTER => Event::Key(Key::Enter),
        // This is the escape key when pressed by itself.
        // When used for control sequences, it should have been caught earlier.
        27 => Event::Key(Key::Esc),
        // `Backspace` sends 127, but Ctrl-H sends `Backspace`
        127 |
        ncurses::KEY_BACKSPACE => Event::Key(Key::Backspace),

        410 => Event::WindowResize,

        // Values 512 and above are probably extensions
        // Those keys don't seem to be documented...
        519 => Event::Alt(Key::Del),
        520 => Event::AltShift(Key::Del),
        521 => Event::Ctrl(Key::Del),
        522 => Event::CtrlShift(Key::Del),
        // 523: CtrlAltDel?
        //
        // 524?
        525 => Event::Alt(Key::Down),
        526 => Event::AltShift(Key::Down),
        527 => Event::Ctrl(Key::Down),
        528 => Event::CtrlShift(Key::Down),
        529 => Event::CtrlAlt(Key::Down),

        530 => Event::Alt(Key::End),
        531 => Event::AltShift(Key::End),
        532 => Event::Ctrl(Key::End),
        533 => Event::CtrlShift(Key::End),
        534 => Event::CtrlAlt(Key::End),

        535 => Event::Alt(Key::Home),
        536 => Event::AltShift(Key::Home),
        537 => Event::Ctrl(Key::Home),
        538 => Event::CtrlShift(Key::Home),
        539 => Event::CtrlAlt(Key::Home),

        540 => Event::Alt(Key::Ins),
        // 541: AltShiftIns?
        542 => Event::Ctrl(Key::Ins),
        // 543: CtrlShiftIns?
        544 => Event::CtrlAlt(Key::Ins),

        545 => Event::Alt(Key::Left),
        546 => Event::AltShift(Key::Left),
        547 => Event::Ctrl(Key::Left),
        548 => Event::CtrlShift(Key::Left),
        549 => Event::CtrlAlt(Key::Left),

        550 => Event::Alt(Key::PageDown),
        551 => Event::AltShift(Key::PageDown),
        552 => Event::Ctrl(Key::PageDown),
        553 => Event::CtrlShift(Key::PageDown),
        554 => Event::CtrlAlt(Key::PageDown),

        555 => Event::Alt(Key::PageUp),
        556 => Event::AltShift(Key::PageUp),
        557 => Event::Ctrl(Key::PageUp),
        558 => Event::CtrlShift(Key::PageUp),
        559 => Event::CtrlAlt(Key::PageUp),

        560 => Event::Alt(Key::Right),
        561 => Event::AltShift(Key::Right),
        562 => Event::Ctrl(Key::Right),
        563 => Event::CtrlShift(Key::Right),
        564 => Event::CtrlAlt(Key::Right),
        // 565?
        566 => Event::Alt(Key::Up),
        567 => Event::AltShift(Key::Up),
        568 => Event::Ctrl(Key::Up),
        569 => Event::CtrlShift(Key::Up),
        570 => Event::CtrlAlt(Key::Up),

        ncurses::KEY_B2 => Event::Key(Key::NumpadCenter),
        ncurses::KEY_DC => Event::Key(Key::Del),
        ncurses::KEY_IC => Event::Key(Key::Ins),
        ncurses::KEY_BTAB => Event::Shift(Key::Tab),
        ncurses::KEY_SLEFT => Event::Shift(Key::Left),
        ncurses::KEY_SRIGHT => Event::Shift(Key::Right),
        ncurses::KEY_LEFT => Event::Key(Key::Left),
        ncurses::KEY_RIGHT => Event::Key(Key::Right),
        ncurses::KEY_UP => Event::Key(Key::Up),
        ncurses::KEY_DOWN => Event::Key(Key::Down),
        ncurses::KEY_SR => Event::Shift(Key::Up),
        ncurses::KEY_SF => Event::Shift(Key::Down),
        ncurses::KEY_PPAGE => Event::Key(Key::PageUp),
        ncurses::KEY_NPAGE => Event::Key(Key::PageDown),
        ncurses::KEY_HOME => Event::Key(Key::Home),
        ncurses::KEY_END => Event::Key(Key::End),
        ncurses::KEY_SHOME => Event::Shift(Key::Home),
        ncurses::KEY_SEND => Event::Shift(Key::End),
        ncurses::KEY_SDC => Event::Shift(Key::Del),
        ncurses::KEY_SNEXT => Event::Shift(Key::PageDown),
        ncurses::KEY_SPREVIOUS => Event::Shift(Key::PageUp),
        // All Fn keys use the same enum with associated number
        f @ ncurses::KEY_F1...ncurses::KEY_F12 => {
            Event::Key(Key::from_f((f - ncurses::KEY_F0) as u8))
        }
        f @ 277...288 => Event::Shift(Key::from_f((f - 276) as u8)),
        f @ 289...300 => Event::Ctrl(Key::from_f((f - 288) as u8)),
        f @ 301...312 => Event::CtrlShift(Key::from_f((f - 300) as u8)),
        f @ 313...324 => Event::Alt(Key::from_f((f - 312) as u8)),
        // Values 8-10 (H,I,J) are used by other commands,
        // so we probably won't receive them. Meh~
        c @ 1...25 => Event::CtrlChar((b'a' + (c - 1) as u8) as char),
        _ => Event::Unknown(ch),
    }
}

fn find_closest(color: &Color) -> u8 {
    match *color {
        Color::Dark(BaseColor::Black) => 0,
        Color::Dark(BaseColor::Red) => 1,
        Color::Dark(BaseColor::Green) => 2,
        Color::Dark(BaseColor::Yellow) => 3,
        Color::Dark(BaseColor::Blue) => 4,
        Color::Dark(BaseColor::Magenta) => 5,
        Color::Dark(BaseColor::Cyan) => 6,
        Color::Dark(BaseColor::White) => 7,
        Color::Light(BaseColor::Black) => 8,
        Color::Light(BaseColor::Red) => 9,
        Color::Light(BaseColor::Green) => 10,
        Color::Light(BaseColor::Yellow) => 11,
        Color::Light(BaseColor::Blue) => 12,
        Color::Light(BaseColor::Magenta) => 13,
        Color::Light(BaseColor::Cyan) => 14,
        Color::Light(BaseColor::White) => 15,
        Color::Rgb(r, g, b) => {
            let r = 6 * r as u16 / 256;
            let g = 6 * g as u16 / 256;
            let b = 6 * b as u16 / 256;
            (16 + 36 * r + 6 * g + b) as u8
        }
        Color::RgbLowRes(r, g, b) => (16 + 36 * r + 6 * g + b) as u8,
    }
}
<|endoftext|>


<commit_before>#![feature(os, collections, rustc_private)]

extern crate selecta;

use selecta::configuration::Configuration;
use selecta::search::Search;
use std::old_io::{File, BufferedReader};

#[allow(dead_code)]
fn main() {
    let lines = read_lines("benches/30000.txt".to_string());

    let config = Configuration::from_inputs(lines, None, Some(20));
    let mut search = Search::blank(&config);

    search = search.append_to_search("t").append_to_search("o").append_to_search("a").append_to_search("w").append_to_search("c").backspace().backspace().backspace().append_to_search("w").backspace().append_to_search("a");

    println!("\n{}", search.selection().unwrap_or("None".to_string()));
}

fn read_lines(fname: String) -> Vec<String> {
    let path = Path::new(fname);
    let mut file = BufferedReader::new(File::open(&path));
    let mut result = Vec::new();
    loop {
        match file.read_line() {
            Ok(line) => result.push(line),
            Err(_) => break,
        }
    }
    result
}
<commit_msg>Silence warnings in benches<commit_after>#![feature(io, path)]

extern crate selecta;

use selecta::configuration::Configuration;
use selecta::search::Search;
use std::old_io::{File, BufferedReader};

#[allow(dead_code)]
fn main() {
    let lines = read_lines("benches/30000.txt".to_string());

    let config = Configuration::from_inputs(lines, None, Some(20));
    let mut search = Search::blank(&config);

    search = search.append_to_search("t").append_to_search("o").append_to_search("a").append_to_search("w").append_to_search("c").backspace().backspace().backspace().append_to_search("w").backspace().append_to_search("a");

    println!("\n{}", search.selection().unwrap_or("None".to_string()));
}

fn read_lines(fname: String) -> Vec<String> {
    let path = Path::new(fname);
    let mut file = BufferedReader::new(File::open(&path));
    let mut result = Vec::new();
    loop {
        match file.read_line() {
            Ok(line) => result.push(line),
            Err(_) => break,
        }
    }
    result
}
<|endoftext|>


<commit_before>use std::sync::Arc;

use page_manager::{Pages, Page, PageId, BlockId, Block, RamPageCache, PageCache};

pub struct BlockIter<'a> {
    cache: &'a RamPageCache,
    current_page: Arc<Page>,
    pages: Pages,
    block_counter: BlockId,
    page_counter: usize,
}

impl<'a> BlockIter<'a> {
    pub fn new(cache: &'a RamPageCache, pages: Pages) -> Self {
        BlockIter {
            cache: cache,
            current_page: Arc::new(Page::empty()),
            pages: pages,
            block_counter: BlockId::first(),
            page_counter: 0,
        }
    }

    fn next_page_id(&mut self) -> Option<PageId> {
        self.page_counter += 1;
        if self.page_counter <= self.pages.0.len() {
            let p_id = self.pages.0[self.page_counter - 1];
            Some(p_id)
        } else if let Some(unfull_page) = self.pages.1 {
            self.block_counter = unfull_page.from();
            Some(unfull_page.0)
        } else {
            None
        }
    }
}

impl<'a> Iterator for BlockIter<'a> {
    type Item = Block;

    fn next(&mut self) -> Option<Self::Item> {
        if self.block_counter == BlockId::first() {
            // Get new page
            let page = self.cache.get_page(try_option!(self.next_page_id()));
            self.current_page = page;
        }
        //Special case for last block:
        //1. Unfull page has to exist
        //2. BlockCounter must be >= unfull_page.to()
        if self.page_counter == self.pages.len() && self.pages.1.is_some() &&
           self.block_counter >= self.pages.1.map(|unfull_page| unfull_page.to()).unwrap() {
            return None;
        }
        let res = Some(self.current_page[self.block_counter]);
        self.block_counter.inc();
        res
    }
}

#[cfg(test)]
mod tests {
    use test_utils::create_test_dir;

    use super::BlockIter;
    use page_manager::{UnfullPage, RamPageCache, BlockManager, FsPageManager, Pages, PageId,
                       Block, BlockId, BLOCKSIZE, PAGESIZE};

    fn new_cache(name: &str) -> RamPageCache {
        let path = &create_test_dir(format!("block_iter/{}", name).as_str());
        let pmgr = FsPageManager::new(&path.join("pages.bin"));
        RamPageCache::new(pmgr)
    }

    #[test]
    fn basic() {
        let mut cache = new_cache("basic");
        for i in 0..2048 {
            assert_eq!(cache.store_block(Block([(i % 255) as u8; BLOCKSIZE])),
                       PageId(i));
            for j in 1..PAGESIZE {
                cache.store_in_place(PageId(i),
                                     BlockId(j as u16),
                                     Block([(j % 255) as u8; BLOCKSIZE]));
            }
            cache.flush_page(PageId(i));
        }
        let pages = Pages((0..2048).map(|i| PageId(i)).collect::<Vec<_>>(), None);
        let mut iter = BlockIter::new(&cache, pages);
        for i in 0..2048 {
            assert_eq!(iter.next(), Some(Block([(i % 255) as u8; BLOCKSIZE])));
            for j in 1..PAGESIZE {
                assert_eq!(iter.next(), Some(Block([(j % 255) as u8; BLOCKSIZE])));
            }
        }
    }

    #[test]
    fn unfull() {
        let mut cache = new_cache("unfull");
        assert_eq!(cache.store_block(Block([1; BLOCKSIZE])), PageId(0));
        assert_eq!(cache.flush_unfull(PageId(0), BlockId(1)),
                   UnfullPage::new(PageId(0), BlockId(1), BlockId(2)));
        let mut iter =
            BlockIter::new(&cache,
                           Pages(Vec::new(),
                                 Some(UnfullPage::new(PageId(0), BlockId(1), BlockId(2)))));
        assert_eq!(iter.next(), Some(Block([1; BLOCKSIZE])));
        assert_eq!(iter.next(), None);
    }

    #[test]
    fn multiple_readers() {
        let mut cache = new_cache("basic");
        for i in 0..2048 {
            assert_eq!(cache.store_block(Block([(i % 255) as u8; BLOCKSIZE])),
                       PageId(i));
            for j in 1..PAGESIZE {
                cache.store_in_place(PageId(i),
                                     BlockId(j as u16),
                                     Block([(j % 255) as u8; BLOCKSIZE]));
            }
            cache.flush_page(PageId(i));
        }
        let pages1 = Pages((0..1024).map(|i| PageId(i)).collect::<Vec<_>>(), None);
        let pages2 = Pages((1024..2048).map(|i| PageId(i)).collect::<Vec<_>>(), None);
        let mut iter1 = BlockIter::new(&cache, pages1);
        let mut iter2 = BlockIter::new(&cache, pages2);
        for i in 0..1024 {
            assert_eq!(iter1.next(), Some(Block([(i % 255) as u8; BLOCKSIZE])));
            assert_eq!(iter2.next(),
                       Some(Block([((i + 1024) % 255) as u8; BLOCKSIZE])));
            for j in 1..PAGESIZE {
                assert_eq!(iter1.next(), Some(Block([(j % 255) as u8; BLOCKSIZE])));
                assert_eq!(iter2.next(), Some(Block([(j % 255) as u8; BLOCKSIZE])));
            }
        }
    }

}
<commit_msg>testcase for bug in block_iter<commit_after>use std::sync::Arc;

use page_manager::{Pages, Page, PageId, BlockId, Block, RamPageCache, PageCache};

pub struct BlockIter<'a> {
    cache: &'a RamPageCache,
    current_page: Arc<Page>,
    pages: Pages,
    block_counter: BlockId,
    page_counter: usize,
}

impl<'a> BlockIter<'a> {
    pub fn new(cache: &'a RamPageCache, pages: Pages) -> Self {
        BlockIter {
            cache: cache,
            current_page: Arc::new(Page::empty()),
            pages: pages,
            block_counter: BlockId::first(),
            page_counter: 0,
        }
    }

    fn next_page_id(&mut self) -> Option<PageId> {
        self.page_counter += 1;
        if self.page_counter <= self.pages.0.len() {
            let p_id = self.pages.0[self.page_counter - 1];
            Some(p_id)
        } else if let Some(unfull_page) = self.pages.1 {
            self.block_counter = unfull_page.from();
            Some(unfull_page.0)
        } else {
            None
        }
    }
}

impl<'a> Iterator for BlockIter<'a> {
    type Item = Block;

    fn next(&mut self) -> Option<Self::Item> {
        if self.block_counter == BlockId::first() {
            // Get new page
            let page = self.cache.get_page(try_option!(self.next_page_id()));
            self.current_page = page;
        }
        //Special case for last block:
        //1. Unfull page has to exist
        //2. BlockCounter must be >= unfull_page.to()
        if self.page_counter == self.pages.len() && self.pages.1.is_some() &&
           self.block_counter >= self.pages.1.map(|unfull_page| unfull_page.to()).unwrap() {
            return None;
        }
        let res = Some(self.current_page[self.block_counter]);
        self.block_counter.inc();
        res
    }
}

#[cfg(test)]
mod tests {
    use test_utils::create_test_dir;

    use super::BlockIter;
    use page_manager::{UnfullPage, RamPageCache, BlockManager, FsPageManager, Pages, PageId,
                       Block, BlockId, BLOCKSIZE, PAGESIZE};

    fn new_cache(name: &str) -> RamPageCache {
        let path = &create_test_dir(format!("block_iter/{}", name).as_str());
        let pmgr = FsPageManager::new(&path.join("pages.bin"));
        RamPageCache::new(pmgr)
    }

    #[test]
    fn basic() {
        let mut cache = new_cache("basic");
        for i in 0..2048 {
            assert_eq!(cache.store_block(Block([(i % 255) as u8; BLOCKSIZE])),
                       PageId(i));
            for j in 1..PAGESIZE {
                cache.store_in_place(PageId(i),
                                     BlockId(j as u16),
                                     Block([(j % 255) as u8; BLOCKSIZE]));
            }
            cache.flush_page(PageId(i));
        }
        let pages = Pages((0..2048).map(|i| PageId(i)).collect::<Vec<_>>(), None);
        let mut iter = BlockIter::new(&cache, pages);
        for i in 0..2048 {
            assert_eq!(iter.next(), Some(Block([(i % 255) as u8; BLOCKSIZE])));
            for j in 1..PAGESIZE {
                assert_eq!(iter.next(), Some(Block([(j % 255) as u8; BLOCKSIZE])));
            }
        }
    }

    #[test]
    fn unfull() {
        let mut cache = new_cache("unfull");
        assert_eq!(cache.store_block(Block([1; BLOCKSIZE])), PageId(0));
        assert_eq!(cache.flush_unfull(PageId(0), BlockId(1)),
                   UnfullPage::new(PageId(0), BlockId(1), BlockId(2)));
        let mut iter =
            BlockIter::new(&cache,
                           Pages(Vec::new(),
                                 Some(UnfullPage::new(PageId(0), BlockId(1), BlockId(2)))));
        assert_eq!(iter.next(), Some(Block([1; BLOCKSIZE])));
        assert_eq!(iter.next(), None);
    }

    #[test]
    fn full_unfull() {
        let mut cache = new_cache("full_unfull");
        // Fill with full pages
        for i in 0..2048 {
            assert_eq!(cache.store_block(Block([(i % 255) as u8; BLOCKSIZE])),
                       PageId(i));
            for j in 1..PAGESIZE {
                cache.store_in_place(PageId(i),
                                     BlockId(j as u16),
                                     Block([(j % 255) as u8; BLOCKSIZE]));
            }
            cache.flush_page(PageId(i));
        }
        // Add Unfull page
        assert_eq!(cache.store_block(Block([1; BLOCKSIZE])), PageId(2048));
        assert_eq!(cache.flush_unfull(PageId(2048), BlockId(1)),
                   UnfullPage::new(PageId(2048), BlockId(1), BlockId(2)));
        let mut iter =
            BlockIter::new(&cache,
                           Pages((0..2048).map(|i| PageId(i)).collect::<Vec<_>>(),
                                 Some(UnfullPage::new(PageId(2048), BlockId(1), BlockId(2)))));
        // Iterate over full pages
        for i in 0..2048 {
            assert_eq!(iter.next(), Some(Block([(i % 255) as u8; BLOCKSIZE])));
            for j in 1..PAGESIZE {
                assert_eq!(iter.next(), Some(Block([(j % 255) as u8; BLOCKSIZE])));
            }
        }
        // Unfull page
        assert_eq!(iter.next(), Some(Block([1; BLOCKSIZE])));
        assert_eq!(iter.next(), None);
    }

    #[test]
    fn filled_unfull() {
        let mut cache = new_cache("filled_unfull");
        assert_eq!(cache.store_block(Block([0; BLOCKSIZE])), PageId(0));
        for i in 1..PAGESIZE - 1 {
            cache.store_in_place(PageId(0),
                                 BlockId(i as u16),
                                 Block([(i % 255) as u8; BLOCKSIZE]));
        }
        let unfull_page = cache.flush_unfull(PageId(0), BlockId::last());
        let mut iter = BlockIter::new(&cache, Pages(Vec::new(), Some(unfull_page)));
        for i in 0..PAGESIZE -1 {
            assert_eq!(iter.next(), Some(Block([(i % 255) as u8; BLOCKSIZE])));
        }
        assert_eq!(iter.next(), None);
    }

    #[test]
    fn multiple_readers() {
        let mut cache = new_cache("basic");
        for i in 0..2048 {
            assert_eq!(cache.store_block(Block([(i % 255) as u8; BLOCKSIZE])),
                       PageId(i));
            for j in 1..PAGESIZE {
                cache.store_in_place(PageId(i),
                                     BlockId(j as u16),
                                     Block([(j % 255) as u8; BLOCKSIZE]));
            }
            cache.flush_page(PageId(i));
        }
        let pages1 = Pages((0..1024).map(|i| PageId(i)).collect::<Vec<_>>(), None);
        let pages2 = Pages((1024..2048).map(|i| PageId(i)).collect::<Vec<_>>(), None);
        let mut iter1 = BlockIter::new(&cache, pages1);
        let mut iter2 = BlockIter::new(&cache, pages2);
        for i in 0..1024 {
            assert_eq!(iter1.next(), Some(Block([(i % 255) as u8; BLOCKSIZE])));
            assert_eq!(iter2.next(),
                       Some(Block([((i + 1024) % 255) as u8; BLOCKSIZE])));
            for j in 1..PAGESIZE {
                assert_eq!(iter1.next(), Some(Block([(j % 255) as u8; BLOCKSIZE])));
                assert_eq!(iter2.next(), Some(Block([(j % 255) as u8; BLOCKSIZE])));
            }
        }
    }

}
<|endoftext|>


<commit_before>use std::error::Error;
use std::io;
use lexing;
use lexing::token::Token;
use super::world::World;

pub fn lex(world: World, _args: Vec<String>) -> i32 {
    let tokens = lexing::lex(lexing::char_iter::chars(world.stdin));
    match write_lexed(world.stdout, world.stderr, tokens) {
        Ok(_) => 0,
        Err(e) => {
            world.stderr.write(e.description().as_bytes())
                .expect("Failed to write an error to error stream.");
            2
        }
    }
}

fn write_lexed<I: Iterator<Item=Token>>(
    stdout: &mut io::Write, stderr: &mut io::Write, tokens: I
) -> io::Result<usize> {
    stdout.write(b"tokens = import(language.lexing.tokens);\n[\n")?;
    for t in tokens {
        match t {
            Token::IntTok(i) => {
                stdout.write(b"    tokens.int(\"")?;
                stdout.write(i.as_bytes())?;
                stdout.write(b"\"),\n")?;
            },
            Token::SymbolTok(s) => {
                stdout.write(b"    tokens.symbol(\"")?;
                stdout.write(s.as_bytes())?;
                stdout.write(b"\"),\n")?;
            },
            Token::OperatorTok(o) => {
                stdout.write(b"    tokens.operator(\"")?;
                stdout.write(o.as_bytes())?;
                stdout.write(b"\"),\n")?;
            },
            Token::IoErrorTok(e) => {
                return Err(
                    io::Error::new(
                        io::ErrorKind::Other,
                        format!(
                            "{file}:{line}:{column} IO error: {err}\n",
                            file="-",
                            line=1,
                            column=1,
                            err=e,
                        )
                    )
                )
            },
            Token::BadIntLexErrorTok(actual, correct) => {
                return Err(
                    io::Error::new(
                        io::ErrorKind::Other,
                        format!(
                            "{file}:{line}:{column} Lexing error: \
                            the number \"{actual}\" has underscores in the \
                            wrong place: it should be written \"{correct}\".\n",
                            file="-",
                            line=1,
                            column=1,
                            actual=actual,
                            correct=correct,
                        )
                    )
                )
            },
        }
    }
    stdout.write(b"];\n")?;
    Ok(0)
}

#[cfg(test)]
mod tests {
    use std::convert::From;
    use super::*;
    use super::super::fakeworld::tests::FakeWorld;

    fn assert_vec_eq(left: &Vec<u8>, right: &[u8]) {

        let sleft = String::from_utf8(left.clone());
        let sright = String::from_utf8(Vec::from(&right[..]));

        match (sleft, sright) {
            (Ok(le), Ok(ri)) => assert_eq!(le, ri),
            (Ok(_), Err(e)) => panic!(e),
            (Err(e), _) => panic!(e),
        }
    }

    #[test]
    fn simple_expression_printed_as_code() {
        let mut fake = FakeWorld::new(b"1 + 2\n", &["lex", "-"]);
        let args = vec!(String::from("-"));
        let status = lex(fake.world(), args);
        assert_eq!(status, 0);
        assert_vec_eq(&fake.stderr, b"");
        assert_vec_eq(&fake.stdout, b"\
            tokens = import(language.lexing.tokens);\n\
            [\n    \
                tokens.int(\"1\"),\n    \
                tokens.operator(\"+\"),\n    \
                tokens.int(\"2\"),\n\
            ];\n\
            "
        );
    }
}
<commit_msg>Test error output in lexing, and remove unused argument<commit_after>use std::error::Error;
use std::io;
use lexing;
use lexing::token::Token;
use super::world::World;

pub fn lex(world: World, _args: Vec<String>) -> i32 {
    let tokens = lexing::lex(lexing::char_iter::chars(world.stdin));
    match write_lexed(world.stdout, tokens) {
        Ok(_) => 0,
        Err(e) => {
            world.stderr.write(e.description().as_bytes())
                .expect("Failed to write an error to error stream.");
            2
        }
    }
}

fn write_lexed<I: Iterator<Item=Token>>(
    stdout: &mut io::Write, tokens: I
) -> io::Result<usize> {
    stdout.write(b"tokens = import(language.lexing.tokens);\n[\n")?;
    for t in tokens {
        match t {
            Token::IntTok(i) => {
                stdout.write(b"    tokens.int(\"")?;
                stdout.write(i.as_bytes())?;
                stdout.write(b"\"),\n")?;
            },
            Token::SymbolTok(s) => {
                stdout.write(b"    tokens.symbol(\"")?;
                stdout.write(s.as_bytes())?;
                stdout.write(b"\"),\n")?;
            },
            Token::OperatorTok(o) => {
                stdout.write(b"    tokens.operator(\"")?;
                stdout.write(o.as_bytes())?;
                stdout.write(b"\"),\n")?;
            },
            Token::IoErrorTok(e) => {
                return Err(
                    io::Error::new(
                        io::ErrorKind::Other,
                        format!(
                            "{file}:{line}:{column} IO error: {err}\n",
                            file="-",
                            line=1,
                            column=1,
                            err=e,
                        )
                    )
                )
            },
            Token::BadIntLexErrorTok(actual, correct) => {
                return Err(
                    io::Error::new(
                        io::ErrorKind::Other,
                        format!(
                            "{file}:{line}:{column} Lexing error: \
                            the number \"{actual}\" has underscores in the \
                            wrong place: it should be written \"{correct}\".\n",
                            file="-",
                            line=1,
                            column=1,
                            actual=actual,
                            correct=correct,
                        )
                    )
                )
            },
        }
    }
    stdout.write(b"];\n")?;
    Ok(0)
}

#[cfg(test)]
mod tests {
    use std::convert::From;
    use super::*;
    use super::super::fakeworld::tests::FakeWorld;

    fn assert_vec_eq(left: &Vec<u8>, right: &[u8]) {

        let sleft = String::from_utf8(left.clone());
        let sright = String::from_utf8(Vec::from(&right[..]));

        match (sleft, sright) {
            (Ok(le), Ok(ri)) => assert_eq!(le, ri),
            (Ok(_), Err(e)) => panic!(e),
            (Err(e), _) => panic!(e),
        }
    }

    #[test]
    fn simple_expression_printed_as_code() {
        let mut fake = FakeWorld::new(b"1 + 2\n", &["lex", "-"]);
        let args = vec!(String::from("-"));
        let status = lex(fake.world(), args);
        assert_eq!(status, 0);
        assert_vec_eq(&fake.stderr, b"");
        assert_vec_eq(&fake.stdout, b"\
            tokens = import(language.lexing.tokens);\n\
            [\n    \
                tokens.int(\"1\"),\n    \
                tokens.operator(\"+\"),\n    \
                tokens.int(\"2\"),\n\
            ];\n\
            "
        );
    }

    #[test]
    fn lex_error_printed_to_stderr() {
        let mut fake = FakeWorld::new(b"1000\n", &["lex", "-"]);
        let args = vec!(String::from("-"));
        let status = lex(fake.world(), args);
        assert_eq!(status, 2);
        assert_vec_eq(
            &fake.stderr, b"\
            -:1:1 Lexing error: the number \"1000\" has underscores in the \
            wrong place: it should be written \"1_000\".\n"
        );
        assert_vec_eq(&fake.stdout, b"\
            tokens = import(language.lexing.tokens);\n\
            [\n"
        );
    }
}
<|endoftext|>


<commit_before>//! general purpose combinators

#![allow(unused_imports)]

#[cfg(feature = "alloc")]
use lib::std::boxed::Box;

#[cfg(feature = "std")]
use lib::std::fmt::Debug;
use internal::*;
use error::ParseError;
use traits::{AsChar, InputIter, InputLength, InputTakeAtPosition};
use traits::{need_more, need_more_err, AtEof, ParseTo};
use lib::std::ops::{Range, RangeFrom, RangeTo};
use traits::{Compare, CompareResult, Offset, Slice};
use error::ErrorKind;
use lib::std::mem::transmute;

#[macro_use]
mod macros;

#[cfg(feature = "alloc")]
#[inline]
pub fn tag_cl<'a, 'b>(rec: &'a [u8]) -> Box<Fn(&'b [u8]) -> IResult<&'b [u8], &'b [u8]> + 'a> {
  Box::new(move |i: &'b [u8]| -> IResult<&'b [u8], &'b [u8]> {
    if i.len() >= rec.len() && &i[0..rec.len()] == rec {
      Ok((&i[rec.len()..], &i[0..rec.len()]))
    } else {
      let e: ErrorKind = ErrorKind::TagClosure;
      Err(Err::Error(error_position!(i, e)))
    }
  })
}

#[cfg(feature = "std")]
#[inline]
pub fn print<T: Debug>(input: T) -> IResult<T, ()> {
  println!("{:?}", input);
  Ok((input, ()))
}

#[inline]
pub fn begin(input: &[u8]) -> IResult<(), &[u8]> {
  Ok(((), input))
}

pub fn sized_buffer<'a, E: ParseError<&'a[u8]>>(input: &'a[u8]) -> IResult<&'a[u8], &'a[u8], E> {
  if input.is_empty() {
    return need_more(input, Needed::Unknown);
  }

  let len = input[0] as usize;

  if input.len() >= len + 1 {
    Ok((&input[len + 1..], &input[1..len + 1]))
  } else {
    need_more(input, Needed::Size(1 + len))
  }
}

/// Recognizes non empty buffers
#[inline]
pub fn non_empty<T, E: ParseError<T>>(input: T) -> IResult<T, T, E>
where
  T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
  T: InputLength + AtEof,
{
  if input.input_len() == 0 {
    return need_more_err(input, Needed::Unknown, ErrorKind::NonEmpty);
  } else {
    Ok((input.slice(input.input_len()..), input))
  }
}

/// Return the remaining input.
#[inline]
pub fn rest<T, E: ParseError<T>>(input: T) -> IResult<T, T, E>
where
  T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
  T: InputLength,
{
  Ok((input.slice(input.input_len()..), input))
}

/// Return the length of the remaining input.
#[inline]
pub fn rest_len<T, E: ParseError<T>>(input: T) -> IResult<T, usize, E>
where
  T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
  T: InputLength,
{
  let len = input.input_len();
  Ok((input, len))
}

/// Return the remaining input, for strings.
#[inline]
pub fn rest_s<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, &'a str, E> {
  Ok((&input[input.len()..], input))
}

pub fn map<I, O1, O2, E: ParseError<I>, F, G>(first: F, second: G) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(O1) -> O2,
{
  move |input: I| {
    let (input, o1) = first(input)?;
    Ok((input, second(o1)))
  }
}

pub fn map_res<I: Clone, O1, O2, E: ParseError<I>, E2, F, G>(first: F, second: G) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(O1) -> Result<O2, E2>,
{
  move |input: I| {
    let i = input.clone();
    let (input, o1) = first(input)?;
    match second(o1) {
      Ok(o2) => Ok((input, o2)),
      Err(_) => Err(Err::Error(E::from_error_kind(i, ErrorKind::MapRes))),
    }
  }
}

pub fn map_opt<I: Clone, O1, O2, E: ParseError<I>, F, G>(first: F, second: G) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(O1) -> Option<O2>,
{
  move |input: I| {
    let i = input.clone();
    let (input, o1) = first(input)?;
    match second(o1) {
      Some(o2) => Ok((input, o2)),
      None => Err(Err::Error(E::from_error_kind(i, ErrorKind::MapOpt))),
    }
  }
}

pub fn map_parser<I: Clone, O1, O2, E: ParseError<I>, F, G>(first: F, second: G) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(O1) -> IResult<O1, O2, E>,
  O1: InputLength,
{
  move |input: I| {
    let i = input.clone();
    let (input, o1) = first(input)?;
    let (o1, o2) = second(o1)?;
    Ok((input, o2))
  }
}

pub fn flat_map<I, O1, O2, E: ParseError<I>, F, G, H>(first: F, second: G) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(O1) -> H,
  H: Fn(I) -> IResult<I, O2, E>
{
  move |input: I| {
    let (input, o1) = first(input)?;
    second(o1)(input)
  }
}

pub fn opt<I:Clone, O, E: ParseError<I>, F>(f: F) -> impl Fn(I) -> IResult<I, Option<O>, E>
where
  F: Fn(I) -> IResult<I, O, E>,
{
  move |input: I| {
    let i = input.clone();
    match f(input) {
      Ok((i, o)) => Ok((i, Some(o))),
      Err(Err::Error(_)) => Ok((i, None)),
      Err(e) => Err(e),
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use internal::{Err, IResult, Needed};
  use error::ParseError;

  macro_rules! assert_parse(
    ($left: expr, $right: expr) => {
      let res: $crate::IResult<_, _, (_, ErrorKind)> = $left;
      assert_eq!(res, $right);
    };
  );

  #[test]
  #[cfg(feature = "alloc")]
  fn tag_closure() {
    let x = tag_cl(&b"abcd"[..]);
    let r = x(&b"abcdabcdefgh"[..]);
    assert_eq!(r, Ok((&b"abcdefgh"[..], &b"abcd"[..])));

    let r2 = x(&b"abcefgh"[..]);
    assert_eq!(
      r2,
      Err(Err::Error(error_position!(
        &b"abcefgh"[..],
        ErrorKind::TagClosure
      ),))
    );
  }

  #[test]
  #[cfg(feature = "alloc")]
  fn buffer_with_size() {
    use lib::std::vec::Vec;
    let i: Vec<u8> = vec![7, 8];
    let o: Vec<u8> = vec![4, 5, 6];
    //let arr:[u8; 6usize] = [3, 4, 5, 6, 7, 8];
    let arr: [u8; 6usize] = [3, 4, 5, 6, 7, 8];
    let res = sized_buffer::<(_, ErrorKind)>(&arr[..]);
    assert_eq!(res, Ok((&i[..], &o[..])))
  }

  /*#[test]
  fn t1() {
    let v1:Vec<u8> = vec![1,2,3];
    let v2:Vec<u8> = vec![4,5,6];
    let d = Ok((&v1[..], &v2[..]));
    let res = d.flat_map(print);
    assert_eq!(res, Ok((&v2[..], ())));
  }*/

  /*
    #[test]
    fn end_of_input() {
        let not_over = &b"Hello, world!"[..];
        let is_over = &b""[..];
        named!(eof_test, eof!());

        let res_not_over = eof_test(not_over);
        assert_eq!(res_not_over, Err(Err::Error(error_position!(not_over, ErrorKind::Eof))));

        let res_over = eof_test(is_over);
        assert_eq!(res_over, Ok((is_over, is_over)));
    }
    */

  #[test]
  fn rest_on_slices() {
    let input: &[u8] = &b"Hello, world!"[..];
    let empty: &[u8] = &b""[..];
    assert_parse!(rest(input), Ok((empty, input)));
  }

  #[test]
  fn rest_on_strs() {
    let input: &str = "Hello, world!";
    let empty: &str = "";
    assert_parse!(rest(input), Ok((empty, input)));
  }

  #[test]
  fn rest_len_on_slices() {
    let input: &[u8] = &b"Hello, world!"[..];
    assert_parse!(rest_len(input), Ok((input, input.len())));
  }

  use lib::std::convert::From;
  impl From<u32> for CustomError {
    fn from(_: u32) -> Self {
      CustomError
    }
  }

  impl<I> ParseError<I> for CustomError {
    fn from_error_kind(_: I, _: ErrorKind) -> Self {
      CustomError
    }

    fn append(_: I, _: ErrorKind, _: CustomError) -> Self {
      CustomError
    }
  }

  struct CustomError;
  #[allow(dead_code)]
  fn custom_error(input: &[u8]) -> IResult<&[u8], &[u8], CustomError> {
    //fix_error!(input, CustomError, alphanumeric)
    ::character::streaming::alphanumeric(input)
  }

}
<commit_msg>add tests for recently added combinators<commit_after>//! general purpose combinators

#![allow(unused_imports)]

#[cfg(feature = "alloc")]
use lib::std::boxed::Box;

#[cfg(feature = "std")]
use lib::std::fmt::Debug;
use internal::*;
use error::ParseError;
use traits::{AsChar, InputIter, InputLength, InputTakeAtPosition};
use traits::{need_more, need_more_err, AtEof, ParseTo};
use lib::std::ops::{Range, RangeFrom, RangeTo};
use traits::{Compare, CompareResult, Offset, Slice};
use error::ErrorKind;
use lib::std::mem::transmute;

#[macro_use]
mod macros;

#[cfg(feature = "alloc")]
#[inline]
pub fn tag_cl<'a, 'b>(rec: &'a [u8]) -> Box<Fn(&'b [u8]) -> IResult<&'b [u8], &'b [u8]> + 'a> {
  Box::new(move |i: &'b [u8]| -> IResult<&'b [u8], &'b [u8]> {
    if i.len() >= rec.len() && &i[0..rec.len()] == rec {
      Ok((&i[rec.len()..], &i[0..rec.len()]))
    } else {
      let e: ErrorKind = ErrorKind::TagClosure;
      Err(Err::Error(error_position!(i, e)))
    }
  })
}

#[cfg(feature = "std")]
#[inline]
pub fn print<T: Debug>(input: T) -> IResult<T, ()> {
  println!("{:?}", input);
  Ok((input, ()))
}

#[inline]
pub fn begin(input: &[u8]) -> IResult<(), &[u8]> {
  Ok(((), input))
}

pub fn sized_buffer<'a, E: ParseError<&'a[u8]>>(input: &'a[u8]) -> IResult<&'a[u8], &'a[u8], E> {
  if input.is_empty() {
    return need_more(input, Needed::Unknown);
  }

  let len = input[0] as usize;

  if input.len() >= len + 1 {
    Ok((&input[len + 1..], &input[1..len + 1]))
  } else {
    need_more(input, Needed::Size(1 + len))
  }
}

/// Recognizes non empty buffers
#[inline]
pub fn non_empty<T, E: ParseError<T>>(input: T) -> IResult<T, T, E>
where
  T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
  T: InputLength + AtEof,
{
  if input.input_len() == 0 {
    return need_more_err(input, Needed::Unknown, ErrorKind::NonEmpty);
  } else {
    Ok((input.slice(input.input_len()..), input))
  }
}

/// Return the remaining input.
#[inline]
pub fn rest<T, E: ParseError<T>>(input: T) -> IResult<T, T, E>
where
  T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
  T: InputLength,
{
  Ok((input.slice(input.input_len()..), input))
}

/// Return the length of the remaining input.
#[inline]
pub fn rest_len<T, E: ParseError<T>>(input: T) -> IResult<T, usize, E>
where
  T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
  T: InputLength,
{
  let len = input.input_len();
  Ok((input, len))
}

/// Return the remaining input, for strings.
#[inline]
pub fn rest_s<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, &'a str, E> {
  Ok((&input[input.len()..], input))
}

pub fn map<I, O1, O2, E: ParseError<I>, F, G>(first: F, second: G) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(O1) -> O2,
{
  move |input: I| {
    let (input, o1) = first(input)?;
    Ok((input, second(o1)))
  }
}

pub fn map_res<I: Clone, O1, O2, E: ParseError<I>, E2, F, G>(first: F, second: G) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(O1) -> Result<O2, E2>,
{
  move |input: I| {
    let i = input.clone();
    let (input, o1) = first(input)?;
    match second(o1) {
      Ok(o2) => Ok((input, o2)),
      Err(_) => Err(Err::Error(E::from_error_kind(i, ErrorKind::MapRes))),
    }
  }
}

pub fn map_opt<I: Clone, O1, O2, E: ParseError<I>, F, G>(first: F, second: G) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(O1) -> Option<O2>,
{
  move |input: I| {
    let i = input.clone();
    let (input, o1) = first(input)?;
    match second(o1) {
      Some(o2) => Ok((input, o2)),
      None => Err(Err::Error(E::from_error_kind(i, ErrorKind::MapOpt))),
    }
  }
}

pub fn map_parser<I: Clone, O1, O2, E: ParseError<I>, F, G>(first: F, second: G) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(O1) -> IResult<O1, O2, E>,
  O1: InputLength,
{
  move |input: I| {
    let i = input.clone();
    let (input, o1) = first(input)?;
    let (o1, o2) = second(o1)?;
    Ok((input, o2))
  }
}

pub fn flat_map<I, O1, O2, E: ParseError<I>, F, G, H>(first: F, second: G) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(O1) -> H,
  H: Fn(I) -> IResult<I, O2, E>
{
  move |input: I| {
    let (input, o1) = first(input)?;
    second(o1)(input)
  }
}

pub fn opt<I:Clone, O, E: ParseError<I>, F>(f: F) -> impl Fn(I) -> IResult<I, Option<O>, E>
where
  F: Fn(I) -> IResult<I, O, E>,
{
  move |input: I| {
    let i = input.clone();
    match f(input) {
      Ok((i, o)) => Ok((i, Some(o))),
      Err(Err::Error(_)) => Ok((i, None)),
      Err(e) => Err(e),
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use internal::{Err, IResult, Needed};
  use error::ParseError;
  use crate::bytes::complete::take;
  use crate::number::complete::be_u8;

  macro_rules! assert_parse(
    ($left: expr, $right: expr) => {
      let res: $crate::IResult<_, _, (_, ErrorKind)> = $left;
      assert_eq!(res, $right);
    };
  );

  #[test]
  #[cfg(feature = "alloc")]
  fn tag_closure() {
    let x = tag_cl(&b"abcd"[..]);
    let r = x(&b"abcdabcdefgh"[..]);
    assert_eq!(r, Ok((&b"abcdefgh"[..], &b"abcd"[..])));

    let r2 = x(&b"abcefgh"[..]);
    assert_eq!(
      r2,
      Err(Err::Error(error_position!(
        &b"abcefgh"[..],
        ErrorKind::TagClosure
      ),))
    );
  }

  #[test]
  #[cfg(feature = "alloc")]
  fn buffer_with_size() {
    use lib::std::vec::Vec;
    let i: Vec<u8> = vec![7, 8];
    let o: Vec<u8> = vec![4, 5, 6];
    //let arr:[u8; 6usize] = [3, 4, 5, 6, 7, 8];
    let arr: [u8; 6usize] = [3, 4, 5, 6, 7, 8];
    let res = sized_buffer::<(_, ErrorKind)>(&arr[..]);
    assert_eq!(res, Ok((&i[..], &o[..])))
  }

  /*#[test]
  fn t1() {
    let v1:Vec<u8> = vec![1,2,3];
    let v2:Vec<u8> = vec![4,5,6];
    let d = Ok((&v1[..], &v2[..]));
    let res = d.flat_map(print);
    assert_eq!(res, Ok((&v2[..], ())));
  }*/

  /*
    #[test]
    fn end_of_input() {
        let not_over = &b"Hello, world!"[..];
        let is_over = &b""[..];
        named!(eof_test, eof!());

        let res_not_over = eof_test(not_over);
        assert_eq!(res_not_over, Err(Err::Error(error_position!(not_over, ErrorKind::Eof))));

        let res_over = eof_test(is_over);
        assert_eq!(res_over, Ok((is_over, is_over)));
    }
    */

  #[test]
  fn rest_on_slices() {
    let input: &[u8] = &b"Hello, world!"[..];
    let empty: &[u8] = &b""[..];
    assert_parse!(rest(input), Ok((empty, input)));
  }

  #[test]
  fn rest_on_strs() {
    let input: &str = "Hello, world!";
    let empty: &str = "";
    assert_parse!(rest(input), Ok((empty, input)));
  }

  #[test]
  fn rest_len_on_slices() {
    let input: &[u8] = &b"Hello, world!"[..];
    assert_parse!(rest_len(input), Ok((input, input.len())));
  }

  use lib::std::convert::From;
  impl From<u32> for CustomError {
    fn from(_: u32) -> Self {
      CustomError
    }
  }

  impl<I> ParseError<I> for CustomError {
    fn from_error_kind(_: I, _: ErrorKind) -> Self {
      CustomError
    }

    fn append(_: I, _: ErrorKind, _: CustomError) -> Self {
      CustomError
    }
  }

  struct CustomError;
  #[allow(dead_code)]
  fn custom_error(input: &[u8]) -> IResult<&[u8], &[u8], CustomError> {
    //fix_error!(input, CustomError, alphanumeric)
    ::character::streaming::alphanumeric(input)
  }

  #[test]
  fn test_flat_map() {
      let input: &[u8] = &[3, 100, 101, 102, 103, 104][..];
      assert_parse!(flat_map(be_u8, take)(input), Ok((&[103, 104][..], &[100, 101, 102][..])));
  }

  #[test]
  fn test_map_opt() {
      let input: &[u8] = &[50][..];
      assert_parse!(map_opt(be_u8, |u| if u < 20 {Some(u)} else {None})(input), Err(Err::Error((&[50][..], ErrorKind::MapOpt))));
      assert_parse!(map_opt(be_u8, |u| if u > 20 {Some(u)} else {None})(input), Ok((&[][..], 50)));
  }

  #[test]
  fn test_map_parser() {
      let input: &[u8] = &[100, 101, 102, 103, 104][..];
      assert_parse!(map_parser(take(4usize), take(2usize))(input), Ok((&[104][..], &[100, 101][..])));
  }
}
<|endoftext|>


<commit_before>//! # Diesel
//!
//! Diesel is an ORM and query builder designed to reduce the boilerplate for database interactions.
//! If this is your first time reading this documentation,
//! we recommend you start with the [getting started guide].
//! We also have [many other long form guides].
//!
//! [getting started guide]: https://diesel.rs/guides/getting-started/
//! [many other long form guides]: https://diesel.rs/guides
//!
//! # Where to find things
//!
//! ## Declaring your schema
//!
//! For Diesel to validate your queries at compile time
//! it requires you to specify your schema in your code,
//! which you can do with [the `table!` macro][`table!`].
//! `diesel print-schema` can be used
//! to automatically generate these macro calls
//! (by connecting to your database and querying its schema).
//!
//! [`table!`]: macro.table.html
//!
//! ## Getting started
//!
//! Queries usually start from either a table, or a function like [`update`].
//! Those functions can be found [here](#functions).
//!
//! Diesel provides a [`prelude` module](prelude),
//! which exports most of the typically used traits and types.
//! We are conservative about what goes in this module,
//! and avoid anything which has a generic name.
//! Files which use Diesel are expected to have `use diesel::prelude::*;`.
//!
//! [`update`]: fn.update.html
//!
//! ## Constructing a query
//!
//! The tools the query builder gives you can be put into these three categories:
//!
//! - "Query builder methods" are things that map to portions of a whole query
//!   (such as `ORDER` and `WHERE`). These methods usually have the same name
//!   as the SQL they map to, except for `WHERE` which is called `filter` in Diesel
//!   (To not conflict with the Rust keyword).
//!   These methods live in [the `query_dsl` module](query_dsl).
//! - "Expression methods" are things you would call on columns
//!   or other individual values.
//!   These methods live in [the `expression_methods` module](expression_methods)
//!   You can often find these by thinking "what would this be called"
//!   if it were a method
//!   and typing that into the search bar
//!   (e.g. `LIKE` is called `like` in Diesel).
//!   Most operators are named based on the Rust function which maps to that
//!   operator in [`std::ops`][]
//!   (For example `==` is called `.eq`, and `!=` is called `.ne`).
//! - "Bare functions" are normal SQL functions
//!   such as `sum`.
//!   They live in [the `dsl` module](dsl).
//!   Diesel only supports a very small number of these functions.
//!   You can declare additional functions you want to use
//!   with [the `sql_function!` macro][`sql_function!`].
//!
//! [`std::ops`]: //doc.rust-lang.org/stable/std/ops/index.html
//! [`sql_function!`]: macro.sql_function.html
//!
//! ## Serializing and Deserializing
//!
//! Types which represent the result of a SQL query implement
//! a trait called [`Queryable`].
//!
//! Diesel maps "Rust types" (e.g. `i32`) to and from "SQL types"
//! (e.g. [`diesel::sql_types::Integer`]).
//! You can find all the types supported by Diesel in [the `sql_types` module](sql_types).
//! These types are only used to represent a SQL type.
//! You should never put them on your `Queryable` structs.
//!
//! To find all the Rust types which can be used with a given SQL type,
//! see the documentation for that SQL type.
//!
//! To find all the SQL types which can be used with a Rust type,
//! go to the docs for either [`ToSql`] or [`FromSql`],
//! go to the "Implementors" section,
//! and find the Rust type you want to use.
//!
//! [`Queryable`]: deserialize/trait.Queryable.html
//! [`diesel::sql_types::Integer`]: sql_types/struct.Integer.html
//! [`ToSql`]: serialize/trait.ToSql.html
//! [`FromSql`]: deserialize/trait.FromSql.html
//!
//! ## Getting help
//!
//! If you run into problems, Diesel has a very active Gitter room.
//! You can come ask for help at
//! [gitter.im/diesel-rs/diesel](https://gitter.im/diesel-rs/diesel)

#![cfg_attr(feature = "unstable", feature(specialization, trait_alias))]
// For the `specialization` feature.
#![cfg_attr(feature = "unstable", allow(incomplete_features))]
// Built-in Lints
#![deny(warnings)]
#![warn(
    missing_debug_implementations,
    missing_copy_implementations,
    missing_docs
)]
// Clippy lints
#![allow(
    clippy::match_same_arms,
    clippy::needless_doctest_main,
    clippy::option_map_unwrap_or_else,
    clippy::option_map_unwrap_or,
    clippy::redundant_field_names,
    clippy::type_complexity
)]
#![cfg_attr(test, allow(clippy::option_map_unwrap_or, clippy::result_unwrap_used))]
#![warn(
    clippy::option_unwrap_used,
    clippy::result_unwrap_used,
    clippy::print_stdout,
    clippy::wrong_pub_self_convention,
    clippy::mut_mut,
    clippy::non_ascii_literal,
    clippy::similar_names,
    clippy::unicode_not_nfc,
    clippy::enum_glob_use,
    clippy::if_not_else,
    clippy::items_after_statements,
    clippy::used_underscore_binding
)]

#[cfg(feature = "postgres")]
#[macro_use]
extern crate bitflags;
extern crate byteorder;
extern crate diesel_derives;

#[macro_use]
#[doc(hidden)]
pub mod macros;

#[cfg(test)]
#[macro_use]
extern crate cfg_if;

#[cfg(test)]
pub mod test_helpers;

pub mod associations;
pub mod backend;
pub mod connection;
pub mod data_types;
pub mod deserialize;
#[macro_use]
pub mod expression;
pub mod expression_methods;
#[doc(hidden)]
pub mod insertable;
pub mod query_builder;
pub mod query_dsl;
pub mod query_source;
#[cfg(feature = "r2d2")]
pub mod r2d2;
pub mod result;
pub mod serialize;
pub mod upsert;
#[macro_use]
pub mod sql_types;
pub mod migration;
pub mod row;

#[cfg(feature = "mysql")]
pub mod mysql;
#[cfg(feature = "postgres")]
pub mod pg;
#[cfg(feature = "sqlite")]
pub mod sqlite;

mod type_impls;
mod util;

#[doc(hidden)]
#[cfg(feature = "with-deprecated")]
#[deprecated(since = "2.0.0", note = "Use explicit macro imports instead")]
pub use diesel_derives::*;

#[doc(hidden)]
pub type RealBool = bool;

pub mod dsl {
    //! Includes various helper types and bare functions which are named too
    //! generically to be included in prelude, but are often used when using Diesel.

    #[doc(inline)]
    pub use crate::helper_types::*;

    #[doc(inline)]
    pub use crate::expression::dsl::*;

    #[doc(inline)]
    pub use crate::query_builder::functions::{
        delete, insert_into, insert_or_ignore_into, replace_into, select, sql_query, update,
    };
}

pub mod helper_types {
    //! Provide helper types for concisely writing the return type of functions.
    //! As with iterators, it is unfortunately difficult to return a partially
    //! constructed query without exposing the exact implementation of the
    //! function. Without higher kinded types, these various DSLs can't be
    //! combined into a single trait for boxing purposes.
    //!
    //! All types here are in the form `<FirstType as
    //! DslName<OtherTypes>>::Output`. So the return type of
    //! `users.filter(first_name.eq("John")).order(last_name.asc()).limit(10)` would
    //! be `Limit<Order<FindBy<users, first_name, &str>, Asc<last_name>>>`
    use super::query_builder::locking_clause as lock;
    use super::query_dsl::methods::*;
    use super::query_dsl::*;
    use super::query_source::joins;

    #[doc(inline)]
    pub use crate::expression::helper_types::*;

    /// Represents the return type of `.select(selection)`
    pub type Select<Source, Selection> = <Source as SelectDsl<Selection>>::Output;

    /// Represents the return type of `.filter(predicate)`
    pub type Filter<Source, Predicate> = <Source as FilterDsl<Predicate>>::Output;

    /// Represents the return type of `.filter(lhs.eq(rhs))`
    pub type FindBy<Source, Column, Value> = Filter<Source, Eq<Column, Value>>;

    /// Represents the return type of `.for_update()`
    pub type ForUpdate<Source> = <Source as LockingDsl<lock::ForUpdate>>::Output;

    /// Represents the return type of `.for_no_key_update()`
    pub type ForNoKeyUpdate<Source> = <Source as LockingDsl<lock::ForNoKeyUpdate>>::Output;

    /// Represents the return type of `.for_share()`
    pub type ForShare<Source> = <Source as LockingDsl<lock::ForShare>>::Output;

    /// Represents the return type of `.for_key_share()`
    pub type ForKeyShare<Source> = <Source as LockingDsl<lock::ForKeyShare>>::Output;

    /// Represents the return type of `.skip_locked()`
    pub type SkipLocked<Source> = <Source as ModifyLockDsl<lock::SkipLocked>>::Output;

    /// Represents the return type of `.no_wait()`
    pub type NoWait<Source> = <Source as ModifyLockDsl<lock::NoWait>>::Output;

    /// Represents the return type of `.find(pk)`
    pub type Find<Source, PK> = <Source as FindDsl<PK>>::Output;

    /// Represents the return type of `.or_filter(predicate)`
    pub type OrFilter<Source, Predicate> = <Source as OrFilterDsl<Predicate>>::Output;

    /// Represents the return type of `.order(ordering)`
    pub type Order<Source, Ordering> = <Source as OrderDsl<Ordering>>::Output;

    /// Represents the return type of `.then_order_by(ordering)`
    pub type ThenOrderBy<Source, Ordering> = <Source as ThenOrderDsl<Ordering>>::Output;

    /// Represents the return type of `.limit()`
    pub type Limit<Source> = <Source as LimitDsl>::Output;

    /// Represents the return type of `.offset()`
    pub type Offset<Source> = <Source as OffsetDsl>::Output;

    /// Represents the return type of `.inner_join(rhs)`
    pub type InnerJoin<Source, Rhs> =
        <Source as JoinWithImplicitOnClause<Rhs, joins::Inner>>::Output;

    /// Represents the return type of `.inner_join(rhs.on(on))`
    pub type InnerJoinOn<Source, Rhs, On> =
        <Source as InternalJoinDsl<Rhs, joins::Inner, On>>::Output;

    /// Represents the return type of `.left_join(rhs)`
    pub type LeftJoin<Source, Rhs> =
        <Source as JoinWithImplicitOnClause<Rhs, joins::LeftOuter>>::Output;

    /// Represents the return type of `.left_join(rhs.on(on))`
    pub type LeftJoinOn<Source, Rhs, On> =
        <Source as InternalJoinDsl<Rhs, joins::LeftOuter, On>>::Output;

    use super::associations::HasTable;
    use super::query_builder::{AsChangeset, IntoUpdateTarget, UpdateStatement};
    /// Represents the return type of `update(lhs).set(rhs)`
    pub type Update<Target, Changes> = UpdateStatement<
        <Target as HasTable>::Table,
        <Target as IntoUpdateTarget>::WhereClause,
        <Changes as AsChangeset>::Changeset,
    >;

    /// Represents the return type of `.into_boxed::<'a, DB>()`
    pub type IntoBoxed<'a, Source, DB> = <Source as BoxedDsl<'a, DB>>::Output;

    /// Represents the return type of `.distinct()`
    pub type Distinct<Source> = <Source as DistinctDsl>::Output;

    /// Represents the return type of `.distinct_on(expr)`
    #[cfg(feature = "postgres")]
    pub type DistinctOn<Source, Expr> = <Source as DistinctOnDsl<Expr>>::Output;

    /// Represents the return type of `.single_value()`
    pub type SingleValue<Source> = <Source as SingleValueDsl>::Output;

    /// Represents the return type of `.nullable()`
    pub type NullableSelect<Source> = <Source as SelectNullableDsl>::Output;
}

pub mod prelude {
    //! Re-exports important traits and types. Meant to be glob imported when using Diesel.

    #[doc(inline)]
    pub use crate::associations::{Associations, GroupedBy, Identifiable};
    #[doc(inline)]
    pub use crate::connection::Connection;
    #[doc(inline)]
    pub use crate::deserialize::{Queryable, QueryableByName};
    #[doc(inline)]
    pub use crate::expression::{
        AppearsOnTable, BoxableExpression, Expression, IntoSql, SelectableExpression,
    };

    #[doc(inline)]
    pub use crate::expression::functions::sql_function;

    #[doc(inline)]
    pub use crate::expression_methods::*;
    #[doc(inline)]
    pub use crate::insertable::Insertable;
    #[doc(inline)]
    pub use crate::macros::prelude::*;
    #[doc(inline)]
    pub use crate::query_builder::AsChangeset;
    #[doc(inline)]
    pub use crate::query_builder::DecoratableTarget;
    #[doc(hidden)]
    pub use crate::query_dsl::GroupByDsl;
    #[doc(inline)]
    pub use crate::query_dsl::{BelongingToDsl, JoinOnDsl, QueryDsl, RunQueryDsl, SaveChangesDsl};
    #[doc(inline)]
    pub use crate::query_source::{Column, JoinTo, QuerySource, Table};
    #[doc(inline)]
    pub use crate::result::{ConnectionError, ConnectionResult, OptionalExtension, QueryResult};

    #[cfg(feature = "mysql")]
    #[doc(inline)]
    pub use crate::mysql::MysqlConnection;
    #[cfg(feature = "postgres")]
    #[doc(inline)]
    pub use crate::pg::PgConnection;
    #[cfg(feature = "sqlite")]
    #[doc(inline)]
    pub use crate::sqlite::SqliteConnection;
}

pub use crate::prelude::*;
#[doc(inline)]
pub use crate::query_builder::debug_query;
#[doc(inline)]
pub use crate::query_builder::functions::{
    delete, insert_into, insert_or_ignore_into, replace_into, select, sql_query, update,
};
pub use crate::result::Error::NotFound;

pub(crate) mod diesel {
    pub use super::*;
}
<commit_msg>add `RealStr`<commit_after>//! # Diesel
//!
//! Diesel is an ORM and query builder designed to reduce the boilerplate for database interactions.
//! If this is your first time reading this documentation,
//! we recommend you start with the [getting started guide].
//! We also have [many other long form guides].
//!
//! [getting started guide]: https://diesel.rs/guides/getting-started/
//! [many other long form guides]: https://diesel.rs/guides
//!
//! # Where to find things
//!
//! ## Declaring your schema
//!
//! For Diesel to validate your queries at compile time
//! it requires you to specify your schema in your code,
//! which you can do with [the `table!` macro][`table!`].
//! `diesel print-schema` can be used
//! to automatically generate these macro calls
//! (by connecting to your database and querying its schema).
//!
//! [`table!`]: macro.table.html
//!
//! ## Getting started
//!
//! Queries usually start from either a table, or a function like [`update`].
//! Those functions can be found [here](#functions).
//!
//! Diesel provides a [`prelude` module](prelude),
//! which exports most of the typically used traits and types.
//! We are conservative about what goes in this module,
//! and avoid anything which has a generic name.
//! Files which use Diesel are expected to have `use diesel::prelude::*;`.
//!
//! [`update`]: fn.update.html
//!
//! ## Constructing a query
//!
//! The tools the query builder gives you can be put into these three categories:
//!
//! - "Query builder methods" are things that map to portions of a whole query
//!   (such as `ORDER` and `WHERE`). These methods usually have the same name
//!   as the SQL they map to, except for `WHERE` which is called `filter` in Diesel
//!   (To not conflict with the Rust keyword).
//!   These methods live in [the `query_dsl` module](query_dsl).
//! - "Expression methods" are things you would call on columns
//!   or other individual values.
//!   These methods live in [the `expression_methods` module](expression_methods)
//!   You can often find these by thinking "what would this be called"
//!   if it were a method
//!   and typing that into the search bar
//!   (e.g. `LIKE` is called `like` in Diesel).
//!   Most operators are named based on the Rust function which maps to that
//!   operator in [`std::ops`][]
//!   (For example `==` is called `.eq`, and `!=` is called `.ne`).
//! - "Bare functions" are normal SQL functions
//!   such as `sum`.
//!   They live in [the `dsl` module](dsl).
//!   Diesel only supports a very small number of these functions.
//!   You can declare additional functions you want to use
//!   with [the `sql_function!` macro][`sql_function!`].
//!
//! [`std::ops`]: //doc.rust-lang.org/stable/std/ops/index.html
//! [`sql_function!`]: macro.sql_function.html
//!
//! ## Serializing and Deserializing
//!
//! Types which represent the result of a SQL query implement
//! a trait called [`Queryable`].
//!
//! Diesel maps "Rust types" (e.g. `i32`) to and from "SQL types"
//! (e.g. [`diesel::sql_types::Integer`]).
//! You can find all the types supported by Diesel in [the `sql_types` module](sql_types).
//! These types are only used to represent a SQL type.
//! You should never put them on your `Queryable` structs.
//!
//! To find all the Rust types which can be used with a given SQL type,
//! see the documentation for that SQL type.
//!
//! To find all the SQL types which can be used with a Rust type,
//! go to the docs for either [`ToSql`] or [`FromSql`],
//! go to the "Implementors" section,
//! and find the Rust type you want to use.
//!
//! [`Queryable`]: deserialize/trait.Queryable.html
//! [`diesel::sql_types::Integer`]: sql_types/struct.Integer.html
//! [`ToSql`]: serialize/trait.ToSql.html
//! [`FromSql`]: deserialize/trait.FromSql.html
//!
//! ## Getting help
//!
//! If you run into problems, Diesel has a very active Gitter room.
//! You can come ask for help at
//! [gitter.im/diesel-rs/diesel](https://gitter.im/diesel-rs/diesel)

#![cfg_attr(feature = "unstable", feature(specialization, trait_alias))]
// For the `specialization` feature.
#![cfg_attr(feature = "unstable", allow(incomplete_features))]
// Built-in Lints
#![deny(warnings)]
#![warn(
    missing_debug_implementations,
    missing_copy_implementations,
    missing_docs
)]
// Clippy lints
#![allow(
    clippy::match_same_arms,
    clippy::needless_doctest_main,
    clippy::option_map_unwrap_or_else,
    clippy::option_map_unwrap_or,
    clippy::redundant_field_names,
    clippy::type_complexity
)]
#![cfg_attr(test, allow(clippy::option_map_unwrap_or, clippy::result_unwrap_used))]
#![warn(
    clippy::option_unwrap_used,
    clippy::result_unwrap_used,
    clippy::print_stdout,
    clippy::wrong_pub_self_convention,
    clippy::mut_mut,
    clippy::non_ascii_literal,
    clippy::similar_names,
    clippy::unicode_not_nfc,
    clippy::enum_glob_use,
    clippy::if_not_else,
    clippy::items_after_statements,
    clippy::used_underscore_binding
)]

#[cfg(feature = "postgres")]
#[macro_use]
extern crate bitflags;
extern crate byteorder;
extern crate diesel_derives;

#[macro_use]
#[doc(hidden)]
pub mod macros;

#[cfg(test)]
#[macro_use]
extern crate cfg_if;

#[cfg(test)]
pub mod test_helpers;

pub mod associations;
pub mod backend;
pub mod connection;
pub mod data_types;
pub mod deserialize;
#[macro_use]
pub mod expression;
pub mod expression_methods;
#[doc(hidden)]
pub mod insertable;
pub mod query_builder;
pub mod query_dsl;
pub mod query_source;
#[cfg(feature = "r2d2")]
pub mod r2d2;
pub mod result;
pub mod serialize;
pub mod upsert;
#[macro_use]
pub mod sql_types;
pub mod migration;
pub mod row;

#[cfg(feature = "mysql")]
pub mod mysql;
#[cfg(feature = "postgres")]
pub mod pg;
#[cfg(feature = "sqlite")]
pub mod sqlite;

mod type_impls;
mod util;

#[doc(hidden)]
#[cfg(feature = "with-deprecated")]
#[deprecated(since = "2.0.0", note = "Use explicit macro imports instead")]
pub use diesel_derives::*;

#[doc(hidden)]
pub type RealBool = bool;

#[doc(hidden)]
pub type RealStr = &'static str;

pub mod dsl {
    //! Includes various helper types and bare functions which are named too
    //! generically to be included in prelude, but are often used when using Diesel.

    #[doc(inline)]
    pub use crate::helper_types::*;

    #[doc(inline)]
    pub use crate::expression::dsl::*;

    #[doc(inline)]
    pub use crate::query_builder::functions::{
        delete, insert_into, insert_or_ignore_into, replace_into, select, sql_query, update,
    };
}

pub mod helper_types {
    //! Provide helper types for concisely writing the return type of functions.
    //! As with iterators, it is unfortunately difficult to return a partially
    //! constructed query without exposing the exact implementation of the
    //! function. Without higher kinded types, these various DSLs can't be
    //! combined into a single trait for boxing purposes.
    //!
    //! All types here are in the form `<FirstType as
    //! DslName<OtherTypes>>::Output`. So the return type of
    //! `users.filter(first_name.eq("John")).order(last_name.asc()).limit(10)` would
    //! be `Limit<Order<FindBy<users, first_name, &str>, Asc<last_name>>>`
    use super::query_builder::locking_clause as lock;
    use super::query_dsl::methods::*;
    use super::query_dsl::*;
    use super::query_source::joins;

    #[doc(inline)]
    pub use crate::expression::helper_types::*;

    /// Represents the return type of `.select(selection)`
    pub type Select<Source, Selection> = <Source as SelectDsl<Selection>>::Output;

    /// Represents the return type of `.filter(predicate)`
    pub type Filter<Source, Predicate> = <Source as FilterDsl<Predicate>>::Output;

    /// Represents the return type of `.filter(lhs.eq(rhs))`
    pub type FindBy<Source, Column, Value> = Filter<Source, Eq<Column, Value>>;

    /// Represents the return type of `.for_update()`
    pub type ForUpdate<Source> = <Source as LockingDsl<lock::ForUpdate>>::Output;

    /// Represents the return type of `.for_no_key_update()`
    pub type ForNoKeyUpdate<Source> = <Source as LockingDsl<lock::ForNoKeyUpdate>>::Output;

    /// Represents the return type of `.for_share()`
    pub type ForShare<Source> = <Source as LockingDsl<lock::ForShare>>::Output;

    /// Represents the return type of `.for_key_share()`
    pub type ForKeyShare<Source> = <Source as LockingDsl<lock::ForKeyShare>>::Output;

    /// Represents the return type of `.skip_locked()`
    pub type SkipLocked<Source> = <Source as ModifyLockDsl<lock::SkipLocked>>::Output;

    /// Represents the return type of `.no_wait()`
    pub type NoWait<Source> = <Source as ModifyLockDsl<lock::NoWait>>::Output;

    /// Represents the return type of `.find(pk)`
    pub type Find<Source, PK> = <Source as FindDsl<PK>>::Output;

    /// Represents the return type of `.or_filter(predicate)`
    pub type OrFilter<Source, Predicate> = <Source as OrFilterDsl<Predicate>>::Output;

    /// Represents the return type of `.order(ordering)`
    pub type Order<Source, Ordering> = <Source as OrderDsl<Ordering>>::Output;

    /// Represents the return type of `.then_order_by(ordering)`
    pub type ThenOrderBy<Source, Ordering> = <Source as ThenOrderDsl<Ordering>>::Output;

    /// Represents the return type of `.limit()`
    pub type Limit<Source> = <Source as LimitDsl>::Output;

    /// Represents the return type of `.offset()`
    pub type Offset<Source> = <Source as OffsetDsl>::Output;

    /// Represents the return type of `.inner_join(rhs)`
    pub type InnerJoin<Source, Rhs> =
        <Source as JoinWithImplicitOnClause<Rhs, joins::Inner>>::Output;

    /// Represents the return type of `.inner_join(rhs.on(on))`
    pub type InnerJoinOn<Source, Rhs, On> =
        <Source as InternalJoinDsl<Rhs, joins::Inner, On>>::Output;

    /// Represents the return type of `.left_join(rhs)`
    pub type LeftJoin<Source, Rhs> =
        <Source as JoinWithImplicitOnClause<Rhs, joins::LeftOuter>>::Output;

    /// Represents the return type of `.left_join(rhs.on(on))`
    pub type LeftJoinOn<Source, Rhs, On> =
        <Source as InternalJoinDsl<Rhs, joins::LeftOuter, On>>::Output;

    use super::associations::HasTable;
    use super::query_builder::{AsChangeset, IntoUpdateTarget, UpdateStatement};
    /// Represents the return type of `update(lhs).set(rhs)`
    pub type Update<Target, Changes> = UpdateStatement<
        <Target as HasTable>::Table,
        <Target as IntoUpdateTarget>::WhereClause,
        <Changes as AsChangeset>::Changeset,
    >;

    /// Represents the return type of `.into_boxed::<'a, DB>()`
    pub type IntoBoxed<'a, Source, DB> = <Source as BoxedDsl<'a, DB>>::Output;

    /// Represents the return type of `.distinct()`
    pub type Distinct<Source> = <Source as DistinctDsl>::Output;

    /// Represents the return type of `.distinct_on(expr)`
    #[cfg(feature = "postgres")]
    pub type DistinctOn<Source, Expr> = <Source as DistinctOnDsl<Expr>>::Output;

    /// Represents the return type of `.single_value()`
    pub type SingleValue<Source> = <Source as SingleValueDsl>::Output;

    /// Represents the return type of `.nullable()`
    pub type NullableSelect<Source> = <Source as SelectNullableDsl>::Output;
}

pub mod prelude {
    //! Re-exports important traits and types. Meant to be glob imported when using Diesel.

    #[doc(inline)]
    pub use crate::associations::{Associations, GroupedBy, Identifiable};
    #[doc(inline)]
    pub use crate::connection::Connection;
    #[doc(inline)]
    pub use crate::deserialize::{Queryable, QueryableByName};
    #[doc(inline)]
    pub use crate::expression::{
        AppearsOnTable, BoxableExpression, Expression, IntoSql, SelectableExpression,
    };

    #[doc(inline)]
    pub use crate::expression::functions::sql_function;

    #[doc(inline)]
    pub use crate::expression_methods::*;
    #[doc(inline)]
    pub use crate::insertable::Insertable;
    #[doc(inline)]
    pub use crate::macros::prelude::*;
    #[doc(inline)]
    pub use crate::query_builder::AsChangeset;
    #[doc(inline)]
    pub use crate::query_builder::DecoratableTarget;
    #[doc(hidden)]
    pub use crate::query_dsl::GroupByDsl;
    #[doc(inline)]
    pub use crate::query_dsl::{BelongingToDsl, JoinOnDsl, QueryDsl, RunQueryDsl, SaveChangesDsl};
    #[doc(inline)]
    pub use crate::query_source::{Column, JoinTo, QuerySource, Table};
    #[doc(inline)]
    pub use crate::result::{ConnectionError, ConnectionResult, OptionalExtension, QueryResult};

    #[cfg(feature = "mysql")]
    #[doc(inline)]
    pub use crate::mysql::MysqlConnection;
    #[cfg(feature = "postgres")]
    #[doc(inline)]
    pub use crate::pg::PgConnection;
    #[cfg(feature = "sqlite")]
    #[doc(inline)]
    pub use crate::sqlite::SqliteConnection;
}

pub use crate::prelude::*;
#[doc(inline)]
pub use crate::query_builder::debug_query;
#[doc(inline)]
pub use crate::query_builder::functions::{
    delete, insert_into, insert_or_ignore_into, replace_into, select, sql_query, update,
};
pub use crate::result::Error::NotFound;

pub(crate) mod diesel {
    pub use super::*;
}
<|endoftext|>


<commit_before>use error::{CliError, Usage, UsageKind};
use super::Command;

extern crate toml;

use constant::CONFIG_FILE_NAME;
use lib::setting;

pub struct Config {
    command: Option<String>,
    key    : Option<String>,
    value  : Option<String>,
}

impl Command for Config {
    fn validation(&self) -> bool { true }

    fn usage(&self) -> Usage {
        return Usage::new(UsageKind::Config);
    }

    fn main(&self) -> Result<(), CliError> {
        match self.command {
            Some(ref c) => match c.as_ref() {
                "set"  => self.set(),
                "init" => self.init(),
                _      => Err(From::from(self.usage())),
            },
            None => Err(From::from(self.usage())),
        }
    }
}

impl Config {
    pub fn new(command: Option<String>, key: Option<String>, value: Option<String>) -> Config {
        Config { command: command, key: key, value: value }
    }

    fn set(&self) -> Result<(), CliError> {
        let (key, value) = match (self.key.clone(), self.value.clone()) {
            (Some(k), Some(v)) => (k, v),
            _                  => return Err(From::from(self.usage())),
        };

        let key   = try!(setting::ConfigKey::from(key));
        let value = try!(setting::Config::validate(&key, value));

        let config = try!(setting::Config::read());
        let config = try!(config.set(key, value));

        try!(config.create());

        Ok(())
    }

    fn init(&self) -> Result<(), CliError> {
        let message = format!("Do you want to initialize \"{}\"?", CONFIG_FILE_NAME);

        Self::run_after_confirmation(message,|| setting::Config::default().create())
    }
}
<commit_msg>[Refactoring] Reduce useless copies<commit_after>use error::{CliError, Usage, UsageKind};
use super::Command;

extern crate toml;

use constant::CONFIG_FILE_NAME;
use lib::setting;

pub struct Config {
    command: Option<String>,
    key    : Option<String>,
    value  : Option<String>,
}

impl Command for Config {
    fn validation(&self) -> bool { true }

    fn usage(&self) -> Usage {
        return Usage::new(UsageKind::Config);
    }

    fn main(&self) -> Result<(), CliError> {
        match self.command {
            Some(ref c) => match c.as_ref() {
                "set"  => self.set(),
                "init" => self.init(),
                _      => Err(From::from(self.usage())),
            },
            None => Err(From::from(self.usage())),
        }
    }
}

impl Config {
    pub fn new(command: Option<String>, key: Option<String>, value: Option<String>) -> Config {
        Config { command: command, key: key, value: value }
    }

    fn set(&self) -> Result<(), CliError> {
        let (key, value) = match (&self.key, &self.value) {
            (&Some(ref k), &Some(ref v)) => (k, v),
            _                            => return Err(From::from(self.usage())),
        };

        let key   = try!(setting::ConfigKey::from(key));
        let value = try!(setting::Config::validate(&key, value));

        let config = try!(setting::Config::read());
        let config = try!(config.set(key, value));

        try!(config.create());

        Ok(())
    }

    fn init(&self) -> Result<(), CliError> {
        let message = format!("Do you want to initialize \"{}\"?", CONFIG_FILE_NAME);

        Self::run_after_confirmation(message,|| setting::Config::default().create())
    }
}
<|endoftext|>


<commit_before>//! Tests on the command API
use std::sync::{Arc, Mutex, Condvar};

use commands::{self, CommandFn};

lazy_static! {
    static ref ACCESS_PAIR: Arc<(Mutex<bool>, Condvar)>
        = Arc::new((Mutex::new(false), Condvar::new()));
}

// Commands for the commands tests

pub fn command() {
    println!("command being run!");
}

pub fn panic_command() {
    panic!("panic_command panic")
}

/// Wait for the registry to initialize
pub fn wait_for_commands() {
    // First star for lazy static, second for Arc
    let &(ref lock, ref cond) = &**ACCESS_PAIR;
    let mut started = lock.lock().expect("Unable to lock ACCESS_PAIR lock!");
    while !*started {
        started = cond.wait(started)
            .expect("Oh boy, I can't wait for the commands to start!");
    }
}

#[test]
fn add_commands() {
    // Command
    assert!(commands::set("command".to_string(), Arc::new(command))
        .is_none(), "Unable to initialize command in registry");

    // Panicking command
    assert!(commands::set("panic_command".to_string(), Arc::new(panic_command))
        .is_none(), "Unable to initialize command in registry");

   // Allow waiting threads to continue
    let &(ref lock, ref cond) = &**ACCESS_PAIR;
    let mut started = lock.lock().expect("Couldn't unlock threads");
    *started = true;
    cond.notify_all();
}

#[test]
fn run_command() {
    wait_for_commands();
    let command = commands::get("command")
        .expect("Command not found");
    command();
}

#[test]
#[should_panic(expected = "command panic")]
fn run_panic_command() {
    wait_for_commands();
    let command = commands::get("panic_command")
        .expect("Command not found");
    command();
}
<commit_msg>Add command::get test<commit_after>//! Tests on the command API
use std::sync::{Arc, Mutex, Condvar};

use commands::{self, CommandFn};

lazy_static! {
    static ref ACCESS_PAIR: Arc<(Mutex<bool>, Condvar)>
        = Arc::new((Mutex::new(false), Condvar::new()));
}

// Commands for the commands tests

pub fn command() {
    println!("command being run!");
}

pub fn panic_command() {
    panic!("panic_command panic")
}

/// Wait for the registry to initialize
pub fn wait_for_commands() {
    // First star for lazy static, second for Arc
    let &(ref lock, ref cond) = &**ACCESS_PAIR;
    let mut started = lock.lock().expect("Unable to lock ACCESS_PAIR lock!");
    while !*started {
        started = cond.wait(started)
            .expect("Oh boy, I can't wait for the commands to start!");
    }
}

#[test]
fn add_commands() {
    // Command
    assert!(commands::set("command".to_string(), Arc::new(command))
        .is_none(), "Unable to initialize command in registry");

    // Panicking command
    assert!(commands::set("panic_command".to_string(), Arc::new(panic_command))
        .is_none(), "Unable to initialize command in registry");

   // Allow waiting threads to continue
    let &(ref lock, ref cond) = &**ACCESS_PAIR;
    let mut started = lock.lock().expect("Couldn't unlock threads");
    *started = true;
    cond.notify_all();
}

#[test]
fn get_command() {
    wait_for_commands();
    assert!(commands::get("command").is_some(), "Could not get command!");
}

#[test]
fn run_command() {
    wait_for_commands();
    let command = commands::get("command")
        .expect("Command not found");
    command();
}

#[test]
#[should_panic(expected = "command panic")]
fn run_panic_command() {
    wait_for_commands();
    let command = commands::get("panic_command")
        .expect("Command not found");
    command();
}
<|endoftext|>