<commit_before>use std::io::{Cursor};

use byteorder::{LittleEndian, WriteBytesExt};

use mul_reader::{simple_from_vecs};
use art::{ArtReader, TileOrStatic, Art, Tile, STATIC_OFFSET};

#[test]
fn test_load_tile() {
    let mut data = Cursor::new(vec![]);
    data.write_u32::<LittleEndian>(0).unwrap();  // Header
    for _i in 0..1022 {
        data.write_u16::<LittleEndian>(0xFFFF).unwrap();
    }

    let mul_reader = simple_from_vecs(vec![
        data.into_inner(),
    ]);
    let mut reader = ArtReader::from_mul(mul_reader);
    match reader.read(0) {
        Ok(TileOrStatic::Tile(tile)) => {
            assert_eq!(tile.header, 0);
            assert_eq!(tile.image_data[0], 0xFFFF);
        },
        Ok(_) => {
            panic!("Got Static instead of Tile");
        },
        Err(err) => panic!("{}", err)
    };
}

#[test]
fn test_tile_to_32bit() {
    let tile = Tile {
        header: 0,
        image_data: [0xFFFF; 1022]
    };
    let (width, height, data) = tile.to_32bit();
    assert_eq!(width, 44);
    assert_eq!(height, 44);
    assert_eq!(data.len(), 44 * 44);

    // Check the first row
    for i in 0..44 {
        if i == 21 || i == 22 {
            assert_eq!(data[i], 0xFFFFFFFF);
        } else {
            assert_eq!(data[i], 0);
        }
    }

    // Check the middle row
    for i in 0..44 {
        assert_eq!(data[i + (22 * 44)], 0xFFFFFFFF);
    }
}

#[test]
#[cfg(feature = "use-sdl2")]
fn test_tile_to_surface() {
    let tile = Tile {
        header: 0,
        image_data: [0xFFFF; 1022]
    };
    let surface = tile.to_surface();
    assert_eq!(surface.width(), 44);
    assert_eq!(surface.height(), 44);
    let data = surface.without_lock().unwrap();
    assert_eq!(data.len(), 44 * 44 * 4);

    // Check the first row
    for i in 0..44 {
        if i == 21 || i == 22 {
            assert_eq!(data[(i * 4)], 0xFF);
            assert_eq!(data[(i * 4) + 1], 0xFF);
            assert_eq!(data[(i * 4) + 2], 0xFF);
            assert_eq!(data[(i * 4) + 3], 0xFF);
        } else {
            assert_eq!(data[(i * 4)], 0);
            assert_eq!(data[(i * 4) + 1], 0);
            assert_eq!(data[(i * 4) + 2], 0);
            assert_eq!(data[(i * 4) + 3], 0);
        }
    }

    // Check the middle row
    for i in 0..44 {
        assert_eq!(data[((i + (22 * 44)) * 4)], 0xFF);
        assert_eq!(data[((i + (22 * 44)) * 4) + 1], 0xFF);
        assert_eq!(data[((i + (22 * 44)) * 4) + 2], 0xFF);
        assert_eq!(data[((i + (22 * 44)) * 4) + 3], 0xFF);
    }
}

#[test]
fn test_load_static() {
    let mut data = Cursor::new(vec![]);
    data.write_u32::<LittleEndian>(0).unwrap();  // Header
    for _i in 0..1022 {
        data.write_u16::<LittleEndian>(0xFFFF).unwrap();
    }

    let mut padded = vec![];
    for _i in 0..STATIC_OFFSET {
        padded.push(vec![]);
    }
    padded.push(data.into_inner());

    let mul_reader = simple_from_vecs(padded);
    let mut reader = ArtReader::from_mul(mul_reader);
    match reader.read(STATIC_OFFSET) {
        Ok(TileOrStatic::Static(stat)) => {
        },
        Ok(_) => {
            panic!("Got Tile instead of Static");
        },
        Err(err) => panic!("{}", err)
    };
}

/*#[test]
fn dump_art() {
    use mul_reader::MulWriter;
    use art::{Art, Tile};
    use std::io::FileMode;
    let dummy_tile = Tile {header: 0, image_data: [0xFFFF, ..1022]};
    let mut mul_writer = MulWriter::new(&Path::new("./testdata/test_art.idx"), &Path::new("./testdata/test_art.mul"), FileMode::Truncate).ok().expect("Can't open files for writing");

    let serialized = dummy_tile.serialize();

    for i in range(0, 0x4000u32) {
        mul_writer.append(&serialized, None, None).ok().expect("Can't write white tile");
    }
}*/
<commit_msg>Working towards proper test data<commit_after>use std::io::{Cursor};

use byteorder::{LittleEndian, WriteBytesExt};

use mul_reader::{simple_from_vecs};
use art::{ArtReader, TileOrStatic, Art, Tile, STATIC_OFFSET};

#[test]
fn test_load_tile() {
    let mut data = Cursor::new(vec![]);
    data.write_u32::<LittleEndian>(0).unwrap();  // Header
    for _i in 0..1022 {
        data.write_u16::<LittleEndian>(0xFFFF).unwrap();
    }

    let mul_reader = simple_from_vecs(vec![
        data.into_inner(),
    ]);
    let mut reader = ArtReader::from_mul(mul_reader);
    match reader.read(0) {
        Ok(TileOrStatic::Tile(tile)) => {
            assert_eq!(tile.header, 0);
            assert_eq!(tile.image_data[0], 0xFFFF);
        },
        Ok(_) => {
            panic!("Got Static instead of Tile");
        },
        Err(err) => panic!("{}", err)
    };
}

#[test]
fn test_tile_to_32bit() {
    let tile = Tile {
        header: 0,
        image_data: [0xFFFF; 1022]
    };
    let (width, height, data) = tile.to_32bit();
    assert_eq!(width, 44);
    assert_eq!(height, 44);
    assert_eq!(data.len(), 44 * 44);

    // Check the first row
    for i in 0..44 {
        if i == 21 || i == 22 {
            assert_eq!(data[i], 0xFFFFFFFF);
        } else {
            assert_eq!(data[i], 0);
        }
    }

    // Check the middle row
    for i in 0..44 {
        assert_eq!(data[i + (22 * 44)], 0xFFFFFFFF);
    }
}

#[test]
#[cfg(feature = "use-sdl2")]
fn test_tile_to_surface() {
    let tile = Tile {
        header: 0,
        image_data: [0xFFFF; 1022]
    };
    let surface = tile.to_surface();
    assert_eq!(surface.width(), 44);
    assert_eq!(surface.height(), 44);
    let data = surface.without_lock().unwrap();
    assert_eq!(data.len(), 44 * 44 * 4);

    // Check the first row
    for i in 0..44 {
        if i == 21 || i == 22 {
            assert_eq!(data[(i * 4)], 0xFF);
            assert_eq!(data[(i * 4) + 1], 0xFF);
            assert_eq!(data[(i * 4) + 2], 0xFF);
            assert_eq!(data[(i * 4) + 3], 0xFF);
        } else {
            assert_eq!(data[(i * 4)], 0);
            assert_eq!(data[(i * 4) + 1], 0);
            assert_eq!(data[(i * 4) + 2], 0);
            assert_eq!(data[(i * 4) + 3], 0);
        }
    }

    // Check the middle row
    for i in 0..44 {
        assert_eq!(data[((i + (22 * 44)) * 4)], 0xFF);
        assert_eq!(data[((i + (22 * 44)) * 4) + 1], 0xFF);
        assert_eq!(data[((i + (22 * 44)) * 4) + 2], 0xFF);
        assert_eq!(data[((i + (22 * 44)) * 4) + 3], 0xFF);
    }
}

#[test]
fn test_load_static() {
    let mut data = Cursor::new(vec![]);
    data.write_u16::<LittleEndian>(0).unwrap();  // Size
    data.write_u16::<LittleEndian>(0).unwrap();  // Trigger
    data.write_u16::<LittleEndian>(0).unwrap();  // Width
    data.write_u16::<LittleEndian>(0).unwrap();  // Height

    data.write_u16::<LittleEndian>(0).unwrap();  // Offset table, one per row

    data.write_u16::<LittleEndian>(0).unwrap();  // Run padding
    data.write_u16::<LittleEndian>(0).unwrap();  // Run colour

    let mut padded = vec![];
    for _i in 0..STATIC_OFFSET {
        padded.push(vec![]);
    }
    padded.push(data.into_inner());

    let mul_reader = simple_from_vecs(padded);
    let mut reader = ArtReader::from_mul(mul_reader);
    match reader.read(STATIC_OFFSET) {
        Ok(TileOrStatic::Static(stat)) => {
        },
        Ok(_) => {
            panic!("Got Tile instead of Static");
        },
        Err(err) => panic!("{}", err)
    };
}

/*#[test]
fn dump_art() {
    use mul_reader::MulWriter;
    use art::{Art, Tile};
    use std::io::FileMode;
    let dummy_tile = Tile {header: 0, image_data: [0xFFFF, ..1022]};
    let mut mul_writer = MulWriter::new(&Path::new("./testdata/test_art.idx"), &Path::new("./testdata/test_art.mul"), FileMode::Truncate).ok().expect("Can't open files for writing");

    let serialized = dummy_tile.serialize();

    for i in range(0, 0x4000u32) {
        mul_writer.append(&serialized, None, None).ok().expect("Can't write white tile");
    }
}*/
<|endoftext|>


<commit_before>use std::cmp::{max, min};
use std::mem;

use term_input::{Key, Arrow};
use termbox_simple::Termbox;

use trie::Trie;
use tui::style;
use tui::termbox;
use tui::widget::{WidgetRet, Widget};
use utils;

// TODO: Make these settings
const SCROLLOFF : i32 = 5;
const HIST_SIZE : usize = 30;

pub struct TextField {
    /// The message that's currently being edited (not yet sent)
    buffer : Vec<char>,

    /// Cursor in currently shown line
    cursor : i32,

    /// Horizontal scroll
    scroll : i32,

    /// Width of the widget
    width : i32,

    /// A history of sent messages/commands. Once added messages are never
    /// modified. A modification attempt should result in a new buffer with a
    /// copy of the vector in history. (old contents of the buffer will be lost)
    history : Vec<Vec<char>>,

    mode : Mode,
}

enum Mode {
    /// Editing the buffer
    Edit,

    /// Browsing history
    History(i32),

    /// Auto-completing a nick in channel
    Autocomplete {
        original_buffer    : Vec<char>,
        insertion_point    : usize,
        word_starts        : usize,
        completions        : Vec<String>,
        current_completion : usize,
    }
}

impl TextField {
    pub fn new(width : i32) -> TextField {
        TextField {
            buffer: Vec::with_capacity(512),
            cursor: 0,
            scroll: 0,
            width: width,
            history: Vec::with_capacity(HIST_SIZE),
            mode: Mode::Edit,
        }
    }

    pub fn resize_(&mut self, width : i32, _ : i32) {
        self.width = width;
        self.move_cursor_to_end();
    }

