<commit_before>use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;

use super::ast;

#[derive(PartialEq, Debug)]
pub struct SymbolTable {
    parent: Option<Rc<RefCell<SymbolTable>>>,
    id_counter: u32,
    vars: HashMap<String, Rc<ast::Variable>>,
}

impl Default for SymbolTable {
    fn default() -> SymbolTable {
        SymbolTable::new(None, 1)
    }
}

impl SymbolTable {
    pub fn new(parent: Option<Rc<RefCell<SymbolTable>>>, id_counter: u32) -> SymbolTable {
        SymbolTable {
            parent: parent,
            id_counter: id_counter,
            vars: HashMap::new(),
        }
    }

    pub fn insert(&mut self, var: &mut Rc<ast::Variable>) -> Rc<ast::Variable> {
        let new = Rc::new(ast::Variable {
            id: self.id_counter,
            type_: var.type_,
            name: var.name.clone(),
        });
        self.id_counter += 1;
        self.vars.insert(var.name.clone(), new.clone());
        new
    }

    pub fn lookup(&self, var: &String) -> Option<Rc<ast::Variable>> {
        if let Some(v) = self.vars.get(var) {
            return Some(v.clone());
        }
        match self.parent {
            Some(ref p) => p.borrow().lookup(var),
            None => None,
        }
    }
}

pub fn symbolize(fun: &mut ast::Node<ast::Function>) {
    // arguments
    for arg in fun.node.args.iter_mut() {
        *arg = fun.node.symbols.borrow_mut().insert(arg);
    }

    symbolize_statement(fun.node.symbols.clone(), &mut fun.node.body);
}

fn symbolize_statement(symbols: Rc<RefCell<SymbolTable>>, stmt: &mut ast::Node<ast::Statement>) {
    match stmt.node {
        ast::Statement::Expression { ref mut expr } => symbolize_expression(symbols, expr),
        ast::Statement::Declaration { ref mut var } => *var = symbols.borrow_mut().insert(var),
        ast::Statement::Assignment { ref mut var, ref mut expr } => {
            *var = symbols.borrow().lookup(&var.name).unwrap();
            symbolize_expression(symbols, expr);
        }
        ast::Statement::If { ref mut cond, ref mut on_true, ref mut on_false } => {
            symbolize_expression(symbols.clone(), cond);
            symbolize_statement(symbols.clone(), on_true);
            if let Some(ref mut stmt) = *on_false {
                symbolize_statement(symbols.clone(), stmt);
            }
        }
        ast::Statement::While { ref mut cond, ref mut body } => {
            symbolize_expression(symbols.clone(), cond);
            symbolize_statement(symbols.clone(), body);
        }
        ast::Statement::Return { expr: Some(ref mut e) } => symbolize_expression(symbols, e),
        ast::Statement::Compound { ref mut stmts, symbols: ref mut next } => {
            *next = Rc::new(RefCell::new(SymbolTable::new(Some(symbols.clone()),
                                                          symbols.borrow().id_counter)));
            for stmt in stmts.iter_mut() {
                symbolize_statement(next.clone(), stmt);
            }
        }
        _ => (),
    }
}

fn symbolize_expression(symbols: Rc<RefCell<SymbolTable>>, expr: &mut ast::Node<ast::Expression>) {
    match expr.node {
        ast::Expression::Variable { ref mut var } => {
            *var = symbols.borrow().lookup(&var.name).unwrap()
        }
        ast::Expression::Call { ref mut args, .. } => {
            for arg in args.iter_mut() {
                symbolize_expression(symbols.clone(), arg);
            }
        }
        ast::Expression::Unary { ref mut expr, .. } => symbolize_expression(symbols.clone(), expr),
        ast::Expression::Binary { ref mut left, ref mut right, .. } => {
            symbolize_expression(symbols.clone(), left);
            symbolize_expression(symbols.clone(), right);
        }
        ast::Expression::Parenthesis { ref mut expr } => {
            symbolize_expression(symbols.clone(), expr)
        }
        _ => (),
    }
}
<commit_msg>Front: Add error handling to symbolizer<commit_after>use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;

use super::ast;

#[derive(PartialEq, Debug)]
pub struct SymbolTable {
    parent: Option<Rc<RefCell<SymbolTable>>>,
    id_counter: u32,
    vars: HashMap<String, Rc<ast::Variable>>,
}

impl Default for SymbolTable {
    fn default() -> SymbolTable {
        SymbolTable::new(None, 1)
    }
}

impl SymbolTable {
    pub fn new(parent: Option<Rc<RefCell<SymbolTable>>>, id_counter: u32) -> SymbolTable {
        SymbolTable {
            parent: parent,
            id_counter: id_counter,
            vars: HashMap::new(),
        }
    }

    pub fn insert(&mut self, var: &mut Rc<ast::Variable>) -> Result<Rc<ast::Variable>, String> {
        // check for duplicate
        if self.vars.contains_key(&var.name) {
            return Err(format!("`{}` already declared", var.name));
        }

        // insert new one
        let new = Rc::new(ast::Variable {
            id: self.id_counter,
            type_: var.type_,
            name: var.name.clone(),
        });
        self.id_counter += 1;
        self.vars.insert(var.name.clone(), new.clone());

        // return reference to final variable
        Ok(new)
    }

    pub fn lookup(&self, var: &String) -> Result<Rc<ast::Variable>, String> {
        if let Some(v) = self.vars.get(var) {
            return Ok(v.clone());
        }

        // check previous scope
        match self.parent {
            Some(ref p) => p.borrow().lookup(var),
            None => Err(format!("`{}` unknown variable", var)),
        }
    }
}

pub fn symbolize(fun: &mut ast::Node<ast::Function>) -> Result<(), String> {
    // arguments
    for arg in fun.node.args.iter_mut() {
        *arg = try!(fun.node.symbols.borrow_mut().insert(arg));
    }

    symbolize_statement(fun.node.symbols.clone(), &mut fun.node.body)
}

fn symbolize_statement(symbols: Rc<RefCell<SymbolTable>>, stmt: &mut ast::Node<ast::Statement>) -> Result<(), String> {
    match stmt.node {
        ast::Statement::Expression { ref mut expr } => symbolize_expression(symbols, expr),
        ast::Statement::Declaration { ref mut var } => {
            *var = try!(symbols.borrow_mut().insert(var));
            Ok(())
        }
        ast::Statement::Assignment { ref mut var, ref mut expr } => {
            *var = try!(symbols.borrow().lookup(&var.name));
            symbolize_expression(symbols, expr)
        }
        ast::Statement::If { ref mut cond, ref mut on_true, ref mut on_false } => {
            try!(symbolize_expression(symbols.clone(), cond));
            try!(symbolize_statement(symbols.clone(), on_true));
            if let Some(ref mut stmt) = *on_false {
                symbolize_statement(symbols.clone(), stmt)
            } else {
                Ok(())
            }
        }
        ast::Statement::While { ref mut cond, ref mut body } => {
            try!(symbolize_expression(symbols.clone(), cond));
            symbolize_statement(symbols.clone(), body)
        }
        ast::Statement::Return { expr: Some(ref mut e) } => symbolize_expression(symbols, e),
        ast::Statement::Compound { ref mut stmts, symbols: ref mut next } => {
            *next = Rc::new(RefCell::new(SymbolTable::new(Some(symbols.clone()),
                                                          symbols.borrow().id_counter)));
            for stmt in stmts.iter_mut() {
                try!(symbolize_statement(next.clone(), stmt));
            }
            Ok(())
        }
        _ => Ok(()),
    }
}

fn symbolize_expression(symbols: Rc<RefCell<SymbolTable>>, expr: &mut ast::Node<ast::Expression>) -> Result<(), String> {
    match expr.node {
        ast::Expression::Variable { ref mut var } => {
            *var = try!(symbols.borrow().lookup(&var.name));
            Ok(())
        }
        ast::Expression::Call { ref mut args, .. } => {
            for arg in args.iter_mut() {
                try!(symbolize_expression(symbols.clone(), arg));
            }
            Ok(())
        }
        ast::Expression::Unary { ref mut expr, .. } => symbolize_expression(symbols.clone(), expr),
        ast::Expression::Binary { ref mut left, ref mut right, .. } => {
            try!(symbolize_expression(symbols.clone(), left));
            symbolize_expression(symbols.clone(), right)
        }
        ast::Expression::Parenthesis { ref mut expr } => {
            symbolize_expression(symbols.clone(), expr)
        }
        _ => Ok(()),
    }
}
<|endoftext|>


<commit_before>use std::fmt::{self, Formatter, Debug};

use backend::Backend;
use super::js_var::{JsPtrEnum, JsVar};

#[derive(Clone)]
pub struct NativeFn(fn(Box<Backend>, Vec<(JsVar, Option<JsPtrEnum>)>) -> (JsVar, Option<JsPtrEnum>));

impl NativeFn {
    pub fn new(func: fn(Box<Backend>, Vec<(JsVar, Option<JsPtrEnum>)>) -> (JsVar, Option<JsPtrEnum>)) -> NativeFn
{
      NativeFn(func)
    }
}

impl Debug for NativeFn {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "[native_code]")
    }
}
<commit_msg>add ability to call native function<commit_after>use std::fmt::{self, Formatter, Debug};

use backend::Backend;
use super::js_var::{JsPtrEnum, JsVar};

#[derive(Clone)]
pub struct NativeFn(fn(Box<Backend>, Vec<(JsVar, Option<JsPtrEnum>)>) -> (JsVar, Option<JsPtrEnum>));

impl NativeFn {
    pub fn new(func: fn(Box<Backend>, Vec<(JsVar, Option<JsPtrEnum>)>) -> (JsVar, Option<JsPtrEnum>)) -> NativeFn
{
      NativeFn(func)
    }

    pub fn call(&self, backend: Box<Backend>, args: Vec<(JsVar, Option<JsPtrEnum>)>) -> (JsVar,
Option<JsPtrEnum>) {
        self.0(backend, args)
    }
}

impl Debug for NativeFn {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "[native_code]")
    }
}
<|endoftext|>


<commit_before>//! Contains concret implementations of OrbTk's default widgets. It contains also layout widgets.

use std::any::{Any, TypeId};
use std::cell::Cell;
use std::rc::Rc;

use dces::{Component, ComponentBox, Entity, EntityComponentManager, NotFound, SharedComponentBox};

use state::State;
use layout_object::{DefaultLayoutObject, LayoutObject};
use render_object::RenderObject;
use theme::Selector;
use event::EventHandler;
use tree::Tree;

pub use self::button::*;
pub use self::center::*;
pub use self::column::*;
pub use self::container::*;
pub use self::row::*;
pub use self::scroll_viewer::*;
pub use self::stack::*;
pub use self::text_block::*;
pub use self::text_box::*;

mod button;
mod center;
mod column;
mod container;
mod macros;
mod row;
mod scroll_viewer;
mod stack;
mod text_block;
mod text_box;

#[derive(Copy, Clone)]
pub struct Drawable;

// pub struct Key(pub String);

pub struct Padding {
    pub left: u32,
    pub top: u32,
    pub right: u32,
    pub bottom: u32,
}

pub enum Template {
    Empty,
    Single(Rc<Widget>),
    Mutli(Vec<Rc<Widget>>),
}

