<commit_before>// Created by Jakob Lautrup Nysom @ 31-12-2015

use std::collections::HashMap;
use std::iter::Iterator;

type Id = usize;

#[derive(Debug, Clone)]
struct ArgumentDescription<'a> {
    name: Option<&'a str>,
    help: Option<&'a str>,
}

impl <'a> ArgumentDescription<'a> {
    pub fn empty() -> ArgumentDescription<'a> {
        ArgumentDescription {
            name: None,
            help: None,
        }
    }
}

#[derive(Debug, Clone)]
enum MultipleArguments {
    Count(usize),
    ZeroOrMore,
    OneOrMore,
}

#[derive(Debug, Clone)]
struct SingleArgument;

#[derive(Debug, Clone)]
struct FlagArgument;

// =============================================================================
// ========================= Specialized arguments =============================
// =============================================================================

#[derive(Debug, Clone)]
pub struct RequiredSingleArgument<'a> {
    name: &'a str,
    desc: ArgumentDescription<'a>,
}

impl <'a> RequiredSingleArgument<'a> {
    pub fn add_to(&self, parser: &mut ArgumentParser<'a>)
            -> Result<RequiredSingleTag, String> {
        let res = parser.add_required_single(self);
        res.map(|id| RequiredSingleTag { id: id })
    }
}

#[derive(Debug, Clone)]
pub struct RequiredMultipleArguments<'a> {
    name: &'a str,
    argtype: MultipleArguments,
    desc: ArgumentDescription<'a>,
}

impl <'a> RequiredMultipleArguments<'a> {
    pub fn add_to(&self, parser: &mut ArgumentParser<'a>)
            -> Result<RequiredMultiplesTag, String> {
        let res = parser.add_required_multiple(self);
        res.map(|id| RequiredMultiplesTag { id: id })
    }
}

// =============================================================================
// ======================== Argument count builders ============================
// =============================================================================

#[derive(Debug)]
pub struct Required<'a> {
    name: &'a str,
}

impl <'a> Required<'a> {
    pub fn single(self) -> RequiredSingleArgument<'a> {
        RequiredSingleArgument {
            name: self.name,
            desc: ArgumentDescription::empty(),
        }
    }
}

#[derive(Debug, Clone)]
enum OptionalName<'a> {
    Short(&'a str),
    Long(&'a str),
    ShortAndLong(&'a str, &'a str),
}

#[derive(Debug)]
pub struct Optional<'a> {
    name: OptionalName<'a>,
}

// =============================================================================
// ================================== Tags =====================================
// =============================================================================

#[derive(Debug, Clone)]
pub struct RequiredSingleTag {
    id: Id
}

impl RequiredSingleTag {
    /// Gets the value of this tag in the parsed arguments
    pub fn get<'a>(&self, arguments: &ParsedArguments<'a>) -> &'a str {
        arguments.get_required_single(&self.id)
    }
}

#[derive(Debug, Clone)]
pub struct RequiredMultiplesTag {
    id: Id
}

impl RequiredMultiplesTag {
    /// Gets the value of this tag in the parsed arguments
    pub fn get<'a>(&self, arguments: &'a ParsedArguments<'a>) -> &Vec<&'a str> {
        arguments.get_required_multiple(&self.id)
    }
}

// =============================================================================
// ============================ Parsed arguments ===============================
// =============================================================================

#[derive(Debug)]
pub struct ParsedArguments<'a> {
    req_singles: HashMap<Id, &'a str>,
    req_vararg: Option<(Id, Vec<&'a str>)>,
    opt_singles: HashMap<Id, Option<&'a str>>,
    opt_multiples: HashMap<Id, Option<Vec<&'a str>>>,
    opt_flags: HashMap<Id, bool>,
}

impl <'a> ParsedArguments<'a> {
    fn get_required_single(&self, id: &Id) -> &'a str {
        self.req_singles.get(id).unwrap_or_else(|| panic!(format!(
            "No required single argument found with id {}", id
        )))
    }

    fn get_required_multiple(&'a self, id: &Id) -> &'a Vec<&'a str> {
        if let Some((ref vid, ref args)) = self.req_vararg {
            if vid == id {
                args
            } else {
                panic!(format!("The given tag has the wrong id for the
                    multiple-parameter argument ({} != {})!", id, vid
                ))
            }
        } else {
            panic!("No multiple-parameter argument was defined");
        }
    }

    fn get_optional_single(&'a self, id: &Id) -> &'a Option<&'a str> {
        self.opt_singles.get(id).unwrap_or_else(|| panic!(format!(
            "No optional single-parameter argument found with id {}", id
        )))
    }

    fn get_optional_multiple(&'a self, id: &Id) -> &'a Option<Vec<&'a str>> {
        self.opt_multiples.get(id).unwrap_or_else(|| panic!(format!(
            "No optional multiple-parameter argument found with id {}", id
        )))
    }

    fn get_flag(&self, id: &Id) -> bool {
        *self.opt_flags.get(id).unwrap_or_else(|| panic!(format!(
            "No flag found with id {}", id
        )))
    }
}

// =============================================================================
// ========================== Argument constructors ============================
// =============================================================================

/// An argument for the parser
pub struct Argument;

impl <'a> Argument {
    pub fn required(name: &'a str) -> Required<'a> {
        Required {
            name: name
        }
    }

    pub fn optional_short(name: &'a str) -> Optional {
        Optional {
            name: OptionalName::Short(name)
        }
    }

    pub fn optional_long(name: &'a str) -> Optional<'a> {
        Optional {
            name: OptionalName::Long(name)
        }
    }

    pub fn optional_short_and_long(short_name: &'a str, long_name: &'a str)
            -> Optional<'a> {
        Optional {
            name: OptionalName::ShortAndLong(short_name, long_name)
        }
    }
}

// =============================================================================
// ================================= Parser ====================================
// =============================================================================

#[derive(Debug, Clone)]
pub struct ArgumentParser<'a> {
    pub title: &'a str,
    next_id: Id,
    req_singles: Vec<(Id, RequiredSingleArgument<'a>)>,
    req_vararg: Option<(Id, RequiredMultipleArguments<'a>)>,
    //opt_multiples: Vec<(Id, <'a>)>,
    //opt_singles: Vec<(Id, <'a>)>,
    //opt_flags: Vec<(Id, <'a>)>,
}

impl <'a> ArgumentParser<'a> {
    pub fn new(title: &str) -> ArgumentParser {
        ArgumentParser {
            title: title,
            next_id: 1,
            req_singles: Vec::new(),
            req_vararg: None,
            //opt_multiples: Vec::new(),
            //opt_singles: Vec::new(),
            //opt_flags: Vec::new(),
        }
    }

    fn generate_id(&mut self) -> Id {
        let id = self.next_id;
        self.next_id += 1;
        id
    }

    fn add_required_single(&mut self, arg: &RequiredSingleArgument<'a>)
            -> Result<Id, String> {
        if self.req_vararg.is_some() {
            Err(format!("Could not add the argument '{}', since all required
                single-parameter arguments must be added before the
                variable-parameter argument", arg.name))
        } else {
            let id = self.generate_id();
            self.req_singles.push((id, arg.clone()));
            Ok(id)
        }
    }

    fn add_required_multiple(&mut self, arg: &RequiredMultipleArguments<'a>)
            -> Result<Id, String> {
        if self.req_vararg.is_some() {
            Err(String::from("There is already a multi-count argument defined
                for the parser"))
        } else {
            let id = self.generate_id();
            self.req_vararg = Some((id, arg.clone()));
            Ok(id)
        }
    }

    pub fn parse(&self, args: &[&str] )
            -> Result<ParsedArguments<'a>, String> {
        let mut req_singles = HashMap::new();
        let mut req_vararg = None;
        let mut opt_singles = HashMap::new();
        let mut opt_multiples = HashMap::new();
        let mut opt_flags = HashMap::new();

        let mut parsed = ParsedArguments {
            req_singles: req_singles,
            req_vararg: req_vararg,
            opt_singles: opt_singles,
            opt_multiples: opt_multiples,
            opt_flags: opt_flags,
        };

        for arg in args.iter() {
            println!("Parsing '{}'", arg);
        }

        Ok(parsed)
    }
}<commit_msg>Restrict the length of 'short' argument names<commit_after>// Created by Jakob Lautrup Nysom @ 31-12-2015

use std::collections::HashMap;
use std::iter::Iterator;

type Id = usize;

#[derive(Debug, Clone)]
struct ArgumentDescription<'a> {
    name: Option<&'a str>,
    help: Option<&'a str>,
}

impl <'a> ArgumentDescription<'a> {
    pub fn empty() -> ArgumentDescription<'a> {
        ArgumentDescription {
            name: None,
            help: None,
        }
    }
}

#[derive(Debug, Clone)]
enum MultipleArguments {
    Count(usize),
    ZeroOrMore,
    OneOrMore,
}

#[derive(Debug, Clone)]
struct SingleArgument;

#[derive(Debug, Clone)]
struct FlagArgument;

// =============================================================================
// ========================= Specialized arguments =============================
// =============================================================================

#[derive(Debug, Clone)]
pub struct RequiredSingleArgument<'a> {
    name: &'a str,
    desc: ArgumentDescription<'a>,
}

impl <'a> RequiredSingleArgument<'a> {
    pub fn add_to(&self, parser: &mut ArgumentParser<'a>)
            -> Result<RequiredSingleTag, String> {
        let res = parser.add_required_single(self);
        res.map(|id| RequiredSingleTag { id: id })
    }
}

#[derive(Debug, Clone)]
pub struct RequiredMultipleArguments<'a> {
    name: &'a str,
    argtype: MultipleArguments,
    desc: ArgumentDescription<'a>,
}

impl <'a> RequiredMultipleArguments<'a> {
    pub fn add_to(&self, parser: &mut ArgumentParser<'a>)
            -> Result<RequiredMultiplesTag, String> {
        let res = parser.add_required_multiple(self);
        res.map(|id| RequiredMultiplesTag { id: id })
    }
}

// =============================================================================
// ======================== Argument count builders ============================
// =============================================================================

#[derive(Debug)]
pub struct Required<'a> {
    name: &'a str,
}

impl <'a> Required<'a> {
    pub fn single(self) -> RequiredSingleArgument<'a> {
        RequiredSingleArgument {
            name: self.name,
            desc: ArgumentDescription::empty(),
        }
    }
}

#[derive(Debug, Clone)]
enum OptionalName<'a> {
    Short(char),
    Long(&'a str),
    ShortAndLong(char, &'a str),
}

#[derive(Debug)]
pub struct Optional<'a> {
    name: OptionalName<'a>,
}

// =============================================================================
// ================================== Tags =====================================
// =============================================================================

#[derive(Debug, Clone)]
pub struct RequiredSingleTag {
    id: Id
}

impl RequiredSingleTag {
    /// Gets the value of this tag in the parsed arguments
    pub fn get<'a>(&self, arguments: &ParsedArguments<'a>) -> &'a str {
        arguments.get_required_single(&self.id)
    }
}