    pub fn draw_(&self, tb : &mut Termbox, pos_x : i32, pos_y : i32) {
        match self.mode {
            Mode::Edit => {
                draw_line(tb, &self.buffer, pos_x, pos_y, self.scroll, self.width, self.cursor);
            },
            Mode::History(hist_curs) => {
                draw_line(tb,
                          &self.history[hist_curs as usize],
                          pos_x, pos_y, self.scroll, self.width, self.cursor);
            },
            Mode::Autocomplete {
                ref original_buffer, insertion_point, word_starts,
                ref completions, current_completion
            } => {
                // draw a placeholder for the cursor
                tb.change_cell(pos_x + self.cursor - self.scroll, pos_y,
                               ' ',
                               style::USER_MSG.fg, style::USER_MSG.bg);

                let completion : &str = &completions[current_completion];

                let mut orig_buf_iter = original_buffer.iter().cloned();
                let mut completion_iter = completion.chars();

                let iter : utils::InsertIterator<char> =
                    utils::insert_iter(&mut orig_buf_iter, &mut completion_iter, insertion_point);

                for (char_idx, char) in iter.enumerate() {
                    if char_idx >= ((self.scroll + self.width) as usize) {
                        break;
                    }

                    if char_idx >= self.scroll as usize {
                        if char_idx >= word_starts &&
                                char_idx < insertion_point + completion.len() {
                            tb.change_cell(pos_x + (char_idx as i32) - self.scroll, pos_y,
                                           char,
                                           style::COMPLETION.fg, style::COMPLETION.bg);
                        } else {
                            tb.change_cell(pos_x + (char_idx as i32) - self.scroll, pos_y,
                                           char,
                                           style::USER_MSG.fg, style::USER_MSG.bg);
                        }

                    }
                }

                tb.set_cursor(pos_x + self.cursor - self.scroll, pos_y);
            },
        }
    }

    pub fn keypressed_(&mut self, key : Key) -> WidgetRet {
        match key {
            Key::Char(ch) => {
                self.modify();
                self.buffer.insert(self.cursor as usize, ch);
                self.inc_cursor();
                WidgetRet::KeyHandled
            },

            Key::Backspace => {
                if self.cursor > 0 {
                    self.modify();
                    self.buffer.remove(self.cursor as usize - 1);
                    self.dec_cursor();
                }
                WidgetRet::KeyHandled
            },

            Key::Ctrl(ch) => {
                if ch == 'a' {
                    self.move_cursor(0);
                    WidgetRet::KeyHandled
                }

                else if ch == 'e' {
                    self.move_cursor_to_end();
                    WidgetRet::KeyHandled
                }

                else if ch == 'k' {
                    if self.cursor != self.line_len() {
                        self.modify();
                        self.buffer.drain(self.cursor as usize ..);
                    }
                    WidgetRet::KeyHandled
                }

                else if ch == 'w' {
                    self.consume_word_before_curs();
                    WidgetRet::KeyHandled
                }

                else {
                    WidgetRet::KeyIgnored
                }
            },

            Key::Arrow(Arrow::Left) => {
                self.dec_cursor();
                WidgetRet::KeyHandled
            },

            Key::Arrow(Arrow::Right) => {
                self.inc_cursor();
                WidgetRet::KeyHandled
            },

            Key::Enter => {
                if self.line_len() > 0 {
                    self.modify();

                    let ret = mem::replace(&mut self.buffer, Vec::new());
                    if self.history.len() == HIST_SIZE {
                        let mut reuse = self.history.remove(0);
                        reuse.clear();
                        reuse.extend_from_slice(&ret);
                        self.history.push(reuse);
                    } else {
                        self.history.push(ret.clone());
                    }

                    self.move_cursor(0);

                    WidgetRet::Input(ret)
                } else {
                    WidgetRet::KeyHandled
                }
            },

            ////////////////////////////////////////////////////////////////////
            // Scrolling in history or autocompletion list

            Key::Arrow(Arrow::Up) => {
                let mode = mem::replace(&mut self.mode, Mode::Edit);

                match mode {
                    Mode::Edit => {
                        if !self.history.is_empty() {
                            self.mode = Mode::History((self.history.len() as i32) - 1);
                            self.move_cursor_to_end();
                        }
                    },
                    Mode::History(hist_curs) => {
                        self.mode = Mode::History(
                            if hist_curs > 0 { hist_curs - 1 } else { hist_curs });
                        self.move_cursor_to_end();
                    },
                    Mode::Autocomplete {
                        original_buffer, insertion_point,
                        word_starts, completions, current_completion, ..
                    } => {
                        let current_completion =
                            if current_completion != completions.len() - 1 {
                                current_completion + 1
                            } else {
                                current_completion
                            };

                        let cursor = (insertion_point + completions[current_completion].len()) as i32;

                        self.mode = Mode::Autocomplete {
                            original_buffer: original_buffer,
                            insertion_point: insertion_point,
                            word_starts: word_starts,
                            completions: completions,
                            current_completion: current_completion,
                        };

                        self.move_cursor(cursor);
                    },
                }

                WidgetRet::KeyHandled
            },

            Key::Arrow(Arrow::Down) => {
                let mode = mem::replace(&mut self.mode, Mode::Edit);

                match mode {
                    Mode::Edit => {},
                    Mode::History(hist_curs) => {
                        if hist_curs != (self.history.len() - 1) as i32 {
                            self.mode = Mode::History(hist_curs + 1);
                        } else {
                            self.mode = Mode::Edit;
                        }
                        self.move_cursor_to_end();
                    },
                    Mode::Autocomplete {
                        original_buffer, insertion_point,
                        word_starts, completions, current_completion, ..
                    } => {
                        let current_completion =
                            if current_completion > 0 {
                                current_completion - 1
                            } else {
                                current_completion
                            };

                        let cursor = (insertion_point + completions[current_completion].len()) as i32;

                        self.mode = Mode::Autocomplete {
                            original_buffer: original_buffer,
                            insertion_point: insertion_point,
                            word_starts: word_starts,
                            completions: completions,
                            current_completion: current_completion,
                        };

                        self.move_cursor(cursor);
                    },
                }

                WidgetRet::KeyHandled
            },

            ////////////////////////////////////////////////////////////////////

            _ => WidgetRet::KeyIgnored,
        }
    }

    fn consume_word_before_curs(&mut self) {
        // No modifications can happen if the scroll is at the beginning
        if self.cursor == 0 {
            return;
        }

        self.modify();

        let char = self.buffer[(self.cursor - 1) as usize];

        // Try to imitate vim's behaviour here.
        if char.is_whitespace() {
            self.consume_before(|c| c.is_whitespace());
        }

        else if char.is_alphanumeric() {
            self.consume_before(|c| c.is_alphanumeric());
        }

        else {
            self.consume_before(|c| !c.is_alphanumeric());
        }
    }

    fn consume_before<F>(&mut self, f : F) where F : Fn(char) -> bool {
        let end_range = self.cursor as usize;
        let mut begin_range = self.cursor - 1;
        while begin_range >= 0 && f(self.buffer[begin_range as usize]) {
            begin_range -= 1;
        }
        self.buffer.drain(((begin_range + 1) as usize) .. end_range);
        self.move_cursor(begin_range + 1);
    }

    // Ignoring auto-completions
    fn shown_line(&self) -> &Vec<char> {
        match self.mode {
            Mode::Edit | Mode::Autocomplete { .. } => &self.buffer,
            Mode::History(hist_curs) => &self.history[hist_curs as usize],
        }
    }

    fn line_len(&self) -> i32 {
        match self.mode {
            Mode::Edit => {
                self.buffer.len() as i32
            },
            Mode::History(hist_curs) => {
                self.history[hist_curs as usize].len() as i32
            },
            Mode::Autocomplete { ref original_buffer, ref completions, current_completion, .. } => {
                (original_buffer.len() + completions[current_completion].len()) as i32
            },
        }
    }

    ////////////////////////////////////////////////////////////////////////////

    fn in_autocomplete(&self) -> bool {
        match self.mode {
            Mode::Autocomplete { .. } => true,
            _ => false
        }
    }

    fn modify(&mut self) {
        match self.mode {
            Mode::Edit => {},
            Mode::History(hist_idx) => {
                self.buffer.clear();
                self.buffer.extend_from_slice(&self.history[hist_idx as usize]);
            },
            Mode::Autocomplete {
                ref mut original_buffer,
                mut insertion_point,
                ref mut completions,
                current_completion,
                ..
            } => {
                let mut buffer  : Vec<char>   = mem::replace(original_buffer, vec![]);
                let completions : Vec<String> = mem::replace(completions, vec![]);
                let word = &completions[current_completion];

                // FIXME: This is inefficient
                for char in word.chars() {
                    buffer.insert(insertion_point, char);
                    insertion_point += 1;
                }

                self.buffer = buffer;
            }
        }

        self.mode = Mode::Edit;
    }

    ////////////////////////////////////////////////////////////////////////////
    // Manipulating cursor

    fn inc_cursor(&mut self) {
        let cur = min(self.line_len(), self.cursor + 1);
        self.move_cursor(cur);
    }

    fn dec_cursor(&mut self) {
        let cur = max(0, self.cursor - 1);
        self.move_cursor(cur);
    }

    fn move_cursor_to_end(&mut self) {
        let cursor = self.line_len();
        self.move_cursor(cursor);
    }

    fn move_cursor(&mut self, cursor : i32) {
        assert!(cursor >= 0 && cursor <= self.line_len());
        self.cursor = cursor;

        if self.line_len() + 1 < self.width {
            self.scroll = 0;
        } else {
            let scrolloff = { if self.width < 2 * SCROLLOFF + 1 { 0 } else { SCROLLOFF } };

            let left_end  = self.scroll;
            let right_end = self.scroll + self.width;

            if cursor - scrolloff < left_end {
                self.scroll = max(0, cursor - scrolloff);
            } else if cursor + scrolloff >= right_end {
                self.scroll = min(// +1 because cursor should be visible, i.e.
                                  // right_end > cursor should hold after this
                                  max(0, cursor + 1 + scrolloff - self.width),
                                  // +1 because cursor goes one more character
                                  // after the buffer, to be able to add chars
                                  max(0, self.line_len() + 1 - self.width));
            }
        }
    }
}

fn draw_line(tb: &mut Termbox, line : &[char], pos_x : i32, pos_y : i32, scroll : i32, width : i32, cursor : i32) {
    let slice : &[char] = &line[ scroll as usize .. min(line.len(), (scroll + width) as usize) ];

    termbox::print_chars(tb, pos_x, pos_y, style::USER_MSG.fg, style::USER_MSG.bg, slice);

    // On my terminal the cursor is only shown when there's a character
    // under it.
    if cursor as usize >= line.len() {
        tb.change_cell(pos_x + cursor - scroll, pos_y,
                       ' ',
                       style::USER_MSG.fg, style::USER_MSG.bg);
    }
    tb.set_cursor(pos_x + cursor - scroll, pos_y);
}

impl Widget for TextField {
    fn resize(&mut self, width : i32, height : i32) {
        self.resize_(width, height);
    }

    fn draw(&self, tb : &mut Termbox, pos_x : i32, pos_y : i32) {
        self.draw_(tb, pos_x, pos_y);
    }

    fn keypressed(&mut self, key : Key) -> WidgetRet {
        self.keypressed_(key)
    }

    fn autocomplete(&mut self, dict : &Trie) {
        if self.in_autocomplete() {
            // AWFUL CODE YO
            self.keypressed(Key::Arrow(Arrow::Up));
            return;
        }

        let cursor_right = self.cursor;
        let mut cursor_left = max(0, cursor_right - 1);

        let completions = {
            let line = self.shown_line();

            while cursor_left >= 0
                    && line.get(cursor_left as usize).map(|c| c.is_alphanumeric()).unwrap_or(false) {
                cursor_left -= 1;
            }

            let word = {
                if cursor_left == cursor_right {
                    &[]
                } else {
                    cursor_left += 1;
                    &line[ (cursor_left as usize) .. (cursor_right as usize) ]
                }
            };

            dict.drop_pfx(&mut word.iter().cloned())
        };

        if !completions.is_empty() {
            let completion_len = completions[0].len();
            self.mode = Mode::Autocomplete {
                original_buffer: self.shown_line().to_owned(),
                insertion_point: self.cursor as usize,
                word_starts: cursor_left as usize,
                completions: completions,
                current_completion: 0,
            };
            let cursor = self.cursor;
            self.move_cursor(cursor + completion_len as i32);
        }
    }
}
<commit_msg>text_field: Fix C-w behavior<commit_after>use std::cmp::{max, min};
use std::mem;

