<commit_before>#![feature(asm)]

// External libraries
extern crate dylib;
use dylib::DynamicLibrary;

use std::path::Path;
use std::mem::transmute;

use std::process::Command;
use std::thread;

use std::sync::atomic::{AtomicBool, Ordering, AtomicPtr};
use std::option::Option;

use std::sync::{Arc, RwLock};
use std::fmt;

// Internal libraries
extern crate gr;
use gr::*;

#[derive(Clone)]
enum OpType {
    Func(String),
    Const(usize),
    Var(usize),
    UVar(usize),
    Op(String),
    Pow(i32)
}

impl fmt::Display for OpType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

        let outstring = match self {
            &OpType::Func(ref s) => format!("f{}", s),
            &OpType::Const(i) => format!("c{}", i),
            &OpType::Var(i) => format!("i{}", i),
            &OpType::UVar(i) => format!("v{}", i),
            &OpType::Op(ref s) => format!("o{}", s),
            &OpType::Pow(i) => format!("p{}", i)
        };
        write!(f, "{}", outstring)
    }

}

#[derive(Clone)]
pub struct FuncObj {
    handle: Arc<RwLock<Option<DynamicLibrary>>>,
    user_vars: Vec<GI>,
    constants: Vec<GI>,
    instructions: Vec<OpType>,
    switched: Arc<AtomicBool>,
    function: Arc<AtomicPtr<fn(&Vec<GI>, &Vec<GI>) -> GI>>,

}

unsafe impl Sync for FuncObj {}
unsafe impl Send for FuncObj {}
fn dummy(_x: &Vec<GI>, _c: &Vec<GI>) -> GI {
    GI::new_c("1.0").unwrap()
}

impl FuncObj {
    pub fn call(&self, _x: &Vec<GI>) -> GI {
        if self.switched.load(Ordering::Acquire) {
            let real_func = unsafe{
                std::mem::transmute::<*mut fn(&Vec<GI>, &Vec<GI>)->GI,
                                      fn(&Vec<GI>, &Vec<GI>)->GI>(
                    (self.function.load(Ordering::Acquire)))};
            real_func(_x, &self.constants)
        }
        else {
            self.interpreted(_x, &self.constants)
        }
    }

    fn set(&self, f: fn(&Vec<GI>,&Vec<GI>) -> GI, handle: DynamicLibrary) {
        // This FuncObj owns the handle from the dynamic lib as the lifetime of
        // f is tied to the lifetime of the handle.
        self.function.store(unsafe{std::mem::transmute::<fn(&Vec<GI>, &Vec<GI>)->GI,
                                                         *mut fn(&Vec<GI>, &Vec<GI>)->GI>(f)}, Ordering::Release);
        let mut h = self.handle.write().unwrap();
        *h = Some(handle);
        self.switched.store(true, Ordering::Release);
    }

    fn interpreted(&self, _x: &Vec<GI>, _c: &Vec<GI>) -> GI {
        let mut stack: Vec<GI> = Vec::new();
        for inst in &self.instructions {
            match inst {
                &OpType::Func(ref s) => {
                    let op = stack.last_mut().unwrap();
                    match s.as_str() {
                        "abs" => op.abs(),
                        "sin" => op.sin(),
                        "asin"=> op.asin(),
                        "cos" => op.cos(),
                        "acos" => op.acos(),
                        "tan" => op.tan(),
                        "atan" => op.atan(),
                        "exp" => op.exp(),
                        "log" => op.log(),
                        "neg" => op.neg(),
                        "sqrt" => op.sqrt(),
                        _     => unreachable!()
                    };
                },
                &OpType::Const(i) => {
                    stack.push(self.constants[i]);
                },
                &OpType::Var(i) => {
                    stack.push(_x[i]);
                },
                &OpType::UVar(i) => {
                    stack.push(self.user_vars[i]);
                },
                &OpType::Op(ref s) => {
                    let right = stack.pop().unwrap();
                    let left = stack.last_mut().unwrap();
                    match s.as_str() {
                        "+" => left.add(right),
                        "-" => left.sub(right),
                        "*" => left.mul(right),
                        "/" => left.div(right),
                        "p" => left.powi(right),
                        _   => unreachable!()
                    };
                },
                &OpType::Pow(exp) => {
                    let arg = stack.last_mut().unwrap();
                    arg.pow(exp);
                }
            }
        }
        stack[0]
    }

    pub fn new(consts: &Vec<GI>, instructions: &String, debug: bool, suffix: String) -> FuncObj {
        let mut insts = vec![];

        for inst in instructions.split(',') {
            let dummy = inst.trim().to_string();
            let (first, rest) = dummy.split_at(1);
            insts.push(match first {
                "c" => OpType::Const(rest.to_string().parse::<usize>().unwrap()),
                "i" => OpType::Var(rest.to_string().parse::<usize>().unwrap()),
                "v" => OpType::UVar(rest.to_string().parse::<usize>().unwrap()),
                "o" => OpType::Op(rest.to_string()),
                "f" => OpType::Func(rest.to_string()),
                "p" => OpType::Pow(rest.to_string().parse::<i32>().unwrap()),
                _   => panic!()
            });
        }
        let result =
            FuncObj{handle: Arc::new(RwLock::new(Option::None)),
                user_vars: vec![],
                constants: consts.clone(),
                instructions: insts,
                switched: Arc::new(AtomicBool::new(false)),
                function: Arc::new(AtomicPtr::new(unsafe{std::mem::transmute::<fn(&Vec<GI>, &Vec<GI>)->GI,
                                                                               *mut fn(&Vec<GI>, &Vec<GI>)->GI>(dummy)}))
        };

        {
            let fo_c = result.clone();
            thread::spawn(move || {
                &fo_c.compile(debug, &suffix);
            })
        };
        result
    }

    fn compile(&self, debug: bool, suffix: &String) {
        let mut process = Command::new("build_func.sh");
        if debug {
            println!("compile suffix: {}", suffix);
        }
        let ignore = process.arg(suffix.clone()).output()
            .unwrap_or_else(|e| {panic!("Could not compile: {}", e)});

        if !ignore.status.success() {
            panic!("Could not compile: {}\n----\n{}", String::from_utf8(ignore.stdout).unwrap(),
                   String::from_utf8(ignore.stderr).unwrap());
        }

        DynamicLibrary::prepend_search_path(Path::new("./.compiled"));
        let dylib: String = "libfunc_".to_string() + suffix + ".so".into();

        let f = match DynamicLibrary::open(Some(Path::new(&dylib)))
        {
            Ok(lib) => lib,
            Err(err) => panic!("Could not load library: {}", err)
        };
        let g = unsafe{match f.symbol("gelpia_func") {
            Ok(func) => transmute::<*mut u32, fn(&Vec<GI>, &Vec<GI>)->GI>(func),
            Err(err) => panic!("Could not load function: {}", err),
        }};

        self.set(g, f);
    }
}

#[test]
fn test1() {
    let constants = vec![GI::new_c("1"), GI::new_c("2"), GI::new_c("3")];
    let f = FuncObj::new(&constants,
                         &"c0,c1,o-,c2,o+".to_string());
    let expected = ((GI::new_c("1") - GI::new_c("2")) + GI::new_c("3")).to_string();
    assert!(f.call(&vec![]).to_string() == expected);
}

#[test]
fn test2() {
    let consts = vec![GI::new_c("1"), GI::new_c("2"), GI::new_c("3")];
    let f = FuncObj::new(&consts,
                         &"c0,fsin,c1,o*,fcos,c2,o/".to_string());
    let expected = cos(sin(consts[0]) * consts[1])/consts[2];
    assert!(f.call(&vec![]).to_string() == expected.to_string());
}