pub trait Widget: Any {
    fn template(&self) -> Template {
        Template::Empty
    }

    fn all_properties(&self) -> Vec<PropertyResult> {
        let mut properties = self.properties();
        if let Some(_) = self.render_object() {
            properties.push(Property::new(Drawable).build());
        }

        properties
    }

    fn properties(&self) -> Vec<PropertyResult> {
        vec![]
    }

    fn render_object(&self) -> Option<Box<RenderObject>> {
        None
    }

    fn layout_object(&self) -> Box<LayoutObject> {
        Box::new(DefaultLayoutObject)
    }

    fn event_handlers(&self) -> Vec<Rc<EventHandler>> {
        vec![]
    }

    fn state(&self) -> Option<Rc<State>> {
        None
    }
}

pub struct WidgetContainer<'a> {
    tree: &'a Tree,
    ecm: &'a mut EntityComponentManager,
    current_node: Entity,
}

impl<'a> WidgetContainer<'a> {
    pub fn new(root: Entity, ecm: &'a mut EntityComponentManager, tree: &'a Tree) -> Self {
        WidgetContainer {
            tree,
            ecm,
            current_node: root,
        }
    }

    pub fn borrow_property<P: Component>(&self) -> Result<&P, NotFound> {
        self.ecm.borrow_component::<P>(self.current_node)
    }

    pub fn borrow_mut_property<P: Component>(&mut self) -> Result<&mut P, NotFound> {
        self.ecm.borrow_mut_component::<P>(self.current_node)
    }

    pub fn borrow_parent_property<P: Component>(&self) -> Result<&P, NotFound> {
        self.ecm.borrow_component::<P>(self.tree.parent[&self.current_node])
    }

    pub fn borrow_mut_parent_property<P: Component>(&mut self) -> Result<&mut P, NotFound> {
        self.ecm.borrow_mut_component::<P>(self.tree.parent[&self.current_node])
    }

    pub fn borrow_child_property<P: Component>(&self, index: usize) -> Result<&P, NotFound> {
        if index >= self.tree.children[&self.current_node].len() {
            return Result::Err(NotFound::Component(TypeId::of::<P>()))
        }

        self.ecm.borrow_component::<P>(self.tree.children[&self.current_node][index])
    }

    pub fn borrow_mut_child_property<P: Component>(&mut self, index: usize) -> Result<&mut P, NotFound> {
         if index >= self.tree.children[&self.current_node].len() {
            return Result::Err(NotFound::Component(TypeId::of::<P>()))
        }

        self.ecm.borrow_mut_component::<P>(self.tree.children[&self.current_node][index])
    }
}

pub fn add_selector_to_widget(pseudo_class: &str, widget: &mut WidgetContainer) {
    if let Ok(selector) = widget.borrow_mut_property::<Selector>() {
        selector.pseudo_classes.insert(String::from(pseudo_class));
    }
}

pub fn remove_selector_from_widget(pseudo_class: &str, widget: &mut WidgetContainer) {
    if let Ok(selector) = widget.borrow_mut_property::<Selector>() {
        selector.pseudo_classes.remove (pseudo_class);
    }
}

pub enum PropertyResult {
    Property(ComponentBox, Rc<Cell<Option<Entity>>>),
    Source(SharedComponentBox),
    PropertyNotFound,
}

pub struct Property<C>
where
    C: Component + Clone,
{
    pub source: Rc<Cell<Option<Entity>>>,
    property: Option<C>,
}

impl<C> Property<C>
where
    C: Component + Clone,
{
    pub fn new(property: C) -> Self {
        Property {
            source: Rc::new(Cell::new(None)),
            property: Some(property),
        }
    }

    pub fn build(&self) -> PropertyResult {
        if let Some(source) = self.source.get() {
            return PropertyResult::Source(SharedComponentBox::new::<C>(source));
        }

        if let Some(property) = &self.property {
            return PropertyResult::Property(ComponentBox::new(property.clone()), self.source.clone())
        }

        PropertyResult::PropertyNotFound
    }
}

impl<C> Clone for Property<C>
where
    C: Component + Clone,
{
    fn clone(&self) -> Self {
        Property {
            source: self.source.clone(),
            property: None,
        }
    }
}
<commit_msg>Update signator of shared combonent box.<commit_after>//! Contains concret implementations of OrbTk's default widgets. It contains also layout widgets.

use std::any::{Any, TypeId};
use std::cell::Cell;
use std::rc::Rc;

use dces::{Component, ComponentBox, Entity, EntityComponentManager, NotFound, SharedComponentBox};

use state::State;
use layout_object::{DefaultLayoutObject, LayoutObject};
use render_object::RenderObject;
use theme::Selector;
use event::EventHandler;
use tree::Tree;

pub use self::button::*;
pub use self::center::*;
pub use self::column::*;
pub use self::container::*;
pub use self::row::*;
pub use self::scroll_viewer::*;
pub use self::stack::*;
pub use self::text_block::*;
pub use self::text_box::*;

mod button;
mod center;
mod column;
mod container;
mod macros;
mod row;
mod scroll_viewer;
mod stack;
mod text_block;
mod text_box;

#[derive(Copy, Clone)]
pub struct Drawable;

// pub struct Key(pub String);

pub struct Padding {
    pub left: u32,
    pub top: u32,
    pub right: u32,
    pub bottom: u32,
}

pub enum Template {
    Empty,
    Single(Rc<Widget>),
    Mutli(Vec<Rc<Widget>>),
}

pub trait Widget: Any {
    fn template(&self) -> Template {
        Template::Empty
    }

    fn all_properties(&self) -> Vec<PropertyResult> {
        let mut properties = self.properties();
        if let Some(_) = self.render_object() {
            properties.push(Property::new(Drawable).build());
        }

        properties
    }

    fn properties(&self) -> Vec<PropertyResult> {
        vec![]
    }

    fn render_object(&self) -> Option<Box<RenderObject>> {
        None
    }

    fn layout_object(&self) -> Box<LayoutObject> {
        Box::new(DefaultLayoutObject)
    }

    fn event_handlers(&self) -> Vec<Rc<EventHandler>> {
        vec![]
    }

    fn state(&self) -> Option<Rc<State>> {
        None
    }
}

pub struct WidgetContainer<'a> {
    tree: &'a Tree,
    ecm: &'a mut EntityComponentManager,
    current_node: Entity,
}

impl<'a> WidgetContainer<'a> {
    pub fn new(root: Entity, ecm: &'a mut EntityComponentManager, tree: &'a Tree) -> Self {
        WidgetContainer {
            tree,
            ecm,
            current_node: root,
        }
    }

    pub fn borrow_property<P: Component>(&self) -> Result<&P, NotFound> {
        self.ecm.borrow_component::<P>(self.current_node)
    }

    pub fn borrow_mut_property<P: Component>(&mut self) -> Result<&mut P, NotFound> {
        self.ecm.borrow_mut_component::<P>(self.current_node)
    }

    pub fn borrow_parent_property<P: Component>(&self) -> Result<&P, NotFound> {
        self.ecm.borrow_component::<P>(self.tree.parent[&self.current_node])
    }

    pub fn borrow_mut_parent_property<P: Component>(&mut self) -> Result<&mut P, NotFound> {
        self.ecm.borrow_mut_component::<P>(self.tree.parent[&self.current_node])
    }

    pub fn borrow_child_property<P: Component>(&self, index: usize) -> Result<&P, NotFound> {
        if index >= self.tree.children[&self.current_node].len() {
            return Result::Err(NotFound::Component(TypeId::of::<P>()))
        }

        self.ecm.borrow_component::<P>(self.tree.children[&self.current_node][index])
    }

    pub fn borrow_mut_child_property<P: Component>(&mut self, index: usize) -> Result<&mut P, NotFound> {
         if index >= self.tree.children[&self.current_node].len() {
            return Result::Err(NotFound::Component(TypeId::of::<P>()))
        }

        self.ecm.borrow_mut_component::<P>(self.tree.children[&self.current_node][index])
    }
}

pub fn add_selector_to_widget(pseudo_class: &str, widget: &mut WidgetContainer) {
    if let Ok(selector) = widget.borrow_mut_property::<Selector>() {
        selector.pseudo_classes.insert(String::from(pseudo_class));
    }
}

pub fn remove_selector_from_widget(pseudo_class: &str, widget: &mut WidgetContainer) {
    if let Ok(selector) = widget.borrow_mut_property::<Selector>() {
        selector.pseudo_classes.remove (pseudo_class);
    }
}

pub enum PropertyResult {
    Property(ComponentBox, Rc<Cell<Option<Entity>>>),
    Source(SharedComponentBox),
    PropertyNotFound,
}

pub struct Property<C>
where
    C: Component + Clone,
{
    pub source: Rc<Cell<Option<Entity>>>,
    property: Option<C>,
}

impl<C> Property<C>
where
    C: Component + Clone,
{
    pub fn new(property: C) -> Self {
        Property {
            source: Rc::new(Cell::new(None)),
            property: Some(property),
        }
    }

    pub fn build(&self) -> PropertyResult {
        if let Some(source) = self.source.get() {
            return PropertyResult::Source(SharedComponentBox::new::<C>(source));
        }

        if let Some(property) = &self.property {
            return PropertyResult::Property(ComponentBox::new(property.clone()), self.source.clone())
        }

        PropertyResult::PropertyNotFound
    }
}

impl<C> Clone for Property<C>
where
    C: Component + Clone,
{
    fn clone(&self) -> Self {
        Property {
            source: self.source.clone(),
            property: None,
        }
    }
}

pub struct PbProperty
{
    pub source: Rc<Cell<Option<Entity>>>,
    property: Option<Box<Component>>,
}

impl PbProperty
{
    pub fn new(property: Box<Component>) -> Self {
        PbProperty {
            source: Rc::new(Cell::new(None)),
            property: Some(property),
        }
    }

    pub fn build(&self) -> PropertyResult {
        if let Some(source) = self.source.get() {
            return PropertyResult::Source(SharedComponentBox::new::<C>(source));
        }

        if let Some(property) = &self.property {
            return PropertyResult::Property(ComponentBox::new(property.clone()), self.source.clone())
        }

        PropertyResult::PropertyNotFound
    }
}

impl Clone for PbProperty
{
    fn clone(&self) -> Self {
        PbProperty {
            source: self.source.clone(),
            property: None,
        }
    }
}

pub struct PbTemplate {
    pub properties: Vec<PropertyResult>,
    pub event_handlers: Vec<Box<EventHandler>>,
    pub layout_object: Box<LayoutObject>,
    pub render_object: Option<Box<RenderObject>>,
    pub state: Option<Box<State>>,
    pub children: Vec<PbTemplate>,
}

impl Default for PbTemplate {
    fn default() -> Self {
        PbTemplate {
            properties: vec![],
            event_handlers: vec![],
            layout_object: Box::new(DefaultLayoutObject),
            render_object: None,
            state: None,
            children: vec![],
        }
    }
}

pub trait PbWidget {
    fn template(&self) -> PbTemplate;
}

pub struct PbText {

}

impl PbWidget for PbText {
    fn template(&self) -> PbTemplate {
        PbTemplate {
            ..Default::default()
        }
    }
}

pub struct PbContainer {

}

impl PbWidget for PbContainer {
    fn template(&self) -> PbTemplate {
        PbTemplate {
            ..Default::default()
        }
    }
}