use term_input::{Key, Arrow};
use termbox_simple::Termbox;

use trie::Trie;
use tui::style;
use tui::termbox;
use tui::widget::{WidgetRet, Widget};
use utils;

// TODO: Make these settings
const SCROLLOFF : i32 = 5;
const HIST_SIZE : usize = 30;

pub struct TextField {
    /// The message that's currently being edited (not yet sent)
    buffer : Vec<char>,

    /// Cursor in currently shown line
    cursor : i32,

    /// Horizontal scroll
    scroll : i32,

    /// Width of the widget
    width : i32,

    /// A history of sent messages/commands. Once added messages are never
    /// modified. A modification attempt should result in a new buffer with a
    /// copy of the vector in history. (old contents of the buffer will be lost)
    history : Vec<Vec<char>>,

    mode : Mode,
}

enum Mode {
    /// Editing the buffer
    Edit,

    /// Browsing history
    History(i32),

    /// Auto-completing a nick in channel
    Autocomplete {
        original_buffer    : Vec<char>,
        insertion_point    : usize,
        word_starts        : usize,
        completions        : Vec<String>,
        current_completion : usize,
    }
}

impl TextField {
    pub fn new(width : i32) -> TextField {
        TextField {
            buffer: Vec::with_capacity(512),
            cursor: 0,
            scroll: 0,
            width: width,
            history: Vec::with_capacity(HIST_SIZE),
            mode: Mode::Edit,
        }
    }

    pub fn resize_(&mut self, width : i32, _ : i32) {
        self.width = width;
        self.move_cursor_to_end();
    }

    pub fn draw_(&self, tb : &mut Termbox, pos_x : i32, pos_y : i32) {
        match self.mode {
            Mode::Edit => {
                draw_line(tb, &self.buffer, pos_x, pos_y, self.scroll, self.width, self.cursor);
            },
            Mode::History(hist_curs) => {
                draw_line(tb,
                          &self.history[hist_curs as usize],
                          pos_x, pos_y, self.scroll, self.width, self.cursor);
            },
            Mode::Autocomplete {
                ref original_buffer, insertion_point, word_starts,
                ref completions, current_completion
            } => {
                // draw a placeholder for the cursor
                tb.change_cell(pos_x + self.cursor - self.scroll, pos_y,
                               ' ',
                               style::USER_MSG.fg, style::USER_MSG.bg);

                let completion : &str = &completions[current_completion];

                let mut orig_buf_iter = original_buffer.iter().cloned();
                let mut completion_iter = completion.chars();

                let iter : utils::InsertIterator<char> =
                    utils::insert_iter(&mut orig_buf_iter, &mut completion_iter, insertion_point);

                for (char_idx, char) in iter.enumerate() {
                    if char_idx >= ((self.scroll + self.width) as usize) {
                        break;
                    }

                    if char_idx >= self.scroll as usize {
                        if char_idx >= word_starts &&
                                char_idx < insertion_point + completion.len() {
                            tb.change_cell(pos_x + (char_idx as i32) - self.scroll, pos_y,
                                           char,
                                           style::COMPLETION.fg, style::COMPLETION.bg);
                        } else {
                            tb.change_cell(pos_x + (char_idx as i32) - self.scroll, pos_y,
                                           char,
                                           style::USER_MSG.fg, style::USER_MSG.bg);
                        }

                    }
                }

                tb.set_cursor(pos_x + self.cursor - self.scroll, pos_y);
            },
        }
    }

    pub fn keypressed_(&mut self, key : Key) -> WidgetRet {
        match key {
            Key::Char(ch) => {
                self.modify();
                self.buffer.insert(self.cursor as usize, ch);
                self.inc_cursor();
                WidgetRet::KeyHandled
            },

            Key::Backspace => {
                if self.cursor > 0 {
                    self.modify();
                    self.buffer.remove(self.cursor as usize - 1);
                    self.dec_cursor();
                }
                WidgetRet::KeyHandled
            },

            Key::Ctrl(ch) => {
                if ch == 'a' {
                    self.move_cursor(0);
                    WidgetRet::KeyHandled
                }

                else if ch == 'e' {
                    self.move_cursor_to_end();
                    WidgetRet::KeyHandled
                }

                else if ch == 'k' {
                    if self.cursor != self.line_len() {
                        self.modify();
                        self.buffer.drain(self.cursor as usize ..);
                    }
                    WidgetRet::KeyHandled
                }

                else if ch == 'w' {
                    self.consume_word_before_curs();
                    WidgetRet::KeyHandled
                }

                else {
                    WidgetRet::KeyIgnored
                }
            },

            Key::Arrow(Arrow::Left) => {
                self.dec_cursor();
                WidgetRet::KeyHandled
            },

            Key::Arrow(Arrow::Right) => {
                self.inc_cursor();
                WidgetRet::KeyHandled
            },

            Key::Enter => {
                if self.line_len() > 0 {
                    self.modify();

                    let ret = mem::replace(&mut self.buffer, Vec::new());
                    if self.history.len() == HIST_SIZE {
                        let mut reuse = self.history.remove(0);
                        reuse.clear();
                        reuse.extend_from_slice(&ret);
                        self.history.push(reuse);
                    } else {
                        self.history.push(ret.clone());
                    }

                    self.move_cursor(0);

                    WidgetRet::Input(ret)
                } else {
                    WidgetRet::KeyHandled
                }
            },

            ////////////////////////////////////////////////////////////////////
            // Scrolling in history or autocompletion list

            Key::Arrow(Arrow::Up) => {
                let mode = mem::replace(&mut self.mode, Mode::Edit);

                match mode {
                    Mode::Edit => {
                        if !self.history.is_empty() {
                            self.mode = Mode::History((self.history.len() as i32) - 1);
                            self.move_cursor_to_end();
                        }
                    },
                    Mode::History(hist_curs) => {
                        self.mode = Mode::History(
                            if hist_curs > 0 { hist_curs - 1 } else { hist_curs });
                        self.move_cursor_to_end();
                    },
                    Mode::Autocomplete {
                        original_buffer, insertion_point,
                        word_starts, completions, current_completion, ..
                    } => {
                        let current_completion =
                            if current_completion != completions.len() - 1 {
                                current_completion + 1
                            } else {
                                current_completion
                            };

                        let cursor = (insertion_point + completions[current_completion].len()) as i32;

                        self.mode = Mode::Autocomplete {
                            original_buffer: original_buffer,
                            insertion_point: insertion_point,
                            word_starts: word_starts,
                            completions: completions,
                            current_completion: current_completion,
                        };

                        self.move_cursor(cursor);
                    },
                }

                WidgetRet::KeyHandled
            },

            Key::Arrow(Arrow::Down) => {
                let mode = mem::replace(&mut self.mode, Mode::Edit);

                match mode {
                    Mode::Edit => {},
                    Mode::History(hist_curs) => {
                        if hist_curs != (self.history.len() - 1) as i32 {
                            self.mode = Mode::History(hist_curs + 1);
                        } else {
                            self.mode = Mode::Edit;
                        }
                        self.move_cursor_to_end();
                    },
                    Mode::Autocomplete {
                        original_buffer, insertion_point,
                        word_starts, completions, current_completion, ..
                    } => {
                        let current_completion =
                            if current_completion > 0 {
                                current_completion - 1
                            } else {
                                current_completion
                            };

                        let cursor = (insertion_point + completions[current_completion].len()) as i32;

                        self.mode = Mode::Autocomplete {
                            original_buffer: original_buffer,
                            insertion_point: insertion_point,
                            word_starts: word_starts,
                            completions: completions,
                            current_completion: current_completion,
                        };

                        self.move_cursor(cursor);
                    },
                }

                WidgetRet::KeyHandled
            },

            ////////////////////////////////////////////////////////////////////

            _ => WidgetRet::KeyIgnored,
        }
    }

    fn consume_word_before_curs(&mut self) {
        // No modifications can happen if the scroll is at the beginning
        if self.cursor == 0 {
            return;
        }

        self.modify();

        let char = self.buffer[(self.cursor - 1) as usize];

        // Try to imitate vim's behaviour here.
        if char.is_whitespace() {
            self.consume_before(|c| c.is_whitespace());
            self.consume_before(|c| c.is_alphanumeric());
        } else {
            self.consume_before(|c| c.is_alphanumeric());
        }
    }

    fn consume_before<F>(&mut self, f : F) where F : Fn(char) -> bool {
        let end_range = self.cursor as usize;
        let mut begin_range = self.cursor - 1;
        while begin_range >= 0 && f(self.buffer[begin_range as usize]) {
            begin_range -= 1;
        }
        self.buffer.drain(((begin_range + 1) as usize) .. end_range);
        self.move_cursor(begin_range + 1);
    }

    // Ignoring auto-completions
    fn shown_line(&self) -> &Vec<char> {
        match self.mode {
            Mode::Edit | Mode::Autocomplete { .. } => &self.buffer,
            Mode::History(hist_curs) => &self.history[hist_curs as usize],
        }
    }

    fn line_len(&self) -> i32 {
        match self.mode {
            Mode::Edit => {
                self.buffer.len() as i32
            },
            Mode::History(hist_curs) => {
                self.history[hist_curs as usize].len() as i32
            },
            Mode::Autocomplete { ref original_buffer, ref completions, current_completion, .. } => {
                (original_buffer.len() + completions[current_completion].len()) as i32
            },
        }
    }

    ////////////////////////////////////////////////////////////////////////////

    fn in_autocomplete(&self) -> bool {
        match self.mode {
            Mode::Autocomplete { .. } => true,
            _ => false
        }
    }

    fn modify(&mut self) {
        match self.mode {
            Mode::Edit => {},
            Mode::History(hist_idx) => {
                self.buffer.clear();
                self.buffer.extend_from_slice(&self.history[hist_idx as usize]);
            },
            Mode::Autocomplete {
                ref mut original_buffer,
                mut insertion_point,
                ref mut completions,
                current_completion,
                ..
            } => {
                let mut buffer  : Vec<char>   = mem::replace(original_buffer, vec![]);
                let completions : Vec<String> = mem::replace(completions, vec![]);
                let word = &completions[current_completion];

                // FIXME: This is inefficient
                for char in word.chars() {
                    buffer.insert(insertion_point, char);
                    insertion_point += 1;
                }

                self.buffer = buffer;
            }
        }

        self.mode = Mode::Edit;
    }

    ////////////////////////////////////////////////////////////////////////////
    // Manipulating cursor

    fn inc_cursor(&mut self) {
        let cur = min(self.line_len(), self.cursor + 1);
        self.move_cursor(cur);
    }

    fn dec_cursor(&mut self) {
        let cur = max(0, self.cursor - 1);
        self.move_cursor(cur);
    }

    fn move_cursor_to_end(&mut self) {
        let cursor = self.line_len();
        self.move_cursor(cursor);
    }