#[derive(Debug, Clone)]
pub struct RequiredMultiplesTag {
    id: Id
}

impl RequiredMultiplesTag {
    /// Gets the value of this tag in the parsed arguments
    pub fn get<'a>(&self, arguments: &'a ParsedArguments<'a>) -> &Vec<&'a str> {
        arguments.get_required_multiple(&self.id)
    }
}

// =============================================================================
// ============================ Parsed arguments ===============================
// =============================================================================

#[derive(Debug)]
pub struct ParsedArguments<'a> {
    req_singles: HashMap<Id, &'a str>,
    req_vararg: Option<(Id, Vec<&'a str>)>,
    opt_singles: HashMap<Id, Option<&'a str>>,
    opt_multiples: HashMap<Id, Option<Vec<&'a str>>>,
    opt_flags: HashMap<Id, bool>,
}

impl <'a> ParsedArguments<'a> {
    fn get_required_single(&self, id: &Id) -> &'a str {
        self.req_singles.get(id).unwrap_or_else(|| panic!(format!(
            "No required single argument found with id {}", id
        )))
    }

    fn get_required_multiple(&'a self, id: &Id) -> &'a Vec<&'a str> {
        if let Some((ref vid, ref args)) = self.req_vararg {
            if vid == id {
                args
            } else {
                panic!(format!("The given tag has the wrong id for the
                    multiple-parameter argument ({} != {})!", id, vid
                ))
            }
        } else {
            panic!("No multiple-parameter argument was defined");
        }
    }

    fn get_optional_single(&'a self, id: &Id) -> &'a Option<&'a str> {
        self.opt_singles.get(id).unwrap_or_else(|| panic!(format!(
            "No optional single-parameter argument found with id {}", id
        )))
    }

    fn get_optional_multiple(&'a self, id: &Id) -> &'a Option<Vec<&'a str>> {
        self.opt_multiples.get(id).unwrap_or_else(|| panic!(format!(
            "No optional multiple-parameter argument found with id {}", id
        )))
    }

    fn get_flag(&self, id: &Id) -> bool {
        *self.opt_flags.get(id).unwrap_or_else(|| panic!(format!(
            "No flag found with id {}", id
        )))
    }
}

// =============================================================================
// ========================== Argument constructors ============================
// =============================================================================

/// An argument for the parser.
pub struct Argument;

impl <'a> Argument {
    /// Creates a builder for a new required argument with the given name.
    pub fn required(name: &'a str) -> Required<'a> {
        Required {
            name: name
        }
    }

    /// Creates a builder for an optional argument with the given short name
    /// prefixed by '-' (eg '-a').
    pub fn optional_short(name: char) -> Optional<'a> {
        Optional {
            name: OptionalName::Short(name)
        }
    }

    /// Creates a builder for an optional argument with the given long name
    /// prefixed by '--' (eg '--all').
    pub fn optional_long(name: &'a str) -> Optional<'a> {
        Optional {
            name: OptionalName::Long(name)
        }
    }

    /// Creates a builder for an optional argument with the given short and
    /// long names, where the short name is prefixed by '-' and the long name by
    /// '--'.
    pub fn optional_short_and_long(short_name: char, long_name: &'a str)
            -> Optional<'a> {
        Optional {
            name: OptionalName::ShortAndLong(short_name, long_name)
        }
    }
}

// =============================================================================
// ================================= Parser ====================================
// =============================================================================