pub struct PbButton {

}

impl PbWidget for PbButton {
    fn template(&self) -> PbTemplate {
        PbTemplate {
            ..Default::default()
        }
    }
}<|endoftext|>


<commit_before>extern crate csv;
extern crate rustc_serialize;

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};

//////////////////////////////DISTANCES////////////////////////////////
fn manhattan_dist(x: &Vec<f32>, y: &Vec<f32>) -> f32 {
    if x.len() != y.len() {
        panic!("Should compare vectors of same size");
    }
    let mut distance = 0.0;

    for i in 0..x.len() {
        if x[i] > 0.0 && y[i] > 0.0 {
            distance += (x[i] - y[i]).abs();
        }
    }

    distance
}
///////////////////////////////////////////////////////////////////////

struct IndexedDB(HashMap<String, HashMap<String, f32>>, HashMap<String, HashMap<String, f32>>);

fn load_db(path: &str) -> IndexedDB {
    let mut rdr = csv::Reader::from_file(path).unwrap().has_headers(false);
    let mut ratings: HashMap<String, HashMap<String, f32>> = HashMap::new();
    let mut features: HashMap<String, HashMap<String, f32>> = HashMap::new();

    for record in rdr.decode() {
        let (user_id, feat_id, rating): (String, String, f32) = record.unwrap();
        let (user_id2, feat_id2, rating2) = (user_id.clone(), feat_id.clone(), rating);

        match ratings.entry(user_id) {
            Vacant(entry) => {
                let mut user_ratings = HashMap::new();
                user_ratings.insert(feat_id, rating);
                entry.insert(user_ratings);
            }
            Occupied(entry) => {
                entry.into_mut().insert(feat_id, rating);
            }
        }

        match features.entry(feat_id2) {
            Vacant(entry) => {
                let mut movie_ratings = HashMap::new();
                movie_ratings.insert(user_id2, rating2);
                entry.insert(movie_ratings);
            }
            Occupied(entry) => {
                entry.into_mut().insert(user_id2, rating2);
            }
        }
    }

    IndexedDB(ratings, features)
}

fn median(vec: &Vec<f32>) -> f32 {
    let mut vec_cpy = vec.clone();
    vec_cpy.sort_by(|a, b| a.partial_cmp(b).unwrap());
    let length = vec_cpy.len();
    let mid = length / 2;
    let mut ret = vec_cpy[mid];
    if length % 2 == 0 {
        ret += vec_cpy[mid - 1];
        ret /= 2.0;
    }
    println!("{} /2 -> {}", length, length / 2);
    ret
}

fn abs_standard_deviation(vec: &Vec<f32>) -> (f32, f32) {
    let median = median(vec);
    let mut asd = 0.0;

    for x in vec.iter() {
        asd += (x - median).abs();
    }

    (asd / vec.len() as f32, median)
}

fn mod_standard_score(val: f32, vec: &Vec<f32>) -> f32 {
    let (asd, median) = abs_standard_deviation(vec);

    (val - median) / asd
}

fn user_rating_vector(db: &IndexedDB, id: &str) -> Vec<f32> {
    let mut ret_vec = Vec::new();
    if let Some(ref ratings) = db.0.get(&String::from(id)) {
        for (_, &rating) in ratings.iter() {
            ret_vec.push(rating);
        }
    }

    ret_vec
}

fn nearest_neighbors(db: &IndexedDB,
                     id: &str,
                     func: fn(&Vec<f32>, &Vec<f32>) -> f32)
                     -> Vec<(f32, String)> {
    let obj_vec = user_rating_vector(db, id);
    let mut dist_vec: Vec<(f32, String)> = Vec::new();

    println!("OBJ: {:?}", obj_vec);

    for (rec_id, _) in db.0.iter() {
        if id != rec_id.as_str() {
            let rec_str = rec_id.clone();
            let rec_vec = user_rating_vector(db, rec_id);
            println!("{:?}", rec_vec);
            println!("{} -> {}", rec_str, func(&obj_vec, &rec_vec));
            dist_vec.push((func(&obj_vec, &rec_vec), rec_str));
        }
    }

    dist_vec.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());
    dist_vec
}

fn main() {
    println!("Loading database, please wait...");
    let db = load_db("./data/music.csv");
    println!("Database ready!\n---------------------------------------------");

    println!("{:?}",
             nearest_neighbors(&db, "Dr Dog/Fate", manhattan_dist));

    // println!("Med: {:?}", abs_standard_deviation(&mut vec![43., 45., 55., 69., 70., 75., 105., 115.]));
}
<commit_msg>Corrected user_rating_vector -> now everything has the same results<commit_after>extern crate csv;
extern crate rustc_serialize;

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};

//////////////////////////////DISTANCES////////////////////////////////
fn manhattan_dist(x: &Vec<f32>, y: &Vec<f32>) -> f32 {
    if x.len() != y.len() {
        panic!("Should compare vectors of same size");
    }
    let mut distance = 0.0;

    for i in 0..x.len() {
        if x[i] > 0.0 && y[i] > 0.0 {
            distance += (x[i] - y[i]).abs();
        }
    }

    distance
}
///////////////////////////////////////////////////////////////////////

struct IndexedDB(HashMap<String, HashMap<String, f32>>, HashMap<String, HashMap<String, f32>>);

fn load_db(path: &str) -> IndexedDB {
    let mut rdr = csv::Reader::from_file(path).unwrap().has_headers(false);
    let mut ratings: HashMap<String, HashMap<String, f32>> = HashMap::new();
    let mut features: HashMap<String, HashMap<String, f32>> = HashMap::new();

    for record in rdr.decode() {
        let (user_id, feat_id, rating): (String, String, f32) = record.unwrap();
        let (user_id2, feat_id2, rating2) = (user_id.clone(), feat_id.clone(), rating);

        match ratings.entry(user_id) {
            Vacant(entry) => {
                let mut user_ratings = HashMap::new();
                user_ratings.insert(feat_id, rating);
                entry.insert(user_ratings);
            }
            Occupied(entry) => {
                entry.into_mut().insert(feat_id, rating);
            }
        }

        match features.entry(feat_id2) {
            Vacant(entry) => {
                let mut movie_ratings = HashMap::new();
                movie_ratings.insert(user_id2, rating2);
                entry.insert(movie_ratings);
            }
            Occupied(entry) => {
                entry.into_mut().insert(user_id2, rating2);
            }
        }
    }

    IndexedDB(ratings, features)
}

fn median(vec: &Vec<f32>) -> f32 {
    let mut vec_cpy = vec.clone();
    vec_cpy.sort_by(|a, b| a.partial_cmp(b).unwrap());
    let length = vec_cpy.len();
    let mid = length / 2;
    let mut ret = vec_cpy[mid];
    if length % 2 == 0 {
        ret += vec_cpy[mid - 1];
        ret /= 2.0;
    }
    println!("{} /2 -> {}", length, length / 2);
    ret
}

fn abs_standard_deviation(vec: &Vec<f32>) -> (f32, f32) {
    let median = median(vec);
    let mut asd = 0.0;

    for x in vec.iter() {
        asd += (x - median).abs();
    }

    (asd / vec.len() as f32, median)
}

fn mod_standard_score(val: f32, vec: &Vec<f32>) -> f32 {
    let (asd, median) = abs_standard_deviation(vec);

    (val - median) / asd
}

// fn user_rating_vector(db: &IndexedDB, id: &str) -> Vec<f32> {
//     let mut ret_vec = Vec::new();
//     if let Some(ref ratings) = db.0.get(&String::from(id)) {
//         for (_, &rating) in ratings.iter() {
//             ret_vec.push(rating);
//         }
//     }

//     ret_vec
// }

fn users_rating_vectors(db: &IndexedDB, id1: &str, id2: &str) -> (Vec<f32>, Vec<f32>) {
    let mut usr1_vec: Vec<f32> = Vec::new();
    let mut usr2_vec: Vec<f32> = Vec::new();

    if let Some(ref ratings1) = db.0.get(&String::from(id1)) {
        for (feat1_id, &rating1) in ratings1.iter() {
            usr1_vec.push(rating1);
            if let Some(ref ratings2) = db.0.get(&String::from(id2)) {
                if let Some(rating2) = ratings2.get(feat1_id) {
                    usr2_vec.push(*rating2);
                } else {
                    usr2_vec.push(0.0);
                }
            } else {
                panic!("user2 is not found!");
            }
        }
    } else {
        panic!("user1 not found!");
    }

    if let Some(ref ratings2) = db.0.get(&String::from(id2)) {
        for (feat2_id, &rating2) in ratings2.iter() {
            if let Some(ref ratings1) = db.0.get(&String::from(id1)) {
                if let Some(_) = ratings1.get(feat2_id) {
                } else {
                    usr2_vec.push(rating2);
                    usr1_vec.push(0.0);
                }
            } else {
                panic!("user2 is not found!");
            }
        }
    } else {
        panic!("user1 not found!");
    }

    (usr1_vec, usr2_vec)
}

fn nearest_neighbors(db: &IndexedDB,
                     id: &str,
                     func: fn(&Vec<f32>, &Vec<f32>) -> f32)
                     -> Vec<(f32, String)> {
    // let obj_vec = user_rating_vector(db, id);
    let mut dist_vec: Vec<(f32, String)> = Vec::new();

    // println!("OBJ: {:?}", obj_vec);

    for (rec_id, _) in db.0.iter() {
        if id != rec_id.as_str() {
            let rec_str = rec_id.clone();
            let (obj_vec, rec_vec) = users_rating_vectors(db, id, rec_id);
            println!("{:?}", rec_vec);
            println!("{} -> {}", rec_str, func(&obj_vec, &rec_vec));
            dist_vec.push((func(&obj_vec, &rec_vec), rec_str));
        }
    }

    dist_vec.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());
    dist_vec
}

fn main() {
    println!("Loading database, please wait...");
    let db = load_db("./data/music.csv");
    println!("Database ready!\n---------------------------------------------");

    println!("{:?}", nearest_neighbors(&db, "Dr Dog/Fate", manhattan_dist));

    // println!("Med: {:?}", abs_standard_deviation(&mut vec![43., 45., 55., 69., 70., 75., 105., 115.]));
}
<|endoftext|>


<commit_before>use derivative::Derivative;
use std::cmp::Reverse;
use std::collections::hash_map::Entry;
use std::collections::{BinaryHeap, HashMap, HashSet};

use crate::entity::storage::AsStorage;
use crate::entity::traverse::Adjacency;
use crate::entity::view::{Bind, Unbind};
use crate::entity::EntityError;
use crate::geometry::Metric;

#[derivative(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
#[derive(Derivative)]
struct KeyedMetric<K, Q>(
    #[derivative(Ord = "ignore", PartialEq = "ignore", PartialOrd = "ignore")] K,
    Q,
)
where
    Q: Eq + Ord;