    fn move_cursor(&mut self, cursor : i32) {
        assert!(cursor >= 0 && cursor <= self.line_len());
        self.cursor = cursor;

        if self.line_len() + 1 < self.width {
            self.scroll = 0;
        } else {
            let scrolloff = { if self.width < 2 * SCROLLOFF + 1 { 0 } else { SCROLLOFF } };

            let left_end  = self.scroll;
            let right_end = self.scroll + self.width;

            if cursor - scrolloff < left_end {
                self.scroll = max(0, cursor - scrolloff);
            } else if cursor + scrolloff >= right_end {
                self.scroll = min(// +1 because cursor should be visible, i.e.
                                  // right_end > cursor should hold after this
                                  max(0, cursor + 1 + scrolloff - self.width),
                                  // +1 because cursor goes one more character
                                  // after the buffer, to be able to add chars
                                  max(0, self.line_len() + 1 - self.width));
            }
        }
    }
}

fn draw_line(tb: &mut Termbox, line : &[char], pos_x : i32, pos_y : i32, scroll : i32, width : i32, cursor : i32) {
    let slice : &[char] = &line[ scroll as usize .. min(line.len(), (scroll + width) as usize) ];

    termbox::print_chars(tb, pos_x, pos_y, style::USER_MSG.fg, style::USER_MSG.bg, slice);

    // On my terminal the cursor is only shown when there's a character
    // under it.
    if cursor as usize >= line.len() {
        tb.change_cell(pos_x + cursor - scroll, pos_y,
                       ' ',
                       style::USER_MSG.fg, style::USER_MSG.bg);
    }
    tb.set_cursor(pos_x + cursor - scroll, pos_y);
}

impl Widget for TextField {
    fn resize(&mut self, width : i32, height : i32) {
        self.resize_(width, height);
    }

    fn draw(&self, tb : &mut Termbox, pos_x : i32, pos_y : i32) {
        self.draw_(tb, pos_x, pos_y);
    }

    fn keypressed(&mut self, key : Key) -> WidgetRet {
        self.keypressed_(key)
    }

    fn autocomplete(&mut self, dict : &Trie) {
        if self.in_autocomplete() {
            // AWFUL CODE YO
            self.keypressed(Key::Arrow(Arrow::Up));
            return;
        }

        let cursor_right = self.cursor;
        let mut cursor_left = max(0, cursor_right - 1);

        let completions = {
            let line = self.shown_line();

            while cursor_left >= 0
                    && line.get(cursor_left as usize).map(|c| c.is_alphanumeric()).unwrap_or(false) {
                cursor_left -= 1;
            }

            let word = {
                if cursor_left == cursor_right {
                    &[]
                } else {
                    cursor_left += 1;
                    &line[ (cursor_left as usize) .. (cursor_right as usize) ]
                }
            };

            dict.drop_pfx(&mut word.iter().cloned())
        };

        if !completions.is_empty() {
            let completion_len = completions[0].len();
            self.mode = Mode::Autocomplete {
                original_buffer: self.shown_line().to_owned(),
                insertion_point: self.cursor as usize,
                word_starts: cursor_left as usize,
                completions: completions,
                current_completion: 0,
            };
            let cursor = self.cursor;
            self.move_cursor(cursor + completion_len as i32);
        }
    }
}
<|endoftext|>


<commit_before>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Aleksander Bielawski <pabzdzdzwiagief@gmail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

extern crate getopts;

extern crate uucore;

use std::fs::OpenOptions;
use std::io::{copy, sink, stdin, stdout, Error, ErrorKind, Read, Result, Write};
use std::path::{Path, PathBuf};

static NAME: &str = "tee";
static VERSION: &str = env!("CARGO_PKG_VERSION");

pub fn uumain(args: impl uucore::Args) -> i32 {
    let args = args.collect_str();

    match options(&args).and_then(exec) {
        Ok(_) => 0,
        Err(_) => 1,
    }
}

#[allow(dead_code)]
struct Options {
    program: String,
    append: bool,
    ignore_interrupts: bool,
    print_and_exit: Option<String>,
    files: Vec<String>,
}

fn options(args: &[String]) -> Result<Options> {
    let mut opts = getopts::Options::new();

    opts.optflag("a", "append", "append to the given FILEs, do not overwrite");
    opts.optflag("i", "ignore-interrupts", "ignore interrupt signals");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    opts.parse(&args[1..])
        .map_err(|e| Error::new(ErrorKind::Other, format!("{}", e)))
        .and_then(|m| {
            let version = format!("{} {}", NAME, VERSION);
            let arguments = "[OPTION]... [FILE]...";
            let brief = "Copy standard input to each FILE, and also to standard output.";
            let comment = "If a FILE is -, it refers to a file named - .";
            let help = format!(
                "{}\n\nUsage:\n  {} {}\n\n{}\n{}",
                version,
                NAME,
                arguments,
                opts.usage(brief),
                comment
            );
            let names: Vec<String> = m.free.clone().into_iter().collect();
            let to_print = if m.opt_present("help") {
                Some(help)
            } else if m.opt_present("version") {
                Some(version)
            } else {
                None
            };
            Ok(Options {
                program: NAME.to_owned(),
                append: m.opt_present("append"),
                ignore_interrupts: m.opt_present("ignore-interrupts"),
                print_and_exit: to_print,
                files: names,
            })
        })
        .map_err(|message| warn(format!("{}", message).as_ref()))
}

fn exec(options: Options) -> Result<()> {
    match options.print_and_exit {
        Some(text) => {
            println!("{}", text);
            Ok(())
        }
        None => tee(options),
    }
}

fn tee(options: Options) -> Result<()> {
    let mut writers: Vec<Box<dyn Write>> = options
        .files
        .clone()
        .into_iter()
        .map(|file| open(file, options.append))
        .collect();
    writers.push(Box::new(stdout()));
    let output = &mut MultiWriter { writers };
    let input = &mut NamedReader {
        inner: Box::new(stdin()) as Box<dyn Read>,
    };
    if copy(input, output).is_err() || output.flush().is_err() {
        Err(Error::new(ErrorKind::Other, ""))
    } else {
        Ok(())
    }
}

fn open(name: String, append: bool) -> Box<dyn Write> {
    let path = PathBuf::from(name);
    let inner: Box<dyn Write> = {
        let mut options = OpenOptions::new();
        let mode = if append {
            options.append(true)
        } else {
            options.truncate(true)
        };
        match mode.write(true).create(true).open(path.as_path()) {
            Ok(file) => Box::new(file),
            Err(_) => Box::new(sink()),
        }
    };
    Box::new(NamedWriter { inner, path }) as Box<dyn Write>
}

struct MultiWriter {
    writers: Vec<Box<dyn Write>>,
}

impl Write for MultiWriter {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        for writer in &mut self.writers {
            writer.write_all(buf)?;
        }
        Ok(buf.len())
    }

    fn flush(&mut self) -> Result<()> {
        for writer in &mut self.writers {
            writer.flush()?;
        }
        Ok(())
    }
}

struct NamedWriter {
    inner: Box<dyn Write>,
    path: PathBuf,
}

impl Write for NamedWriter {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        match self.inner.write(buf) {
            Err(f) => {
                self.inner = Box::new(sink()) as Box<dyn Write>;
                warn(format!("{}: {}", self.path.display(), f.to_string()).as_ref());
                Err(f)
            }
            okay => okay,
        }
    }

    fn flush(&mut self) -> Result<()> {
        match self.inner.flush() {
            Err(f) => {
                self.inner = Box::new(sink()) as Box<dyn Write>;
                warn(format!("{}: {}", self.path.display(), f.to_string()).as_ref());
                Err(f)
            }
            okay => okay,
        }
    }
}

struct NamedReader {
    inner: Box<dyn Read>,
}

impl Read for NamedReader {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        match self.inner.read(buf) {
            Err(f) => {
                warn(format!("{}: {}", Path::new("stdin").display(), f.to_string()).as_ref());
                Err(f)
            }
            okay => okay,
        }
    }
}

fn warn(message: &str) -> Error {
    eprintln!("{}: {}", NAME, message);
    Error::new(ErrorKind::Other, format!("{}: {}", NAME, message))
}
<commit_msg>refactor/polish ~ fix `cargo clippy` complaint (bind_instead_of_map)<commit_after>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Aleksander Bielawski <pabzdzdzwiagief@gmail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

extern crate getopts;

extern crate uucore;

use std::fs::OpenOptions;
use std::io::{copy, sink, stdin, stdout, Error, ErrorKind, Read, Result, Write};
use std::path::{Path, PathBuf};

static NAME: &str = "tee";
static VERSION: &str = env!("CARGO_PKG_VERSION");

pub fn uumain(args: impl uucore::Args) -> i32 {
    let args = args.collect_str();

    match options(&args).and_then(exec) {
        Ok(_) => 0,
        Err(_) => 1,
    }
}

#[allow(dead_code)]
struct Options {
    program: String,
    append: bool,
    ignore_interrupts: bool,
    print_and_exit: Option<String>,
    files: Vec<String>,
}

fn options(args: &[String]) -> Result<Options> {
    let mut opts = getopts::Options::new();

    opts.optflag("a", "append", "append to the given FILEs, do not overwrite");
    opts.optflag("i", "ignore-interrupts", "ignore interrupt signals");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    opts.parse(&args[1..])
        .map_err(|e| Error::new(ErrorKind::Other, format!("{}", e)))
        .map(|m| {
            let version = format!("{} {}", NAME, VERSION);
            let arguments = "[OPTION]... [FILE]...";
            let brief = "Copy standard input to each FILE, and also to standard output.";
            let comment = "If a FILE is -, it refers to a file named - .";
            let help = format!(
                "{}\n\nUsage:\n  {} {}\n\n{}\n{}",
                version,
                NAME,
                arguments,
                opts.usage(brief),
                comment
            );
            let names: Vec<String> = m.free.clone().into_iter().collect();
            let to_print = if m.opt_present("help") {
                Some(help)
            } else if m.opt_present("version") {
                Some(version)
            } else {
                None
            };
            Options {
                program: NAME.to_owned(),
                append: m.opt_present("append"),
                ignore_interrupts: m.opt_present("ignore-interrupts"),
                print_and_exit: to_print,
                files: names,
            }
        })
        .map_err(|message| warn(format!("{}", message).as_ref()))
}

fn exec(options: Options) -> Result<()> {
    match options.print_and_exit {
        Some(text) => {
            println!("{}", text);
            Ok(())
        }
        None => tee(options),
    }
}

fn tee(options: Options) -> Result<()> {
    let mut writers: Vec<Box<dyn Write>> = options
        .files
        .clone()
        .into_iter()
        .map(|file| open(file, options.append))
        .collect();
    writers.push(Box::new(stdout()));
    let output = &mut MultiWriter { writers };
    let input = &mut NamedReader {
        inner: Box::new(stdin()) as Box<dyn Read>,
    };
    if copy(input, output).is_err() || output.flush().is_err() {
        Err(Error::new(ErrorKind::Other, ""))
    } else {
        Ok(())
    }
}

fn open(name: String, append: bool) -> Box<dyn Write> {
    let path = PathBuf::from(name);
    let inner: Box<dyn Write> = {
        let mut options = OpenOptions::new();
        let mode = if append {
            options.append(true)
        } else {
            options.truncate(true)
        };
        match mode.write(true).create(true).open(path.as_path()) {
            Ok(file) => Box::new(file),
            Err(_) => Box::new(sink()),
        }
    };
    Box::new(NamedWriter { inner, path }) as Box<dyn Write>
}

struct MultiWriter {
    writers: Vec<Box<dyn Write>>,
}

impl Write for MultiWriter {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        for writer in &mut self.writers {
            writer.write_all(buf)?;
        }
        Ok(buf.len())
    }

    fn flush(&mut self) -> Result<()> {
        for writer in &mut self.writers {
            writer.flush()?;
        }
        Ok(())
    }
}

struct NamedWriter {
    inner: Box<dyn Write>,
    path: PathBuf,
}