#[test]
fn sum_inputs() {
    let consts = vec![];
    let v = vec![GI::new_d(1.0, 1.0), GI::new_d(1.0, 2.0), GI::new_d(1.0, 3.0),
                 GI::new_d(1.0, 4.0), GI::new_d(1.0, 5.0), GI::new_d(1.0, 6.0)];
    let f = FuncObj::new(&consts,
                         &"i0,i1, o+, i2, o+, i3, o+, i4, o+, i5, o+".to_string());
    let expected = (v[0] + v[1] + v[2] + v[3] + v[4] + v[5]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test3() {
    let consts = vec![GI::new_c("0.1")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, fsin".to_string());
    let expected = sin(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test4() {
    let consts = vec![GI::new_c("[-3, 4]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, fabs".to_string());
    let expected = abs(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test5() {
    let consts = vec![GI::new_c("[-3, 4]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, fcos".to_string());
    let expected = cos(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test6() {
    let consts = vec![GI::new_c("[-3, 4]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, ftan".to_string());
    let expected = tan(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test7() {
    let consts = vec![GI::new_c("[-3, 4]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, fexp".to_string());
    let expected = exp(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test8() {
    let consts = vec![GI::new_c("[-3, 4]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, fneg".to_string());
    let expected = (-consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test9() {
    let consts = vec![GI::new_c("[0.1, .2]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, flog".to_string());
    let expected = log(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}
#[test]
fn test10() {
    let consts = vec![GI::new_c("[2.0, 3.0]"),
                      GI::new_c("[1.5, 2.5]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                         &"c0, c1, op".to_string());
    let expected = powi(consts[0], consts[1]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}
#[test]
fn test_power() {
    let consts = vec![GI::new_c("[2.0, 3.0]"),
                      GI::new_c("[1.5, 2.5]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                         &"c0, p-1, c1, p2, o+".to_string());
    let expected = (pow(consts[0], -1) + pow(consts[1], 2)).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}
<commit_msg>Added hyperbolic functions to function library.<commit_after>#![feature(asm)]

// External libraries
extern crate dylib;
use dylib::DynamicLibrary;

use std::path::Path;
use std::mem::transmute;

use std::process::Command;
use std::thread;

use std::sync::atomic::{AtomicBool, Ordering, AtomicPtr};
use std::option::Option;

use std::sync::{Arc, RwLock};
use std::fmt;

// Internal libraries
extern crate gr;
use gr::*;

#[derive(Clone)]
enum OpType {
    Func(String),
    Const(usize),
    Var(usize),
    UVar(usize),
    Op(String),
    Pow(i32)
}

impl fmt::Display for OpType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

        let outstring = match self {
            &OpType::Func(ref s) => format!("f{}", s),
            &OpType::Const(i) => format!("c{}", i),
            &OpType::Var(i) => format!("i{}", i),
            &OpType::UVar(i) => format!("v{}", i),
            &OpType::Op(ref s) => format!("o{}", s),
            &OpType::Pow(i) => format!("p{}", i)
        };
        write!(f, "{}", outstring)
    }

}

#[derive(Clone)]
pub struct FuncObj {
    handle: Arc<RwLock<Option<DynamicLibrary>>>,
    user_vars: Vec<GI>,
    constants: Vec<GI>,
    instructions: Vec<OpType>,
    switched: Arc<AtomicBool>,
    function: Arc<AtomicPtr<fn(&Vec<GI>, &Vec<GI>) -> GI>>,

}

unsafe impl Sync for FuncObj {}
unsafe impl Send for FuncObj {}
fn dummy(_x: &Vec<GI>, _c: &Vec<GI>) -> GI {
    GI::new_c("1.0").unwrap()
}

impl FuncObj {
    pub fn call(&self, _x: &Vec<GI>) -> GI {
        if self.switched.load(Ordering::Acquire) {
            let real_func = unsafe{
                std::mem::transmute::<*mut fn(&Vec<GI>, &Vec<GI>)->GI,
                                      fn(&Vec<GI>, &Vec<GI>)->GI>(
                    (self.function.load(Ordering::Acquire)))};
            real_func(_x, &self.constants)
        }
        else {
            self.interpreted(_x, &self.constants)
        }
    }

    fn set(&self, f: fn(&Vec<GI>,&Vec<GI>) -> GI, handle: DynamicLibrary) {
        // This FuncObj owns the handle from the dynamic lib as the lifetime of
        // f is tied to the lifetime of the handle.
        self.function.store(unsafe{std::mem::transmute::<fn(&Vec<GI>, &Vec<GI>)->GI,
                                                         *mut fn(&Vec<GI>, &Vec<GI>)->GI>(f)}, Ordering::Release);
        let mut h = self.handle.write().unwrap();
        *h = Some(handle);
        self.switched.store(true, Ordering::Release);
    }

    fn interpreted(&self, _x: &Vec<GI>, _c: &Vec<GI>) -> GI {
        let mut stack: Vec<GI> = Vec::new();
        for inst in &self.instructions {
            match inst {
                &OpType::Func(ref s) => {
                    let op = stack.last_mut().unwrap();
                    match s.as_str() {
                        "abs" => op.abs(),
                        "sin" => op.sin(),
                        "asin"=> op.asin(),
                        "cos" => op.cos(),
                        "acos" => op.acos(),
                        "tan" => op.tan(),
                        "atan" => op.atan(),
                        "exp" => op.exp(),
                        "log" => op.log(),
                        "neg" => op.neg(),
                        "sqrt" => op.sqrt(),
                        "sinh" => op.sinh(),
                        "cosh" => op.cosh(),
                        "tanh" => op.tanh(),
                        "asinh" => op.asinh(),
                        "acosh" => op.acosh(),
                        "atanh" => op.atanh(),
                        _     => unreachable!()
                    };
                },
                &OpType::Const(i) => {
                    stack.push(self.constants[i]);
                },
                &OpType::Var(i) => {
                    stack.push(_x[i]);
                },
                &OpType::UVar(i) => {
                    stack.push(self.user_vars[i]);
                },
                &OpType::Op(ref s) => {
                    let right = stack.pop().unwrap();
                    let left = stack.last_mut().unwrap();
                    match s.as_str() {
                        "+" => left.add(right),
                        "-" => left.sub(right),
                        "*" => left.mul(right),
                        "/" => left.div(right),
                        "p" => left.powi(right),
                        _   => unreachable!()
                    };
                },
                &OpType::Pow(exp) => {
                    let arg = stack.last_mut().unwrap();
                    arg.pow(exp);
                }
            }
        }
        stack[0]
    }

    pub fn new(consts: &Vec<GI>, instructions: &String, debug: bool, suffix: String) -> FuncObj {
        let mut insts = vec![];

        for inst in instructions.split(',') {
            let dummy = inst.trim().to_string();
            let (first, rest) = dummy.split_at(1);
            insts.push(match first {
                "c" => OpType::Const(rest.to_string().parse::<usize>().unwrap()),
                "i" => OpType::Var(rest.to_string().parse::<usize>().unwrap()),
                "v" => OpType::UVar(rest.to_string().parse::<usize>().unwrap()),
                "o" => OpType::Op(rest.to_string()),
                "f" => OpType::Func(rest.to_string()),
                "p" => OpType::Pow(rest.to_string().parse::<i32>().unwrap()),
                _   => panic!()
            });
        }
        let result =
            FuncObj{handle: Arc::new(RwLock::new(Option::None)),
                user_vars: vec![],
                constants: consts.clone(),
                instructions: insts,
                switched: Arc::new(AtomicBool::new(false)),
                function: Arc::new(AtomicPtr::new(unsafe{std::mem::transmute::<fn(&Vec<GI>, &Vec<GI>)->GI,
                                                                               *mut fn(&Vec<GI>, &Vec<GI>)->GI>(dummy)}))
        };

        {
            let fo_c = result.clone();
            thread::spawn(move || {
                &fo_c.compile(debug, &suffix);
            })
        };
        result
    }

    fn compile(&self, debug: bool, suffix: &String) {
        let mut process = Command::new("build_func.sh");
        if debug {
            println!("compile suffix: {}", suffix);
        }
        let ignore = process.arg(suffix.clone()).output()
            .unwrap_or_else(|e| {panic!("Could not compile: {}", e)});

        if !ignore.status.success() {
            panic!("Could not compile: {}\n----\n{}", String::from_utf8(ignore.stdout).unwrap(),
                   String::from_utf8(ignore.stderr).unwrap());
        }

        DynamicLibrary::prepend_search_path(Path::new("./.compiled"));
        let dylib: String = "libfunc_".to_string() + suffix + ".so".into();

        let f = match DynamicLibrary::open(Some(Path::new(&dylib)))
        {
            Ok(lib) => lib,
            Err(err) => panic!("Could not load library: {}", err)
        };
        let g = unsafe{match f.symbol("gelpia_func") {
            Ok(func) => transmute::<*mut u32, fn(&Vec<GI>, &Vec<GI>)->GI>(func),
            Err(err) => panic!("Could not load function: {}", err),
        }};

        self.set(g, f);
    }
}

#[test]
fn test1() {
    let constants = vec![GI::new_c("1"), GI::new_c("2"), GI::new_c("3")];
    let f = FuncObj::new(&constants,
                         &"c0,c1,o-,c2,o+".to_string());
    let expected = ((GI::new_c("1") - GI::new_c("2")) + GI::new_c("3")).to_string();
    assert!(f.call(&vec![]).to_string() == expected);
}

#[test]
fn test2() {
    let consts = vec![GI::new_c("1"), GI::new_c("2"), GI::new_c("3")];
    let f = FuncObj::new(&consts,
                         &"c0,fsin,c1,o*,fcos,c2,o/".to_string());
    let expected = cos(sin(consts[0]) * consts[1])/consts[2];
    assert!(f.call(&vec![]).to_string() == expected.to_string());
}

#[test]
fn sum_inputs() {
    let consts = vec![];
    let v = vec![GI::new_d(1.0, 1.0), GI::new_d(1.0, 2.0), GI::new_d(1.0, 3.0),
                 GI::new_d(1.0, 4.0), GI::new_d(1.0, 5.0), GI::new_d(1.0, 6.0)];
    let f = FuncObj::new(&consts,
                         &"i0,i1, o+, i2, o+, i3, o+, i4, o+, i5, o+".to_string());
    let expected = (v[0] + v[1] + v[2] + v[3] + v[4] + v[5]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test3() {
    let consts = vec![GI::new_c("0.1")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, fsin".to_string());
    let expected = sin(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test4() {
    let consts = vec![GI::new_c("[-3, 4]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, fabs".to_string());
    let expected = abs(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test5() {
    let consts = vec![GI::new_c("[-3, 4]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, fcos".to_string());
    let expected = cos(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test6() {
    let consts = vec![GI::new_c("[-3, 4]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, ftan".to_string());
    let expected = tan(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test7() {
    let consts = vec![GI::new_c("[-3, 4]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, fexp".to_string());
    let expected = exp(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test8() {
    let consts = vec![GI::new_c("[-3, 4]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, fneg".to_string());
    let expected = (-consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}

#[test]
fn test9() {
    let consts = vec![GI::new_c("[0.1, .2]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                &"c0, flog".to_string());
    let expected = log(consts[0]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}
#[test]
fn test10() {
    let consts = vec![GI::new_c("[2.0, 3.0]"),
                      GI::new_c("[1.5, 2.5]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                         &"c0, c1, op".to_string());
    let expected = powi(consts[0], consts[1]).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}
#[test]
fn test_power() {
    let consts = vec![GI::new_c("[2.0, 3.0]"),
                      GI::new_c("[1.5, 2.5]")];
    let v = vec![];
    let f = FuncObj::new(&consts,
                         &"c0, p-1, c1, p2, o+".to_string());
    let expected = (pow(consts[0], -1) + pow(consts[1], 2)).to_string();
    let real = f.call(&v).to_string();
    assert!(real == expected, "real = {}, expected = {}", real, expected);
}
<|endoftext|>


<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::config::TestOnlyConfig;
use anyhow::Context;
use guppy::graph::{BuildTargetId, BuildTargetKind, PackageGraph, PackageSet};
use indoc::indoc;
use x_core::WorkspaceStatus;
use x_lint::prelude::*;

/// Ensure that every package in the workspace is classified as either a default member or test-only.
#[derive(Debug)]
pub struct DefaultOrTestOnly<'cfg> {
    test_only: PackageSet<'cfg>,
}

impl<'cfg> DefaultOrTestOnly<'cfg> {
    pub fn new(package_graph: &'cfg PackageGraph, config: &TestOnlyConfig) -> crate::Result<Self> {
        let test_only = package_graph
            .resolve_workspace_names(&config.members)
            .with_context(|| "error while initializing default-or-test-only lint")?;
        Ok(Self { test_only })
    }
}

impl<'cfg> Linter for DefaultOrTestOnly<'cfg> {
    fn name(&self) -> &'static str {
        "default-or-test-only"
    }
}

impl<'cfg> PackageLinter for DefaultOrTestOnly<'cfg> {
    fn run<'l>(
        &self,
        ctx: &PackageContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let default_members = ctx.project_ctx().default_members()?;
        let package = ctx.metadata();

        let binary_kind = package
            .build_targets()
            .filter_map(|target| {
                if matches!(target.id(), BuildTargetId::Binary(_)) {
                    return Some("binary");
                }
                // If this is the library target, then look for the first binary-equivalent-kind
                if let (BuildTargetId::Library, BuildTargetKind::LibraryOrExample(crate_types)) =
                    (target.id(), target.kind())
                {
                    return crate_types
                        .iter()
                        .filter_map(|crate_type| {
                            // These library types are equivalent to binaries.
                            if crate_type == "cdylib"
                                || crate_type == "dylib"
                                || crate_type == "staticlib"
                            {
                                Some(crate_type.as_str())
                            } else {
                                None
                            }
                        })
                        .next();
                }
                None
            })
            .next();

        let status = default_members.status_of(package.id());
        let test_only = self
            .test_only
            .contains(package.id())
            .expect("package is known");

        match (binary_kind, status, test_only) {
            (None, WorkspaceStatus::Absent, false) => {
                // Library, not reachable from default members and not marked test-only.
                let msg = indoc!(
                    "library package, not a dependency of default-members:
                     * if test-only, add to test-only in x.toml
                     * otherwise, make it a dependency of a default member (listed in root Cargo.toml)"
                );
                out.write(LintLevel::Error, msg);
            }
            (None, WorkspaceStatus::Absent, true) => {
                // Test-only library package. This is fine.
            }
            (None, WorkspaceStatus::Dependency, false) => {
                // Library, dependency of default members. This is fine.
            }
            (None, WorkspaceStatus::Dependency, true) => {
                // Library, dependency of default members and listed in test-only.

                // For a better error message, look at what immediately depends on the package and
                // is in default members.
                let mut reverse_deps = package
                    .reverse_direct_links()
                    .filter_map(|link| {
                        if !link.dev_only()
                            && default_members.status_of(link.from().id())
                                != WorkspaceStatus::Absent
                        {
                            Some(link.from().name())
                        } else {
                            None
                        }
                    })
                    .collect::<Vec<_>>();
                reverse_deps.sort_unstable();
                let reverse_str = reverse_deps.join(", ");
                let msg = format!(
                    "{} {}",
                    indoc!(
                        "library package, dependency of default members and test-only:
                        * remove from test-only if production code
                        * otherwise, ensure it is not a dependency of default members:",
                    ),
                    reverse_str,
                );
                out.write(LintLevel::Error, msg);
            }
            (None, WorkspaceStatus::RootMember, false) => {
                // Library, listed in default members. It shouldn't be.
                let msg = indoc!(
                    "library package, listed in default-members:
                     * if test-only, add to test-only in x.toml instead
                     * otherwise, remove it from default-members and make it a dependency of a binary"
                );
                out.write(LintLevel::Error, msg);
            }
            (None, WorkspaceStatus::RootMember, true) => {
                // Library, listed in default members and in test-only. It shouldn't be.
                let msg = indoc!(
                    "library package, listed in default-members and test-only:
                     * if test-only, add to test-only in x.toml and remove from default-members
                     * otherwise, remove it from both and make it a dependency of a default-member"
                );
                out.write(LintLevel::Error, msg);
            }
            (Some(kind), WorkspaceStatus::Absent, false) => {
                // Binary, not listed in default members, not test-only and not reachable from one.
                let msg = format!(
                    "{} {}",
                    kind,
                    indoc!(
                        "package, not listed in default-members:
                         * if test-only, add to test-only in x.toml
                         * otherwise, list it in root Cargo.toml's default-members"
                    ),
                );
                out.write(LintLevel::Error, msg);
            }
            (Some(_), WorkspaceStatus::Absent, true) => {
                // Test-only binary. This is fine.
            }
            (Some(kind), WorkspaceStatus::Dependency, false) => {
                // Binary, not listed in default members but reachable from one.
                let msg = format!(
                    "{} {}",
                    kind,
                    indoc!(
                        "package, not listed in default-members:
                         * list it in root Cargo.toml's default-members
                         (note: dependency of a default member, so assumed to be a production crate)"
                    ),
                );
                out.write(LintLevel::Error, msg)
            }
            (Some(kind), WorkspaceStatus::Dependency, true) => {
                // Binary, not listed in default members but a dependency of one + test-only
                let msg = format!(
                    "{} {}",
                    kind,
                    indoc!(
                        "package, not listed in default-members but a dependency, and in test-only:
                         * remove it from test-only in x.toml, AND
                         * list it in root Cargo.toml's default-members
                         (note: dependency of a default member, so assumed to be a production crate)"
                    ),
                );
                out.write(LintLevel::Error, msg)
            }
            (Some(_), WorkspaceStatus::RootMember, false) => {
                // Binary, listed in default-members. This is fine.
            }
            (Some(kind), WorkspaceStatus::RootMember, true) => {
                // Binary, listed in default-members and test-only.
                let msg = format!(
                    "{} {}",
                    kind,
                    indoc!(
                        "package, listed in both default-members and test-only:
                         * remove it from test-only in x.toml
                         (note: default member, so assumed to be a production crate)"
                    ),
                );
                out.write(LintLevel::Error, msg)
            }
        }

        Ok(RunStatus::Executed)
    }
}
<commit_msg>x: allow published packages in default-members<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::config::TestOnlyConfig;
use anyhow::Context;
use guppy::graph::{BuildTargetId, BuildTargetKind, PackageGraph, PackageSet};
use indoc::indoc;
use x_core::WorkspaceStatus;
use x_lint::prelude::*;

/// Ensure that every package in the workspace is classified as either a default member or test-only.
#[derive(Debug)]
pub struct DefaultOrTestOnly<'cfg> {
    test_only: PackageSet<'cfg>,
}

impl<'cfg> DefaultOrTestOnly<'cfg> {
    pub fn new(package_graph: &'cfg PackageGraph, config: &TestOnlyConfig) -> crate::Result<Self> {
        let test_only = package_graph
            .resolve_workspace_names(&config.members)
            .with_context(|| "error while initializing default-or-test-only lint")?;
        Ok(Self { test_only })
    }
}

impl<'cfg> Linter for DefaultOrTestOnly<'cfg> {
    fn name(&self) -> &'static str {
        "default-or-test-only"
    }
}

impl<'cfg> PackageLinter for DefaultOrTestOnly<'cfg> {
    fn run<'l>(
        &self,
        ctx: &PackageContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let default_members = ctx.project_ctx().default_members()?;
        let package = ctx.metadata();

        let binary_kind = package
            .build_targets()
            .filter_map(|target| {
                if matches!(target.id(), BuildTargetId::Binary(_)) {
                    return Some("binary");
                }
                // If this is the library target, then look for the first binary-equivalent-kind
                if let (BuildTargetId::Library, BuildTargetKind::LibraryOrExample(crate_types)) =
                    (target.id(), target.kind())
                {
                    return crate_types
                        .iter()
                        .filter_map(|crate_type| {
                            // These library types are equivalent to binaries.
                            if crate_type == "cdylib"
                                || crate_type == "dylib"
                                || crate_type == "staticlib"
                            {
                                Some(crate_type.as_str())
                            } else {
                                None
                            }
                        })
                        .next();
                }
                None
            })
            .next();

        let status = default_members.status_of(package.id());
        let test_only = self
            .test_only
            .contains(package.id())
            .expect("package is known");

        match (binary_kind, status, test_only) {
            (None, WorkspaceStatus::Absent, false) => {
                // Library, not reachable from default members and not marked test-only.
                let msg = indoc!(
                    "library package, not a dependency of default-members:
                     * if test-only, add to test-only in x.toml
                     * otherwise, make it a dependency of a default member (listed in root Cargo.toml)"
                );
                out.write(LintLevel::Error, msg);
            }
            (None, WorkspaceStatus::Absent, true) => {
                // Test-only library package. This is fine.
            }
            (None, WorkspaceStatus::Dependency, false) => {
                // Library, dependency of default members. This is fine.
            }
            (None, WorkspaceStatus::Dependency, true) => {
                // Library, dependency of default members and listed in test-only.

                // For a better error message, look at what immediately depends on the package and
                // is in default members.
                let mut reverse_deps = package
                    .reverse_direct_links()
                    .filter_map(|link| {
                        if !link.dev_only()
                            && default_members.status_of(link.from().id())
                                != WorkspaceStatus::Absent
                        {
                            Some(link.from().name())
                        } else {
                            None
                        }
                    })
                    .collect::<Vec<_>>();
                reverse_deps.sort_unstable();
                let reverse_str = reverse_deps.join(", ");
                let msg = format!(
                    "{} {}",
                    indoc!(
                        "library package, dependency of default members and test-only:
                        * remove from test-only if production code
                        * otherwise, ensure it is not a dependency of default members:",
                    ),
                    reverse_str,
                );
                out.write(LintLevel::Error, msg);
            }
            (None, WorkspaceStatus::RootMember, false) => {
                if matches!(package.publish(), Some(&[])) {
                    // Library, listed in default members. It shouldn't be.
                    // unless it is a published library
                    let msg = indoc!(
                        "library package, listed in default-members:
                         * if test-only, add to test-only in x.toml instead
                         * if the library is intended to be published, add `publish = [\"crates-io\"] to the Cargo.toml of this package
                         * otherwise, remove it from default-members and make it a dependency of a binary"
                    );
                    out.write(LintLevel::Error, msg);
                }
            }
            (None, WorkspaceStatus::RootMember, true) => {
                // Library, listed in default members and in test-only. It shouldn't be.
                let msg = indoc!(
                    "library package, listed in default-members and test-only:
                     * if test-only, add to test-only in x.toml and remove from default-members
                     * otherwise, remove it from both and make it a dependency of a default-member"
                );
                out.write(LintLevel::Error, msg);
            }
            (Some(kind), WorkspaceStatus::Absent, false) => {
                // Binary, not listed in default members, not test-only and not reachable from one.
                let msg = format!(
                    "{} {}",
                    kind,
                    indoc!(
                        "package, not listed in default-members:
                         * if test-only, add to test-only in x.toml
                         * otherwise, list it in root Cargo.toml's default-members"
                    ),
                );
                out.write(LintLevel::Error, msg);
            }
            (Some(_), WorkspaceStatus::Absent, true) => {
                // Test-only binary. This is fine.
            }
            (Some(kind), WorkspaceStatus::Dependency, false) => {
                // Binary, not listed in default members but reachable from one.
                let msg = format!(
                    "{} {}",
                    kind,
                    indoc!(
                        "package, not listed in default-members:
                         * list it in root Cargo.toml's default-members
                         (note: dependency of a default member, so assumed to be a production crate)"
                    ),
                );
                out.write(LintLevel::Error, msg)
            }
            (Some(kind), WorkspaceStatus::Dependency, true) => {
                // Binary, not listed in default members but a dependency of one + test-only
                let msg = format!(
                    "{} {}",
                    kind,
                    indoc!(
                        "package, not listed in default-members but a dependency, and in test-only:
                         * remove it from test-only in x.toml, AND
                         * list it in root Cargo.toml's default-members
                         (note: dependency of a default member, so assumed to be a production crate)"
                    ),
                );
                out.write(LintLevel::Error, msg)
            }
            (Some(_), WorkspaceStatus::RootMember, false) => {
                // Binary, listed in default-members. This is fine.
            }
            (Some(kind), WorkspaceStatus::RootMember, true) => {
                // Binary, listed in default-members and test-only.
                let msg = format!(
                    "{} {}",
                    kind,
                    indoc!(
                        "package, listed in both default-members and test-only:
                         * remove it from test-only in x.toml
                         (note: default member, so assumed to be a production crate)"
                    ),
                );
                out.write(LintLevel::Error, msg)
            }
        }

        Ok(RunStatus::Executed)
    }
}
<|endoftext|>


<commit_before>// FIXME: Replace these examples with executable tests
//! Traits related to relationships between multiple tables.
//!
//! **Note: This feature is under active development, and we are seeking feedback on the APIs that
//! have been released. Please feel free to [open issues][open-issue], or join [our chat][gitter]
//! to provide feedback.**
//!
//! [open-issue]: https://github.com/diesel-rs/diesel/issues/new
//! [gitter]: https://gitter.im/diesel-rs/diesel
//!
//! Note: This guide is written assuming the usage of `diesel_codegen` or `diesel_codegen_syntex`.
//! If you are using [`custom_derive`][custom-derive] instead, you will need to replace
//! `#[belongs_to(Foo)]` with `#[derive(BelongsTo(Foo, foreign_key = foo_id))]` and
//! `#[has_many(bars)]` with `#[derive(HasMany(bars, foreign_key = bar_id))]`.
//!
//! [custom-derive]: https://crates.io/crates/custom_derive
//!
//! Associations in Diesel are bidirectional, but primarily focus on the child-to-parent
//! relationship. You can declare an association between two records with `#[has_many]` and
//! `#[belongs_to]`.
//!
//! ```ignore
//! #[derive(Identifiable, Queryable)]
//! #[has_many(posts)]
//! pub struct User {
//!     id: i32,
//!     name: String,
//! }
//!
//! #[derive(Identifiable, Queryable)]
//! #[belongs_to(User)]
//! pub struct Post {
//!     id: i32,
//!     user_id: i32,
//!     title: String,
//! }
//! ```
//!
//! `#[has_many]` should be passed the name of the table that the children will be loaded from,
//! while `#[belongs_to]` is given the name of the struct that represents the parent. Both types
//! must implement the [`Identifiable`][identifiable] trait.
//!
//! [Identifiable]: associations/trait.Identifiable.html
//!
//! `#[has_many]` actually has no behavior on its own. It only enables joining between the two
//! tables. If you are only accessing data through the [`belonging_to`][belonging-to] method, you
//! only need to define the `#[belongs_to]` side.
//!
//! Once the associations are defined, you can join between the two tables using the
//! [`inner_join`][inner-join] or [`left_outer_join`][left-outer-join].
//!
//! [inner-join]: query_source/trait.Table.html#method.inner_join
//! [left-outer-join]: query_source/trait.Table.html#method.left_outer_join
//!
//! ```ignore
//! let data: Vec<(User, Post)> = users::table.inner_join(posts::table).load(&connection);
//! ```
//!
//! Note: Due to language limitations, only two tables can be joined per query. This will change in
//! the future.
//!
//! Typically however, queries are loaded in multiple queries. For most datasets, the reduced
//! amount of duplicated information sent over the wire saves more time than the extra round trip
//! costs us. You can load the children for a single parent using the
//! [`belonging_to`][belonging-to]
//!
//! [belonging-to]: prelude/trait.BelongingToDsl.html#tymethod.belonging_to
//!
//! ```ignore
//! let user = try!(users::find(1).first(&connection));
//! let posts = Post::belonging_to(&user).load(&connection);
//! ```
//!
//! If you're coming from other ORMs, you'll notice that this design is quite different from most.
//! There you would have an instance method on the parent, or have the children stored somewhere on
//! the posts. This design leads to many problems, including [N+1 query
//! bugs][load-your-entire-database-into-memory-lol], and runtime errors when accessing an
//! association that isn't there.
//!
//! [load-your-entire-database-into-memory-lol]: http://stackoverflow.com/q/97197/1254484
//!
//! In Diesel, data and its associations are considered to be separate. If you want to pass around
//! a user and all of its posts, that type is `(User, Vec<Post>)`.
//!
//! Next lets look at how to load the children for more than one parent record.
//! [`belonging_to`][belonging-to] can be used to load the data, but we'll also need to group it
//! with its parents. For this we use an additional method [`grouped_by`][grouped-by]
//!
//! [grouped-by]: associations/trait.GroupedBy.html#tymethod.grouped_by
//!
//! ```ignore
//! fn first_twenty_users_and_their_posts(conn: &PgConnection) -> QueryResult<Vec<(User, Vec<Post>)>> {
//!     let users = try!(users::limit(20).load::<User>(conn));
//!     let posts = try!(Post::belonging_to(&users).load::<Post>(conn));
//!     let grouped_posts = posts.grouped_by(&users);
//!     users.into_iter().zip(grouped_posts).collect()
//! }
//! ```
//!
//! [`grouped_by`][grouped-by] takes a `Vec<Child>` and a `Vec<Parent>` and returns a
//! `Vec<Vec<Child>>` where the index of the children matches the index of the parent they belong
//! to. Or to put it another way, it returns them in an order ready to be `zip`ed with the parents. You
//! can do this multiple times. For example, if you wanted to load the comments for all the posts
//! as well, you could do this: (explicit type annotations have been added for documentation
//! purposes)
//!
//! ```ignore
//! let posts: Vec<Post> = try!(Post::belonging_to(&users).load());
//! let comments: Vec<Comment> = try!(Comment::belonging_to(&posts).load());
//! let comments: Vec<Vec<Comment>> = comments.grouped_by(&posts);
//! let posts_and_comments: Vec<Vec<(Post, Vec<Comment>)>> = posts.into_iter().zip(comments).grouped_by(&users);
//! let result: Vec<(User, Vec<(Post, Vec<Comment>)>)> = users.into_iter().zip(posts_and_comments).collect();
//! ```
//!
//! And that's it. This module will be expanded in the future with more complex joins, and the
//! ability to define "through" associations (e.g. load all the comments left on any posts written
//! by a user in a single query). However, the goal is to provide simple building blocks which can
//! be used to construct the complex behavior applications need.
mod belongs_to;

use std::hash::Hash;

use query_dsl::FindDsl;
use query_source::Table;

pub use self::belongs_to::{BelongsTo, GroupedBy};

pub trait Identifiable {
    type Id: Hash + Eq + Copy;
    type Table: Table + FindDsl<Self::Id>;

    fn table() -> Self::Table;
    fn id(&self) -> Self::Id;
}
<commit_msg>Fix broken doc links<commit_after>// FIXME: Replace these examples with executable tests
//! Traits related to relationships between multiple tables.
//!
//! **Note: This feature is under active development, and we are seeking feedback on the APIs that
//! have been released. Please feel free to [open issues][open-issue], or join [our chat][gitter]
//! to provide feedback.**
//!
//! [open-issue]: https://github.com/diesel-rs/diesel/issues/new
//! [gitter]: https://gitter.im/diesel-rs/diesel
//!
//! Note: This guide is written assuming the usage of `diesel_codegen` or `diesel_codegen_syntex`.
//! If you are using [`custom_derive`][custom-derive] instead, you will need to replace
//! `#[belongs_to(Foo)]` with `#[derive(BelongsTo(Foo, foreign_key = foo_id))]` and
//! `#[has_many(bars)]` with `#[derive(HasMany(bars, foreign_key = bar_id))]`.
//!
//! [custom-derive]: https://crates.io/crates/custom_derive
//!
//! Associations in Diesel are bidirectional, but primarily focus on the child-to-parent
//! relationship. You can declare an association between two records with `#[has_many]` and
//! `#[belongs_to]`.
//!
//! ```ignore
//! #[derive(Identifiable, Queryable)]
//! #[has_many(posts)]
//! pub struct User {
//!     id: i32,
//!     name: String,
//! }
//!
//! #[derive(Identifiable, Queryable)]
//! #[belongs_to(User)]
//! pub struct Post {
//!     id: i32,
//!     user_id: i32,
//!     title: String,
//! }
//! ```
//!
//! `#[has_many]` should be passed the name of the table that the children will be loaded from,
//! while `#[belongs_to]` is given the name of the struct that represents the parent. Both types
//! must implement the [`Identifiable`][identifiable] trait.
//!
//! [Identifiable]: trait.Identifiable.html
//!
//! `#[has_many]` actually has no behavior on its own. It only enables joining between the two
//! tables. If you are only accessing data through the [`belonging_to`][belonging-to] method, you
//! only need to define the `#[belongs_to]` side.
//!
//! Once the associations are defined, you can join between the two tables using the
//! [`inner_join`][inner-join] or [`left_outer_join`][left-outer-join].
//!
//! [inner-join]: /diesel/query_source/trait.Table.html#method.inner_join
//! [left-outer-join]: /diesel/query_source/trait.Table.html#method.left_outer_join
//!
//! ```ignore
//! let data: Vec<(User, Post)> = users::table.inner_join(posts::table).load(&connection);
//! ```
//!
//! Note: Due to language limitations, only two tables can be joined per query. This will change in
//! the future.
//!
//! Typically however, queries are loaded in multiple queries. For most datasets, the reduced
//! amount of duplicated information sent over the wire saves more time than the extra round trip
//! costs us. You can load the children for a single parent using the
//! [`belonging_to`][belonging-to]
//!
//! [belonging-to]: /diesel/prelude/trait.BelongingToDsl.html#tymethod.belonging_to
//!
//! ```ignore
//! let user = try!(users::find(1).first(&connection));
//! let posts = Post::belonging_to(&user).load(&connection);
//! ```
//!
//! If you're coming from other ORMs, you'll notice that this design is quite different from most.
//! There you would have an instance method on the parent, or have the children stored somewhere on
//! the posts. This design leads to many problems, including [N+1 query
//! bugs][load-your-entire-database-into-memory-lol], and runtime errors when accessing an
//! association that isn't there.
//!
//! [load-your-entire-database-into-memory-lol]: http://stackoverflow.com/q/97197/1254484
//!
//! In Diesel, data and its associations are considered to be separate. If you want to pass around
//! a user and all of its posts, that type is `(User, Vec<Post>)`.
//!
//! Next lets look at how to load the children for more than one parent record.
//! [`belonging_to`][belonging-to] can be used to load the data, but we'll also need to group it
//! with its parents. For this we use an additional method [`grouped_by`][grouped-by]
//!
//! [grouped-by]: trait.GroupedBy.html#tymethod.grouped_by
//!
//! ```ignore
//! fn first_twenty_users_and_their_posts(conn: &PgConnection) -> QueryResult<Vec<(User, Vec<Post>)>> {
//!     let users = try!(users::limit(20).load::<User>(conn));
//!     let posts = try!(Post::belonging_to(&users).load::<Post>(conn));
//!     let grouped_posts = posts.grouped_by(&users);
//!     users.into_iter().zip(grouped_posts).collect()
//! }
//! ```
//!
//! [`grouped_by`][grouped-by] takes a `Vec<Child>` and a `Vec<Parent>` and returns a
//! `Vec<Vec<Child>>` where the index of the children matches the index of the parent they belong
//! to. Or to put it another way, it returns them in an order ready to be `zip`ed with the parents. You
//! can do this multiple times. For example, if you wanted to load the comments for all the posts
//! as well, you could do this: (explicit type annotations have been added for documentation
//! purposes)
//!
//! ```ignore
//! let posts: Vec<Post> = try!(Post::belonging_to(&users).load());
//! let comments: Vec<Comment> = try!(Comment::belonging_to(&posts).load());
//! let comments: Vec<Vec<Comment>> = comments.grouped_by(&posts);
//! let posts_and_comments: Vec<Vec<(Post, Vec<Comment>)>> = posts.into_iter().zip(comments).grouped_by(&users);
//! let result: Vec<(User, Vec<(Post, Vec<Comment>)>)> = users.into_iter().zip(posts_and_comments).collect();
//! ```
//!
//! And that's it. This module will be expanded in the future with more complex joins, and the
//! ability to define "through" associations (e.g. load all the comments left on any posts written
//! by a user in a single query). However, the goal is to provide simple building blocks which can
//! be used to construct the complex behavior applications need.
mod belongs_to;

use std::hash::Hash;

use query_dsl::FindDsl;
use query_source::Table;

pub use self::belongs_to::{BelongsTo, GroupedBy};

pub trait Identifiable {
    type Id: Hash + Eq + Copy;
    type Table: Table + FindDsl<Self::Id>;

    fn table() -> Self::Table;
    fn id(&self) -> Self::Id;
}
<|endoftext|>


<commit_before>extern crate rusty_machine as rm;
extern crate rand;

use rm::linalg::{Matrix, BaseMatrix};
use rand::{Rng, ThreadRng};
use std::collections::HashMap;

fn generate_arm(content_id: &usize, arms: &HashMap<usize, Arm>, feature_dim: &usize) -> Arm {
    let arm: Arm;
    if !arms.contains_key(content_id) {
        arm = Arm::new(*feature_dim, *content_id, 0.0001, 0.0);
    }else{
        arm = arms.get(content_id).unwrap().clone();
    };
    arm
}

#[derive(Debug, Clone)]
struct Arm{
    content_id : usize,
    alpha : f64,
    norm_mean : Matrix<f64>,
    cov_matrix: Matrix<f64>,
    win_rate : f64,
    win : f64,
    lose : f64,
}

impl Arm {
    fn new(feature_dim: usize, content_id: usize, alpha: f64, win_rate: f64) -> Arm {
        Arm {
            content_id: content_id,
            norm_mean: Matrix::zeros(1, feature_dim),
            cov_matrix: Matrix::ones(1, feature_dim),
            alpha: alpha,
            win_rate: win_rate,
            win: 0.0,
            lose: 0.0,
        }
    }

    fn update(&mut self, features: Matrix<f64>, is_click: bool) {
        // error of diag
        self.cov_matrix += Matrix::new(self.cov_matrix.rows(),
                                        self.cov_matrix.cols(),
                                        (&features.transpose()*&features).diag());
        let cost_of_click = is_click as i8 as f64;

        let feat_mul_cost_vec = features.iter().map(|x| cost_of_click*x).collect::<Vec<f64>>();
        let feat_mul_cost = Matrix::new(features.rows(), features.cols(), feat_mul_cost_vec);
        self.norm_mean += feat_mul_cost;

        if is_click{
            self.win += 1.;
        } else{
            self.lose += 1.;
        }
        self.win_rate = &self.win/(&self.win + &self.lose);
    }

    fn predict(&mut self, features: &Matrix<f64>) -> f64 {
        let one_div_cov_vec = self.cov_matrix.iter().map(|x| 1.0/x).collect::<Vec<f64>>();
        let one_div_cov = Matrix::new(self.cov_matrix.rows(),
                                      self.cov_matrix.cols(), one_div_cov_vec);
        // Since the covariance matrix preserves only the diagonal components,
        // it suffices to take the inverse matrix
        let theta = &one_div_cov.elemul(&self.norm_mean);
        // Again, the inverse matrix of the covariance matrix
        // is computed by taking reciprocal
        let mut tmp: f64 = ((features.elemul(&one_div_cov))*features.transpose()).data()[0];
        tmp = &tmp.sqrt()*&self.alpha;
        (theta*features.transpose()).data()[0] + &tmp
    }

    fn print_result(&mut self) {
        println!("content_id:{}, total_num:{}, win_rate:{}",
                &self.content_id, &self.win+&self.lose, &self.win_rate);
    }
}

struct Viewer{
    gender: String,
    rng: ThreadRng,
}

impl Viewer {
    fn new(gender: String) -> Viewer{
        Viewer{
            gender: gender,
            rng: rand::thread_rng(),
        }
    }

    fn view(&mut self, content_id: &usize) -> bool{
        if &self.gender=="man" {
            // Men are easy to click on ads with id 5 or less
            if *content_id < 6 {
                return Some(self.rng.next_f32()).and_then(|n| if n>0.3 {Some(true)} else {Some(false)}).unwrap();
            } else{
                return Some(self.rng.next_f32()).and_then(|n| if n>0.7 {Some(true)} else {Some(false)}).unwrap();
            }
        } else {
            // Women are easy to click on ads with id 6 or higher
            if *content_id > 5{
                return Some(self.rng.next_f32()).and_then(|n| if n>0.3 {Some(true)} else {Some(false)}).unwrap();
            } else {
                return Some(self.rng.next_f32()).and_then(|n| if n>0.7 {Some(true)} else {Some(false)}).unwrap();
            }
        }
    }
}

struct Rulet{
    rng: ThreadRng,
}

impl Rulet{
    fn new() -> Rulet {
        Rulet{
            rng: rand::thread_rng(),
        }
    }

    fn generate_features(&mut self, viewer: &Viewer) -> Matrix<f64> {
        let features = Some(&viewer.gender)
            .and_then(|gender|
                if gender=="man" {Some(Matrix::new(1,2,vec![1.,0.]))}
                else {Some(Matrix::new(1,2,vec![0.,1.]))}
            ).unwrap();
        features
    }

    fn generate_content(&mut self) -> usize{
        self.rng.gen_range(0, 10)
    }

    fn generate_gender(&mut self) -> String {
        if self.rng.next_f32() > 0.5{
            return "man".to_string();
        } else{
            return "women".to_string();
        }
    }
}

fn main() {
    /*Context is for men and women only
    Men are easy to click on ads with id 5 or less
    Women are easy to click on ads with id 6 or higher
    */
    let feature_dim = 2;
    let num_of_views = 10000;
    let mut rulet = Rulet::new();

    let mut content_id: usize;
    let mut features: Matrix<f64>;
    let mut is_clicked: bool;
    let mut arms: HashMap<usize, Arm> = HashMap::new();

    for step in 0..num_of_views {
        let mut viewer = Viewer::new(rulet.generate_gender());

        content_id = rulet.generate_content();
        features = rulet.generate_features(&viewer);
        is_clicked = viewer.view(&content_id);

        let mut arm = generate_arm(&content_id, &arms, &feature_dim);
        arm.update(features, is_clicked);
        arms.remove(&content_id);
        arms.insert(content_id, arm.clone());
    }

    let man_mat: Matrix<f64> = Matrix::new(1,2, vec![1.,0.]);
    let woman_mat: Matrix<f64> = Matrix::new(1,2, vec![0.,1.]);

    println!("print result======");
    for (_, arm) in arms.iter() {
        let mut arm = arm.clone();  // impl needs mutable self
        &arm.print_result();
        println!("Click rate when men browse: {}", &arm.predict(&man_mat) );
        println!("Click rate when women browse: {}", &arm.predict(&woman_mat) );
    }

}
<commit_msg>remove unnecessary variables<commit_after>extern crate rusty_machine as rm;
extern crate rand;

use rm::linalg::{Matrix, BaseMatrix};
use rand::{Rng, ThreadRng};
use std::collections::HashMap;

fn generate_arm(content_id: &usize, arms: &HashMap<usize, Arm>, feature_dim: &usize) -> Arm {
    let arm: Arm;
    if !arms.contains_key(content_id) {
        arm = Arm::new(*feature_dim, *content_id, 0.0001, 0.0);
    }else{
        arm = arms.get(content_id).unwrap().clone();
    };
    arm
}

#[derive(Debug, Clone)]
struct Arm{
    content_id : usize,
    alpha : f64,
    norm_mean : Matrix<f64>,
    cov_matrix: Matrix<f64>,
    win_rate : f64,
    win : f64,
    lose : f64,
}

impl Arm {
    fn new(feature_dim: usize, content_id: usize, alpha: f64, win_rate: f64) -> Arm {
        Arm {
            content_id: content_id,
            norm_mean: Matrix::zeros(1, feature_dim),
            cov_matrix: Matrix::ones(1, feature_dim),
            alpha: alpha,
            win_rate: win_rate,
            win: 0.0,
            lose: 0.0,
        }
    }

    fn update(&mut self, features: Matrix<f64>, is_click: bool) {
        // error of diag
        self.cov_matrix += Matrix::new(self.cov_matrix.rows(),
                                        self.cov_matrix.cols(),
                                        (&features.transpose()*&features).diag());
        let cost_of_click = is_click as i8 as f64;

        let feat_mul_cost_vec = features.iter().map(|x| cost_of_click*x).collect::<Vec<f64>>();
        let feat_mul_cost = Matrix::new(features.rows(), features.cols(), feat_mul_cost_vec);
        self.norm_mean += feat_mul_cost;

        if is_click{
            self.win += 1.;
        } else{
            self.lose += 1.;
        }
        self.win_rate = &self.win/(&self.win + &self.lose);
    }

    fn predict(&mut self, features: &Matrix<f64>) -> f64 {
        let one_div_cov_vec = self.cov_matrix.iter().map(|x| 1.0/x).collect::<Vec<f64>>();
        let one_div_cov = Matrix::new(self.cov_matrix.rows(),
                                      self.cov_matrix.cols(), one_div_cov_vec);
        // Since the covariance matrix preserves only the diagonal components,
        // it suffices to take the inverse matrix
        let theta = &one_div_cov.elemul(&self.norm_mean);
        // Again, the inverse matrix of the covariance matrix
        // is computed by taking reciprocal
        let mut tmp: f64 = ((features.elemul(&one_div_cov))*features.transpose()).data()[0];
        tmp = &tmp.sqrt()*&self.alpha;
        (theta*features.transpose()).data()[0] + &tmp
    }

    fn print_result(&mut self) {
        println!("content_id:{}, total_num:{}, win_rate:{}",
                &self.content_id, &self.win+&self.lose, &self.win_rate);
    }
}

struct Viewer{
    gender: String,
    rng: ThreadRng,
}

impl Viewer {
    fn new(gender: String) -> Viewer{
        Viewer{
            gender: gender,
            rng: rand::thread_rng(),
        }
    }

    fn view(&mut self, content_id: &usize) -> bool{
        if &self.gender=="man" {
            // Men are easy to click on ads with id 5 or less
            if *content_id < 6 {
                return Some(self.rng.next_f32()).and_then(|n| if n>0.3 {Some(true)} else {Some(false)}).unwrap();
            } else{
                return Some(self.rng.next_f32()).and_then(|n| if n>0.7 {Some(true)} else {Some(false)}).unwrap();
            }
        } else {
            // Women are easy to click on ads with id 6 or higher
            if *content_id > 5{
                return Some(self.rng.next_f32()).and_then(|n| if n>0.3 {Some(true)} else {Some(false)}).unwrap();
            } else {
                return Some(self.rng.next_f32()).and_then(|n| if n>0.7 {Some(true)} else {Some(false)}).unwrap();
            }
        }
    }
}

struct Rulet{
    rng: ThreadRng,
}

impl Rulet{
    fn new() -> Rulet {
        Rulet{
            rng: rand::thread_rng(),
        }
    }

    fn generate_features(&mut self, viewer: &Viewer) -> Matrix<f64> {
        let features = Some(&viewer.gender)
            .and_then(|gender|
                if gender=="man" {Some(Matrix::new(1,2,vec![1.,0.]))}
                else {Some(Matrix::new(1,2,vec![0.,1.]))}
            ).unwrap();
        features
    }

    fn generate_content(&mut self) -> usize{
        self.rng.gen_range(0, 10)
    }

    fn generate_gender(&mut self) -> String {
        if self.rng.next_f32() > 0.5{
            return "man".to_string();
        } else{
            return "women".to_string();
        }
    }
}

fn main() {
    /*Context is for men and women only
    Men are easy to click on ads with id 5 or less
    Women are easy to click on ads with id 6 or higher
    */
    let feature_dim = 2;
    let num_of_views = 10000;
    let mut rulet = Rulet::new();

    let mut content_id: usize;
    let mut features: Matrix<f64>;
    let mut is_clicked: bool;
    let mut arms: HashMap<usize, Arm> = HashMap::new();

    for _ in 0..num_of_views {
        let mut viewer = Viewer::new(rulet.generate_gender());

        content_id = rulet.generate_content();
        features = rulet.generate_features(&viewer);
        is_clicked = viewer.view(&content_id);

        let mut arm = generate_arm(&content_id, &arms, &feature_dim);
        arm.update(features, is_clicked);
        arms.remove(&content_id);
        arms.insert(content_id, arm.clone());
    }

    let man_mat: Matrix<f64> = Matrix::new(1,2, vec![1.,0.]);
    let woman_mat: Matrix<f64> = Matrix::new(1,2, vec![0.,1.]);

    println!("print result======");
    for (_, arm) in arms.iter() {
        let mut arm = arm.clone();  // impl needs mutable self
        &arm.print_result();
        println!("Click rate when men browse: {}", &arm.predict(&man_mat) );
        println!("Click rate when women browse: {}", &arm.predict(&woman_mat) );
    }

}
<|endoftext|>


<commit_before>use byteorder::{ReadBytesExt, WriteBytesExt};
use std::error::Error;
use std::io::prelude::*;

use backend::Backend;
use types::{self, FromSql, ToSql, IsNull};

impl<DB: Backend<RawValue=[u8]>> FromSql<types::SmallInt, DB> for i16 {
    fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error+Send+Sync>> {
        let mut bytes = not_none!(bytes);
        debug_assert!(bytes.len() <= 2, "Received more than 2 bytes decoding i16. \
                      Was an Integer expression accidentally identified as SmallInt?");
        bytes.read_i16::<DB::ByteOrder>().map_err(|e| Box::new(e) as Box<Error+Send+Sync>)
    }
}

impl<DB: Backend> ToSql<types::SmallInt, DB> for i16 {
    fn to_sql<W: Write>(&self, out: &mut W) -> Result<IsNull, Box<Error+Send+Sync>> {
        out.write_i16::<DB::ByteOrder>(*self)
            .map(|_| IsNull::No)
            .map_err(|e| Box::new(e) as Box<Error+Send+Sync>)
    }
}

impl<DB: Backend<RawValue=[u8]>> FromSql<types::Integer, DB> for i32 {
    fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error+Send+Sync>> {
        let mut bytes = not_none!(bytes);
        debug_assert!(bytes.len() <= 4, "Received more than 4 bytes decoding i32. \
                      Was a BigInteger expression accidentally identified as Integer?");
        bytes.read_i32::<DB::ByteOrder>().map_err(|e| Box::new(e) as Box<Error+Send+Sync>)
    }
}

impl<DB: Backend> ToSql<types::Integer, DB> for i32 {
    fn to_sql<W: Write>(&self, out: &mut W) -> Result<IsNull, Box<Error+Send+Sync>> {
        out.write_i32::<DB::ByteOrder>(*self)
            .map(|_| IsNull::No)
            .map_err(|e| Box::new(e) as Box<Error+Send+Sync>)
    }
}

impl<DB: Backend<RawValue=[u8]>> FromSql<types::BigInt, DB> for i64 {
    fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error+Send+Sync>> {
        let mut bytes = not_none!(bytes);
        debug_assert!(bytes.len() <= 8, "Received more than 8 bytes decoding i64. \
                      Was an expression of a different type misidentified as BigInteger?");
        bytes.read_i64::<DB::ByteOrder>().map_err(|e| Box::new(e) as Box<Error+Send+Sync>)
    }
}

impl<DB: Backend> ToSql<types::BigInt, DB> for i64 {
    fn to_sql<W: Write>(&self, out: &mut W) -> Result<IsNull, Box<Error+Send+Sync>> {
        out.write_i64::<DB::ByteOrder>(*self)
            .map(|_| IsNull::No)
            .map_err(|e| Box::new(e) as Box<Error+Send+Sync>)
    }
}
<commit_msg>Provide a more helpful error message when too few bytes were received<commit_after>use byteorder::{ReadBytesExt, WriteBytesExt};
use std::error::Error;
use std::io::prelude::*;

use backend::Backend;
use types::{self, FromSql, ToSql, IsNull};

impl<DB: Backend<RawValue=[u8]>> FromSql<types::SmallInt, DB> for i16 {
    fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error+Send+Sync>> {
        let mut bytes = not_none!(bytes);
        debug_assert!(bytes.len() <= 2, "Received more than 2 bytes decoding i16. \
                      Was an Integer expression accidentally identified as SmallInt?");
        debug_assert!(bytes.len() == 2, "Received fewer than 2 bytes decoding i16. \
                      Was an expression of a different type accidentally identified \
                      as SmallInt?");
        bytes.read_i16::<DB::ByteOrder>().map_err(|e| Box::new(e) as Box<Error+Send+Sync>)
    }
}

impl<DB: Backend> ToSql<types::SmallInt, DB> for i16 {
    fn to_sql<W: Write>(&self, out: &mut W) -> Result<IsNull, Box<Error+Send+Sync>> {
        out.write_i16::<DB::ByteOrder>(*self)
            .map(|_| IsNull::No)
            .map_err(|e| Box::new(e) as Box<Error+Send+Sync>)
    }
}

impl<DB: Backend<RawValue=[u8]>> FromSql<types::Integer, DB> for i32 {
    fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error+Send+Sync>> {
        let mut bytes = not_none!(bytes);
        debug_assert!(bytes.len() <= 4, "Received more than 4 bytes decoding i32. \
                      Was a BigInteger expression accidentally identified as Integer?");
        debug_assert!(bytes.len() == 4, "Received fewer than 4 bytes decoding i32. \
                      Was a SmallInteger expression accidentally identified as Integer?");
        bytes.read_i32::<DB::ByteOrder>().map_err(|e| Box::new(e) as Box<Error+Send+Sync>)
    }
}

impl<DB: Backend> ToSql<types::Integer, DB> for i32 {
    fn to_sql<W: Write>(&self, out: &mut W) -> Result<IsNull, Box<Error+Send+Sync>> {
        out.write_i32::<DB::ByteOrder>(*self)
            .map(|_| IsNull::No)
            .map_err(|e| Box::new(e) as Box<Error+Send+Sync>)
    }
}

impl<DB: Backend<RawValue=[u8]>> FromSql<types::BigInt, DB> for i64 {
    fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error+Send+Sync>> {
        let mut bytes = not_none!(bytes);
        debug_assert!(bytes.len() <= 8, "Received more than 8 bytes decoding i64. \
                      Was an expression of a different type misidentified as BigInteger?");
        debug_assert!(bytes.len() == 8, "Received fewer than 8 bytes decoding i64. \
                      Was an Integer expression misidentified as BigInteger?");
        bytes.read_i64::<DB::ByteOrder>().map_err(|e| Box::new(e) as Box<Error+Send+Sync>)
    }
}

impl<DB: Backend> ToSql<types::BigInt, DB> for i64 {
    fn to_sql<W: Write>(&self, out: &mut W) -> Result<IsNull, Box<Error+Send+Sync>> {
        out.write_i64::<DB::ByteOrder>(*self)
            .map(|_| IsNull::No)
            .map_err(|e| Box::new(e) as Box<Error+Send+Sync>)
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::error::Error;
use std::sync::Arc;

use buffer::TrackedBuffer;
use command_buffer::cb::CommandsListBuildPrimaryPool;
use command_buffer::cb::Flags;
use command_buffer::cb::Kind;
use command_buffer::cb::UnsyncedCommandBuffer;
use command_buffer::pool::CommandPool;
use command_buffer::submit::Submit;
use command_buffer::submit::SubmitBuilder;
use command_buffer::CommandsList;
use command_buffer::CommandsListSink;
use command_buffer::CommandsListSinkCaller;
use command_buffer::SecondaryCommandBuffer;
use device::Device;
use device::Queue;
use image::Layout;
use image::TrackedImage;
use sync::AccessFlagBits;
use sync::PipelineStages;
use VulkanObject;
use vk;

use OomError;

pub struct AutobarriersCommandBuffer<L, P> where P: CommandPool {
    // The actual command buffer.
    inner: UnsyncedCommandBuffer<WrappedCommandsList<L>, P>
}

impl<L, P> CommandsListBuildPrimaryPool<L, P> for AutobarriersCommandBuffer<L, P>
    where L: CommandsList, P: CommandPool
{
    fn build_primary_with_pool(pool: P, list: L)
                               -> Result<AutobarriersCommandBuffer<L, P>, OomError>
        where Self: Sized
    {
        let kind = Kind::primary();
        let flags = Flags::SimultaneousUse;

        let cmd = unsafe {
            try!(UnsyncedCommandBuffer::new(WrappedCommandsList(list), pool, kind, flags))
        };

        Ok(AutobarriersCommandBuffer {
            inner: cmd,
        })
    }
}

unsafe impl<L, P> Submit for AutobarriersCommandBuffer<L, P>
    where L: CommandsList, P: CommandPool
{
    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }

    unsafe fn append_submission<'a>(&'a self, base: SubmitBuilder<'a>, queue: &Arc<Queue>)
                                    -> Result<SubmitBuilder<'a>, Box<Error>>
    {
        // FIXME: totally unsynchronized here
        Ok(base.add_command_buffer(&self.inner))
    }
}

// TODO: we're not necessarily a secondary command buffer
unsafe impl<L, P> SecondaryCommandBuffer for AutobarriersCommandBuffer<L, P>
    where L: CommandsList, P: CommandPool
{
    #[inline]
    fn inner(&self) -> vk::CommandBuffer {
        self.inner.internal_object()
    }

    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }

    #[inline]
    fn append<'a>(&'a self, builder: &mut CommandsListSink<'a>) {
        self.inner.commands_list().append(builder);
    }
}

struct WrappedCommandsList<L>(L);
unsafe impl<L> CommandsList for WrappedCommandsList<L> where L: CommandsList {
    #[inline]
    fn append<'a>(&'a self, builder: &mut CommandsListSink<'a>) {
        /*let device = pool.device().clone();

        self.0.append(&mut Sink {
            output: builder,
            device: &device,
        });*/
        unimplemented!()
    }
}

// Helper object for AutobarriersCommandBuffer. Implementation detail.
struct Sink<'c: 'o, 'o> {
    output: &'o mut CommandsListSink<'c>,
    device: &'o Arc<Device>,
}

impl<'c: 'o, 'o> CommandsListSink<'c> for Sink<'c, 'o> {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.device
    }

    #[inline]
    fn add_command(&mut self, f: Box<CommandsListSinkCaller<'c> + 'c>) {
        self.output.add_command(f);
    }

    #[inline]
    fn add_buffer_transition(&mut self, _: &TrackedBuffer, _: usize, _: usize, _: bool,
                             _: PipelineStages, _: AccessFlagBits)
    {
    }

    #[inline]
    fn add_image_transition(&mut self, _: &TrackedImage, _: u32, _: u32, _: u32, _: u32,
                            _: bool, _: Layout, _: PipelineStages, _: AccessFlagBits)
    {
    }

    #[inline]
    fn add_image_transition_notification(&mut self, _: &TrackedImage, _: u32, _: u32, _: u32,
                                         _: u32, _: Layout, _: PipelineStages, _: AccessFlagBits)
    {
    }
}
<commit_msg>Triangle example runs again<commit_after>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::error::Error;
use std::sync::Arc;

use buffer::TrackedBuffer;
use command_buffer::cb::CommandsListBuildPrimaryPool;
use command_buffer::cb::Flags;
use command_buffer::cb::Kind;
use command_buffer::cb::UnsyncedCommandBuffer;
use command_buffer::pool::CommandPool;
use command_buffer::submit::Submit;
use command_buffer::submit::SubmitBuilder;
use command_buffer::CommandsList;
use command_buffer::CommandsListSink;
use command_buffer::CommandsListSinkCaller;
use command_buffer::SecondaryCommandBuffer;
use device::Device;
use device::Queue;
use image::Layout;
use image::TrackedImage;
use sync::AccessFlagBits;
use sync::PipelineStages;
use VulkanObject;
use vk;

use OomError;

pub struct AutobarriersCommandBuffer<L, P> where P: CommandPool {
    // The actual command buffer.
    inner: UnsyncedCommandBuffer<WrappedCommandsList<L>, P>
}

impl<L, P> CommandsListBuildPrimaryPool<L, P> for AutobarriersCommandBuffer<L, P>
    where L: CommandsList, P: CommandPool
{
    fn build_primary_with_pool(pool: P, list: L)
                               -> Result<AutobarriersCommandBuffer<L, P>, OomError>
        where Self: Sized
    {
        let kind = Kind::primary();
        let flags = Flags::SimultaneousUse;

        let cmd = unsafe {
            let device = pool.device().clone();
            try!(UnsyncedCommandBuffer::new(WrappedCommandsList(list, device), pool, kind, flags))
        };

        Ok(AutobarriersCommandBuffer {
            inner: cmd,
        })
    }
}

unsafe impl<L, P> Submit for AutobarriersCommandBuffer<L, P>
    where L: CommandsList, P: CommandPool
{
    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }

    unsafe fn append_submission<'a>(&'a self, base: SubmitBuilder<'a>, queue: &Arc<Queue>)
                                    -> Result<SubmitBuilder<'a>, Box<Error>>
    {
        // FIXME: totally unsynchronized here
        Ok(base.add_command_buffer(&self.inner))
    }
}

// TODO: we're not necessarily a secondary command buffer
unsafe impl<L, P> SecondaryCommandBuffer for AutobarriersCommandBuffer<L, P>
    where L: CommandsList, P: CommandPool
{
    #[inline]
    fn inner(&self) -> vk::CommandBuffer {
        self.inner.internal_object()
    }

    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }

    #[inline]
    fn append<'a>(&'a self, builder: &mut CommandsListSink<'a>) {
        self.inner.commands_list().append(builder);
    }
}

struct WrappedCommandsList<L>(L, Arc<Device>);
unsafe impl<L> CommandsList for WrappedCommandsList<L> where L: CommandsList {
    #[inline]
    fn append<'a>(&'a self, builder: &mut CommandsListSink<'a>) {
        self.0.append(&mut Sink {
            output: builder,
            device: &self.1,
        });
    }
}

// Helper object for AutobarriersCommandBuffer. Implementation detail.
struct Sink<'c: 'o, 'o> {
    output: &'o mut CommandsListSink<'c>,
    device: &'o Arc<Device>,
}

impl<'c: 'o, 'o> CommandsListSink<'c> for Sink<'c, 'o> {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.device
    }

    #[inline]
    fn add_command(&mut self, f: Box<CommandsListSinkCaller<'c> + 'c>) {
        self.output.add_command(f);
    }

    #[inline]
    fn add_buffer_transition(&mut self, _: &TrackedBuffer, _: usize, _: usize, _: bool,
                             _: PipelineStages, _: AccessFlagBits)
    {
    }

    #[inline]
    fn add_image_transition(&mut self, _: &TrackedImage, _: u32, _: u32, _: u32, _: u32,
                            _: bool, _: Layout, _: PipelineStages, _: AccessFlagBits)
    {
    }

    #[inline]
    fn add_image_transition_notification(&mut self, _: &TrackedImage, _: u32, _: u32, _: u32,
                                         _: u32, _: Layout, _: PipelineStages, _: AccessFlagBits)
    {
    }
}
<|endoftext|>


<commit_before>mod classes;
mod comments;
mod numbers;
mod ptr;
mod strings;

use crate::{
    SyntaxKind::{self, *},
    TextUnit,
};

use self::{
    classes::*,
    comments::{scan_comment, scan_shebang},
    numbers::scan_number,
    ptr::Ptr,
    strings::{
        is_string_literal_start, scan_byte_char_or_string, scan_char, scan_raw_string, scan_string,
    },
};

/// A token of Rust source.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Token {
    /// The kind of token.
    pub kind: SyntaxKind,
    /// The length of the token.
    pub len: TextUnit,
}

/// Break a string up into its component tokens
pub fn tokenize(text: &str) -> Vec<Token> {
    let mut text = text;
    let mut acc = Vec::new();
    while !text.is_empty() {
        let token = next_token(text);
        acc.push(token);
        let len: u32 = token.len.into();
        text = &text[len as usize..];
    }
    acc
}

/// Get the next token from a string
pub fn next_token(text: &str) -> Token {
    assert!(!text.is_empty());
    let mut ptr = Ptr::new(text);
    let c = ptr.bump().unwrap();
    let kind = next_token_inner(c, &mut ptr);
    let len = ptr.into_len();
    Token { kind, len }
}

fn next_token_inner(c: char, ptr: &mut Ptr) -> SyntaxKind {
    if is_whitespace(c) {
        ptr.bump_while(is_whitespace);
        return WHITESPACE;
    }

    match c {
        '#' => {
            if scan_shebang(ptr) {
                return SHEBANG;
            }
        }
        '/' => {
            if let Some(kind) = scan_comment(ptr) {
                return kind;
            }
        }
        _ => (),
    }

    let ident_start = is_ident_start(c) && !is_string_literal_start(c, ptr.current(), ptr.nth(1));
    if ident_start {
        return scan_ident(c, ptr);
    }

    if is_dec_digit(c) {
        let kind = scan_number(c, ptr);
        scan_literal_suffix(ptr);
        return kind;
    }

    // One-byte tokens.
    if let Some(kind) = SyntaxKind::from_char(c) {
        return kind;
    }

    match c {
        // Multi-byte tokens.
        '.' => {
            return match (ptr.current(), ptr.nth(1)) {
                (Some('.'), Some('.')) => {
                    ptr.bump();
                    ptr.bump();
                    DOTDOTDOT
                }
                (Some('.'), Some('=')) => {
                    ptr.bump();
                    ptr.bump();
                    DOTDOTEQ
                }
                (Some('.'), _) => {
                    ptr.bump();
                    DOTDOT
                }
                _ => DOT,
            };
        }
        ':' => {
            return match ptr.current() {
                Some(':') => {
                    ptr.bump();
                    COLONCOLON
                }
                _ => COLON,
            };
        }
        '=' => {
            return match ptr.current() {
                Some('=') => {
                    ptr.bump();
                    EQEQ
                }
                Some('>') => {
                    ptr.bump();
                    FAT_ARROW
                }
                _ => EQ,
            };
        }
        '!' => {
            return match ptr.current() {
                Some('=') => {
                    ptr.bump();
                    NEQ
                }
                _ => EXCL,
            };
        }
        '-' => {
            return if ptr.at('>') {
                ptr.bump();
                THIN_ARROW
            } else {
                MINUS
            };
        }

        // If the character is an ident start not followed by another single
        // quote, then this is a lifetime name:
        '\'' => {
            return if ptr.at_p(is_ident_start) && !ptr.at_str("''") {
                ptr.bump();
                while ptr.at_p(is_ident_continue) {
                    ptr.bump();
                }
                // lifetimes shouldn't end with a single quote
                // if we find one, then this is an invalid character literal
                if ptr.at('\'') {
                    ptr.bump();
                    return CHAR; // TODO: error reporting
                }
                LIFETIME
            } else {
                scan_char(ptr);
                scan_literal_suffix(ptr);
                CHAR
            };
        }
        'b' => {
            let kind = scan_byte_char_or_string(ptr);
            scan_literal_suffix(ptr);
            return kind;
        }
        '"' => {
            scan_string(ptr);
            scan_literal_suffix(ptr);
            return STRING;
        }
        'r' => {
            scan_raw_string(ptr);
            scan_literal_suffix(ptr);
            return RAW_STRING;
        }
        _ => (),
    }
    ERROR
}

fn scan_ident(c: char, ptr: &mut Ptr) -> SyntaxKind {
    let is_single_letter = match ptr.current() {
        None => true,
        Some(c) if !is_ident_continue(c) => true,
        _ => false,
    };
    if is_single_letter {
        return if c == '_' { UNDERSCORE } else { IDENT };
    }
    ptr.bump_while(is_ident_continue);
    if let Some(kind) = SyntaxKind::from_keyword(ptr.current_token_text()) {
        return kind;
    }
    IDENT
}

fn scan_literal_suffix(ptr: &mut Ptr) {
    if ptr.at_p(is_ident_start) {
        ptr.bump();
    }
    ptr.bump_while(is_ident_continue);
}
<commit_msg>Remove uneeded todo in lexer<commit_after>mod classes;
mod comments;
mod numbers;
mod ptr;
mod strings;

use crate::{
    SyntaxKind::{self, *},
    TextUnit,
};

use self::{
    classes::*,
    comments::{scan_comment, scan_shebang},
    numbers::scan_number,
    ptr::Ptr,
    strings::{
        is_string_literal_start, scan_byte_char_or_string, scan_char, scan_raw_string, scan_string,
    },
};

/// A token of Rust source.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Token {
    /// The kind of token.
    pub kind: SyntaxKind,
    /// The length of the token.
    pub len: TextUnit,
}

/// Break a string up into its component tokens
pub fn tokenize(text: &str) -> Vec<Token> {
    let mut text = text;
    let mut acc = Vec::new();
    while !text.is_empty() {
        let token = next_token(text);
        acc.push(token);
        let len: u32 = token.len.into();
        text = &text[len as usize..];
    }
    acc
}

/// Get the next token from a string
pub fn next_token(text: &str) -> Token {
    assert!(!text.is_empty());
    let mut ptr = Ptr::new(text);
    let c = ptr.bump().unwrap();
    let kind = next_token_inner(c, &mut ptr);
    let len = ptr.into_len();
    Token { kind, len }
}

fn next_token_inner(c: char, ptr: &mut Ptr) -> SyntaxKind {
    if is_whitespace(c) {
        ptr.bump_while(is_whitespace);
        return WHITESPACE;
    }

    match c {
        '#' => {
            if scan_shebang(ptr) {
                return SHEBANG;
            }
        }
        '/' => {
            if let Some(kind) = scan_comment(ptr) {
                return kind;
            }
        }
        _ => (),
    }

    let ident_start = is_ident_start(c) && !is_string_literal_start(c, ptr.current(), ptr.nth(1));
    if ident_start {
        return scan_ident(c, ptr);
    }

    if is_dec_digit(c) {
        let kind = scan_number(c, ptr);
        scan_literal_suffix(ptr);
        return kind;
    }

    // One-byte tokens.
    if let Some(kind) = SyntaxKind::from_char(c) {
        return kind;
    }

    match c {
        // Multi-byte tokens.
        '.' => {
            return match (ptr.current(), ptr.nth(1)) {
                (Some('.'), Some('.')) => {
                    ptr.bump();
                    ptr.bump();
                    DOTDOTDOT
                }
                (Some('.'), Some('=')) => {
                    ptr.bump();
                    ptr.bump();
                    DOTDOTEQ
                }
                (Some('.'), _) => {
                    ptr.bump();
                    DOTDOT
                }
                _ => DOT,
            };
        }
        ':' => {
            return match ptr.current() {
                Some(':') => {
                    ptr.bump();
                    COLONCOLON
                }
                _ => COLON,
            };
        }
        '=' => {
            return match ptr.current() {
                Some('=') => {
                    ptr.bump();
                    EQEQ
                }
                Some('>') => {
                    ptr.bump();
                    FAT_ARROW
                }
                _ => EQ,
            };
        }
        '!' => {
            return match ptr.current() {
                Some('=') => {
                    ptr.bump();
                    NEQ
                }
                _ => EXCL,
            };
        }
        '-' => {
            return if ptr.at('>') {
                ptr.bump();
                THIN_ARROW
            } else {
                MINUS
            };
        }

        // If the character is an ident start not followed by another single
        // quote, then this is a lifetime name:
        '\'' => {
            return if ptr.at_p(is_ident_start) && !ptr.at_str("''") {
                ptr.bump();
                while ptr.at_p(is_ident_continue) {
                    ptr.bump();
                }
                // lifetimes shouldn't end with a single quote
                // if we find one, then this is an invalid character literal
                if ptr.at('\'') {
                    ptr.bump();
                    return CHAR;
                }
                LIFETIME
            } else {
                scan_char(ptr);
                scan_literal_suffix(ptr);
                CHAR
            };
        }
        'b' => {
            let kind = scan_byte_char_or_string(ptr);
            scan_literal_suffix(ptr);
            return kind;
        }
        '"' => {
            scan_string(ptr);
            scan_literal_suffix(ptr);
            return STRING;
        }
        'r' => {
            scan_raw_string(ptr);
            scan_literal_suffix(ptr);
            return RAW_STRING;
        }
        _ => (),
    }
    ERROR
}

fn scan_ident(c: char, ptr: &mut Ptr) -> SyntaxKind {
    let is_single_letter = match ptr.current() {
        None => true,
        Some(c) if !is_ident_continue(c) => true,
        _ => false,
    };
    if is_single_letter {
        return if c == '_' { UNDERSCORE } else { IDENT };
    }
    ptr.bump_while(is_ident_continue);
    if let Some(kind) = SyntaxKind::from_keyword(ptr.current_token_text()) {
        return kind;
    }
    IDENT
}

fn scan_literal_suffix(ptr: &mut Ptr) {
    if ptr.at_p(is_ident_start) {
        ptr.bump();
    }
    ptr.bump_while(is_ident_continue);
}
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>read and print a single card<commit_after>use std::io;
use std::io::Write;

fn main() {
    print!("scalyc>");
    io::stdout().flush().unwrap();
    let mut card = String::new();
    io::stdin().read_line(&mut card).expect("failed to read line");
    println!("The card is {}", card);
}
<|endoftext|>


<commit_before>//! Try to guess the types of files on disk.

use std::fs;
use std::io::Read;
use std::path::Path;

use errors::*;

/// Internal helper function which looks for "magic" bytes at the start of
/// a file.
fn has_magic(path: &Path, magic: &[u8]) -> Result<bool> {
    let mkerr = || ErrorKind::ReadFile(path.to_owned());
    let mut f = fs::File::open(path).chain_err(&mkerr)?;
    let mut bytes = vec![0; magic.len()];
    f.read_exact(&mut bytes).chain_err(&mkerr)?;
    Ok(magic == &bytes[..])
}

/// Does the specified path appear to point to an `*.idx` file?
pub fn is_idx_file<P: AsRef<Path>>(path: P) -> Result<bool> {
    has_magic(path.as_ref(),
              b"# VobSub index file, v7 (do not modify this line!)")
}

#[test]
fn probe_idx_files() {
    assert!(is_idx_file("../fixtures/tiny.idx").unwrap());
    assert!(!is_idx_file("../fixtures/tiny.sub").unwrap());
}

/// Does the specified path appear to point to a `*.sub` file?
///
/// Note that this may (or may not) return false positives for certain
/// MPEG-2 related formats.
pub fn is_sub_file<P: AsRef<Path>>(path: P) -> Result<bool> {
    has_magic(path.as_ref(),
              &[0x00, 0x00, 0x01, 0xba])
}

#[test]
fn probe_sub_files() {
    assert!(is_sub_file("../fixtures/tiny.sub").unwrap());
    assert!(!is_sub_file("../fixtures/tiny.idx").unwrap());
}
<commit_msg>Don't check version number when probing idx file type<commit_after>//! Try to guess the types of files on disk.

use std::fs;
use std::io::Read;
use std::path::Path;

use errors::*;

/// Internal helper function which looks for "magic" bytes at the start of
/// a file.
fn has_magic(path: &Path, magic: &[u8]) -> Result<bool> {
    let mkerr = || ErrorKind::ReadFile(path.to_owned());
    let mut f = fs::File::open(path).chain_err(&mkerr)?;
    let mut bytes = vec![0; magic.len()];
    f.read_exact(&mut bytes).chain_err(&mkerr)?;
    Ok(magic == &bytes[..])
}

/// Does the specified path appear to point to an `*.idx` file?
pub fn is_idx_file<P: AsRef<Path>>(path: P) -> Result<bool> {
    has_magic(path.as_ref(),
              b"# VobSub index file")
}

#[test]
fn probe_idx_files() {
    assert!(is_idx_file("../fixtures/tiny.idx").unwrap());
    assert!(!is_idx_file("../fixtures/tiny.sub").unwrap());
}

/// Does the specified path appear to point to a `*.sub` file?
///
/// Note that this may (or may not) return false positives for certain
/// MPEG-2 related formats.
pub fn is_sub_file<P: AsRef<Path>>(path: P) -> Result<bool> {
    has_magic(path.as_ref(),
              &[0x00, 0x00, 0x01, 0xba])
}

#[test]
fn probe_sub_files() {
    assert!(is_sub_file("../fixtures/tiny.sub").unwrap());
    assert!(!is_sub_file("../fixtures/tiny.idx").unwrap());
}
<|endoftext|>