pub fn metrics_with<'a, M, T, Q, F>(
    from: T,
    to: Option<T::Key>,
    f: F,
) -> Result<HashMap<T::Key, (Option<T::Key>, Q)>, EntityError>
where
    M: 'a + AsStorage<T::Entity>,
    T: Adjacency + Bind<&'a M> + Copy + Unbind<&'a M>,
    Q: Copy + Metric,
    F: Fn(T, T) -> Q,
{
    let (storage, from) = from.unbind();
    let capacity = if to.is_some() {
        0
    }
    else {
        storage.as_storage().len()
    };
    let mut buffer = BinaryHeap::new();
    let mut breadcrumbs = HashSet::with_capacity(capacity);
    let mut metrics = HashMap::with_capacity(capacity);

    metrics.insert(from, (None, Q::zero()));
    buffer.push(KeyedMetric(from, Reverse(Q::zero())));
    while let Some(KeyedMetric(key, Reverse(metric))) = buffer.pop() {
        if Some(key) == to {
            break;
        }
        let entity = T::bind(storage, key).ok_or_else(|| EntityError::EntityNotFound)?;
        if breadcrumbs.insert(entity.key()) {
            for adjacent in entity
                .adjacency()
                .into_iter()
                .map(|key| T::bind(storage, key))
            {
                let adjacent = adjacent.ok_or_else(|| EntityError::EntityNotFound)?;
                let summand = f(entity, adjacent);
                if summand < Q::zero() {
                    return Err(EntityError::Geometry);
                }
                let metric = metric + summand;
                match metrics.entry(adjacent.key()) {
                    Entry::Occupied(entry) => {
                        if metric < entry.get().1 {
                            entry.into_mut().1 = metric;
                        }
                    }
                    Entry::Vacant(entry) => {
                        entry.insert((Some(entity.key()), metric));
                    }
                }
                buffer.push(KeyedMetric(adjacent.key(), Reverse(metric)));
            }
        }
    }
    Ok(metrics)
}

#[cfg(test)]
mod tests {
    use decorum::R64;
    use nalgebra::Point2;
    use theon::space::InnerSpace;

    use crate::entity::{dijkstra, EntityError};
    use crate::graph::MeshGraph;
    use crate::prelude::*;
    use crate::primitive::{Tetragon, Trigon};

    #[test]
    fn decreasing_summand() {
        let graph = MeshGraph::<Point2<f64>>::from_raw_buffers(
            vec![Tetragon::new(0usize, 1, 2, 3)],
            vec![(-1.0, -1.0), (1.0, -1.0), (1.0, 1.0), (-1.0, 1.0)],
        )
        .unwrap();
        let vertex = graph.vertices().nth(0).unwrap();
        assert_eq!(
            Err(EntityError::Geometry),
            dijkstra::metrics_with(vertex, None, |_, _| -1isize)
        )
    }

    #[test]
    fn logical_metrics() {
        let graph = MeshGraph::<()>::from_raw_buffers(vec![Trigon::new(0usize, 1, 2)], vec![(); 3])
            .unwrap();
        let vertex = graph.vertices().nth(0).unwrap();
        let metrics = dijkstra::metrics_with(vertex, None, |_, _| 1usize).unwrap();
        let a = vertex.key();
        let b = vertex.outgoing_arc().destination_vertex().key();
        let c = vertex.outgoing_arc().next_arc().destination_vertex().key();
        let aq = *metrics.get(&a).unwrap();
        let bq = *metrics.get(&b).unwrap();
        let cq = *metrics.get(&c).unwrap();

        assert_eq!(aq, (None, 0));
        assert_eq!(bq, (Some(a), 1));
        assert_eq!(cq, (Some(a), 1));
    }

    #[allow(clippy::float_cmp)]
    #[test]
    fn euclidean_distance_metrics() {
        let graph = MeshGraph::<Point2<f64>>::from_raw_buffers(
            vec![Tetragon::new(0usize, 1, 2, 3)],
            vec![(-1.0, -1.0), (1.0, -1.0), (1.0, 1.0), (-1.0, 1.0)],
        )
        .unwrap();
        let vertex = graph.vertices().nth(0).unwrap();
        let metrics = dijkstra::metrics_with(vertex, None, |from, to| {
            R64::from((to.position() - from.position()).magnitude())
        })
        .unwrap();
        let a = vertex.key();
        let b = vertex.outgoing_arc().destination_vertex().key();
        let c = vertex.outgoing_arc().next_arc().destination_vertex().key();
        let d = vertex
            .outgoing_arc()
            .next_arc()
            .next_arc()
            .destination_vertex()
            .key();
        let aq = *metrics.get(&a).unwrap();
        let bq = *metrics.get(&b).unwrap();
        let cq = *metrics.get(&c).unwrap();
        let dq = *metrics.get(&d).unwrap();

        assert_eq!(aq, (None, 0.0.into()));
        assert_eq!(bq, (Some(a), 2.0.into()));
        assert_eq!(cq, (Some(b), 4.0.into()));
        assert_eq!(dq, (Some(a), 2.0.into()));
    }
}
<commit_msg>Reduce immediate complexity of `metrics_with` return type.<commit_after>use derivative::Derivative;
use std::cmp::Reverse;
use std::collections::hash_map::Entry;
use std::collections::{BinaryHeap, HashMap, HashSet};

use crate::entity::storage::AsStorage;
use crate::entity::traverse::Adjacency;
use crate::entity::view::{Bind, Unbind};
use crate::entity::EntityError;
use crate::geometry::Metric;

pub type MetricTree<K, Q> = HashMap<K, (Option<K>, Q)>;

#[derivative(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
#[derive(Derivative)]
struct KeyedMetric<K, Q>(
    #[derivative(Ord = "ignore", PartialEq = "ignore", PartialOrd = "ignore")] K,
    Q,
)
where
    Q: Eq + Ord;

pub fn metrics_with<'a, M, T, Q, F>(
    from: T,
    to: Option<T::Key>,
    f: F,
) -> Result<MetricTree<T::Key, Q>, EntityError>
where
    M: 'a + AsStorage<T::Entity>,
    T: Adjacency + Bind<&'a M> + Copy + Unbind<&'a M>,
    Q: Copy + Metric,
    F: Fn(T, T) -> Q,
{
    let (storage, from) = from.unbind();
    let capacity = if to.is_some() {
        0
    }
    else {
        storage.as_storage().len()
    };
    let mut buffer = BinaryHeap::new();
    let mut breadcrumbs = HashSet::with_capacity(capacity);
    let mut metrics = HashMap::with_capacity(capacity);

    metrics.insert(from, (None, Q::zero()));
    buffer.push(KeyedMetric(from, Reverse(Q::zero())));
    while let Some(KeyedMetric(key, Reverse(metric))) = buffer.pop() {
        if Some(key) == to {
            break;
        }
        let entity = T::bind(storage, key).ok_or_else(|| EntityError::EntityNotFound)?;
        if breadcrumbs.insert(entity.key()) {
            for adjacent in entity
                .adjacency()
                .into_iter()
                .map(|key| T::bind(storage, key))
            {
                let adjacent = adjacent.ok_or_else(|| EntityError::EntityNotFound)?;
                let summand = f(entity, adjacent);
                if summand < Q::zero() {
                    return Err(EntityError::Geometry);
                }
                let metric = metric + summand;
                match metrics.entry(adjacent.key()) {
                    Entry::Occupied(entry) => {
                        if metric < entry.get().1 {
                            entry.into_mut().1 = metric;
                        }
                    }
                    Entry::Vacant(entry) => {
                        entry.insert((Some(entity.key()), metric));
                    }
                }
                buffer.push(KeyedMetric(adjacent.key(), Reverse(metric)));
            }
        }
    }
    Ok(metrics)
}

#[cfg(test)]
mod tests {
    use decorum::R64;
    use nalgebra::Point2;
    use theon::space::InnerSpace;

    use crate::entity::{dijkstra, EntityError};
    use crate::graph::MeshGraph;
    use crate::prelude::*;
    use crate::primitive::{Tetragon, Trigon};

    #[test]
    fn decreasing_summand() {
        let graph = MeshGraph::<Point2<f64>>::from_raw_buffers(
            vec![Tetragon::new(0usize, 1, 2, 3)],
            vec![(-1.0, -1.0), (1.0, -1.0), (1.0, 1.0), (-1.0, 1.0)],
        )
        .unwrap();
        let vertex = graph.vertices().nth(0).unwrap();
        assert_eq!(
            Err(EntityError::Geometry),
            dijkstra::metrics_with(vertex, None, |_, _| -1isize)
        )
    }

    #[test]
    fn logical_metrics() {
        let graph = MeshGraph::<()>::from_raw_buffers(vec![Trigon::new(0usize, 1, 2)], vec![(); 3])
            .unwrap();
        let vertex = graph.vertices().nth(0).unwrap();
        let metrics = dijkstra::metrics_with(vertex, None, |_, _| 1usize).unwrap();
        let a = vertex.key();
        let b = vertex.outgoing_arc().destination_vertex().key();
        let c = vertex.outgoing_arc().next_arc().destination_vertex().key();
        let aq = *metrics.get(&a).unwrap();
        let bq = *metrics.get(&b).unwrap();
        let cq = *metrics.get(&c).unwrap();

        assert_eq!(aq, (None, 0));
        assert_eq!(bq, (Some(a), 1));
        assert_eq!(cq, (Some(a), 1));
    }

    #[allow(clippy::float_cmp)]
    #[test]
    fn euclidean_distance_metrics() {
        let graph = MeshGraph::<Point2<f64>>::from_raw_buffers(
            vec![Tetragon::new(0usize, 1, 2, 3)],
            vec![(-1.0, -1.0), (1.0, -1.0), (1.0, 1.0), (-1.0, 1.0)],
        )
        .unwrap();
        let vertex = graph.vertices().nth(0).unwrap();
        let metrics = dijkstra::metrics_with(vertex, None, |from, to| {
            R64::from((to.position() - from.position()).magnitude())
        })
        .unwrap();
        let a = vertex.key();
        let b = vertex.outgoing_arc().destination_vertex().key();
        let c = vertex.outgoing_arc().next_arc().destination_vertex().key();
        let d = vertex
            .outgoing_arc()
            .next_arc()
            .next_arc()
            .destination_vertex()
            .key();
        let aq = *metrics.get(&a).unwrap();
        let bq = *metrics.get(&b).unwrap();
        let cq = *metrics.get(&c).unwrap();
        let dq = *metrics.get(&d).unwrap();

        assert_eq!(aq, (None, 0.0.into()));
        assert_eq!(bq, (Some(a), 2.0.into()));
        assert_eq!(cq, (Some(b), 4.0.into()));
        assert_eq!(dq, (Some(a), 2.0.into()));
    }
}
<|endoftext|>


<commit_before>use crate::{
    hotkey::{Hook, KeyCode},
    HotkeyConfig, SharedTimer,
};

pub use crate::hotkey::{Error, Result};

// This enum might be better situated in hotkey_config, but the last method should stay in this file
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
enum Hotkey {
    Split,
    /// The key to use for resetting the current attempt.
    Reset,
    /// The key to use for undoing the last split.
    Undo,
    /// The key to use for skipping the current split.
    Skip,
    /// The key to use for pausing the current attempt and starting a new
    /// attempt.
    Pause,
    /// The key to use for removing all the pause times from the current time.
    UndoAllPauses,
    /// The key to use for switching to the previous comparison.
    PreviousComparison,
    /// The key to use for switching to the next comparison.
    NextComparison,
    /// The key to use for toggling between the `Real Time` and `Game Time`
    /// timing methods.
    ToggleTimingMethod,
}