impl Write for NamedWriter {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        match self.inner.write(buf) {
            Err(f) => {
                self.inner = Box::new(sink()) as Box<dyn Write>;
                warn(format!("{}: {}", self.path.display(), f.to_string()).as_ref());
                Err(f)
            }
            okay => okay,
        }
    }

    fn flush(&mut self) -> Result<()> {
        match self.inner.flush() {
            Err(f) => {
                self.inner = Box::new(sink()) as Box<dyn Write>;
                warn(format!("{}: {}", self.path.display(), f.to_string()).as_ref());
                Err(f)
            }
            okay => okay,
        }
    }
}

struct NamedReader {
    inner: Box<dyn Read>,
}

impl Read for NamedReader {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        match self.inner.read(buf) {
            Err(f) => {
                warn(format!("{}: {}", Path::new("stdin").display(), f.to_string()).as_ref());
                Err(f)
            }
            okay => okay,
        }
    }
}

fn warn(message: &str) -> Error {
    eprintln!("{}: {}", NAME, message);
    Error::new(ErrorKind::Other, format!("{}: {}", NAME, message))
}
<|endoftext|>


<commit_before>fn create1() -> Vec<&'static str> {
    let mut m = vec![];
    for n in 0..10 {
        m.push("hello");
    }
    m.clone()
}

fn create2(t: &str) -> Vec<&str> {
    let mut m = vec![];
    for n in 0..10 {
        m.push(t);
    }
    m.clone()
}

fn main() {
    let mut u = create1();

    for n in u.iter() {
        println!("{}", n);
    }

    let mut v = create2("hello");

    for n in v.iter() {
        println!("{}", n);
    }
}<commit_msg>extended code<commit_after>fn create1() -> Vec<&'static str> {
    let mut m = vec![];
    for n in 0..10 {
        m.push("hello");
    }
    m.clone()
}

fn create2(t: &str) -> Vec<&str> {
    let mut m = vec![];
    for n in 0..10 {
        m.push(t);
    }
    m.clone()
}

fn create3(t: &str) -> Vec<&str> {
    vec![t; 10]
}

fn main() {
    let mut u = create1();

    for n in u.iter() {
        println!("{}", n);
    }

    let mut v = create2("hello");

    for n in v.iter() {
        println!("{}", n);
    }

    let w = create3("hello");
    for n in &w {
        println!("{}", n);
    }
}<|endoftext|>


<commit_before>use prelude::*;

use BytesError;

use winapi::shared::guiddef;

#[cfg(feature = "guid")]
impl Uuid {
    /// Attempts to create a [`Uuid`] from a little endian winapi `GUID`
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub fn from_guid(guid: guiddef::GUID) -> Result<Uuid, BytesError> {
        Uuid::from_fields_le(
            guid.Data1 as u32,
            guid.Data2 as u16,
            guid.Data3 as u16,
            &(guid.Data4 as [u8; 8]),
        )
    }

    /// Converts a [`Uuid`] into a little endian winapi `GUID`
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub fn to_guid(&self) -> guiddef::GUID {
        let (data1, data2, data3, data4) = self.to_fields_le();

        guiddef::GUID {
            Data1: data1,
            Data2: data2,
            Data3: data3,
            Data4: *data4,
        }
    }
}

#[cfg(feature = "guid")]
#[cfg(test)]
mod tests {
    use prelude::*;
    use std::str::FromStr;
    use winapi::shared::guiddef;

    #[test]
    fn test_to_uuid() {
        let uuid =
            Uuid::from_str("735d359d-4bc4-4e07-8c49-eb3e99a048dc").unwrap();
        let guid = uuid.to_guid();
        assert_eq!(Ok(uuid), Uuid::from_guid(guid));
    }

    #[test]
    fn test_from_guid() {
        let guid = guiddef::GUID {
            Data1: 0x4a35229d,
            Data2: 0x5527,
            Data3: 0x4f30,
            Data4: [0x86, 0x47, 0x9d, 0xc5, 0x4e, 0x1e, 0xe1, 0xe8],
        };

        let uuid = Uuid::from_guid(guid).unwrap();
        assert_eq!(
            "4a35229d-5527-4f30-8647-9dc54e1ee1e8",
            uuid.to_hyphenated().to_string()
        );
        assert_eq!(Ok(uuid), Uuid::from_guid(guid));
    }
}
<commit_msg>add roundtrip guid test<commit_after>use prelude::*;

use BytesError;

use winapi::shared::guiddef;

#[cfg(feature = "guid")]
impl Uuid {
    /// Attempts to create a [`Uuid`] from a little endian winapi `GUID`
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub fn from_guid(guid: guiddef::GUID) -> Result<Uuid, BytesError> {
        Uuid::from_fields_le(
            guid.Data1 as u32,
            guid.Data2 as u16,
            guid.Data3 as u16,
            &(guid.Data4 as [u8; 8]),
        )
    }

    /// Converts a [`Uuid`] into a little endian winapi `GUID`
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub fn to_guid(&self) -> guiddef::GUID {
        let (data1, data2, data3, data4) = self.to_fields_le();

        guiddef::GUID {
            Data1: data1,
            Data2: data2,
            Data3: data3,
            Data4: *data4,
        }
    }
}

#[cfg(feature = "guid")]
#[cfg(test)]
mod tests {
    use prelude::*;
    use std::str::FromStr;
    use winapi::shared::guiddef;

    #[test]
    fn test_from_guid() {
        let guid = guiddef::GUID {
            Data1: 0x4a35229d,
            Data2: 0x5527,
            Data3: 0x4f30,
            Data4: [0x86, 0x47, 0x9d, 0xc5, 0x4e, 0x1e, 0xe1, 0xe8],
        };

        let uuid = Uuid::from_guid(guid).unwrap();
        assert_eq!(
            "9d22354a-2755-304f-8647-9dc54e1ee1e8",
            uuid.to_hyphenated().to_string()
        );
    }

    #[test]
    fn test_guid_roundtrip() {
        let guid_in = guiddef::GUID {
            Data1: 0x4a35229d,
            Data2: 0x5527,
            Data3: 0x4f30,
            Data4: [0x86, 0x47, 0x9d, 0xc5, 0x4e, 0x1e, 0xe1, 0xe8],
        };

        let uuid = Uuid::from_guid(guid_in).unwrap();
        let guid_out = uuid.to_guid();

        assert_eq!(
            (guid_in.Data1, guid_in.Data2, guid_in.Data3, guid_in.Data4),
            (
                guid_out.Data1,
                guid_out.Data2,
                guid_out.Data3,
                guid_out.Data4
            )
        );
    }
}
<|endoftext|>


<commit_before>use hdr_histogram::simple_hdr_histogram::*;

#[test]
fn count_at_value_on_empty() {
    let the_hist = init_histo(1, 100000, 3);

    assert_eq!(the_hist.get_count_at_value(1).unwrap(), 0);
    assert_eq!(the_hist.get_count_at_value(5000).unwrap(), 0);
    assert_eq!(the_hist.get_count_at_value(100000).unwrap(), 0);
}

#[test]
fn count_at_value_after_record() {
    let mut the_hist = init_histo(1, 100000, 3);

    the_hist.record_single_value(5000).unwrap();

    assert_eq!(the_hist.get_count_at_value(1).unwrap(), 0);
    assert_eq!(the_hist.get_count_at_value(5000).unwrap(), 1);
    assert_eq!(the_hist.get_count_at_value(100000).unwrap(), 0);
}

#[test]
fn can_get_count_after_record() {
    let mut the_hist = init_histo(1, 100000, 3);
    the_hist.record_single_value(5000).unwrap();

    let count = the_hist.get_count();
    assert_eq!(count, 1);
}

#[test]
fn can_get_max_after_record() {
    let mut the_hist = init_histo(1, 100000, 3);
    the_hist.record_single_value(5000).unwrap();

    let max = the_hist.get_max();
    assert_eq!(max, 5000);
}

#[test]
fn can_record_single_value() {
    let mut the_hist = init_histo(1, 100000, 3);
    the_hist.record_single_value(5000).unwrap();
}

#[test]
fn can_compute_indexes_for_smallest_value() {
    let the_hist = init_histo(1, 100000, 3);
    let value = 1;
    assert_eq!(the_hist.get_bucket_index(value), 0);
    assert_eq!(the_hist.get_sub_bucket_index(value, 0), 1);
    assert_eq!(the_hist.counts_array_index(value), 1);
}

#[test]
fn can_compute_counts_array_index() {
    let the_hist = init_histo(1, 100000, 3);
    let result = the_hist.counts_array_index(5000);

    assert_eq!(result, 3298);
}

#[test]
fn can_get_bucket_index() {
    let the_hist = init_histo(1, 100000, 3);
    let result = the_hist.get_bucket_index(5000);
    assert_eq!(result, 2)
}

#[test]
fn can_get_sub_bucket_index() {
    let the_hist = init_histo(1, 100000, 3);
    let result = the_hist.get_sub_bucket_index(5000, 2);
    assert_eq!(result, 1250)
}

/// lowest_discernible_value: must be >= 1
/// highest_trackable_value: must be >= 2 * lowest_discernible_value
/// num_significant_digits: must be <= 5
fn init_histo(lowest_discernible_value: u64, highest_trackable_value: u64, num_significant_digits: u32) -> SimpleHdrHistogram<u64> {

    assert!(lowest_discernible_value >= 1);
    assert!(highest_trackable_value >= 2 * lowest_discernible_value);
    assert!(num_significant_digits <= 5);

    let largest_value_with_single_unit_resolution = 2_u64 * 10_u64.pow(num_significant_digits);

    let unit_magnitude = ((lowest_discernible_value as f64).ln() / 2_f64.ln()) as u32;
    let unit_magnitude_mask: u64  = (1_u64 << unit_magnitude) - 1;

    // find nearest power of 2 to largest_value_with_single_unit_resolution
    let sub_bucket_count_magnitude: u32 =
    ((largest_value_with_single_unit_resolution as f64).ln() / 2_f64.ln()).ceil() as u32;

    // ugly looking... how should ternaries be done?
    let sub_bucket_half_count_magnitude: u32 = (if sub_bucket_count_magnitude > 1 { sub_bucket_count_magnitude } else { 1 }) - 1;
    let sub_bucket_count: usize = 2_usize.pow(sub_bucket_half_count_magnitude + 1);
    let sub_bucket_half_count: usize = sub_bucket_count / 2;
    // TODO is this cast OK?
    let sub_bucket_mask = ((sub_bucket_count - 1) << unit_magnitude) as u64;

    let counts_arr_len = counts_arr_len(highest_trackable_value, sub_bucket_count, unit_magnitude);
    let bucket_count = buckets_needed_for_value(highest_trackable_value, sub_bucket_count, unit_magnitude);

    let leading_zero_count_base: usize = (64_u32 - unit_magnitude - sub_bucket_half_count_magnitude - 1) as usize;

    SimpleHdrHistogram {
        leading_zeros_count_base: leading_zero_count_base,
        sub_bucket_mask: sub_bucket_mask,
        unit_magnitude: unit_magnitude,
        sub_bucket_count: sub_bucket_count,
        sub_bucket_half_count: sub_bucket_half_count,
        sub_bucket_half_count_magnitude: sub_bucket_half_count_magnitude,
        counts: vec![0; counts_arr_len],
        counts_array_length: counts_arr_len,
        normalizing_index_offset: 0_usize, // 0 for normal Histogram ctor in Java impl
        min_non_zero_value: u64::max_value(),
        total_count: 0,
        max_value: 0,
        unit_magnitude_mask: unit_magnitude_mask
    }
}