#[derive(Debug, Clone)]
pub struct ArgumentParser<'a> {
    pub title: &'a str,
    next_id: Id,
    req_singles: Vec<(Id, RequiredSingleArgument<'a>)>,
    req_vararg: Option<(Id, RequiredMultipleArguments<'a>)>,
    //opt_multiples: Vec<(Id, <'a>)>,
    //opt_singles: Vec<(Id, <'a>)>,
    //opt_flags: Vec<(Id, <'a>)>,
}

impl <'a> ArgumentParser<'a> {
    pub fn new(title: &str) -> ArgumentParser {
        ArgumentParser {
            title: title,
            next_id: 1,
            req_singles: Vec::new(),
            req_vararg: None,
            //opt_multiples: Vec::new(),
            //opt_singles: Vec::new(),
            //opt_flags: Vec::new(),
        }
    }

    fn generate_id(&mut self) -> Id {
        let id = self.next_id;
        self.next_id += 1;
        id
    }

    fn add_required_single(&mut self, arg: &RequiredSingleArgument<'a>)
            -> Result<Id, String> {
        if self.req_vararg.is_some() {
            Err(format!("Could not add the argument '{}', since all required
                single-parameter arguments must be added before the
                variable-parameter argument", arg.name))
        } else {
            let id = self.generate_id();
            self.req_singles.push((id, arg.clone()));
            Ok(id)
        }
    }

    fn add_required_multiple(&mut self, arg: &RequiredMultipleArguments<'a>)
            -> Result<Id, String> {
        if self.req_vararg.is_some() {
            Err(String::from("There is already a multi-count argument defined
                for the parser"))
        } else {
            let id = self.generate_id();
            self.req_vararg = Some((id, arg.clone()));
            Ok(id)
        }
    }

    pub fn parse(&self, args: &[&str] )
            -> Result<ParsedArguments<'a>, String> {
        let mut req_singles = HashMap::new();
        let mut req_vararg = None;
        let mut opt_singles = HashMap::new();
        let mut opt_multiples = HashMap::new();
        let mut opt_flags = HashMap::new();

        let mut parsed = ParsedArguments {
            req_singles: req_singles,
            req_vararg: req_vararg,
            opt_singles: opt_singles,
            opt_multiples: opt_multiples,
            opt_flags: opt_flags,
        };

        for arg in args.iter() {
            println!("Parsing '{}'", arg);
        }

        Ok(parsed)
    }
}<|endoftext|>


<commit_before>mod screen;

use self::screen::Screen;
use data::{Editable, Named, Selectable};
use std::{cmp, iter};
use termion::{color, style, terminal_size};

pub struct View {
    message: Option<String>,
    is_prompt: bool,
    line_offset: usize,
    screen: Screen,
}

const TAB_LENGTH: usize = 4;

impl View {
    pub fn new() -> Self {
        View {
            message: None,
            is_prompt: false,
            line_offset: 0,
            screen: Screen::new(),
        }
    }

    pub fn message(&mut self, message: &str) {
        self.is_prompt = false;
        self.message = Some(String::from(message));
    }

    pub fn prompt(&mut self, prompt: &str, message: &str) {
        self.is_prompt = true;
        let msg = String::from(prompt) + message;
        self.message = Some(msg);
    }

    pub fn quiet(&mut self) {
        self.is_prompt = false;
        self.message = None;
    }

    pub fn center_view(&mut self, line: usize) {
        self.line_offset = line
            .checked_sub(self.lines_height() as usize / 2)
            .unwrap_or(0);
    }

    pub fn adjust_view(&mut self, line: usize) {
        if line < self.line_offset {
            self.line_offset = line;
        } else if line + 1 >= self.line_offset + self.lines_height() {
            self.line_offset = 1 + line - self.lines_height();
        }
    }

    pub fn scroll_view<T: Editable>(&mut self, offset: isize, content: &T) {
        self.line_offset = cmp::min(
            cmp::max((self.line_offset as isize) + offset, 0),
            (content.line_count() as isize) - 1,
        ) as usize;
    }

    pub fn render<T>(&mut self, content: &T)
    where
        T: Editable + Named + Selectable,
    {
        self.screen.clear(&color::Reset);
        self.paint_lines(content);
        self.paint_status(content);
        self.paint_message();
        self.paint_cursor(content);
        self.screen.present();
    }

    pub fn translate_coordinates<T>(&self, content: &T, x: u16, y: u16) -> (usize, usize)
    where
        T: Editable,
    {
        let line = cmp::min(
            (y as isize + self.line_offset as isize - 1) as usize,
            content.line_count() - 1,
        );
        let visual_col = (cmp::max(
            0,
            x as isize - self.line_number_width(content.line_count()) as isize - 2,
        )) as usize;
        // find out if we clicked through a tab
        let col = content
            .iter_line(line)
            .scan(0, |state, x| {
                *state += if x == '\t' { TAB_LENGTH } else { 1 };
                Some(*state)
            }).take_while(|&x| x <= visual_col)
            .count();
        (line, col)
    }

    fn paint_message(&self) {
        if let Some(ref message) = self.message {
            let y = self.lines_height() + 1;
            self.screen.draw(0, y, message);
        }
    }

    fn paint_cursor<T>(&mut self, content: &T)
    where
        T: Editable + Selectable,
    {
        // FIXME: don't print the cursor if off screen, though we should in the future for long
        // lines
        if (content.line()) < self.line_offset
            || content.line() >= self.line_offset + self.lines_height()
            || content.col() >= self.lines_width(content.line_count())
            || content.sel().is_some()
        {
            self.screen.hide_cursor();
            return;
        }

        // in the case of a prompt, the cursor should be drawn in the message line
        let (x, y) = if self.is_prompt {
            (
                self.message.clone().unwrap().chars().count(),
                self.lines_height() + 1,
            )
        } else {
            let (a, b) = self.cursor_pos(content);
            (a, b)
        };
        self.screen.move_cursor(x, y);
        self.screen.show_cursor();
    }

    fn paint_status<T>(&self, content: &T)
    where
        T: Editable + Named,
    {
        let line = content.line();
        let column = content.col();
        let line_count = content.line_count();
        let advance = ((line + 1) as f64 / line_count as f64 * 100.0).floor();

        let (screen_width, _) = terminal_size().unwrap();
        let empty_line = (0..screen_width).map(|_| ' ').collect::<String>();
        let y = self.lines_height();
        let style = format!("{}{}", color::Fg(color::White), style::Invert);

        self.screen.draw_with_style(0, y, &empty_line, &style);
        self.screen.draw_with_style(0, y, content.name(), &style);

        let position_info = format!("{}% {}/{}: {}", advance, line + 1, line_count, column);
        let x = screen_width as usize - position_info.len();
        self.screen.draw_with_style(x, y, &position_info, &style);
    }

    fn paint_lines<T>(&self, content: &T)
    where
        T: Editable + Selectable,
    {
        let line_offset = self.line_offset as usize;
        let lines_height = self.lines_height() as usize;
        let lines_width = self.lines_width(content.line_count()) as usize;
        let line_count = content.line_count();

        let line_start = self.line_number_width(line_count) as usize + 1;

        for (y, line) in content
            .lines()
            .skip(line_offset)
            .take(cmp::min(lines_height, line_count))
            .enumerate()
        {
            // paint line number and initialize display for this line
            let line_index = line_offset + y;
            self.screen.draw_with_style(
                0,
                y,
                &format!("{}", 1 + line_index),
                &format!("{}", color::Fg(color::White)),
            );

            if line.len_chars() > 1 {
                let line_start_char_index = content.line_index_to_char_index(line_index);
                for (x, c) in line
                    .chars()
                    .flat_map(|c| {
                        if c == '\t' {
                            iter::repeat(' ').take(TAB_LENGTH) // FIXME: selection should consider tabs
                        } else {
                            iter::repeat(c).take(1)
                        }
                    }).enumerate()
                {
                    let char_index = line_start_char_index + x;

                    if x < lines_width {
                        if content.in_sel(char_index) {
                            self.screen.draw_with_style(
                                x + line_start,
                                y,
                                &format!("{}", c),
                                &format!("{}", style::Invert),
                            );
                        } else {
                            self.screen.draw(x + line_start, y, &format!("{}", c));
                        }
                    }
                }
            } else if content.line_in_sel(line_offset + y) {
                self.screen
                    .draw_with_style(line_start, y, " ", &format!("{}", style::Invert));
            }
        }
    }

    fn cursor_pos<T: Editable>(&self, content: &T) -> (usize, usize) {
        // TODO: column offsetting for long lines
        let line = content.line();
        let first_line = self.line_offset;
        let y = line - first_line as usize;
        // we can't trust the actual column because tabs have variable length
        let visual_col = content.col();
        let column: usize = content
            .iter_line(line)
            .map(|x| if x == '\t' { TAB_LENGTH } else { 1 })
            .take(visual_col)
            .sum();
        (
            (self.line_number_width(content.line_count()) as usize + 1 + column),
            y,
        )
    }

    fn line_number_width(&self, line_count: usize) -> u16 {
        line_count.to_string().len() as u16
    }

    fn status_height(&self) -> u16 {
        2
    }

    pub fn lines_height(&self) -> usize {
        let (_, screen_height) = terminal_size().unwrap();
        let incompressible = self.status_height() as usize;
        cmp::max(screen_height as usize, incompressible) - incompressible
    }

    pub fn lines_width(&self, line_count: usize) -> usize {
        let (screen_width, _) = terminal_size().unwrap();
        let incompressible = self.line_number_width(line_count) as usize + 1;
        cmp::max(screen_width as usize, incompressible) - incompressible
    }
}
<commit_msg>Formatting<commit_after>mod screen;

use self::screen::Screen;
use data::{Editable, Named, Selectable};
use std::{cmp, iter};
use termion::{color, style, terminal_size};

pub struct View {
    message: Option<String>,
    is_prompt: bool,
    line_offset: usize,
    screen: Screen,
}

const TAB_LENGTH: usize = 4;

impl View {
    pub fn new() -> Self {
        View {
            message: None,
            is_prompt: false,
            line_offset: 0,
            screen: Screen::new(),
        }
    }

    pub fn message(&mut self, message: &str) {
        self.is_prompt = false;
        self.message = Some(String::from(message));
    }

    pub fn prompt(&mut self, prompt: &str, message: &str) {
        self.is_prompt = true;
        let msg = String::from(prompt) + message;
        self.message = Some(msg);
    }

    pub fn quiet(&mut self) {
        self.is_prompt = false;
        self.message = None;
    }

    pub fn center_view(&mut self, line: usize) {
        self.line_offset = line
            .checked_sub(self.lines_height() as usize / 2)
            .unwrap_or(0);
    }

    pub fn adjust_view(&mut self, line: usize) {
        if line < self.line_offset {
            self.line_offset = line;
        } else if line + 1 >= self.line_offset + self.lines_height() {
            self.line_offset = 1 + line - self.lines_height();
        }
    }

    pub fn scroll_view<T: Editable>(&mut self, offset: isize, content: &T) {
        self.line_offset = cmp::min(
            cmp::max((self.line_offset as isize) + offset, 0),
            (content.line_count() as isize) - 1,
        ) as usize;
    }

    pub fn render<T>(&mut self, content: &T)
    where
        T: Editable + Named + Selectable,
    {
        self.screen.clear(&color::Reset);
        self.paint_lines(content);
        self.paint_status(content);
        self.paint_message();
        self.paint_cursor(content);
        self.screen.present();
    }

    pub fn translate_coordinates<T>(&self, content: &T, x: u16, y: u16) -> (usize, usize)
    where
        T: Editable,
    {
        let line = cmp::min(
            (y as isize + self.line_offset as isize - 1) as usize,
            content.line_count() - 1,
        );
        let visual_col = (cmp::max(
            0,
            x as isize - self.line_number_width(content.line_count()) as isize - 2,
        )) as usize;
        // find out if we clicked through a tab
        let col = content
            .iter_line(line)
            .scan(0, |state, x| {
                *state += if x == '\t' { TAB_LENGTH } else { 1 };
                Some(*state)
            })
            .take_while(|&x| x <= visual_col)
            .count();
        (line, col)
    }

    fn paint_message(&self) {
        if let Some(ref message) = self.message {
            let y = self.lines_height() + 1;
            self.screen.draw(0, y, message);
        }
    }

    fn paint_cursor<T>(&mut self, content: &T)
    where
        T: Editable + Selectable,
    {
        // FIXME: don't print the cursor if off screen, though we should in the future for long
        // lines
        if (content.line()) < self.line_offset
            || content.line() >= self.line_offset + self.lines_height()
            || content.col() >= self.lines_width(content.line_count())
            || content.sel().is_some()
        {
            self.screen.hide_cursor();
            return;
        }

        // in the case of a prompt, the cursor should be drawn in the message line
        let (x, y) = if self.is_prompt {
            (
                self.message.clone().unwrap().chars().count(),
                self.lines_height() + 1,
            )
        } else {
            let (a, b) = self.cursor_pos(content);
            (a, b)
        };
        self.screen.move_cursor(x, y);
        self.screen.show_cursor();
    }

    fn paint_status<T>(&self, content: &T)
    where
        T: Editable + Named,
    {
        let line = content.line();
        let column = content.col();
        let line_count = content.line_count();
        let advance = ((line + 1) as f64 / line_count as f64 * 100.0).floor();

        let (screen_width, _) = terminal_size().unwrap();
        let empty_line = (0..screen_width).map(|_| ' ').collect::<String>();
        let y = self.lines_height();
        let style = format!("{}{}", color::Fg(color::White), style::Invert);

        self.screen.draw_with_style(0, y, &empty_line, &style);
        self.screen.draw_with_style(0, y, content.name(), &style);

        let position_info = format!("{}% {}/{}: {}", advance, line + 1, line_count, column);
        let x = screen_width as usize - position_info.len();
        self.screen.draw_with_style(x, y, &position_info, &style);
    }

    fn paint_lines<T>(&self, content: &T)
    where
        T: Editable + Selectable,
    {
        let line_offset = self.line_offset as usize;
        let lines_height = self.lines_height() as usize;
        let lines_width = self.lines_width(content.line_count()) as usize;
        let line_count = content.line_count();

        let line_start = self.line_number_width(line_count) as usize + 1;

        for (y, line) in content
            .lines()
            .skip(line_offset)
            .take(cmp::min(lines_height, line_count))
            .enumerate()
        {
            // paint line number and initialize display for this line
            let line_index = line_offset + y;
            self.screen.draw_with_style(
                0,
                y,
                &format!("{}", 1 + line_index),
                &format!("{}", color::Fg(color::White)),
            );

            if line.len_chars() > 1 {
                let line_start_char_index = content.line_index_to_char_index(line_index);
                for (x, c) in line
                    .chars()
                    .flat_map(|c| {
                        if c == '\t' {
                            iter::repeat(' ').take(TAB_LENGTH) // FIXME: selection should consider tabs
                        } else {
                            iter::repeat(c).take(1)
                        }
                    })
                    .enumerate()
                {
                    let char_index = line_start_char_index + x;

                    if x < lines_width {
                        if content.in_sel(char_index) {
                            self.screen.draw_with_style(
                                x + line_start,
                                y,
                                &format!("{}", c),
                                &format!("{}", style::Invert),
                            );
                        } else {
                            self.screen.draw(x + line_start, y, &format!("{}", c));
                        }
                    }
                }
            } else if content.line_in_sel(line_offset + y) {
                self.screen
                    .draw_with_style(line_start, y, " ", &format!("{}", style::Invert));
            }
        }
    }

    fn cursor_pos<T: Editable>(&self, content: &T) -> (usize, usize) {
        // TODO: column offsetting for long lines
        let line = content.line();
        let first_line = self.line_offset;
        let y = line - first_line as usize;
        // we can't trust the actual column because tabs have variable length
        let visual_col = content.col();
        let column: usize = content
            .iter_line(line)
            .map(|x| if x == '\t' { TAB_LENGTH } else { 1 })
            .take(visual_col)
            .sum();
        (
            (self.line_number_width(content.line_count()) as usize + 1 + column),
            y,
        )
    }

    fn line_number_width(&self, line_count: usize) -> u16 {
        line_count.to_string().len() as u16
    }

    fn status_height(&self) -> u16 {
        2
    }

    pub fn lines_height(&self) -> usize {
        let (_, screen_height) = terminal_size().unwrap();
        let incompressible = self.status_height() as usize;
        cmp::max(screen_height as usize, incompressible) - incompressible
    }

    pub fn lines_width(&self, line_count: usize) -> usize {
        let (screen_width, _) = terminal_size().unwrap();
        let incompressible = self.line_number_width(line_count) as usize + 1;
        cmp::max(screen_width as usize, incompressible) - incompressible
    }
}
<|endoftext|>


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

use std::num::Float;

use {gradient, math, Seed};

/// 2-dimensional perlin noise
pub fn perlin2<T: Float>(seed: &Seed, point: &math::Point2<T>) -> T {
    #[inline(always)]
    fn gradient<T: Float>(seed: &Seed, whole: math::Point2<isize>, frac: math::Vector2<T>) -> T {
        math::dot2(frac, gradient::get2(seed.get2(whole)))
    }

    let floored = math::map2(*point, Float::floor);
    let whole0  = math::map2(*point, math::cast);
    let whole1  = math::add2(whole0, math::one2());
    let frac0   = math::sub2(*point, floored);
    let frac1   = math::sub2(*point, math::one2());
    let curve   = math::map2(frac0, math::scurve5);

    let f00 = gradient(seed, [whole0[0], whole0[1]], [frac0[0], frac0[1]]);
    let f10 = gradient(seed, [whole1[0], whole0[1]], [frac1[0], frac0[1]]);
    let f01 = gradient(seed, [whole0[0], whole1[1]], [frac0[0], frac1[1]]);
    let f11 = gradient(seed, [whole1[0], whole1[1]], [frac1[0], frac1[1]]);

    math::bilerp(curve, f00, f10, f01, f11)
}

/// 3-dimensional perlin noise
pub fn perlin3<T: Float>(seed: &Seed, point: &math::Point3<T>) -> T {
    #[inline(always)]
    fn gradient<T: Float>(seed: &Seed, whole: math::Point3<isize>, frac: math::Vector3<T>) -> T {
        math::dot3(frac, gradient::get3(seed.get3(whole)))
    }

    let floored = math::map3(*point, Float::floor);
    let whole0  = math::map3(*point, math::cast);
    let whole1  = math::add3(whole0, math::one3());
    let frac0   = math::sub3(*point, floored);
    let frac1   = math::sub3(*point, math::one3());
    let curve   = math::map3(frac0, math::scurve5);

    let f000 = gradient(seed, [whole0[0], whole0[1], whole0[2]], [frac0[0], frac0[1], frac0[2]]);
    let f100 = gradient(seed, [whole1[0], whole0[1], whole0[2]], [frac1[0], frac0[1], frac0[2]]);
    let f010 = gradient(seed, [whole0[0], whole1[1], whole0[2]], [frac0[0], frac1[1], frac0[2]]);
    let f110 = gradient(seed, [whole1[0], whole1[1], whole0[2]], [frac1[0], frac1[1], frac0[2]]);
    let f001 = gradient(seed, [whole0[0], whole0[1], whole1[2]], [frac0[0], frac0[1], frac1[2]]);
    let f101 = gradient(seed, [whole1[0], whole0[1], whole1[2]], [frac1[0], frac0[1], frac1[2]]);
    let f011 = gradient(seed, [whole0[0], whole1[1], whole1[2]], [frac0[0], frac1[1], frac1[2]]);
    let f111 = gradient(seed, [whole1[0], whole1[1], whole1[2]], [frac1[0], frac1[1], frac1[2]]);

    math::trilerp(curve, f000, f100, f010, f110, f001, f101, f011, f111)
}

/// 4-dimensional perlin noise
pub fn perlin4<T: Float>(seed: &Seed, point: &math::Point4<T>) -> T {
    #[inline(always)]
    fn gradient<T: Float>(seed: &Seed, whole: math::Point4<isize>, frac: math::Vector4<T>) -> T {
        math::dot4(frac, gradient::get4(seed.get4(whole)))
    }

    let floored = math::map4(*point, Float::floor);
    let whole0  = math::map4(*point, math::cast);
    let whole1  = math::add4(whole0, math::one4());
    let frac0   = math::sub4(*point, floored);
    let frac1   = math::sub4(*point, math::one4());
    let curve   = math::map4(frac0, math::scurve5);

    let f0000 = gradient(seed, [whole0[0], whole0[1], whole0[2], whole0[3]], [frac0[0], frac0[1], frac0[2], frac0[3]]);
    let f1000 = gradient(seed, [whole1[0], whole0[1], whole0[2], whole0[3]], [frac1[0], frac0[1], frac0[2], frac0[3]]);
    let f0001 = gradient(seed, [whole0[0], whole1[1], whole0[2], whole0[3]], [frac0[0], frac1[1], frac0[2], frac0[3]]);
    let f1001 = gradient(seed, [whole1[0], whole1[1], whole0[2], whole0[3]], [frac1[0], frac1[1], frac0[2], frac0[3]]);
    let f0010 = gradient(seed, [whole0[0], whole0[1], whole1[2], whole0[3]], [frac0[0], frac0[1], frac1[2], frac0[3]]);
    let f1010 = gradient(seed, [whole1[0], whole0[1], whole1[2], whole0[3]], [frac1[0], frac0[1], frac1[2], frac0[3]]);
    let f0011 = gradient(seed, [whole0[0], whole1[1], whole1[2], whole0[3]], [frac0[0], frac1[1], frac1[2], frac0[3]]);
    let f1011 = gradient(seed, [whole1[0], whole1[1], whole1[2], whole0[3]], [frac1[0], frac1[1], frac1[2], frac0[3]]);
    let f0100 = gradient(seed, [whole0[0], whole0[1], whole0[2], whole1[3]], [frac0[0], frac0[1], frac0[2], frac1[3]]);
    let f1100 = gradient(seed, [whole1[0], whole0[1], whole0[2], whole1[3]], [frac1[0], frac0[1], frac0[2], frac1[3]]);
    let f0101 = gradient(seed, [whole0[0], whole1[1], whole0[2], whole1[3]], [frac0[0], frac1[1], frac0[2], frac1[3]]);
    let f1101 = gradient(seed, [whole1[0], whole1[1], whole0[2], whole1[3]], [frac1[0], frac1[1], frac0[2], frac1[3]]);
    let f0110 = gradient(seed, [whole0[0], whole0[1], whole1[2], whole1[3]], [frac0[0], frac0[1], frac1[2], frac1[3]]);
    let f1110 = gradient(seed, [whole1[0], whole0[1], whole1[2], whole1[3]], [frac1[0], frac0[1], frac1[2], frac1[3]]);
    let f0111 = gradient(seed, [whole0[0], whole1[1], whole1[2], whole1[3]], [frac0[0], frac1[1], frac1[2], frac1[3]]);
    let f1111 = gradient(seed, [whole1[0], whole1[1], whole1[2], whole1[3]], [frac1[0], frac1[1], frac1[2], frac1[3]]);

    math::quadlerp(curve, f0000, f1000, f0001, f1001, f0010, f1010, f0011, f1011, f0100, f1100, f0101, f1101, f0110, f1110, f0111, f1111)
}
<commit_msg>Use correct input to generate frac1<commit_after>// Copyright 2015 The noise-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::num::Float;

use {gradient, math, Seed};

/// 2-dimensional perlin noise
pub fn perlin2<T: Float>(seed: &Seed, point: &math::Point2<T>) -> T {
    #[inline(always)]
    fn gradient<T: Float>(seed: &Seed, whole: math::Point2<isize>, frac: math::Vector2<T>) -> T {
        math::dot2(frac, gradient::get2(seed.get2(whole)))
    }

    let floored = math::map2(*point, Float::floor);
    let whole0  = math::map2(*point, math::cast);
    let whole1  = math::add2(whole0, math::one2());
    let frac0   = math::sub2(*point, floored);
    let frac1   = math::sub2(frac0, math::one2());
    let curve   = math::map2(frac0, math::scurve5);

    let f00 = gradient(seed, [whole0[0], whole0[1]], [frac0[0], frac0[1]]);
    let f10 = gradient(seed, [whole1[0], whole0[1]], [frac1[0], frac0[1]]);
    let f01 = gradient(seed, [whole0[0], whole1[1]], [frac0[0], frac1[1]]);
    let f11 = gradient(seed, [whole1[0], whole1[1]], [frac1[0], frac1[1]]);

    math::bilerp(curve, f00, f10, f01, f11)
}

/// 3-dimensional perlin noise
pub fn perlin3<T: Float>(seed: &Seed, point: &math::Point3<T>) -> T {
    #[inline(always)]
    fn gradient<T: Float>(seed: &Seed, whole: math::Point3<isize>, frac: math::Vector3<T>) -> T {
        math::dot3(frac, gradient::get3(seed.get3(whole)))
    }

    let floored = math::map3(*point, Float::floor);
    let whole0  = math::map3(*point, math::cast);
    let whole1  = math::add3(whole0, math::one3());
    let frac0   = math::sub3(*point, floored);
    let frac1   = math::sub3(frac0, math::one3());
    let curve   = math::map3(frac0, math::scurve5);

    let f000 = gradient(seed, [whole0[0], whole0[1], whole0[2]], [frac0[0], frac0[1], frac0[2]]);
    let f100 = gradient(seed, [whole1[0], whole0[1], whole0[2]], [frac1[0], frac0[1], frac0[2]]);
    let f010 = gradient(seed, [whole0[0], whole1[1], whole0[2]], [frac0[0], frac1[1], frac0[2]]);
    let f110 = gradient(seed, [whole1[0], whole1[1], whole0[2]], [frac1[0], frac1[1], frac0[2]]);
    let f001 = gradient(seed, [whole0[0], whole0[1], whole1[2]], [frac0[0], frac0[1], frac1[2]]);
    let f101 = gradient(seed, [whole1[0], whole0[1], whole1[2]], [frac1[0], frac0[1], frac1[2]]);
    let f011 = gradient(seed, [whole0[0], whole1[1], whole1[2]], [frac0[0], frac1[1], frac1[2]]);
    let f111 = gradient(seed, [whole1[0], whole1[1], whole1[2]], [frac1[0], frac1[1], frac1[2]]);

    math::trilerp(curve, f000, f100, f010, f110, f001, f101, f011, f111)
}

/// 4-dimensional perlin noise
pub fn perlin4<T: Float>(seed: &Seed, point: &math::Point4<T>) -> T {
    #[inline(always)]
    fn gradient<T: Float>(seed: &Seed, whole: math::Point4<isize>, frac: math::Vector4<T>) -> T {
        math::dot4(frac, gradient::get4(seed.get4(whole)))
    }

    let floored = math::map4(*point, Float::floor);
    let whole0  = math::map4(*point, math::cast);
    let whole1  = math::add4(whole0, math::one4());
    let frac0   = math::sub4(*point, floored);
    let frac1   = math::sub4(frac0, math::one4());
    let curve   = math::map4(frac0, math::scurve5);

    let f0000 = gradient(seed, [whole0[0], whole0[1], whole0[2], whole0[3]], [frac0[0], frac0[1], frac0[2], frac0[3]]);
    let f1000 = gradient(seed, [whole1[0], whole0[1], whole0[2], whole0[3]], [frac1[0], frac0[1], frac0[2], frac0[3]]);
    let f0001 = gradient(seed, [whole0[0], whole1[1], whole0[2], whole0[3]], [frac0[0], frac1[1], frac0[2], frac0[3]]);
    let f1001 = gradient(seed, [whole1[0], whole1[1], whole0[2], whole0[3]], [frac1[0], frac1[1], frac0[2], frac0[3]]);
    let f0010 = gradient(seed, [whole0[0], whole0[1], whole1[2], whole0[3]], [frac0[0], frac0[1], frac1[2], frac0[3]]);
    let f1010 = gradient(seed, [whole1[0], whole0[1], whole1[2], whole0[3]], [frac1[0], frac0[1], frac1[2], frac0[3]]);
    let f0011 = gradient(seed, [whole0[0], whole1[1], whole1[2], whole0[3]], [frac0[0], frac1[1], frac1[2], frac0[3]]);
    let f1011 = gradient(seed, [whole1[0], whole1[1], whole1[2], whole0[3]], [frac1[0], frac1[1], frac1[2], frac0[3]]);
    let f0100 = gradient(seed, [whole0[0], whole0[1], whole0[2], whole1[3]], [frac0[0], frac0[1], frac0[2], frac1[3]]);
    let f1100 = gradient(seed, [whole1[0], whole0[1], whole0[2], whole1[3]], [frac1[0], frac0[1], frac0[2], frac1[3]]);
    let f0101 = gradient(seed, [whole0[0], whole1[1], whole0[2], whole1[3]], [frac0[0], frac1[1], frac0[2], frac1[3]]);
    let f1101 = gradient(seed, [whole1[0], whole1[1], whole0[2], whole1[3]], [frac1[0], frac1[1], frac0[2], frac1[3]]);
    let f0110 = gradient(seed, [whole0[0], whole0[1], whole1[2], whole1[3]], [frac0[0], frac0[1], frac1[2], frac1[3]]);
    let f1110 = gradient(seed, [whole1[0], whole0[1], whole1[2], whole1[3]], [frac1[0], frac0[1], frac1[2], frac1[3]]);
    let f0111 = gradient(seed, [whole0[0], whole1[1], whole1[2], whole1[3]], [frac0[0], frac1[1], frac1[2], frac1[3]]);
    let f1111 = gradient(seed, [whole1[0], whole1[1], whole1[2], whole1[3]], [frac1[0], frac1[1], frac1[2], frac1[3]]);

    math::quadlerp(curve, f0000, f1000, f0001, f1001, f0010, f1010, f0011, f1011, f0100, f1100, f0101, f1101, f0110, f1110, f0111, f1111)
}
<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation for SGX using RDRAND instruction
use crate::Error;
use core::mem;
use core::arch::x86_64::{__cpuid, _rdrand64_step};
use core::num::NonZeroU32;
use lazy_static::lazy_static;

// Recommendation from "Intel® Digital Random Number Generator (DRNG) Software
// Implementation Guide" - Section 5.2.1 and "Intel® 64 and IA-32 Architectures
// Software Developer’s Manual" - Volume 1 - Section 7.3.17.1.
const RETRY_LIMIT: usize = 10;
const WORD_SIZE: usize = mem::size_of::<u64>();

#[target_feature(enable = "rdrand")]
unsafe fn rdrand() -> Result<[u8; WORD_SIZE], Error> {
    for _ in 0..RETRY_LIMIT {
        let mut el = mem::uninitialized();
        if _rdrand64_step(&mut el) == 1 {
            return Ok(el.to_ne_bytes());
        }
    }
    error!("RDRAND failed, CPU issue likely");
    Err(Error::UNKNOWN)
}

#[cfg(all(target_env = "sgx", not(target_feature = "rdrand")))]
compile_error!("SGX targets must enable RDRAND to get randomness");

// TODO use is_x86_feature_detected!("rdrand") when that works in core. See:
//   https://github.com/rust-lang-nursery/stdsimd/issues/464
fn is_rdrand_supported() -> bool {
    if cfg!(target_feature = "rdrand") {
        true
    } else {
        // SAFETY: All x86_64 CPUs support CPUID leaf 1
        const FLAG: u32 = 1 << 30;
        lazy_static! {
            static ref HAS_RDRAND: bool = unsafe { __cpuid(1).ecx & FLAG != 0 };
        }
        *HAS_RDRAND
    }
}

pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
    if !is_rdrand_supported() {
        return Err(Error::UNAVAILABLE);
    }

    // SAFETY: After this point, rdrand is supported, so calling the rdrand
    // functions is not undefined behavior.
    unsafe { rdrand_exact(dest) }
}

#[target_feature(enable = "rdrand")]
unsafe fn rdrand_exact(dest: &mut [u8]) -> Result<(), Error> {
    // We use chunks_exact_mut instead of chunks_mut as it allows almost all
    // calls to memcpy to be elided by the compiler.
    let mut chunks = dest.chunks_exact_mut(WORD_SIZE);
    for chunk in chunks.by_ref() {
        chunk.copy_from_slice(&rdrand()?);
    }

    let tail = chunks.into_remainder();
    let n = tail.len();
    if n > 0 {
        tail.copy_from_slice(&rdrand()?[..n]);
    }
    Ok(())
}

#[inline(always)]
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
<commit_msg>Improve compile_error! message<commit_after>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation for SGX using RDRAND instruction
use crate::Error;
use core::mem;
use core::arch::x86_64::{__cpuid, _rdrand64_step};
use core::num::NonZeroU32;
use lazy_static::lazy_static;

// Recommendation from "Intel® Digital Random Number Generator (DRNG) Software
// Implementation Guide" - Section 5.2.1 and "Intel® 64 and IA-32 Architectures
// Software Developer’s Manual" - Volume 1 - Section 7.3.17.1.
const RETRY_LIMIT: usize = 10;
const WORD_SIZE: usize = mem::size_of::<u64>();

#[target_feature(enable = "rdrand")]
unsafe fn rdrand() -> Result<[u8; WORD_SIZE], Error> {
    for _ in 0..RETRY_LIMIT {
        let mut el = mem::uninitialized();
        if _rdrand64_step(&mut el) == 1 {
            return Ok(el.to_ne_bytes());
        }
    }
    error!("RDRAND failed, CPU issue likely");
    Err(Error::UNKNOWN)
}

// "rdrand" target feature requires "+rdrnd" flag, see https://github.com/rust-lang/rust/issues/49653.
#[cfg(all(target_env = "sgx", not(target_feature = "rdrand")))]
compile_error!(
    "SGX targets require 'rdrand' target feature. Enable by using -C target-feature=+rdrnd."
);

// TODO use is_x86_feature_detected!("rdrand") when that works in core. See:
//   https://github.com/rust-lang-nursery/stdsimd/issues/464
fn is_rdrand_supported() -> bool {
    if cfg!(target_feature = "rdrand") {
        true
    } else {
        // SAFETY: All x86_64 CPUs support CPUID leaf 1
        const FLAG: u32 = 1 << 30;
        lazy_static! {
            static ref HAS_RDRAND: bool = unsafe { __cpuid(1).ecx & FLAG != 0 };
        }
        *HAS_RDRAND
    }
}

pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
    if !is_rdrand_supported() {
        return Err(Error::UNAVAILABLE);
    }

    // SAFETY: After this point, rdrand is supported, so calling the rdrand
    // functions is not undefined behavior.
    unsafe { rdrand_exact(dest) }
}

#[target_feature(enable = "rdrand")]
unsafe fn rdrand_exact(dest: &mut [u8]) -> Result<(), Error> {
    // We use chunks_exact_mut instead of chunks_mut as it allows almost all
    // calls to memcpy to be elided by the compiler.
    let mut chunks = dest.chunks_exact_mut(WORD_SIZE);
    for chunk in chunks.by_ref() {
        chunk.copy_from_slice(&rdrand()?);
    }

    let tail = chunks.into_remainder();
    let n = tail.len();
    if n > 0 {
        tail.copy_from_slice(&rdrand()?[..n]);
    }
    Ok(())
}

#[inline(always)]
pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use config::Config;
use domain_store::{DomainError, DomainRecord};
use errors::*;
use iron::headers::ContentType;
use iron::prelude::*;
use iron::status::{self, Status};
use params::{FromValue, Params, Value};
use pdns::pdns_endpoint;
use router::Router;
use serde_json;
use std::time::{SystemTime, UNIX_EPOCH};
use uuid::Uuid;

fn domain_for_name(name: &str, config: &Config) -> String {
    format!("{}.box.{}.", name, config.domain)
}

fn register(req: &mut Request, config: &Config) -> IronResult<Response> {
    // Extract the local_ip and token parameter,
    // and the public IP from the socket.
    let public_ip = format!("{}", req.remote_addr.ip());

    let map = req.get_ref::<Params>().unwrap(); // TODO: don't unwrap.
    let token = map.find(&["token"]);
    let local_ip = map.find(&["local_ip"]);

    // Both parameters are mandatory.
    if token.is_none() || local_ip.is_none() {
        return EndpointError::with(status::BadRequest, 400);
    }

    let token = String::from_value(token.unwrap()).unwrap();
    let local_ip = String::from_value(local_ip.unwrap()).unwrap();

    info!("GET /register token={} local_ip={} public_ip={}",
          token,
          local_ip,
          public_ip);

    // Save this registration in the database if we know about this token.
    // Check if we have a record with this token, bail out if not.
    match config
              .domain_db
              .get_record_by_token(&token)
              .recv()
              .unwrap() {
        Ok(record) => {
            // Update the record with the challenge.
            let dns_challenge = match record.dns_challenge {
                Some(ref challenge) => Some(challenge.as_str()),
                None => None,
            };
            // Update the timestamp to be current.
            let timestamp = SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap()
                .as_secs() as i64;

            let new_record = DomainRecord::new(&record.name,
                                               &record.token,
                                               dns_challenge,
                                               Some(&local_ip),
                                               Some(&public_ip),
                                               timestamp);
            match config
                      .domain_db
                      .update_record(new_record)
                      .recv()
                      .unwrap() {
                Ok(()) => {
                    // Everything went fine, return an empty 200 OK for now.
                    let mut response = Response::new();
                    response.status = Some(Status::Ok);

                    Ok(response)
                }
                Err(_) => EndpointError::with(status::InternalServerError, 501),
            }
        }
        Err(DomainError::NoRecord) => EndpointError::with(status::BadRequest, 400),
        Err(_) => EndpointError::with(status::InternalServerError, 501),
    }
}

fn ping(req: &mut Request, config: &Config) -> IronResult<Response> {
    info!("GET /ping");

    let map = req.get_ref::<Params>().unwrap(); // TODO: don't unwrap.
    let token = map.find(&["token"]);
    if token.is_none() {
        return EndpointError::with(status::BadRequest, 400);
    }
    let token = String::from_value(token.unwrap()).unwrap();

    match config
              .domain_db
              .get_record_by_token(&token)
              .recv()
              .unwrap() {
        Ok(record) => {
            let mut response = Response::with(serde_json::to_string(&record).unwrap());
            response.headers.set(ContentType::json());
            Ok(response)
        }
        Err(DomainError::NoRecord) => EndpointError::with(status::BadRequest, 400),
        Err(_) => EndpointError::with(status::InternalServerError, 501),
    }
}

fn unsubscribe(req: &mut Request, config: &Config) -> IronResult<Response> {
    info!("GET /unsubscribe");

    let map = req.get_ref::<Params>().unwrap(); // TODO: don't unwrap.
    let token = map.find(&["token"]);
    if token.is_none() {
        return EndpointError::with(status::BadRequest, 400);
    }
    let token = String::from_value(token.unwrap()).unwrap();

    match config
              .domain_db
              .delete_record_by_token(&token)
              .recv()
              .unwrap() {
        Ok(0) => EndpointError::with(status::BadRequest, 400), // No record found for this token.
        Ok(_) => {
            let mut response = Response::new();
            response.status = Some(Status::Ok);

            Ok(response)
        }
        Err(_) => EndpointError::with(status::InternalServerError, 501),
    }
}

fn subscribe(req: &mut Request, config: &Config) -> IronResult<Response> {
    info!("GET /subscribe");

    // Extract the name parameter.
    let map = req.get_ref::<Params>().unwrap(); // TODO: don't unwrap.
    match map.find(&["name"]) {
        Some(&Value::String(ref name)) => {
            let full_name = domain_for_name(name, config);
            info!("trying to register {}", full_name);

            let record = config
                .domain_db
                .get_record_by_name(&full_name)
                .recv()
                .unwrap();
            match record {
                Ok(_) => {
                    // We already have a record for this name, return an error.
                    let mut response = Response::with("{\"error\": \"UnavailableName\"}");
                    response.status = Some(Status::Ok);
                    response.headers.set(ContentType::json());
                    Ok(response)
                }
                Err(DomainError::NoRecord) => {
                    // Create a token, create and store a record and finally return the token.
                    let token = format!("{}", Uuid::new_v4());
                    let record = DomainRecord::new(&full_name, &token, None, None, None, 0);
                    match config.domain_db.add_record(record).recv().unwrap() {
                        Ok(()) => {
                            // We don't want the full domain name or the dns challenge in the
                            // response so we create a local struct.
                            #[derive(Serialize)]
                            struct NameAndToken {
                                name: String,
                                token: String,
                            }
                            let n_and_t = NameAndToken {
                                name: name.to_owned(),
                                token: token,
                            };
                            match serde_json::to_string(&n_and_t) {
                                Ok(serialized) => {
                                    let mut response = Response::with(serialized);
                                    response.status = Some(Status::Ok);
                                    response.headers.set(ContentType::json());

                                    Ok(response)
                                }
                                Err(_) => EndpointError::with(status::InternalServerError, 501)
                            }
                        }
                        Err(_) => EndpointError::with(status::InternalServerError, 501),
                    }
                }
                // Other error, like a db issue.
                Err(_) => EndpointError::with(status::InternalServerError, 501),
            }
        }
        // Missing `name` parameter.
        _ => EndpointError::with(status::BadRequest, 400),
    }
}

fn dns_config(req: &mut Request, config: &Config) -> IronResult<Response> {
    info!("GET /dnsconfig");

    // Extract the challenge and token parameter.
    let map = req.get_ref::<Params>().unwrap(); // TODO: don't unwrap.
    let challenge = map.find(&["challenge"]);
    let token = map.find(&["token"]);

    // Both parameters are mandatory.
    if challenge.is_none() || token.is_none() {
        return EndpointError::with(status::BadRequest, 400);
    }

    let challenge = String::from_value(challenge.unwrap()).unwrap();
    let token = String::from_value(token.unwrap()).unwrap();

    // Check if we have a record with this token, bail out if not.
    match config
              .domain_db
              .get_record_by_token(&token)
              .recv()
              .unwrap() {
        Ok(record) => {
            // Update the record with the challenge.
            let local_ip = match record.local_ip {
                Some(ref ip) => Some(ip.as_str()),
                None => None,
            };
            let public_ip = match record.public_ip {
                Some(ref ip) => Some(ip.as_str()),
                None => None,
            };

            let new_record = DomainRecord::new(&record.name,
                                               &record.token,
                                               Some(&challenge),
                                               local_ip,
                                               public_ip,
                                               record.timestamp);
            match config
                      .domain_db
                      .update_record(new_record)
                      .recv()
                      .unwrap() {
                Ok(()) => {
                    // Everything went fine, return an empty 200 OK for now.
                    let mut response = Response::new();
                    response.status = Some(Status::Ok);

                    Ok(response)
                }
                Err(_) => EndpointError::with(status::InternalServerError, 501),
            }
        }
        Err(DomainError::NoRecord) => EndpointError::with(status::BadRequest, 400),
        Err(_) => EndpointError::with(status::InternalServerError, 501),
    }
}

pub fn create(config: &Config) -> Router {
    let mut router = Router::new();

    let config_ = config.clone();
    router.get("register",
               move |req: &mut Request| -> IronResult<Response> { register(req, &config_) },
               "post_message");

    let config_ = config.clone();
    router.get("ping",
               move |req: &mut Request| -> IronResult<Response> { ping(req, &config_) },
               "ping");

    let config_ = config.clone();
    router.get("subscribe",
               move |req: &mut Request| -> IronResult<Response> { subscribe(req, &config_) },
               "subscribe");

    let config_ = config.clone();
    router.get("unsubscribe",
               move |req: &mut Request| -> IronResult<Response> { unsubscribe(req, &config_) },
               "unsubscribe");

    let config_ = config.clone();
    router.get("dnsconfig",
               move |req: &mut Request| -> IronResult<Response> { dns_config(req, &config_) },
               "dnsconfig");

    let config_ = config.clone();
    router.post("pdns",
                move |req: &mut Request| -> IronResult<Response> { pdns_endpoint(req, &config_) },
                "pdns");

    router
}
<commit_msg>Return an error code for failed subscriptions<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use config::Config;
use domain_store::{DomainError, DomainRecord};
use errors::*;
use iron::headers::ContentType;
use iron::prelude::*;
use iron::status::{self, Status};
use params::{FromValue, Params, Value};
use pdns::pdns_endpoint;
use router::Router;
use serde_json;
use std::time::{SystemTime, UNIX_EPOCH};
use uuid::Uuid;

fn domain_for_name(name: &str, config: &Config) -> String {
    format!("{}.box.{}.", name, config.domain)
}

fn register(req: &mut Request, config: &Config) -> IronResult<Response> {
    // Extract the local_ip and token parameter,
    // and the public IP from the socket.
    let public_ip = format!("{}", req.remote_addr.ip());

    let map = req.get_ref::<Params>().unwrap(); // TODO: don't unwrap.
    let token = map.find(&["token"]);
    let local_ip = map.find(&["local_ip"]);

    // Both parameters are mandatory.
    if token.is_none() || local_ip.is_none() {
        return EndpointError::with(status::BadRequest, 400);
    }

    let token = String::from_value(token.unwrap()).unwrap();
    let local_ip = String::from_value(local_ip.unwrap()).unwrap();

    info!("GET /register token={} local_ip={} public_ip={}",
          token,
          local_ip,
          public_ip);

    // Save this registration in the database if we know about this token.
    // Check if we have a record with this token, bail out if not.
    match config
              .domain_db
              .get_record_by_token(&token)
              .recv()
              .unwrap() {
        Ok(record) => {
            // Update the record with the challenge.
            let dns_challenge = match record.dns_challenge {
                Some(ref challenge) => Some(challenge.as_str()),
                None => None,
            };
            // Update the timestamp to be current.
            let timestamp = SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap()
                .as_secs() as i64;

            let new_record = DomainRecord::new(&record.name,
                                               &record.token,
                                               dns_challenge,
                                               Some(&local_ip),
                                               Some(&public_ip),
                                               timestamp);
            match config
                      .domain_db
                      .update_record(new_record)
                      .recv()
                      .unwrap() {
                Ok(()) => {
                    // Everything went fine, return an empty 200 OK for now.
                    let mut response = Response::new();
                    response.status = Some(Status::Ok);

                    Ok(response)
                }
                Err(_) => EndpointError::with(status::InternalServerError, 501),
            }
        }
        Err(DomainError::NoRecord) => EndpointError::with(status::BadRequest, 400),
        Err(_) => EndpointError::with(status::InternalServerError, 501),
    }
}

fn ping(req: &mut Request, config: &Config) -> IronResult<Response> {
    info!("GET /ping");

    let map = req.get_ref::<Params>().unwrap(); // TODO: don't unwrap.
    let token = map.find(&["token"]);
    if token.is_none() {
        return EndpointError::with(status::BadRequest, 400);
    }
    let token = String::from_value(token.unwrap()).unwrap();

    match config
              .domain_db
              .get_record_by_token(&token)
              .recv()
              .unwrap() {
        Ok(record) => {
            let mut response = Response::with(serde_json::to_string(&record).unwrap());
            response.headers.set(ContentType::json());
            Ok(response)
        }
        Err(DomainError::NoRecord) => EndpointError::with(status::BadRequest, 400),
        Err(_) => EndpointError::with(status::InternalServerError, 501),
    }
}

fn unsubscribe(req: &mut Request, config: &Config) -> IronResult<Response> {
    info!("GET /unsubscribe");

    let map = req.get_ref::<Params>().unwrap(); // TODO: don't unwrap.
    let token = map.find(&["token"]);
    if token.is_none() {
        return EndpointError::with(status::BadRequest, 400);
    }
    let token = String::from_value(token.unwrap()).unwrap();

    match config
              .domain_db
              .delete_record_by_token(&token)
              .recv()
              .unwrap() {
        Ok(0) => EndpointError::with(status::BadRequest, 400), // No record found for this token.
        Ok(_) => {
            let mut response = Response::new();
            response.status = Some(Status::Ok);

            Ok(response)
        }
        Err(_) => EndpointError::with(status::InternalServerError, 501),
    }
}

fn subscribe(req: &mut Request, config: &Config) -> IronResult<Response> {
    info!("GET /subscribe");

    // Extract the name parameter.
    let map = req.get_ref::<Params>().unwrap(); // TODO: don't unwrap.
    match map.find(&["name"]) {
        Some(&Value::String(ref name)) => {
            let full_name = domain_for_name(name, config);
            info!("trying to register {}", full_name);

            let record = config
                .domain_db
                .get_record_by_name(&full_name)
                .recv()
                .unwrap();
            match record {
                Ok(_) => {
                    // We already have a record for this name, return an error.
                    let mut response = Response::with("{\"error\": \"UnavailableName\"}");
                    response.status = Some(Status::BadRequest);
                    response.headers.set(ContentType::json());
                    Ok(response)
                }
                Err(DomainError::NoRecord) => {
                    // Create a token, create and store a record and finally return the token.
                    let token = format!("{}", Uuid::new_v4());
                    let record = DomainRecord::new(&full_name, &token, None, None, None, 0);
                    match config.domain_db.add_record(record).recv().unwrap() {
                        Ok(()) => {
                            // We don't want the full domain name or the dns challenge in the
                            // response so we create a local struct.
                            #[derive(Serialize)]
                            struct NameAndToken {
                                name: String,
                                token: String,
                            }
                            let n_and_t = NameAndToken {
                                name: name.to_owned(),
                                token: token,
                            };
                            match serde_json::to_string(&n_and_t) {
                                Ok(serialized) => {
                                    let mut response = Response::with(serialized);
                                    response.status = Some(Status::Ok);
                                    response.headers.set(ContentType::json());

                                    Ok(response)
                                }
                                Err(_) => EndpointError::with(status::InternalServerError, 501)
                            }
                        }
                        Err(_) => EndpointError::with(status::InternalServerError, 501),
                    }
                }
                // Other error, like a db issue.
                Err(_) => EndpointError::with(status::InternalServerError, 501),
            }
        }
        // Missing `name` parameter.
        _ => EndpointError::with(status::BadRequest, 400),
    }
}

fn dns_config(req: &mut Request, config: &Config) -> IronResult<Response> {
    info!("GET /dnsconfig");

    // Extract the challenge and token parameter.
    let map = req.get_ref::<Params>().unwrap(); // TODO: don't unwrap.
    let challenge = map.find(&["challenge"]);
    let token = map.find(&["token"]);

    // Both parameters are mandatory.
    if challenge.is_none() || token.is_none() {
        return EndpointError::with(status::BadRequest, 400);
    }

    let challenge = String::from_value(challenge.unwrap()).unwrap();
    let token = String::from_value(token.unwrap()).unwrap();

    // Check if we have a record with this token, bail out if not.
    match config
              .domain_db
              .get_record_by_token(&token)
              .recv()
              .unwrap() {
        Ok(record) => {
            // Update the record with the challenge.
            let local_ip = match record.local_ip {
                Some(ref ip) => Some(ip.as_str()),
                None => None,
            };
            let public_ip = match record.public_ip {
                Some(ref ip) => Some(ip.as_str()),
                None => None,
            };

            let new_record = DomainRecord::new(&record.name,
                                               &record.token,
                                               Some(&challenge),
                                               local_ip,
                                               public_ip,
                                               record.timestamp);
            match config
                      .domain_db
                      .update_record(new_record)
                      .recv()
                      .unwrap() {
                Ok(()) => {
                    // Everything went fine, return an empty 200 OK for now.
                    let mut response = Response::new();
                    response.status = Some(Status::Ok);

                    Ok(response)
                }
                Err(_) => EndpointError::with(status::InternalServerError, 501),
            }
        }
        Err(DomainError::NoRecord) => EndpointError::with(status::BadRequest, 400),
        Err(_) => EndpointError::with(status::InternalServerError, 501),
    }
}

pub fn create(config: &Config) -> Router {
    let mut router = Router::new();

    let config_ = config.clone();
    router.get("register",
               move |req: &mut Request| -> IronResult<Response> { register(req, &config_) },
               "post_message");

    let config_ = config.clone();
    router.get("ping",
               move |req: &mut Request| -> IronResult<Response> { ping(req, &config_) },
               "ping");

    let config_ = config.clone();
    router.get("subscribe",
               move |req: &mut Request| -> IronResult<Response> { subscribe(req, &config_) },
               "subscribe");

    let config_ = config.clone();
    router.get("unsubscribe",
               move |req: &mut Request| -> IronResult<Response> { unsubscribe(req, &config_) },
               "unsubscribe");

    let config_ = config.clone();
    router.get("dnsconfig",
               move |req: &mut Request| -> IronResult<Response> { dns_config(req, &config_) },
               "dnsconfig");

    let config_ = config.clone();
    router.post("pdns",
                move |req: &mut Request| -> IronResult<Response> { pdns_endpoint(req, &config_) },
                "pdns");

    router
}
<|endoftext|>


<commit_before>use range::Range;
use std::rc::Rc;

use {
    err_update,
    DebugId,
    ParseError,
    ParseResult,
    Rule,
    Tokenizer,
    TokenizerState,
};

/// Stores information about select.
#[derive(Clone)]
pub struct Select {
    /// The rules to select from.
    pub args: Vec<Rule>,
    /// A debug id to track down the rule generating an error.
    pub debug_id: DebugId,
}

impl Select {
    /// Parses select.
    pub fn parse(
        &self,
        tokenizer: &mut Tokenizer,
        state: &TokenizerState,
        chars: &[char],
        offset: usize,
        refs: &[(Rc<String>, Rule)]
    ) -> ParseResult<TokenizerState> {
        let mut opt_error: Option<(Range, ParseError)> = None;
        for sub_rule in &self.args {
            match sub_rule.parse(tokenizer, state, chars, offset, refs) {
                Ok((range, state, err)) => {
                    err_update(err, &mut opt_error);
                    return Ok((Range::new(offset, range.next_offset() - offset),
                        state, opt_error));
                }
                Err(err) => {
                    err_update(Some(err), &mut opt_error);
                }
            }
        }
        match opt_error {
            None => Err((Range::new(offset, 0), ParseError::InvalidRule(
                "`Select` requires at least one sub rule", self.debug_id))),
            Some(err) => Err(err),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::super::*;
    use range::Range;
    use std::rc::Rc;

    #[test]
    fn invalid_rule() {
        let text = "";
        let chars: Vec<char> = text.chars().collect();
        let mut tokenizer = Tokenizer::new();
        let s = TokenizerState::new();
        let select = Select {
            debug_id: 0,
            args: vec![]
        };
        let res = select.parse(&mut tokenizer, &s, &chars, 0, &[]);
        let invalid_rule = match &res {
            &Err((_, ParseError::InvalidRule(_, _))) => true,
            _ => false
        };
        assert!(invalid_rule);
    }

    #[test]
    fn fail_first() {
        let text = "2";
        let chars: Vec<char> = text.chars().collect();
        let mut tokenizer = Tokenizer::new();
        let s = TokenizerState::new();
        let num: Rc<String> = Rc::new("num".into());
        let select = Select {
            debug_id: 0,
            args: vec![
                Rule::Text(Text {
                    debug_id: 1,
                    allow_empty: true,
                    property: None
                }),
                Rule::Number(Number {
                    debug_id: 2,
                    property: Some(num.clone()),
                    allow_underscore: false,
                })
            ]
        };
        let res = select.parse(&mut tokenizer, &s, &chars, 0, &[]);
        assert_eq!(res, Ok((Range::new(0, 1), TokenizerState(1),
            Some((Range::new(0, 0), ParseError::ExpectedText(1))))));
        assert_eq!(tokenizer.tokens.len(), 1);
        assert_eq!(&tokenizer.tokens[0].1, &MetaData::F64(num.clone(), 2.0));
    }
}
<commit_msg>Use `parse` in select unit tests<commit_after>use range::Range;
use std::rc::Rc;

use {
    err_update,
    DebugId,
    ParseError,
    ParseResult,
    Rule,
    Tokenizer,
    TokenizerState,
};

/// Stores information about select.
#[derive(Clone)]
pub struct Select {
    /// The rules to select from.
    pub args: Vec<Rule>,
    /// A debug id to track down the rule generating an error.
    pub debug_id: DebugId,
}

impl Select {
    /// Parses select.
    pub fn parse(
        &self,
        tokenizer: &mut Tokenizer,
        state: &TokenizerState,
        chars: &[char],
        offset: usize,
        refs: &[(Rc<String>, Rule)]
    ) -> ParseResult<TokenizerState> {
        let mut opt_error: Option<(Range, ParseError)> = None;
        for sub_rule in &self.args {
            match sub_rule.parse(tokenizer, state, chars, offset, refs) {
                Ok((range, state, err)) => {
                    err_update(err, &mut opt_error);
                    return Ok((Range::new(offset, range.next_offset() - offset),
                        state, opt_error));
                }
                Err(err) => {
                    err_update(Some(err), &mut opt_error);
                }
            }
        }
        match opt_error {
            None => Err((Range::new(offset, 0), ParseError::InvalidRule(
                "`Select` requires at least one sub rule", self.debug_id))),
            Some(err) => Err(err),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::super::*;
    use range::Range;
    use std::rc::Rc;

    #[test]
    fn invalid_rule() {
        let text = "";
        let select = Rule::Select(Select {
            debug_id: 0,
            args: vec![]
        });
        let res = parse(&select, &[], &text);
        let invalid_rule = match &res {
            &Err((_, ParseError::InvalidRule(_, _))) => true,
            _ => false
        };
        assert!(invalid_rule);
    }

    #[test]
    fn fail_first() {
        let text = "2";
        let num: Rc<String> = Rc::new("num".into());
        let select = Rule::Select(Select {
            debug_id: 0,
            args: vec![
                Rule::Text(Text {
                    debug_id: 1,
                    allow_empty: true,
                    property: None
                }),
                Rule::Number(Number {
                    debug_id: 2,
                    property: Some(num.clone()),
                    allow_underscore: false,
                })
            ]
        });
        let res = parse(&select, &[], &text);
        assert_eq!(res, Ok(vec![
            (Range::new(0, 1), MetaData::F64(num.clone(), 2.0))
        ]));
    }
}
<|endoftext|>


<commit_before><commit_msg>UT for server to enable refactoring<commit_after>struct Server {
    dummy: i32,
}

static CONNACK_OK : [u8; 4] = [32, 2, 0, 0];

impl Server {
    fn new() -> Self {
        Server { dummy: 5 }
    }

    fn new_client(&mut self, client: &MqttConnection) {
    }

    fn new_message(&mut self, client: &mut MqttConnection, bytes: &[u8]) {
        client.send(&CONNACK_OK)
    }

}

struct MqttConnection<'a> {
    last_msg: &'a [u8],
}

impl<'a> MqttConnection<'a> {
    fn new() -> Self {
        MqttConnection { last_msg: &[] }
    }

    fn send(&mut self, bytes: &'a [u8]) {
        self.last_msg = bytes;
    }
}

#[test]
fn test_connect() {
    let mut server = Server::new();
    let mut client = MqttConnection::new();
    server.new_client(&client);

    let connect_bytes = &[
        0x10u8, 0x2a, // fixed header
        0x00, 0x06, 'M' as u8, 'Q' as u8, 'I' as u8, 's' as u8, 'd' as u8, 'p' as u8,
        0x03, // protocol version
        0xcc, // connection flags 1100111x user, pw, !wr, w(01), w, !c, x
        0x00, 0x0a, // keepalive of 100
        0x00, 0x03, 'c' as u8, 'i' as u8, 'd' as u8, // client ID
        0x00, 0x04, 'w' as u8, 'i' as u8, 'l' as u8, 'l' as u8, // will topic
        0x00, 0x04, 'w' as u8, 'm' as u8, 's' as u8, 'g' as u8, // will msg
        0x00, 0x07, 'g' as u8, 'l' as u8, 'i' as u8, 'f' as u8, 't' as u8, 'e' as u8, 'l' as u8, // username
        0x00, 0x02, 'p' as u8, 'w' as u8, // password
        ][0..];

    server.new_message(&mut client, connect_bytes);
    assert_eq!(client.last_msg, &[32, 2, 0, 0]);
}
<|endoftext|>


<commit_before>use std::thread;
use std::path::Path;

use websocket::{Server, Message, Sender, Receiver};
use websocket::message::Type;
use websocket::header::WebSocketProtocol;

use git2::Repository;
use git2::ObjectType;

use payload;
use Commit;

use serde_xml as xml;

pub fn start() {
    let server = Server::bind("127.0.0.1:2794").unwrap();
    thread::spawn(move || {
        for connection in server {
            thread::spawn(move || {
                let request = connection.unwrap().read_request().unwrap();
                let headers = request.headers.clone();
                request.validate().unwrap();
                let mut response = request.accept();
                println!("Connected");

                if let Some(&WebSocketProtocol(ref protocols)) = headers.get() {
                    if protocols.contains(&("rust-websocket".to_string())) {
                        response.headers.set(WebSocketProtocol(vec!["superconductor".to_string()]));
                    }
                }

                let mut client = response.send().unwrap();
                let message = Message::text(payload::generate(None));
                client.send_message(&message).unwrap();

                let (mut sender, mut receiver) = client.split();
                for message in receiver.incoming_messages() {
                    let message: Message = message.unwrap_or(Message::close());
                    match message.opcode {
                        Type::Close => {
                            let message = Message::close();
                            sender.send_message(&message).unwrap();
                            println!("Client disconnected");
                            return;
                        },
                        Type::Ping => {
                            let message = Message::pong(message.payload);
                            sender.send_message(&message).unwrap();
                        },
                        _ => {
                            let payload = String::from_utf8_lossy(message.payload.as_ref());
                            println!("{:?}", payload);
                            let mut commit: Commit = xml::from_str(&payload).unwrap();
                            println!("{:?}", commit);

                            let repo = Repository::discover(".").unwrap();
                            let head = repo.head().unwrap().peel(ObjectType::Commit).unwrap();
                            let mut index = repo.index().unwrap();

                            let to_remove = index.iter().fold(vec![], |mut acc, entry| {
                                let entry_path = String::from_utf8_lossy(entry.path.as_ref());
                                match commit.include.iter().find(|i| i.as_ref() == entry_path) {
                                    None => acc.push(entry_path.into_owned()),
                                    _ => {}
                                };
                                acc
                            });

                            repo.reset_default(Some(&head), to_remove.iter()).unwrap();
                            for change in commit.clone().include {
                                let path = Path::new(&change);
                                index.add_path(path).unwrap();
                            }
                            index.write().unwrap();

                            if let Some(event) = commit.save_update.clone() {
                                let author = repo.signature().unwrap();
                                let tree_oid = index.write_tree().unwrap();
                                let tree = repo.find_tree(tree_oid).unwrap();
                                repo.commit(Some("HEAD"), &author, &author, &commit.message, &tree, &[&head.as_commit().unwrap()]);
                                let message = Message::text(payload::generate(None));
                                sender.send_message(&message).unwrap();
                            } else {
                                let message = Message::text(payload::generate(Some(commit)));
                                sender.send_message(&message).unwrap();
                            }
                        }
                    }
                }
            });
        }
    });
}

<commit_msg>Yay! It works!<commit_after>use std::thread;
use std::path::Path;

use websocket::{Server, Message, Sender, Receiver};
use websocket::message::Type;
use websocket::header::WebSocketProtocol;

use git2::Repository;
use git2::ObjectType;

use payload;
use Commit;

use serde_xml as xml;

pub fn start() {
    let server = Server::bind("127.0.0.1:2794").unwrap();
    thread::spawn(move || {
        for connection in server {
            thread::spawn(move || {
                let request = connection.unwrap().read_request().unwrap();
                let headers = request.headers.clone();
                request.validate().unwrap();
                let mut response = request.accept();
                println!("Connected");

                if let Some(&WebSocketProtocol(ref protocols)) = headers.get() {
                    if protocols.contains(&("rust-websocket".to_string())) {
                        response.headers.set(WebSocketProtocol(vec!["superconductor".to_string()]));
                    }
                }

                let mut client = response.send().unwrap();
                let message = Message::text(payload::generate(None));
                client.send_message(&message).unwrap();

                let (mut sender, mut receiver) = client.split();
                for message in receiver.incoming_messages() {
                    let message: Message = message.unwrap_or(Message::close());
                    match message.opcode {
                        Type::Close => {
                            let message = Message::close();
                            sender.send_message(&message).unwrap();
                            println!("Client disconnected");
                            return;
                        },
                        Type::Ping => {
                            let message = Message::pong(message.payload);
                            sender.send_message(&message).unwrap();
                        },
                        _ => {
                            let payload = String::from_utf8_lossy(message.payload.as_ref());
                            println!("{:?}", payload);
                            let mut commit: Commit = xml::from_str(&payload).unwrap();
                            println!("{:?}", commit);

                            let repo = Repository::discover(".").unwrap();
                            let head = repo.head().unwrap().peel(ObjectType::Commit).unwrap();
                            let mut index = repo.index().unwrap();

                            let to_remove = index.iter().fold(vec![], |mut acc, entry| {
                                let entry_path = String::from_utf8_lossy(entry.path.as_ref());
                                match commit.include.iter().find(|i| i.as_ref() == entry_path) {
                                    None => acc.push(entry_path.into_owned()),
                                    _ => {}
                                };
                                acc
                            });

                            repo.reset_default(Some(&head), to_remove.iter()).unwrap();
                            for change in commit.clone().include {
                                let path = Path::new(&change);
                                index.add_path(path).unwrap();
                            }
                            index.write().unwrap();

                            if let Some(event) = commit.save_update.clone() {
                                let author = repo.signature().unwrap();
                                index.read(false);
                                let tree_oid = index.write_tree().unwrap();
                                let tree = repo.find_tree(tree_oid).unwrap();
                                repo.commit(Some("HEAD"), &author, &author, &commit.message, &tree, &[&head.as_commit().unwrap()]);
                                let message = Message::text(payload::generate(None));
                                sender.send_message(&message).unwrap();
                            } else {
                                let message = Message::text(payload::generate(Some(commit)));
                                sender.send_message(&message).unwrap();
                            }
                        }
                    }
                }
            });
        }
    });
}

<|endoftext|>