impl Hotkey {
    fn set_keycode(self, config: &mut HotkeyConfig, keycode: Option<KeyCode>) {
        match self {
            Hotkey::Split => config.split = keycode,
            Hotkey::Reset => config.reset = keycode,
            Hotkey::Undo => config.undo = keycode,
            Hotkey::Skip => config.skip = keycode,
            Hotkey::Pause => config.pause = keycode,
            Hotkey::UndoAllPauses => config.undo_all_pauses = keycode,
            Hotkey::PreviousComparison => config.previous_comparison = keycode,
            Hotkey::NextComparison => config.next_comparison = keycode,
            Hotkey::ToggleTimingMethod => config.toggle_timing_method = keycode,
        }
    }

    const fn get_keycode(self, config: &HotkeyConfig) -> Option<KeyCode> {
        match self {
            Hotkey::Split => config.split,
            Hotkey::Reset => config.reset,
            Hotkey::Undo => config.undo,
            Hotkey::Skip => config.skip,
            Hotkey::Pause => config.pause,
            Hotkey::UndoAllPauses => config.undo_all_pauses,
            Hotkey::PreviousComparison => config.previous_comparison,
            Hotkey::NextComparison => config.next_comparison,
            Hotkey::ToggleTimingMethod => config.toggle_timing_method,
        }
    }

    fn callback(self, timer: SharedTimer) -> Box<dyn FnMut() + Send + 'static> {
        match self {
            Hotkey::Split => Box::new(move || timer.write().split_or_start()),
            Hotkey::Reset => Box::new(move || timer.write().reset(true)),
            Hotkey::Undo => Box::new(move || timer.write().undo_split()),
            Hotkey::Skip => Box::new(move || timer.write().skip_split()),
            Hotkey::Pause => Box::new(move || timer.write().toggle_pause_or_start()),
            Hotkey::UndoAllPauses => Box::new(move || timer.write().undo_all_pauses()),
            Hotkey::PreviousComparison => {
                Box::new(move || timer.write().switch_to_previous_comparison())
            }
            Hotkey::NextComparison => Box::new(move || timer.write().switch_to_next_comparison()),
            Hotkey::ToggleTimingMethod => Box::new(move || timer.write().toggle_timing_method()),
        }
    }
}

/// With a Hotkey System the runner can use hotkeys on their keyboard to control
/// the Timer. The hotkeys are global, so the application doesn't need to be in
/// focus. The behavior of the hotkeys depends on the platform and is stubbed
/// out on platforms that don't support hotkeys. You can turn off a Hotkey
/// System temporarily. By default the Hotkey System is activated.
pub struct HotkeySystem {
    config: HotkeyConfig,
    hook: Hook,
    timer: SharedTimer,
    is_active: bool,
}

impl HotkeySystem {
    /// Creates a new Hotkey System for a Timer with the default hotkeys.
    pub fn new(timer: SharedTimer) -> Result<Self> {
        Self::with_config(timer, Default::default())
    }

    /// Creates a new Hotkey System for a Timer with a custom configuration for
    /// the hotkeys.
    pub fn with_config(timer: SharedTimer, config: HotkeyConfig) -> Result<Self> {
        let mut hotkey_system = Self {
            config,
            hook: Hook::new()?,
            timer,
            is_active: false,
        };
        hotkey_system.activate()?;
        Ok(hotkey_system)
    }

    // This method should never be public, because it might mess up the internal state and we might
    // leak a registered hotkey
    unsafe fn register_raw(&mut self, hotkey: Hotkey) -> Result<()> {
        let inner = self.timer.clone();
        if let Some(keycode) = hotkey.get_keycode(&self.config) {
            self.hook.register(keycode, hotkey.callback(inner))?;
        }
        Ok(())
    }

    fn register(&mut self, hotkey: Hotkey, keycode: Option<KeyCode>) -> Result<()> {
        hotkey.set_keycode(&mut self.config, keycode);
        unsafe { self.register_raw(hotkey) }
    }

    // This method should never be public, because it might mess up the internal state and we might
    // leak a registered hotkey
    unsafe fn unregister_raw(&mut self, hotkey: Hotkey) -> Result<()> {
        if let Some(keycode) = hotkey.get_keycode(&self.config) {
            self.hook.unregister(keycode)?;
        }
        Ok(())
    }

    fn unregister(&mut self, hotkey: Hotkey) -> Result<()> {
        hotkey.set_keycode(&mut self.config, None);
        unsafe { self.unregister_raw(hotkey) }
    }

    fn set_hotkey(&mut self, hotkey: Hotkey, keycode: Option<KeyCode>) -> Result<()> {
        // FixMe: We do not check whether the keycode is already in use
        if hotkey.get_keycode(&self.config) == keycode {
            return Ok(());
        }
        if self.is_active {
            self.unregister(hotkey)?;
            self.register(hotkey, keycode)?;
        }
        Ok(())
    }

    /// Sets the key to use for splitting and starting a new attempt.
    pub fn set_split(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::Split, hotkey)
    }

    /// Sets the key to use for resetting the current attempt.
    pub fn set_reset(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::Reset, hotkey)
    }

    /// Sets the key to use for pausing the current attempt and starting a new
    /// attempt.
    pub fn set_pause(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::Pause, hotkey)
    }

    /// Sets the key to use for skipping the current split.
    pub fn set_skip(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::Skip, hotkey)
    }

    /// Sets the key to use for undoing the last split.
    pub fn set_undo(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::Undo, hotkey)
    }

    /// Sets the key to use for switching to the previous comparison.
    pub fn set_previous_comparison(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::PreviousComparison, hotkey)
    }

    /// Sets the key to use for switching to the next comparison.
    pub fn set_next_comparison(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::NextComparison, hotkey)
    }

    /// Sets the key to use for removing all the pause times from the current
    /// time.
    pub fn set_undo_all_pauses(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::UndoAllPauses, hotkey)
    }

    /// Sets the key to use for toggling between the `Real Time` and `Game Time`
    /// timing methods.
    pub fn set_toggle_timing_method(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::ToggleTimingMethod, hotkey)
    }

    /// Deactivates the Hotkey System. No hotkeys will go through until it gets
    /// activated again. If it's already deactivated, nothing happens.
    pub fn deactivate(&mut self) -> Result<()> {
        if self.is_active {
            unsafe {
                self.unregister_raw(Hotkey::Split)?;
                self.unregister_raw(Hotkey::Reset)?;
                self.unregister_raw(Hotkey::Undo)?;
                self.unregister_raw(Hotkey::Skip)?;
                self.unregister_raw(Hotkey::Pause)?;
                self.unregister_raw(Hotkey::UndoAllPauses)?;
                self.unregister_raw(Hotkey::PreviousComparison)?;
                self.unregister_raw(Hotkey::NextComparison)?;
                self.unregister_raw(Hotkey::ToggleTimingMethod)?;
            }
        }
        self.is_active = false;
        Ok(())
    }

    /// Activates a previously deactivated Hotkey System. If it's already
    /// active, nothing happens.
    pub fn activate(&mut self) -> Result<()> {
        if !self.is_active {
            unsafe {
                self.register_raw(Hotkey::Split)?;
                self.register_raw(Hotkey::Reset)?;
                self.register_raw(Hotkey::Undo)?;
                self.register_raw(Hotkey::Skip)?;
                self.register_raw(Hotkey::Pause)?;
                self.register_raw(Hotkey::UndoAllPauses)?;
                self.register_raw(Hotkey::PreviousComparison)?;
                self.register_raw(Hotkey::NextComparison)?;
                self.register_raw(Hotkey::ToggleTimingMethod)?;
            }
        }
        self.is_active = true;
        Ok(())
    }

    /// Returns true if the Hotkey System is active, false otherwise.
    pub const fn is_active(&self) -> bool {
        self.is_active
    }

    /// Returns the hotkey configuration currently in use by the Hotkey System.
    pub const fn config(&self) -> HotkeyConfig {
        self.config
    }

    /// Applies a new hotkey configuration to the Hotkey System. Each hotkey is
    /// changed to the one specified in the configuration. This operation may
    /// fail if you provide a hotkey configuration where a hotkey is used for
    /// multiple operations.
    pub fn set_config(&mut self, config: HotkeyConfig) -> Result<()> {
        self.set_split(config.split)?;
        self.set_reset(config.reset)?;
        self.set_undo(config.undo)?;
        self.set_skip(config.skip)?;
        self.set_pause(config.pause)?;
        self.set_previous_comparison(config.previous_comparison)?;
        self.set_next_comparison(config.next_comparison)?;
        self.set_undo_all_pauses(config.undo_all_pauses)?;
        self.set_toggle_timing_method(config.toggle_timing_method)?;

        Ok(())
    }
}
<commit_msg>Fix setting hotkeys when `HotkeySystem` is disabled<commit_after>use crate::{
    hotkey::{Hook, KeyCode},
    HotkeyConfig, SharedTimer,
};

pub use crate::hotkey::{Error, Result};

// This enum might be better situated in hotkey_config, but the last method should stay in this file
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
enum Hotkey {
    Split,
    /// The key to use for resetting the current attempt.
    Reset,
    /// The key to use for undoing the last split.
    Undo,
    /// The key to use for skipping the current split.
    Skip,
    /// The key to use for pausing the current attempt and starting a new
    /// attempt.
    Pause,
    /// The key to use for removing all the pause times from the current time.
    UndoAllPauses,
    /// The key to use for switching to the previous comparison.
    PreviousComparison,
    /// The key to use for switching to the next comparison.
    NextComparison,
    /// The key to use for toggling between the `Real Time` and `Game Time`
    /// timing methods.
    ToggleTimingMethod,
}

impl Hotkey {
    fn set_keycode(self, config: &mut HotkeyConfig, keycode: Option<KeyCode>) {
        match self {
            Hotkey::Split => config.split = keycode,
            Hotkey::Reset => config.reset = keycode,
            Hotkey::Undo => config.undo = keycode,
            Hotkey::Skip => config.skip = keycode,
            Hotkey::Pause => config.pause = keycode,
            Hotkey::UndoAllPauses => config.undo_all_pauses = keycode,
            Hotkey::PreviousComparison => config.previous_comparison = keycode,
            Hotkey::NextComparison => config.next_comparison = keycode,
            Hotkey::ToggleTimingMethod => config.toggle_timing_method = keycode,
        }
    }

    const fn get_keycode(self, config: &HotkeyConfig) -> Option<KeyCode> {
        match self {
            Hotkey::Split => config.split,
            Hotkey::Reset => config.reset,
            Hotkey::Undo => config.undo,
            Hotkey::Skip => config.skip,
            Hotkey::Pause => config.pause,
            Hotkey::UndoAllPauses => config.undo_all_pauses,
            Hotkey::PreviousComparison => config.previous_comparison,
            Hotkey::NextComparison => config.next_comparison,
            Hotkey::ToggleTimingMethod => config.toggle_timing_method,
        }
    }