fn buckets_needed_for_value(value: u64, sub_bucket_count: usize, unit_magnitude: u32) -> usize {

    // TODO is this cast ok?
    let mut smallest_untrackable_value: u64 = (sub_bucket_count << unit_magnitude) as u64;
    let mut buckets_needed: usize = 1;

    while smallest_untrackable_value <= value {
        if smallest_untrackable_value > u64::max_value() / 2 {
            return buckets_needed + 1;
        }

        smallest_untrackable_value = smallest_untrackable_value << 1;
        buckets_needed += 1;
    }

    return buckets_needed;
}

fn counts_arr_len_for_buckets(buckets: usize, sub_bucket_count: usize) -> usize {
    (buckets + 1) * (sub_bucket_count / 2)
}

fn counts_arr_len(value: u64, sub_bucket_count: usize, unit_magnitude: u32) -> usize {
    counts_arr_len_for_buckets(buckets_needed_for_value(value, sub_bucket_count, unit_magnitude), sub_bucket_count)
}<commit_msg>add tests around sub bucket calculations<commit_after>use hdr_histogram::simple_hdr_histogram::*;

#[test]
fn count_at_value_on_empty() {
    let h = init_histo(1, 100000, 3);

    assert_eq!(h.get_count_at_value(1).unwrap(), 0);
    assert_eq!(h.get_count_at_value(5000).unwrap(), 0);
    assert_eq!(h.get_count_at_value(100000).unwrap(), 0);
}

#[test]
fn count_at_value_after_record() {
    let mut h = init_histo(1, 100000, 3);

    h.record_single_value(5000).unwrap();

    assert_eq!(h.get_count_at_value(1).unwrap(), 0);
    assert_eq!(h.get_count_at_value(5000).unwrap(), 1);
    assert_eq!(h.get_count_at_value(100000).unwrap(), 0);
}

#[test]
fn can_get_count_after_record() {
    let mut h = init_histo(1, 100000, 3);
    h.record_single_value(5000).unwrap();

    let count = h.get_count();
    assert_eq!(count, 1);
}

#[test]
fn can_get_max_after_record() {
    let mut h = init_histo(1, 100000, 3);
    h.record_single_value(5000).unwrap();

    let max = h.get_max();
    assert_eq!(max, 5000);
}

#[test]
fn can_record_single_value() {
    let mut h = init_histo(1, 100000, 3);
    h.record_single_value(5000).unwrap();
}

#[test]
fn can_compute_indexes_for_smallest_value() {
    let h = init_histo(1, 100000, 3);
    let value = 1;
    assert_eq!(h.get_bucket_index(value), 0);
    assert_eq!(h.get_sub_bucket_index(value, 0), 1);
    assert_eq!(h.counts_array_index(value), 1);
}

#[test]
fn can_compute_counts_array_index() {
    let h = init_histo(1, 100000, 3);
    let result = h.counts_array_index(5000);

    assert_eq!(result, 3298);
}

#[test]
fn can_get_bucket_index() {
    let h = init_histo(1, 100000, 3);
    let result = h.get_bucket_index(5000);
    assert_eq!(result, 2)
}

#[test]
fn can_get_sub_bucket_index() {
    let h = init_histo(1, 100000, 3);
    let result = h.get_sub_bucket_index(5000, 2);
    assert_eq!(result, 1250)
}

#[test]
fn sub_bucket_count_medium_precision() {
    let h = init_histo(1, 100000, 3);

    assert_eq!(2048_usize, h.sub_bucket_count);
    assert_eq!(1024_usize, h.sub_bucket_half_count);
    assert_eq!(10, h.sub_bucket_half_count_magnitude);
    assert_eq!(2047, h.sub_bucket_mask);
}

#[test]
fn sub_bucket_count_min_precision() {
    let h = init_histo(1, 100000, 0);

    assert_eq!(2_usize, h.sub_bucket_count);
    assert_eq!(1_usize, h.sub_bucket_half_count);
    assert_eq!(0, h.sub_bucket_half_count_magnitude);
    assert_eq!(1, h.sub_bucket_mask);
}

#[test]
fn sub_bucket_count_max_precision() {
    let h = init_histo(1, 100000, 5);

    assert_eq!(262144_usize, h.sub_bucket_count);
    assert_eq!(131072usize, h.sub_bucket_half_count);
    assert_eq!(17, h.sub_bucket_half_count_magnitude);
    assert_eq!(262143, h.sub_bucket_mask);
}

/// lowest_discernible_value: must be >= 1
/// highest_trackable_value: must be >= 2 * lowest_discernible_value
/// num_significant_digits: must be <= 5
fn init_histo(lowest_discernible_value: u64, highest_trackable_value: u64, num_significant_digits: u32) -> SimpleHdrHistogram<u64> {

    assert!(lowest_discernible_value >= 1);
    assert!(highest_trackable_value >= 2 * lowest_discernible_value);
    assert!(num_significant_digits <= 5);

    let largest_value_with_single_unit_resolution = 2_u64 * 10_u64.pow(num_significant_digits);

    let unit_magnitude = ((lowest_discernible_value as f64).ln() / 2_f64.ln()) as u32;
    let unit_magnitude_mask: u64  = (1_u64 << unit_magnitude) - 1;

    // find nearest power of 2 to largest_value_with_single_unit_resolution
    let sub_bucket_count_magnitude: u32 =
    ((largest_value_with_single_unit_resolution as f64).ln() / 2_f64.ln()).ceil() as u32;

    // ugly looking... how should ternaries be done?
    let sub_bucket_half_count_magnitude: u32 = (if sub_bucket_count_magnitude > 1 { sub_bucket_count_magnitude } else { 1 }) - 1;
    let sub_bucket_count: usize = 2_usize.pow(sub_bucket_half_count_magnitude + 1);
    let sub_bucket_half_count: usize = sub_bucket_count / 2;
    // TODO is this cast OK?
    let sub_bucket_mask = ((sub_bucket_count - 1) << unit_magnitude) as u64;

    let counts_arr_len = counts_arr_len(highest_trackable_value, sub_bucket_count, unit_magnitude);
    let bucket_count = buckets_needed_for_value(highest_trackable_value, sub_bucket_count, unit_magnitude);

    let leading_zero_count_base: usize = (64_u32 - unit_magnitude - sub_bucket_half_count_magnitude - 1) as usize;

    SimpleHdrHistogram {
        leading_zeros_count_base: leading_zero_count_base,
        unit_magnitude: unit_magnitude,
        sub_bucket_mask: sub_bucket_mask,
        sub_bucket_count: sub_bucket_count,
        sub_bucket_half_count: sub_bucket_half_count,
        sub_bucket_half_count_magnitude: sub_bucket_half_count_magnitude,
        counts: vec![0; counts_arr_len],
        counts_array_length: counts_arr_len,
        normalizing_index_offset: 0_usize, // 0 for normal Histogram ctor in Java impl
        min_non_zero_value: u64::max_value(),
        total_count: 0,
        max_value: 0,
        unit_magnitude_mask: unit_magnitude_mask
    }
}

fn buckets_needed_for_value(value: u64, sub_bucket_count: usize, unit_magnitude: u32) -> usize {

    // TODO is this cast ok?
    let mut smallest_untrackable_value: u64 = (sub_bucket_count << unit_magnitude) as u64;
    let mut buckets_needed: usize = 1;

    while smallest_untrackable_value <= value {
        if smallest_untrackable_value > u64::max_value() / 2 {
            return buckets_needed + 1;
        }

        smallest_untrackable_value = smallest_untrackable_value << 1;
        buckets_needed += 1;
    }

    return buckets_needed;
}

fn counts_arr_len_for_buckets(buckets: usize, sub_bucket_count: usize) -> usize {
    (buckets + 1) * (sub_bucket_count / 2)
}

fn counts_arr_len(value: u64, sub_bucket_count: usize, unit_magnitude: u32) -> usize {
    counts_arr_len_for_buckets(buckets_needed_for_value(value, sub_bucket_count, unit_magnitude), sub_bucket_count)
}<|endoftext|>


<commit_before>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Provider for the `implied_outlives_bounds` query.
//! Do not call this query directory. See [`rustc::traits::query::implied_outlives_bounds`].

use rustc::infer::InferCtxt;
use rustc::infer::canonical::{self, Canonical};
use rustc::traits::{TraitEngine, TraitEngineExt};
use rustc::traits::query::outlives_bounds::OutlivesBound;
use rustc::traits::query::{CanonicalTyGoal, Fallible, NoSolution};
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::ty::outlives::Component;
use rustc::ty::query::Providers;
use rustc::ty::wf;
use syntax::ast::DUMMY_NODE_ID;
use syntax::source_map::DUMMY_SP;
use rustc::traits::FulfillmentContext;

use rustc_data_structures::sync::Lrc;

crate fn provide(p: &mut Providers) {
    *p = Providers {
        implied_outlives_bounds,
        ..*p
    };
}

fn implied_outlives_bounds<'tcx>(
    tcx: TyCtxt<'_, 'tcx, 'tcx>,
    goal: CanonicalTyGoal<'tcx>,
) -> Result<
        Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>>,
        NoSolution,
> {
    tcx.infer_ctxt()
       .enter_canonical_trait_query(&goal, |infcx, _fulfill_cx, key| {
           let (param_env, ty) = key.into_parts();
           compute_implied_outlives_bounds(&infcx, param_env, ty)
       })
}

fn compute_implied_outlives_bounds<'tcx>(
    infcx: &InferCtxt<'_, '_, 'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    ty: Ty<'tcx>
) -> Fallible<Vec<OutlivesBound<'tcx>>> {
    let tcx = infcx.tcx;

    // Sometimes when we ask what it takes for T: WF, we get back that
    // U: WF is required; in that case, we push U onto this stack and
    // process it next. Currently (at least) these resulting
    // predicates are always guaranteed to be a subset of the original
    // type, so we need not fear non-termination.
    let mut wf_types = vec![ty];

    let mut implied_bounds = vec![];

    let mut fulfill_cx = FulfillmentContext::new();

    while let Some(ty) = wf_types.pop() {
        // Compute the obligations for `ty` to be well-formed. If `ty` is
        // an unresolved inference variable, just substituted an empty set
        // -- because the return type here is going to be things we *add*
        // to the environment, it's always ok for this set to be smaller
        // than the ultimate set. (Note: normally there won't be
        // unresolved inference variables here anyway, but there might be
        // during typeck under some circumstances.)
        let obligations =
            wf::obligations(infcx, param_env, DUMMY_NODE_ID, ty, DUMMY_SP).unwrap_or(vec![]);

        // NB: All of these predicates *ought* to be easily proven
        // true. In fact, their correctness is (mostly) implied by
        // other parts of the program. However, in #42552, we had
        // an annoying scenario where:
        //
        // - Some `T::Foo` gets normalized, resulting in a
        //   variable `_1` and a `T: Trait<Foo=_1>` constraint
        //   (not sure why it couldn't immediately get
        //   solved). This result of `_1` got cached.
        // - These obligations were dropped on the floor here,
        //   rather than being registered.
        // - Then later we would get a request to normalize
        //   `T::Foo` which would result in `_1` being used from
        //   the cache, but hence without the `T: Trait<Foo=_1>`
        //   constraint. As a result, `_1` never gets resolved,
        //   and we get an ICE (in dropck).
        //
        // Therefore, we register any predicates involving
        // inference variables. We restrict ourselves to those
        // involving inference variables both for efficiency and
        // to avoids duplicate errors that otherwise show up.
        fulfill_cx.register_predicate_obligations(
            infcx,
            obligations
                .iter()
                .filter(|o| o.predicate.has_infer_types())
                .cloned(),
        );

        // From the full set of obligations, just filter down to the
        // region relationships.
        implied_bounds.extend(obligations.into_iter().flat_map(|obligation| {
            assert!(!obligation.has_escaping_regions());
            match obligation.predicate {
                ty::Predicate::Trait(..) |
                ty::Predicate::Subtype(..) |
                ty::Predicate::Projection(..) |
                ty::Predicate::ClosureKind(..) |
                ty::Predicate::ObjectSafe(..) |
                ty::Predicate::ConstEvaluatable(..) => vec![],

                ty::Predicate::WellFormed(subty) => {
                    wf_types.push(subty);
                    vec![]
                }

                ty::Predicate::RegionOutlives(ref data) => match data.no_late_bound_regions() {
                    None => vec![],
                    Some(ty::OutlivesPredicate(r_a, r_b)) => {
                        vec![OutlivesBound::RegionSubRegion(r_b, r_a)]
                    }
                },

                ty::Predicate::TypeOutlives(ref data) => match data.no_late_bound_regions() {
                    None => vec![],
                    Some(ty::OutlivesPredicate(ty_a, r_b)) => {
                        let ty_a = infcx.resolve_type_vars_if_possible(&ty_a);
                        let components = tcx.outlives_components(ty_a);
                        implied_bounds_from_components(r_b, components)
                    }
                },
            }
        }));
    }

    // Ensure that those obligations that we had to solve
    // get solved *here*.
    match fulfill_cx.select_all_or_error(infcx) {
        Ok(()) => Ok(implied_bounds),
        Err(_) => Err(NoSolution),
    }
}