    fn callback(self, timer: SharedTimer) -> Box<dyn FnMut() + Send + 'static> {
        match self {
            Hotkey::Split => Box::new(move || timer.write().split_or_start()),
            Hotkey::Reset => Box::new(move || timer.write().reset(true)),
            Hotkey::Undo => Box::new(move || timer.write().undo_split()),
            Hotkey::Skip => Box::new(move || timer.write().skip_split()),
            Hotkey::Pause => Box::new(move || timer.write().toggle_pause_or_start()),
            Hotkey::UndoAllPauses => Box::new(move || timer.write().undo_all_pauses()),
            Hotkey::PreviousComparison => {
                Box::new(move || timer.write().switch_to_previous_comparison())
            }
            Hotkey::NextComparison => Box::new(move || timer.write().switch_to_next_comparison()),
            Hotkey::ToggleTimingMethod => Box::new(move || timer.write().toggle_timing_method()),
        }
    }
}

/// With a Hotkey System the runner can use hotkeys on their keyboard to control
/// the Timer. The hotkeys are global, so the application doesn't need to be in
/// focus. The behavior of the hotkeys depends on the platform and is stubbed
/// out on platforms that don't support hotkeys. You can turn off a Hotkey
/// System temporarily. By default the Hotkey System is activated.
pub struct HotkeySystem {
    config: HotkeyConfig,
    hook: Hook,
    timer: SharedTimer,
    is_active: bool,
}

impl HotkeySystem {
    /// Creates a new Hotkey System for a Timer with the default hotkeys.
    pub fn new(timer: SharedTimer) -> Result<Self> {
        Self::with_config(timer, Default::default())
    }

    /// Creates a new Hotkey System for a Timer with a custom configuration for
    /// the hotkeys.
    pub fn with_config(timer: SharedTimer, config: HotkeyConfig) -> Result<Self> {
        let mut hotkey_system = Self {
            config,
            hook: Hook::new()?,
            timer,
            is_active: false,
        };
        hotkey_system.activate()?;
        Ok(hotkey_system)
    }

    // This method should never be public, because it might mess up the internal state and we might
    // leak a registered hotkey
    unsafe fn register_raw(&mut self, hotkey: Hotkey) -> Result<()> {
        let inner = self.timer.clone();
        if let Some(keycode) = hotkey.get_keycode(&self.config) {
            self.hook.register(keycode, hotkey.callback(inner))?;
        }
        Ok(())
    }

    fn register(&mut self, hotkey: Hotkey, keycode: Option<KeyCode>) -> Result<()> {
        hotkey.set_keycode(&mut self.config, keycode);
        unsafe { self.register_raw(hotkey) }
    }

    // This method should never be public, because it might mess up the internal state and we might
    // leak a registered hotkey
    unsafe fn unregister_raw(&mut self, hotkey: Hotkey) -> Result<()> {
        if let Some(keycode) = hotkey.get_keycode(&self.config) {
            self.hook.unregister(keycode)?;
        }
        Ok(())
    }

    fn unregister(&mut self, hotkey: Hotkey) -> Result<()> {
        hotkey.set_keycode(&mut self.config, None);
        unsafe { self.unregister_raw(hotkey) }
    }

    fn set_hotkey(&mut self, hotkey: Hotkey, keycode: Option<KeyCode>) -> Result<()> {
        // FIXME: We do not check whether the keycode is already in use
        if hotkey.get_keycode(&self.config) == keycode {
            return Ok(());
        }
        if self.is_active {
            self.unregister(hotkey)?;
            self.register(hotkey, keycode)?;
        } else {
            hotkey.set_keycode(&mut self.config, keycode);
        }
        Ok(())
    }

    /// Sets the key to use for splitting and starting a new attempt.
    pub fn set_split(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::Split, hotkey)
    }

    /// Sets the key to use for resetting the current attempt.
    pub fn set_reset(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::Reset, hotkey)
    }

    /// Sets the key to use for pausing the current attempt and starting a new
    /// attempt.
    pub fn set_pause(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::Pause, hotkey)
    }

    /// Sets the key to use for skipping the current split.
    pub fn set_skip(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::Skip, hotkey)
    }

    /// Sets the key to use for undoing the last split.
    pub fn set_undo(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::Undo, hotkey)
    }

    /// Sets the key to use for switching to the previous comparison.
    pub fn set_previous_comparison(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::PreviousComparison, hotkey)
    }

    /// Sets the key to use for switching to the next comparison.
    pub fn set_next_comparison(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::NextComparison, hotkey)
    }

    /// Sets the key to use for removing all the pause times from the current
    /// time.
    pub fn set_undo_all_pauses(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::UndoAllPauses, hotkey)
    }

    /// Sets the key to use for toggling between the `Real Time` and `Game Time`
    /// timing methods.
    pub fn set_toggle_timing_method(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::ToggleTimingMethod, hotkey)
    }

    /// Deactivates the Hotkey System. No hotkeys will go through until it gets
    /// activated again. If it's already deactivated, nothing happens.
    pub fn deactivate(&mut self) -> Result<()> {
        if self.is_active {
            unsafe {
                self.unregister_raw(Hotkey::Split)?;
                self.unregister_raw(Hotkey::Reset)?;
                self.unregister_raw(Hotkey::Undo)?;
                self.unregister_raw(Hotkey::Skip)?;
                self.unregister_raw(Hotkey::Pause)?;
                self.unregister_raw(Hotkey::UndoAllPauses)?;
                self.unregister_raw(Hotkey::PreviousComparison)?;
                self.unregister_raw(Hotkey::NextComparison)?;
                self.unregister_raw(Hotkey::ToggleTimingMethod)?;
            }
        }
        self.is_active = false;
        Ok(())
    }

    /// Activates a previously deactivated Hotkey System. If it's already
    /// active, nothing happens.
    pub fn activate(&mut self) -> Result<()> {
        if !self.is_active {
            unsafe {
                self.register_raw(Hotkey::Split)?;
                self.register_raw(Hotkey::Reset)?;
                self.register_raw(Hotkey::Undo)?;
                self.register_raw(Hotkey::Skip)?;
                self.register_raw(Hotkey::Pause)?;
                self.register_raw(Hotkey::UndoAllPauses)?;
                self.register_raw(Hotkey::PreviousComparison)?;
                self.register_raw(Hotkey::NextComparison)?;
                self.register_raw(Hotkey::ToggleTimingMethod)?;
            }
        }
        self.is_active = true;
        Ok(())
    }

    /// Returns true if the Hotkey System is active, false otherwise.
    pub const fn is_active(&self) -> bool {
        self.is_active
    }

    /// Returns the hotkey configuration currently in use by the Hotkey System.
    pub const fn config(&self) -> HotkeyConfig {
        self.config
    }

    /// Applies a new hotkey configuration to the Hotkey System. Each hotkey is
    /// changed to the one specified in the configuration. This operation may
    /// fail if you provide a hotkey configuration where a hotkey is used for
    /// multiple operations.
    pub fn set_config(&mut self, config: HotkeyConfig) -> Result<()> {
        self.set_split(config.split)?;
        self.set_reset(config.reset)?;
        self.set_undo(config.undo)?;
        self.set_skip(config.skip)?;
        self.set_pause(config.pause)?;
        self.set_previous_comparison(config.previous_comparison)?;
        self.set_next_comparison(config.next_comparison)?;
        self.set_undo_all_pauses(config.undo_all_pauses)?;
        self.set_toggle_timing_method(config.toggle_timing_method)?;

        Ok(())
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2015 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.

use Diagnostic;
use DiagnosticId;
use DiagnosticStyledString;
use Applicability;

use Level;
use Handler;
use std::fmt::{self, Debug};
use std::ops::{Deref, DerefMut};
use std::thread::panicking;
use syntax_pos::{MultiSpan, Span};

/// Used for emitting structured error messages and other diagnostic information.
#[must_use]
#[derive(Clone)]
pub struct DiagnosticBuilder<'a> {
    pub handler: &'a Handler,
    diagnostic: Diagnostic,
    allow_suggestions: bool,
}

/// In general, the `DiagnosticBuilder` uses deref to allow access to
/// the fields and methods of the embedded `diagnostic` in a
/// transparent way.  *However,* many of the methods are intended to
/// be used in a chained way, and hence ought to return `self`. In
/// that case, we can't just naively forward to the method on the
/// `diagnostic`, because the return type would be a `&Diagnostic`
/// instead of a `&DiagnosticBuilder<'a>`. This `forward!` macro makes
/// it easy to declare such methods on the builder.
macro_rules! forward {
    // Forward pattern for &self -> &Self
    (pub fn $n:ident(&self, $($name:ident: $ty:ty),*) -> &Self) => {
        pub fn $n(&self, $($name: $ty),*) -> &Self {
            #[allow(deprecated)]
            self.diagnostic.$n($($name),*);
            self
        }
    };

    // Forward pattern for &mut self -> &mut Self
    (pub fn $n:ident(&mut self, $($name:ident: $ty:ty),*) -> &mut Self) => {
        pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
            #[allow(deprecated)]
            self.diagnostic.$n($($name),*);
            self
        }
    };

    // Forward pattern for &mut self -> &mut Self, with S: Into<MultiSpan>
    // type parameter. No obvious way to make this more generic.
    (pub fn $n:ident<S: Into<MultiSpan>>(&mut self, $($name:ident: $ty:ty),*) -> &mut Self) => {
        pub fn $n<S: Into<MultiSpan>>(&mut self, $($name: $ty),*) -> &mut Self {
            #[allow(deprecated)]
            self.diagnostic.$n($($name),*);
            self
        }
    };
}

impl<'a> Deref for DiagnosticBuilder<'a> {
    type Target = Diagnostic;

    fn deref(&self) -> &Diagnostic {
        &self.diagnostic
    }
}

impl<'a> DerefMut for DiagnosticBuilder<'a> {
    fn deref_mut(&mut self) -> &mut Diagnostic {
        &mut self.diagnostic
    }
}

impl<'a> DiagnosticBuilder<'a> {
    /// Emit the diagnostic.
    pub fn emit(&mut self) {
        if self.cancelled() {
            return;
        }

        self.handler.emit_db(&self);
        self.cancel();
    }

    /// Buffers the diagnostic for later emission.
    pub fn buffer(self, buffered_diagnostics: &mut Vec<Diagnostic>) {
        // We need to use `ptr::read` because `DiagnosticBuilder`
        // implements `Drop`.
        let diagnostic;
        unsafe {
            diagnostic = ::std::ptr::read(&self.diagnostic);
            ::std::mem::forget(self);
        };
        buffered_diagnostics.push(diagnostic);
    }

    /// Convenience function for internal use, clients should use one of the
    /// span_* methods instead.
    pub fn sub<S: Into<MultiSpan>>(
        &mut self,
        level: Level,
        message: &str,
        span: Option<S>,
    ) -> &mut Self {
        let span = span.map(|s| s.into()).unwrap_or(MultiSpan::new());
        self.diagnostic.sub(level, message, span, None);
        self
    }

    /// Delay emission of this diagnostic as a bug.
    ///
    /// This can be useful in contexts where an error indicates a bug but
    /// typically this only happens when other compilation errors have already
    /// happened. In those cases this can be used to defer emission of this
    /// diagnostic as a bug in the compiler only if no other errors have been
    /// emitted.
    ///
    /// In the meantime, though, callsites are required to deal with the "bug"
    /// locally in whichever way makes the most sense.
    pub fn delay_as_bug(&mut self) {
        self.level = Level::Bug;
        self.handler.delay_as_bug(self.diagnostic.clone());
        self.cancel();
    }