/// When we have an implied bound that `T: 'a`, we can further break
/// this down to determine what relationships would have to hold for
/// `T: 'a` to hold. We get to assume that the caller has validated
/// those relationships.
fn implied_bounds_from_components(
    sub_region: ty::Region<'tcx>,
    sup_components: Vec<Component<'tcx>>,
) -> Vec<OutlivesBound<'tcx>> {
    sup_components
        .into_iter()
        .flat_map(|component| {
            match component {
                Component::Region(r) =>
                    vec![OutlivesBound::RegionSubRegion(sub_region, r)],
                Component::Param(p) =>
                    vec![OutlivesBound::RegionSubParam(sub_region, p)],
                Component::Projection(p) =>
                    vec![OutlivesBound::RegionSubProjection(sub_region, p)],
                Component::EscapingProjection(_) =>
                // If the projection has escaping regions, don't
                // try to infer any implied bounds even for its
                // free components. This is conservative, because
                // the caller will still have to prove that those
                // free components outlive `sub_region`. But the
                // idea is that the WAY that the caller proves
                // that may change in the future and we want to
                // give ourselves room to get smarter here.
                    vec![],
                Component::UnresolvedInferenceVariable(..) =>
                    vec![],
            }
        })
        .collect()
}
<commit_msg>Rollup merge of #55476 - ljedrz:flat_map_to_filter_map, r=cramertj<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Provider for the `implied_outlives_bounds` query.
//! Do not call this query directory. See [`rustc::traits::query::implied_outlives_bounds`].

use rustc::infer::InferCtxt;
use rustc::infer::canonical::{self, Canonical};
use rustc::traits::{TraitEngine, TraitEngineExt};
use rustc::traits::query::outlives_bounds::OutlivesBound;
use rustc::traits::query::{CanonicalTyGoal, Fallible, NoSolution};
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::ty::outlives::Component;
use rustc::ty::query::Providers;
use rustc::ty::wf;
use syntax::ast::DUMMY_NODE_ID;
use syntax::source_map::DUMMY_SP;
use rustc::traits::FulfillmentContext;

use rustc_data_structures::sync::Lrc;

crate fn provide(p: &mut Providers) {
    *p = Providers {
        implied_outlives_bounds,
        ..*p
    };
}

fn implied_outlives_bounds<'tcx>(
    tcx: TyCtxt<'_, 'tcx, 'tcx>,
    goal: CanonicalTyGoal<'tcx>,
) -> Result<
        Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>>,
        NoSolution,
> {
    tcx.infer_ctxt()
       .enter_canonical_trait_query(&goal, |infcx, _fulfill_cx, key| {
           let (param_env, ty) = key.into_parts();
           compute_implied_outlives_bounds(&infcx, param_env, ty)
       })
}

fn compute_implied_outlives_bounds<'tcx>(
    infcx: &InferCtxt<'_, '_, 'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    ty: Ty<'tcx>
) -> Fallible<Vec<OutlivesBound<'tcx>>> {
    let tcx = infcx.tcx;

    // Sometimes when we ask what it takes for T: WF, we get back that
    // U: WF is required; in that case, we push U onto this stack and
    // process it next. Currently (at least) these resulting
    // predicates are always guaranteed to be a subset of the original
    // type, so we need not fear non-termination.
    let mut wf_types = vec![ty];

    let mut implied_bounds = vec![];

    let mut fulfill_cx = FulfillmentContext::new();

    while let Some(ty) = wf_types.pop() {
        // Compute the obligations for `ty` to be well-formed. If `ty` is
        // an unresolved inference variable, just substituted an empty set
        // -- because the return type here is going to be things we *add*
        // to the environment, it's always ok for this set to be smaller
        // than the ultimate set. (Note: normally there won't be
        // unresolved inference variables here anyway, but there might be
        // during typeck under some circumstances.)
        let obligations =
            wf::obligations(infcx, param_env, DUMMY_NODE_ID, ty, DUMMY_SP).unwrap_or(vec![]);

        // NB: All of these predicates *ought* to be easily proven
        // true. In fact, their correctness is (mostly) implied by
        // other parts of the program. However, in #42552, we had
        // an annoying scenario where:
        //
        // - Some `T::Foo` gets normalized, resulting in a
        //   variable `_1` and a `T: Trait<Foo=_1>` constraint
        //   (not sure why it couldn't immediately get
        //   solved). This result of `_1` got cached.
        // - These obligations were dropped on the floor here,
        //   rather than being registered.
        // - Then later we would get a request to normalize
        //   `T::Foo` which would result in `_1` being used from
        //   the cache, but hence without the `T: Trait<Foo=_1>`
        //   constraint. As a result, `_1` never gets resolved,
        //   and we get an ICE (in dropck).
        //
        // Therefore, we register any predicates involving
        // inference variables. We restrict ourselves to those
        // involving inference variables both for efficiency and
        // to avoids duplicate errors that otherwise show up.
        fulfill_cx.register_predicate_obligations(
            infcx,
            obligations
                .iter()
                .filter(|o| o.predicate.has_infer_types())
                .cloned(),
        );

        // From the full set of obligations, just filter down to the
        // region relationships.
        implied_bounds.extend(obligations.into_iter().flat_map(|obligation| {
            assert!(!obligation.has_escaping_regions());
            match obligation.predicate {
                ty::Predicate::Trait(..) |
                ty::Predicate::Subtype(..) |
                ty::Predicate::Projection(..) |
                ty::Predicate::ClosureKind(..) |
                ty::Predicate::ObjectSafe(..) |
                ty::Predicate::ConstEvaluatable(..) => vec![],

                ty::Predicate::WellFormed(subty) => {
                    wf_types.push(subty);
                    vec![]
                }

                ty::Predicate::RegionOutlives(ref data) => match data.no_late_bound_regions() {
                    None => vec![],
                    Some(ty::OutlivesPredicate(r_a, r_b)) => {
                        vec![OutlivesBound::RegionSubRegion(r_b, r_a)]
                    }
                },

                ty::Predicate::TypeOutlives(ref data) => match data.no_late_bound_regions() {
                    None => vec![],
                    Some(ty::OutlivesPredicate(ty_a, r_b)) => {
                        let ty_a = infcx.resolve_type_vars_if_possible(&ty_a);
                        let components = tcx.outlives_components(ty_a);
                        implied_bounds_from_components(r_b, components)
                    }
                },
            }
        }));
    }

    // Ensure that those obligations that we had to solve
    // get solved *here*.
    match fulfill_cx.select_all_or_error(infcx) {
        Ok(()) => Ok(implied_bounds),
        Err(_) => Err(NoSolution),
    }
}

/// When we have an implied bound that `T: 'a`, we can further break
/// this down to determine what relationships would have to hold for
/// `T: 'a` to hold. We get to assume that the caller has validated
/// those relationships.
fn implied_bounds_from_components(
    sub_region: ty::Region<'tcx>,
    sup_components: Vec<Component<'tcx>>,
) -> Vec<OutlivesBound<'tcx>> {
    sup_components
        .into_iter()
        .filter_map(|component| {
            match component {
                Component::Region(r) =>
                    Some(OutlivesBound::RegionSubRegion(sub_region, r)),
                Component::Param(p) =>
                    Some(OutlivesBound::RegionSubParam(sub_region, p)),
                Component::Projection(p) =>
                    Some(OutlivesBound::RegionSubProjection(sub_region, p)),
                Component::EscapingProjection(_) =>
                // If the projection has escaping regions, don't
                // try to infer any implied bounds even for its
                // free components. This is conservative, because
                // the caller will still have to prove that those
                // free components outlive `sub_region`. But the
                // idea is that the WAY that the caller proves
                // that may change in the future and we want to
                // give ourselves room to get smarter here.
                    None,
                Component::UnresolvedInferenceVariable(..) =>
                    None,
            }
        })
        .collect()
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

// This is necessary for the derive macros which rely on being used in a
// context where the crypto crate is external
use crate as aptos_crypto;
use crate::{
    ed25519::{Ed25519PrivateKey, Ed25519PublicKey, Ed25519Signature},
    multi_ed25519::{MultiEd25519PrivateKey, MultiEd25519PublicKey, MultiEd25519Signature},
    test_utils::{random_serializable_struct, uniform_keypair_strategy},
    traits::*,
};

use aptos_crypto_derive::{
    PrivateKey, PublicKey, Signature, SigningKey, SilentDebug, ValidCryptoMaterial, VerifyingKey,
};
use proptest::prelude::*;
use serde::{Deserialize, Serialize};

// Here we aim to make a point about how we can build an enum generically
// on top of a few choice signing scheme types. This enum implements the
// VerifyingKey, SigningKey for precisely the types selected for that enum
// (here, Ed25519(PublicKey|PrivateKey|Signature) and MultiEd25519(...)).
//
// Note that we do not break type safety (see towards the end), and that
// this enum can safely be put into the usual collection (Vec, HashMap).
//

#[derive(
    Serialize,
    Deserialize,
    Debug,
    Clone,
    PartialEq,
    Eq,
    Hash,
    ValidCryptoMaterial,
    PublicKey,
    VerifyingKey,
)]
#[PrivateKeyType = "PrivateK"]
#[SignatureType = "Sig"]
enum PublicK {
    Ed(Ed25519PublicKey),
    MultiEd(MultiEd25519PublicKey),
}

#[derive(Serialize, Deserialize, SilentDebug, ValidCryptoMaterial, PrivateKey, SigningKey)]
#[PublicKeyType = "PublicK"]
#[SignatureType = "Sig"]
enum PrivateK {
    Ed(Ed25519PrivateKey),
    MultiEd(MultiEd25519PrivateKey),
}

#[allow(clippy::large_enum_variant)]
#[derive(Clone, Debug, PartialEq, Eq, Hash, Signature)]
#[PublicKeyType = "PublicK"]
#[PrivateKeyType = "PrivateK"]
enum Sig {
    Ed(Ed25519Signature),
    MultiEd(MultiEd25519Signature),
}