    /// Add a span/label to be included in the resulting snippet.
    /// This is pushed onto the `MultiSpan` that was created when the
    /// diagnostic was first built. If you don't call this function at
    /// all, and you just supplied a `Span` to create the diagnostic,
    /// then the snippet will just include that `Span`, which is
    /// called the primary span.
    pub fn span_label<T: Into<String>>(&mut self, span: Span, label: T) -> &mut Self {
        self.diagnostic.span_label(span, label);
        self
    }

    forward!(pub fn note_expected_found(&mut self,
                                        label: &dyn fmt::Display,
                                        expected: DiagnosticStyledString,
                                        found: DiagnosticStyledString)
                                        -> &mut Self);

    forward!(pub fn note_expected_found_extra(&mut self,
                                              label: &dyn fmt::Display,
                                              expected: DiagnosticStyledString,
                                              found: DiagnosticStyledString,
                                              expected_extra: &dyn fmt::Display,
                                              found_extra: &dyn fmt::Display)
                                              -> &mut Self);

    forward!(pub fn note(&mut self, msg: &str) -> &mut Self);
    forward!(pub fn span_note<S: Into<MultiSpan>>(&mut self,
                                                  sp: S,
                                                  msg: &str)
                                                  -> &mut Self);
    forward!(pub fn warn(&mut self, msg: &str) -> &mut Self);
    forward!(pub fn span_warn<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) -> &mut Self);
    forward!(pub fn help(&mut self , msg: &str) -> &mut Self);
    forward!(pub fn span_help<S: Into<MultiSpan>>(&mut self,
                                                  sp: S,
                                                  msg: &str)
                                                  -> &mut Self);

    #[deprecated(note = "Use `span_suggestion_short_with_applicability`")]
    forward!(pub fn span_suggestion_short(
                                      &mut self,
                                      sp: Span,
                                      msg: &str,
                                          suggestion: String)
                                          -> &mut Self);

    #[deprecated(note = "Use `multipart_suggestion_with_applicability`")]
    forward!(pub fn multipart_suggestion(
        &mut self,
        msg: &str,
        suggestion: Vec<(Span, String)>
    ) -> &mut Self);

    #[deprecated(note = "Use `span_suggestion_with_applicability`")]
    forward!(pub fn span_suggestion(&mut self,
                                    sp: Span,
                                    msg: &str,
                                    suggestion: String)
                                    -> &mut Self);

    #[deprecated(note = "Use `span_suggestions_with_applicability`")]
    forward!(pub fn span_suggestions(&mut self,
                                     sp: Span,
                                     msg: &str,
                                     suggestions: Vec<String>)
                                     -> &mut Self);

    pub fn multipart_suggestion_with_applicability(&mut self,
                                              msg: &str,
                                              suggestion: Vec<(Span, String)>,
                                              applicability: Applicability)
                                              -> &mut Self {
        if !self.allow_suggestions {
            return self
        }
        self.diagnostic.multipart_suggestion_with_applicability(
            msg,
            suggestion,
            applicability,
        );
        self
    }

    pub fn span_suggestion_with_applicability(&mut self,
                                              sp: Span,
                                              msg: &str,
                                              suggestion: String,
                                              applicability: Applicability)
                                              -> &mut Self {
        if !self.allow_suggestions {
            return self
        }
        self.diagnostic.span_suggestion_with_applicability(
            sp,
            msg,
            suggestion,
            applicability,
        );
        self
    }

    pub fn span_suggestions_with_applicability(&mut self,
                                               sp: Span,
                                               msg: &str,
                                               suggestions: Vec<String>,
                                               applicability: Applicability)
                                               -> &mut Self {
        if !self.allow_suggestions {
            return self
        }
        self.diagnostic.span_suggestions_with_applicability(
            sp,
            msg,
            suggestions,
            applicability,
        );
        self
    }

    pub fn span_suggestion_short_with_applicability(&mut self,
                                                    sp: Span,
                                                    msg: &str,
                                                    suggestion: String,
                                                    applicability: Applicability)
                                                    -> &mut Self {
        if !self.allow_suggestions {
            return self
        }
        self.diagnostic.span_suggestion_short_with_applicability(
            sp,
            msg,
            suggestion,
            applicability,
        );
        self
    }
    forward!(pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self);
    forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self);

    pub fn allow_suggestions(&mut self, allow: bool) -> &mut Self {
        self.allow_suggestions = allow;
        self
    }

    /// Convenience function for internal use, clients should use one of the
    /// struct_* methods on Handler.
    pub fn new(handler: &'a Handler, level: Level, message: &str) -> DiagnosticBuilder<'a> {
        DiagnosticBuilder::new_with_code(handler, level, None, message)
    }

    /// Convenience function for internal use, clients should use one of the
    /// struct_* methods on Handler.
    pub fn new_with_code(handler: &'a Handler,
                         level: Level,
                         code: Option<DiagnosticId>,
                         message: &str)
                         -> DiagnosticBuilder<'a> {
        let diagnostic = Diagnostic::new_with_code(level, code, message);
        DiagnosticBuilder::new_diagnostic(handler, diagnostic)
    }

    /// Creates a new `DiagnosticBuilder` with an already constructed
    /// diagnostic.
    pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic)
                         -> DiagnosticBuilder<'a> {
        DiagnosticBuilder {
            handler,
            diagnostic,
            allow_suggestions: true,
        }
    }
}

impl<'a> Debug for DiagnosticBuilder<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.diagnostic.fmt(f)
    }
}

/// Destructor bomb - a `DiagnosticBuilder` must be either emitted or canceled
/// or we emit a bug.
impl<'a> Drop for DiagnosticBuilder<'a> {
    fn drop(&mut self) {
        if !panicking() && !self.cancelled() {
            let mut db = DiagnosticBuilder::new(self.handler,
                                                Level::Bug,
                                                "Error constructed but not emitted");
            db.emit();
            panic!();
        }
    }
}
<commit_msg>Change diagnostic_builder's forward! macro to enforce trailing argument comma<commit_after>// Copyright 2012-2015 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.

use Diagnostic;
use DiagnosticId;
use DiagnosticStyledString;
use Applicability;

use Level;
use Handler;
use std::fmt::{self, Debug};
use std::ops::{Deref, DerefMut};
use std::thread::panicking;
use syntax_pos::{MultiSpan, Span};

/// Used for emitting structured error messages and other diagnostic information.
#[must_use]
#[derive(Clone)]
pub struct DiagnosticBuilder<'a> {
    pub handler: &'a Handler,
    diagnostic: Diagnostic,
    allow_suggestions: bool,
}

/// In general, the `DiagnosticBuilder` uses deref to allow access to
/// the fields and methods of the embedded `diagnostic` in a
/// transparent way.  *However,* many of the methods are intended to
/// be used in a chained way, and hence ought to return `self`. In
/// that case, we can't just naively forward to the method on the
/// `diagnostic`, because the return type would be a `&Diagnostic`
/// instead of a `&DiagnosticBuilder<'a>`. This `forward!` macro makes
/// it easy to declare such methods on the builder.
macro_rules! forward {
    // Forward pattern for &self -> &Self
    (pub fn $n:ident(&self, $($name:ident: $ty:ty,)*) -> &Self) => {
        pub fn $n(&self, $($name: $ty),*) -> &Self {
            #[allow(deprecated)]
            self.diagnostic.$n($($name),*);
            self
        }
    };

    // Forward pattern for &mut self -> &mut Self
    (pub fn $n:ident(&mut self, $($name:ident: $ty:ty,)*) -> &mut Self) => {
        pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
            #[allow(deprecated)]
            self.diagnostic.$n($($name),*);
            self
        }
    };

    // Forward pattern for &mut self -> &mut Self, with S: Into<MultiSpan>
    // type parameter. No obvious way to make this more generic.
    (pub fn $n:ident<S: Into<MultiSpan>>(&mut self, $($name:ident: $ty:ty,)*) -> &mut Self) => {
        pub fn $n<S: Into<MultiSpan>>(&mut self, $($name: $ty,)*) -> &mut Self {
            #[allow(deprecated)]
            self.diagnostic.$n($($name),*);
            self
        }
    };
}

impl<'a> Deref for DiagnosticBuilder<'a> {
    type Target = Diagnostic;

    fn deref(&self) -> &Diagnostic {
        &self.diagnostic
    }
}

impl<'a> DerefMut for DiagnosticBuilder<'a> {
    fn deref_mut(&mut self) -> &mut Diagnostic {
        &mut self.diagnostic
    }
}

impl<'a> DiagnosticBuilder<'a> {
    /// Emit the diagnostic.
    pub fn emit(&mut self) {
        if self.cancelled() {
            return;
        }

        self.handler.emit_db(&self);
        self.cancel();
    }

    /// Buffers the diagnostic for later emission.
    pub fn buffer(self, buffered_diagnostics: &mut Vec<Diagnostic>) {
        // We need to use `ptr::read` because `DiagnosticBuilder`
        // implements `Drop`.
        let diagnostic;
        unsafe {
            diagnostic = ::std::ptr::read(&self.diagnostic);
            ::std::mem::forget(self);
        };
        buffered_diagnostics.push(diagnostic);
    }

    /// Convenience function for internal use, clients should use one of the
    /// span_* methods instead.
    pub fn sub<S: Into<MultiSpan>>(
        &mut self,
        level: Level,
        message: &str,
        span: Option<S>,
    ) -> &mut Self {
        let span = span.map(|s| s.into()).unwrap_or(MultiSpan::new());
        self.diagnostic.sub(level, message, span, None);
        self
    }

    /// Delay emission of this diagnostic as a bug.
    ///
    /// This can be useful in contexts where an error indicates a bug but
    /// typically this only happens when other compilation errors have already
    /// happened. In those cases this can be used to defer emission of this
    /// diagnostic as a bug in the compiler only if no other errors have been
    /// emitted.
    ///
    /// In the meantime, though, callsites are required to deal with the "bug"
    /// locally in whichever way makes the most sense.
    pub fn delay_as_bug(&mut self) {
        self.level = Level::Bug;
        self.handler.delay_as_bug(self.diagnostic.clone());
        self.cancel();
    }

    /// Add a span/label to be included in the resulting snippet.
    /// This is pushed onto the `MultiSpan` that was created when the
    /// diagnostic was first built. If you don't call this function at
    /// all, and you just supplied a `Span` to create the diagnostic,
    /// then the snippet will just include that `Span`, which is
    /// called the primary span.
    pub fn span_label<T: Into<String>>(&mut self, span: Span, label: T) -> &mut Self {
        self.diagnostic.span_label(span, label);
        self
    }

    forward!(pub fn note_expected_found(&mut self,
                                        label: &dyn fmt::Display,
                                        expected: DiagnosticStyledString,
                                        found: DiagnosticStyledString,
                                        ) -> &mut Self);

    forward!(pub fn note_expected_found_extra(&mut self,
                                              label: &dyn fmt::Display,
                                              expected: DiagnosticStyledString,
                                              found: DiagnosticStyledString,
                                              expected_extra: &dyn fmt::Display,
                                              found_extra: &dyn fmt::Display,
                                              ) -> &mut Self);

    forward!(pub fn note(&mut self, msg: &str,) -> &mut Self);
    forward!(pub fn span_note<S: Into<MultiSpan>>(&mut self,
                                                  sp: S,
                                                  msg: &str,
                                                  ) -> &mut Self);
    forward!(pub fn warn(&mut self, msg: &str,) -> &mut Self);
    forward!(pub fn span_warn<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str,) -> &mut Self);
    forward!(pub fn help(&mut self , msg: &str,) -> &mut Self);
    forward!(pub fn span_help<S: Into<MultiSpan>>(&mut self,
                                                  sp: S,
                                                  msg: &str,
                                                  ) -> &mut Self);

    #[deprecated(note = "Use `span_suggestion_short_with_applicability`")]
    forward!(pub fn span_suggestion_short(
                                      &mut self,
                                      sp: Span,
                                      msg: &str,
                                      suggestion: String,
                                      ) -> &mut Self);

    #[deprecated(note = "Use `multipart_suggestion_with_applicability`")]
    forward!(pub fn multipart_suggestion(
        &mut self,
        msg: &str,
        suggestion: Vec<(Span, String)>,
    ) -> &mut Self);

    #[deprecated(note = "Use `span_suggestion_with_applicability`")]
    forward!(pub fn span_suggestion(&mut self,
                                    sp: Span,
                                    msg: &str,
                                    suggestion: String,
                                    ) -> &mut Self);

    #[deprecated(note = "Use `span_suggestions_with_applicability`")]
    forward!(pub fn span_suggestions(&mut self,
                                     sp: Span,
                                     msg: &str,
                                     suggestions: Vec<String>,
                                     ) -> &mut Self);

    pub fn multipart_suggestion_with_applicability(&mut self,
                                              msg: &str,
                                              suggestion: Vec<(Span, String)>,
                                              applicability: Applicability,
                                              ) -> &mut Self {
        if !self.allow_suggestions {
            return self
        }
        self.diagnostic.multipart_suggestion_with_applicability(
            msg,
            suggestion,
            applicability,
        );
        self
    }

    pub fn span_suggestion_with_applicability(&mut self,
                                              sp: Span,
                                              msg: &str,
                                              suggestion: String,
                                              applicability: Applicability)
                                              -> &mut Self {
        if !self.allow_suggestions {
            return self
        }
        self.diagnostic.span_suggestion_with_applicability(
            sp,
            msg,
            suggestion,
            applicability,
        );
        self
    }

    pub fn span_suggestions_with_applicability(&mut self,
                                               sp: Span,
                                               msg: &str,
                                               suggestions: Vec<String>,
                                               applicability: Applicability)
                                               -> &mut Self {
        if !self.allow_suggestions {
            return self
        }
        self.diagnostic.span_suggestions_with_applicability(
            sp,
            msg,
            suggestions,
            applicability,
        );
        self
    }

    pub fn span_suggestion_short_with_applicability(&mut self,
                                                    sp: Span,
                                                    msg: &str,
                                                    suggestion: String,
                                                    applicability: Applicability)
                                                    -> &mut Self {
        if !self.allow_suggestions {
            return self
        }
        self.diagnostic.span_suggestion_short_with_applicability(
            sp,
            msg,
            suggestion,
            applicability,
        );
        self
    }
    forward!(pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S,) -> &mut Self);
    forward!(pub fn code(&mut self, s: DiagnosticId,) -> &mut Self);

    pub fn allow_suggestions(&mut self, allow: bool) -> &mut Self {
        self.allow_suggestions = allow;
        self
    }

    /// Convenience function for internal use, clients should use one of the
    /// struct_* methods on Handler.
    pub fn new(handler: &'a Handler, level: Level, message: &str) -> DiagnosticBuilder<'a> {
        DiagnosticBuilder::new_with_code(handler, level, None, message)
    }

    /// Convenience function for internal use, clients should use one of the
    /// struct_* methods on Handler.
    pub fn new_with_code(handler: &'a Handler,
                         level: Level,
                         code: Option<DiagnosticId>,
                         message: &str)
                         -> DiagnosticBuilder<'a> {
        let diagnostic = Diagnostic::new_with_code(level, code, message);
        DiagnosticBuilder::new_diagnostic(handler, diagnostic)
    }

    /// Creates a new `DiagnosticBuilder` with an already constructed
    /// diagnostic.
    pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic)
                         -> DiagnosticBuilder<'a> {
        DiagnosticBuilder {
            handler,
            diagnostic,
            allow_suggestions: true,
        }
    }
}

impl<'a> Debug for DiagnosticBuilder<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.diagnostic.fmt(f)
    }
}

/// Destructor bomb - a `DiagnosticBuilder` must be either emitted or canceled
/// or we emit a bug.
impl<'a> Drop for DiagnosticBuilder<'a> {
    fn drop(&mut self) {
        if !panicking() && !self.cancelled() {
            let mut db = DiagnosticBuilder::new(self.handler,
                                                Level::Bug,
                                                "Error constructed but not emitted");
            db.emit();
            panic!();
        }
    }
}
<|endoftext|>


<commit_before>use super::*;

/// A pending log reservation which can be aborted or completed.
/// NB the holder should quickly call `complete` or `abort` as
/// taking too long to decide will cause the underlying IO
/// buffer to become blocked.
pub struct Reservation<'a> {
    pub(super) iobufs: &'a IoBufs,
    pub(super) idx: usize,
    pub(super) data: Vec<u8>,
    pub(super) destination: &'a mut [u8],
    pub(super) flushed: bool,
    pub(super) lsn: Lsn,
    pub(super) lid: LogId,
    pub(super) is_blob: bool,
    pub(super) _guard: Guard,
}

impl<'a> Drop for Reservation<'a> {
    fn drop(&mut self) {
        // We auto-abort if the user never uses a reservation.
        let should_flush = !self.data.is_empty() && !self.flushed;
        if should_flush {
            self.flush(false).unwrap();
        }
    }
}

impl<'a> Reservation<'a> {
    /// Cancel the reservation, placing a failed flush on disk, returning
    /// the (cancelled) log sequence number and file offset.
    pub fn abort(mut self) -> Result<(Lsn, DiskPtr), ()> {
        if self.is_blob {
            let blob_ptr = self.blob_ptr().unwrap();

            assert_eq!(self.lsn, blob_ptr);

            trace!(
                "removing blob for aborted reservation at lsn {}",
                blob_ptr
            );
            remove_blob(blob_ptr, &self.iobufs.config)?;
        }

        self.flush(false)
    }

    /// Complete the reservation, placing the buffer on disk. returns
    /// the log sequence number of the write, and the file offset.
    pub fn complete(mut self) -> Result<(Lsn, DiskPtr), ()> {
        self.flush(true)
    }

    /// Get the log file offset for reading this buffer in the future.
    pub fn lid(&self) -> LogId {
        self.lid
    }

    /// Get the log sequence number for this update.
    pub fn lsn(&self) -> Lsn {
        self.lsn
    }

    /// Get the underlying storage location for the written value.
    /// Note that an blob write still has a pointer in the
    /// log at the provided lid location.
    pub fn ptr(&self) -> DiskPtr {
        if let Some(blob_ptr) = self.blob_ptr() {
            DiskPtr::new_blob(self.lid, blob_ptr)
        } else {
            DiskPtr::new_inline(self.lid)
        }
    }

    fn blob_ptr(&self) -> Option<BlobPointer> {
        if self.is_blob {
            let mut blob_ptr_bytes =
                [0u8; std::mem::size_of::<Lsn>()];
            blob_ptr_bytes
                .copy_from_slice(&self.data[MSG_HEADER_LEN..]);
            let blob_ptr = arr_to_u64(blob_ptr_bytes) as BlobPointer;

            Some(blob_ptr)
        } else {
            None
        }
    }

    fn flush(&mut self, valid: bool) -> Result<(Lsn, DiskPtr), ()> {
        if self.flushed {
            panic!("flushing already-flushed reservation!");
        }

        self.flushed = true;

        if !valid {
            self.data[0] = FAILED_FLUSH;
            // don't actually zero the message, still check its hash
            // on recovery to find corruption.
        }

        self.destination.copy_from_slice(&*self.data);

        self.iobufs.exit_reservation(self.idx)?;

        Ok((self.lsn(), self.ptr()))
    }
}
<commit_msg>Remove incorrect assertion<commit_after>use super::*;

/// A pending log reservation which can be aborted or completed.
/// NB the holder should quickly call `complete` or `abort` as
/// taking too long to decide will cause the underlying IO
/// buffer to become blocked.
pub struct Reservation<'a> {
    pub(super) iobufs: &'a IoBufs,
    pub(super) idx: usize,
    pub(super) data: Vec<u8>,
    pub(super) destination: &'a mut [u8],
    pub(super) flushed: bool,
    pub(super) lsn: Lsn,
    pub(super) lid: LogId,
    pub(super) is_blob: bool,
    pub(super) _guard: Guard,
}

impl<'a> Drop for Reservation<'a> {
    fn drop(&mut self) {
        // We auto-abort if the user never uses a reservation.
        let should_flush = !self.data.is_empty() && !self.flushed;
        if should_flush {
            self.flush(false).unwrap();
        }
    }
}

impl<'a> Reservation<'a> {
    /// Cancel the reservation, placing a failed flush on disk, returning
    /// the (cancelled) log sequence number and file offset.
    pub fn abort(mut self) -> Result<(Lsn, DiskPtr), ()> {
        if self.is_blob {
            let blob_ptr = self.blob_ptr().unwrap();

            trace!(
                "removing blob for aborted reservation at lsn {}",
                blob_ptr
            );
            remove_blob(blob_ptr, &self.iobufs.config)?;
        }

        self.flush(false)
    }

    /// Complete the reservation, placing the buffer on disk. returns
    /// the log sequence number of the write, and the file offset.
    pub fn complete(mut self) -> Result<(Lsn, DiskPtr), ()> {
        self.flush(true)
    }

    /// Get the log file offset for reading this buffer in the future.
    pub fn lid(&self) -> LogId {
        self.lid
    }

    /// Get the log sequence number for this update.
    pub fn lsn(&self) -> Lsn {
        self.lsn
    }

    /// Get the underlying storage location for the written value.
    /// Note that an blob write still has a pointer in the
    /// log at the provided lid location.
    pub fn ptr(&self) -> DiskPtr {
        if let Some(blob_ptr) = self.blob_ptr() {
            DiskPtr::new_blob(self.lid, blob_ptr)
        } else {
            DiskPtr::new_inline(self.lid)
        }
    }

    fn blob_ptr(&self) -> Option<BlobPointer> {
        if self.is_blob {
            let mut blob_ptr_bytes =
                [0u8; std::mem::size_of::<Lsn>()];
            blob_ptr_bytes
                .copy_from_slice(&self.data[MSG_HEADER_LEN..]);
            let blob_ptr = arr_to_u64(blob_ptr_bytes) as BlobPointer;

            Some(blob_ptr)
        } else {
            None
        }
    }

    fn flush(&mut self, valid: bool) -> Result<(Lsn, DiskPtr), ()> {
        if self.flushed {
            panic!("flushing already-flushed reservation!");
        }

        self.flushed = true;

        if !valid {
            self.data[0] = FAILED_FLUSH;
            // don't actually zero the message, still check its hash
            // on recovery to find corruption.
        }

        self.destination.copy_from_slice(&*self.data);

        self.iobufs.exit_reservation(self.idx)?;

        Ok((self.lsn(), self.ptr()))
    }
}
<|endoftext|>