///////////////////////////////////////////////////////
// End of declarations — let's now prove type safety //
///////////////////////////////////////////////////////
proptest! {
    #![proptest_config(ProptestConfig::with_cases(20))]

    #[test]
    #[allow(deprecated)]
    fn test_keys_mix(
        message in random_serializable_struct(),
        ed_keypair1 in uniform_keypair_strategy::<Ed25519PrivateKey, Ed25519PublicKey>(),
        ed_keypair2 in uniform_keypair_strategy::<Ed25519PrivateKey, Ed25519PublicKey>(),
        med_keypair in uniform_keypair_strategy::<MultiEd25519PrivateKey, MultiEd25519PublicKey>()
    ) {
        // this is impossible to write statically, due to the trait not being
        // object-safe (voluntarily), see unsupported_sigs below
        // let mut l: Vec<Box<dyn PrivateKey>> = vec![];
        let mut l: Vec<Ed25519PrivateKey> = vec![ed_keypair1.private_key];
        let ed_key = l.pop().unwrap();
        let signature = ed_key.sign(&message).unwrap();

        // This is business as usual
        prop_assert!(signature.verify(&message, &ed_keypair1.public_key).is_ok());

        // signature-publickey mixups are statically impossible, see unsupported_sigs below
        let mut l2: Vec<PrivateK> = vec![
            PrivateK::MultiEd(med_keypair.private_key),
            PrivateK::Ed(ed_keypair2.private_key),
        ];

        let ed_key = l2.pop().unwrap();
        let ed_signature = ed_key.sign(&message).unwrap();

        // This is still business as usual
        let ed_pubkey2 = PublicK::Ed(ed_keypair2.public_key);
        let good_sigver = ed_signature.verify(&message, &ed_pubkey2);
        prop_assert!(good_sigver.is_ok(), "{:?}", good_sigver);

        // but this still fails, as expected
        let med_pubkey = PublicK::MultiEd(med_keypair.public_key);
        let bad_sigver = ed_signature.verify(&message, &med_pubkey);
        prop_assert!(bad_sigver.is_err(), "{:?}", bad_sigver);

        // And now just in case we're confused again, we pop in the
        // reverse direction
        let med_key = l2.pop().unwrap();
        let med_signature = med_key.sign(&message).unwrap();

        // This is still business as usual
        let good_sigver = med_signature.verify(&message, &med_pubkey);
        prop_assert!(good_sigver.is_ok(), "{:?}", good_sigver);

        // but this still fails, as expected
        let bad_sigver = med_signature.verify(&message, &ed_pubkey2);
        prop_assert!(bad_sigver.is_err(), "{:?}", bad_sigver);
    }
}

#[test]
#[ignore]
fn unsupported_sigs() {
    let t = trybuild::TestCases::new();
    t.compile_fail("src/unit_tests/compilation/cross_test.rs");
    t.compile_fail("src/unit_tests/compilation/cross_test_trait_obj.rs");
    t.compile_fail("src/unit_tests/compilation/cross_test_trait_obj_sig.rs");
    t.compile_fail("src/unit_tests/compilation/cross_test_trait_obj_pub.rs");
}
<commit_msg>[aptos-crypto] Disable broken derive test<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

/*
TODO: Re-enable this test when the derives are fixed
// This is necessary for the derive macros which rely on being used in a
// context where the crypto crate is external
use crate as aptos_crypto;
use crate::{
    ed25519::{Ed25519PrivateKey, Ed25519PublicKey, Ed25519Signature},
    multi_ed25519::{MultiEd25519PrivateKey, MultiEd25519PublicKey, MultiEd25519Signature},
    test_utils::{random_serializable_struct, uniform_keypair_strategy},
    traits::*,
};

use aptos_crypto_derive::{
    PrivateKey, PublicKey, Signature, SigningKey, SilentDebug, ValidCryptoMaterial, VerifyingKey,
};
use proptest::prelude::*;
use serde::{Deserialize, Serialize};

// Here we aim to make a point about how we can build an enum generically
// on top of a few choice signing scheme types. This enum implements the
// VerifyingKey, SigningKey for precisely the types selected for that enum
// (here, Ed25519(PublicKey|PrivateKey|Signature) and MultiEd25519(...)).
//
// Note that we do not break type safety (see towards the end), and that
// this enum can safely be put into the usual collection (Vec, HashMap).
//

#[derive(
    Serialize,
    Deserialize,
    Debug,
    Clone,
    PartialEq,
    Eq,
    Hash,
    ValidCryptoMaterial,
    PublicKey,
    VerifyingKey,
)]
#[PrivateKeyType = "PrivateK"]
#[SignatureType = "Sig"]
enum PublicK {
    Ed(Ed25519PublicKey),
    MultiEd(MultiEd25519PublicKey),
}

#[derive(Serialize, Deserialize, SilentDebug, ValidCryptoMaterial, PrivateKey, SigningKey)]
#[PublicKeyType = "PublicK"]
#[SignatureType = "Sig"]
enum PrivateK {
    Ed(Ed25519PrivateKey),
    MultiEd(MultiEd25519PrivateKey),
}

#[allow(clippy::large_enum_variant)]
#[derive(Clone, Debug, PartialEq, Eq, Hash, Signature)]
#[PublicKeyType = "PublicK"]
#[PrivateKeyType = "PrivateK"]
enum Sig {
    Ed(Ed25519Signature),
    MultiEd(MultiEd25519Signature),
}

///////////////////////////////////////////////////////
// End of declarations — let's now prove type safety //
///////////////////////////////////////////////////////
proptest! {
    #![proptest_config(ProptestConfig::with_cases(20))]

    #[test]
    #[allow(deprecated)]
    fn test_keys_mix(
        message in random_serializable_struct(),
        ed_keypair1 in uniform_keypair_strategy::<Ed25519PrivateKey, Ed25519PublicKey>(),
        ed_keypair2 in uniform_keypair_strategy::<Ed25519PrivateKey, Ed25519PublicKey>(),
        med_keypair in uniform_keypair_strategy::<MultiEd25519PrivateKey, MultiEd25519PublicKey>()
    ) {
        // this is impossible to write statically, due to the trait not being
        // object-safe (voluntarily), see unsupported_sigs below
        // let mut l: Vec<Box<dyn PrivateKey>> = vec![];
        let mut l: Vec<Ed25519PrivateKey> = vec![ed_keypair1.private_key];
        let ed_key = l.pop().unwrap();
        let signature = ed_key.sign(&message).unwrap();

        // This is business as usual
        prop_assert!(signature.verify(&message, &ed_keypair1.public_key).is_ok());

        // signature-publickey mixups are statically impossible, see unsupported_sigs below
        let mut l2: Vec<PrivateK> = vec![
            PrivateK::MultiEd(med_keypair.private_key),
            PrivateK::Ed(ed_keypair2.private_key),
        ];

        let ed_key = l2.pop().unwrap();
        let ed_signature = ed_key.sign(&message).unwrap();

        // This is still business as usual
        let ed_pubkey2 = PublicK::Ed(ed_keypair2.public_key);
        let good_sigver = ed_signature.verify(&message, &ed_pubkey2);
        prop_assert!(good_sigver.is_ok(), "{:?}", good_sigver);

        // but this still fails, as expected
        let med_pubkey = PublicK::MultiEd(med_keypair.public_key);
        let bad_sigver = ed_signature.verify(&message, &med_pubkey);
        prop_assert!(bad_sigver.is_err(), "{:?}", bad_sigver);

        // And now just in case we're confused again, we pop in the
        // reverse direction
        let med_key = l2.pop().unwrap();
        let med_signature = med_key.sign(&message).unwrap();

        // This is still business as usual
        let good_sigver = med_signature.verify(&message, &med_pubkey);
        prop_assert!(good_sigver.is_ok(), "{:?}", good_sigver);

        // but this still fails, as expected
        let bad_sigver = med_signature.verify(&message, &ed_pubkey2);
        prop_assert!(bad_sigver.is_err(), "{:?}", bad_sigver);
    }
}

#[test]
#[ignore]
fn unsupported_sigs() {
    let t = trybuild::TestCases::new();
    t.compile_fail("src/unit_tests/compilation/cross_test.rs");
    t.compile_fail("src/unit_tests/compilation/cross_test_trait_obj.rs");
    t.compile_fail("src/unit_tests/compilation/cross_test_trait_obj_sig.rs");
    t.compile_fail("src/unit_tests/compilation/cross_test_trait_obj_pub.rs");
}
*/
<|endoftext|>


<commit_before>//- /libcore.rs crate:core
//! Signatures of traits, types and functions from the core lib for use in tests.
pub mod cmp {

    pub trait Ord {
        fn cmp(&self, other: &Self) -> Ordering;
        fn max(self, other: Self) -> Self;
        fn min(self, other: Self) -> Self;
        fn clamp(self, min: Self, max: Self) -> Self;
    }
}

pub mod convert {
    pub trait From<T> {
        fn from(t: T) -> Self;
    }

    pub trait Into<T> {
        pub fn into(self) -> T;
    }
}

pub mod default {
    pub trait Default {
        fn default() -> Self;
    }
}

pub mod ops {
    #[lang = "fn"]
    pub trait Fn<Args>: FnMut<Args> {
        extern "rust-call" fn call(&self, args: Args) -> Self::Output;
    }

    #[lang = "fn_mut"]
    pub trait FnMut<Args>: FnOnce<Args> {
        extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
    }
    #[lang = "fn_once"]
    pub trait FnOnce<Args> {
        #[lang = "fn_once_output"]
        type Output;
        extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
    }

    #[lang = "deref"]
    pub trait Deref {
        type Target: ?Sized;
        fn deref(&self) -> &Self::Target;
    }
}

pub mod option {
    pub enum Option<T> {
        None,
        Some(T),
    }
}

pub mod prelude {
    pub mod rust_2018 {
        pub use crate::{
            cmp::Ord,
            convert::{From, Into},
            default::Default,
            iter::{IntoIterator, Iterator},
            ops::{Fn, FnMut, FnOnce},
            option::Option::{self, *},
        };
    }
}
#[prelude_import]
pub use prelude::rust_2018::*;
//- /libstd.rs crate:std deps:core
//! Signatures of traits, types and functions from the std lib for use in tests.

/// Docs for return_keyword
mod return_keyword {}

/// Docs for prim_str
mod prim_str {}

pub use core::ops;
<commit_msg>internal: remove dead code<commit_after>//- /libcore.rs crate:core
//! Signatures of traits, types and functions from the core lib for use in tests.
pub mod cmp {

    pub trait Ord {
        fn cmp(&self, other: &Self) -> Ordering;
        fn max(self, other: Self) -> Self;
        fn min(self, other: Self) -> Self;
        fn clamp(self, min: Self, max: Self) -> Self;
    }
}

pub mod convert {
    pub trait From<T> {
        fn from(t: T) -> Self;
    }

    pub trait Into<T> {
        pub fn into(self) -> T;
    }
}

pub mod default {
    pub trait Default {
        fn default() -> Self;
    }
}

pub mod option {
    pub enum Option<T> {
        None,
        Some(T),
    }
}

pub mod prelude {
    pub mod rust_2018 {
        pub use crate::{
            cmp::Ord,
            convert::{From, Into},
            default::Default,
            iter::{IntoIterator, Iterator},
            ops::{Fn, FnMut, FnOnce},
            option::Option::{self, *},
        };
    }
}
#[prelude_import]
pub use prelude::rust_2018::*;
//- /libstd.rs crate:std deps:core
//! Signatures of traits, types and functions from the std lib for use in tests.

/// Docs for return_keyword
mod return_keyword {}

/// Docs for prim_str
mod prim_str {}

pub use core::ops;
<|endoftext|>