<commit_before>use super::{Value, Node};
use self::Value::Leaf;
use metric::Line;

#[test]
fn line_split_test_1() {
    let l1 = Node::new_leaf("asdf");
    let l2 = Node::new_leaf("qwer");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(0));
    assert_eq!(left.strings().collect::<String>(), "asdfqwer");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "");
    } else { assert!(false) }
}

#[test]
fn line_split_test_2() {
    let l1 = Node::new_leaf("asdf");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(0));
    assert_eq!(left.strings().collect::<String>(), "asdfqwer\n");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "");
    } else { assert!(false) }
}

#[test]
fn line_split_test_3() {
    let l1 = Node::new_leaf("asdf\n");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(0));
    if let Leaf(ref s) = **left {
        assert_eq!(&s[..], "asdf\n");
    } else { assert!(false) }
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "qwer\n");
    } else { assert!(false) }
}

#[test]
#[should_panic(expected = "invalid index!")]
fn line_split_test_4() {
    let l1 = Node::new_leaf("asdf");
    let l2 = Node::new_leaf("qwer");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(1));
}

#[test]
fn line_split_test_5() {
    let l1 = Node::new_leaf("asdf");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(1));
    assert_eq!(left.strings().collect::<String>(), "asdfqwer\n");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "");
    } else { assert!(false) }
}

#[test]
fn line_split_test_6() {
    let l1 = Node::new_leaf("asdf\n");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(1));
    assert_eq!(left.strings().collect::<String>(), "asdf\nqwer\n");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "");
    } else { assert!(false) }
}

#[test]
fn line_split_test_7() {
    let l1 = Node::new_leaf("asdf\n");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(0));
    if let Leaf(ref s) = **left {
        assert_eq!(&s[..], "asdf\n");
    } else { assert!(false) }
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "qwer\n");
    } else { assert!(false) }
}

#[test]
fn line_split_test_8() {
    let l1 = Node::new_leaf("");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(0));
    assert_eq!(left.strings().collect::<String>(), "qwer\n");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "");
    } else { assert!(false) }
}

#[test]
fn line_split_test_9() {
    let l1 = Node::new_leaf("asdf\n");
    let l2 = Node::new_leaf("qwer");
    let l3 = Node::new_leaf("yxcv\n");
    let b1 = Node::new_branch(l1, l2);
    let b2 = Node::new_branch(b1, l3);
    let (left, right) = b2.split(Line(0));
    if let Leaf(ref s) = **left {
        assert_eq!(&s[..], "asdf\n");
    } else { assert!(false) }
    assert_eq!(right.strings().collect::<String>(), "qweryxcv\n");
}

#[test]
fn line_split_test_10() {
    let l1 = Node::new_leaf("asdf");
    let l2 = Node::new_leaf("qwer\n");
    let l3 = Node::new_leaf("yxcv\n");
    let b1 = Node::new_branch(l2, l3);
    let b2 = Node::new_branch(l1, b1);
    let (left, right) = b2.split(Line(0));
    assert_eq!(left.strings().collect::<String>(), "asdfqwer\n");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "yxcv\n");
    } else { assert!(false) }
}
<commit_msg>test(rope internals): another attempt to fix nightly build<commit_after>use internals::{Value, Node};
use self::Value::Leaf;
use metric::Line;

#[test]
fn line_split_test_1() {
    let l1 = Node::new_leaf("asdf");
    let l2 = Node::new_leaf("qwer");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(0));
    assert_eq!(left.strings().collect::<String>(), "asdfqwer");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "");
    } else { assert!(false) }
}

#[test]
fn line_split_test_2() {
    let l1 = Node::new_leaf("asdf");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(0));
    assert_eq!(left.strings().collect::<String>(), "asdfqwer\n");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "");
    } else { assert!(false) }
}

#[test]
fn line_split_test_3() {
    let l1 = Node::new_leaf("asdf\n");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(0));
    if let Leaf(ref s) = **left {
        assert_eq!(&s[..], "asdf\n");
    } else { assert!(false) }
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "qwer\n");
    } else { assert!(false) }
}

#[test]
#[should_panic(expected = "invalid index!")]
fn line_split_test_4() {
    let l1 = Node::new_leaf("asdf");
    let l2 = Node::new_leaf("qwer");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(1));
}

#[test]
fn line_split_test_5() {
    let l1 = Node::new_leaf("asdf");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(1));
    assert_eq!(left.strings().collect::<String>(), "asdfqwer\n");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "");
    } else { assert!(false) }
}

#[test]
fn line_split_test_6() {
    let l1 = Node::new_leaf("asdf\n");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(1));
    assert_eq!(left.strings().collect::<String>(), "asdf\nqwer\n");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "");
    } else { assert!(false) }
}

#[test]
fn line_split_test_7() {
    let l1 = Node::new_leaf("asdf\n");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(0));
    if let Leaf(ref s) = **left {
        assert_eq!(&s[..], "asdf\n");
    } else { assert!(false) }
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "qwer\n");
    } else { assert!(false) }
}

#[test]
fn line_split_test_8() {
    let l1 = Node::new_leaf("");
    let l2 = Node::new_leaf("qwer\n");
    let b = Node::new_branch(l1, l2);
    let (left, right) = b.split(Line(0));
    assert_eq!(left.strings().collect::<String>(), "qwer\n");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "");
    } else { assert!(false) }
}

#[test]
fn line_split_test_9() {
    let l1 = Node::new_leaf("asdf\n");
    let l2 = Node::new_leaf("qwer");
    let l3 = Node::new_leaf("yxcv\n");
    let b1 = Node::new_branch(l1, l2);
    let b2 = Node::new_branch(b1, l3);
    let (left, right) = b2.split(Line(0));
    if let Leaf(ref s) = **left {
        assert_eq!(&s[..], "asdf\n");
    } else { assert!(false) }
    assert_eq!(right.strings().collect::<String>(), "qweryxcv\n");
}

#[test]
fn line_split_test_10() {
    let l1 = Node::new_leaf("asdf");
    let l2 = Node::new_leaf("qwer\n");
    let l3 = Node::new_leaf("yxcv\n");
    let b1 = Node::new_branch(l2, l3);
    let b2 = Node::new_branch(l1, b1);
    let (left, right) = b2.split(Line(0));
    assert_eq!(left.strings().collect::<String>(), "asdfqwer\n");
    if let Leaf(ref s) = **right {
        assert_eq!(&s[..], "yxcv\n");
    } else { assert!(false) }
}
<|endoftext|>


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

use point::Point2D;
use size::Size2D;
use std::cmp::{Eq, Ord};

#[deriving(Eq, Clone)]
pub struct Rect<T> {
    origin: Point2D<T>,
    size: Size2D<T>,
}

pub fn Rect<T:Clone + Ord + Add<T,T> + Sub<T,T>>(origin: Point2D<T>,
                                                 size: Size2D<T>)
        -> Rect<T> {
    return Rect {
        origin: origin,
        size: size
    }
}

impl<T: Clone + Ord + Add<T,T> + Sub<T,T>> Rect<T> {
    pub fn intersects(&self, other: &Rect<T>) -> bool {
        self.origin.x < other.origin.x + other.size.width &&
       other.origin.x <  self.origin.x + self.size.width &&
        self.origin.y < other.origin.y + other.size.height &&
       other.origin.y <  self.origin.y + self.size.height
    }

    pub fn intersection(&self, other: &Rect<T>) -> Option<Rect<T>> {
        if !self.intersects(other) {
            return None;
        }

        let upper_left = Point2D(max(self.origin.x.clone(), other.origin.x.clone()),
                                 max(self.origin.y.clone(), other.origin.y.clone()));

        let lower_right = Point2D(min(self.origin.x + self.size.width,
                                      other.origin.x + other.size.width),
                                  min(self.origin.y + self.size.height,
                                      other.origin.y + other.size.height));

        Some(Rect(upper_left.clone(), Size2D(lower_right.x - upper_left.x,
                                             lower_right.y - upper_left.y)))
    }

    pub fn union(&self, other: &Rect<T>) -> Rect<T> {
        let upper_left = Point2D(min(self.origin.x.clone(), other.origin.x.clone()),
                                 min(self.origin.y.clone(), other.origin.y.clone()));

        let lower_right = Point2D(max(self.origin.x + self.size.width,
                                      other.origin.x + other.size.width),
                                  max(self.origin.y + self.size.height,
                                      other.origin.y + other.size.height));

        Rect {
            origin: upper_left.clone(),
            size: Size2D(lower_right.x - upper_left.x, lower_right.y - upper_left.y)
        }
    }

    pub fn translate(&self, other: &Point2D<T>) -> Rect<T> {
        Rect {
            origin: Point2D(self.origin.x + other.x, self.origin.y + other.y),
            size: self.size.clone()
        }
    }
}

pub fn min<T:Clone + Ord>(x: T, y: T) -> T {
    if x <= y { x } else { y }
}

pub fn max<T:Clone + Ord>(x: T, y: T) -> T {
    if x >= y { x } else { y }
}

#[test]
fn test_min_max() {
    assert!(min(0, 1) == 0);
    assert!(min(-1.0, 0.0) == -1.0);

    assert!(max(0, 1) == 1);
    assert!(max(-1.0, 0.0) == 0.0);
}

#[test]
fn test_translate() {
    let p = Rect(Point2D(0, 0), Size2D(50, 40));
    let pp = p.translate(&Point2D(10,15));

    assert!(pp.size.width == 50);
    assert!(pp.size.height == 40);
    assert!(pp.origin.x == 10);
    assert!(pp.origin.y == 15);

    let r = Rect(Point2D(-10, -5), Size2D(50, 40));
    let rr = r.translate(&Point2D(0,-10));

    assert!(rr.size.width == 50);
    assert!(rr.size.height == 40);
    assert!(rr.origin.x == -10);
    assert!(rr.origin.y == -15);
}

#[test]
fn test_union() {
    let p = Rect(Point2D(0,0), Size2D(50, 40));
    let q = Rect(Point2D(20,20), Size2D(5, 5));
    let r = Rect(Point2D(-15, -30), Size2D(200, 15));
    let s = Rect(Point2D(20, -15), Size2D(250, 200));

    let pq = p.union(&q);
    assert!(pq.origin == Point2D(0, 0));
    assert!(pq.size == Size2D(50, 40));

    let pr = p.union(&r);
    assert!(pr.origin == Point2D(-15, -30));
    assert!(pr.size == Size2D(200, 70));

    let ps = p.union(&s);
    assert!(ps.origin == Point2D(0, -15));
    assert!(ps.size == Size2D(270, 200));

}

#[test]
fn test_intersection() {
    let p = Rect(Point2D(0, 0), Size2D(10, 20));
    let q = Rect(Point2D(5, 15), Size2D(10, 10));
    let r = Rect(Point2D(-5, -5), Size2D(8, 8));

    let pq = p.intersection(&q);
    assert!(pq.is_some());
    let pq = pq.get();
    assert!(pq.origin == Point2D(5, 15));
    assert!(pq.size == Size2D(5, 5));

    let pr = p.intersection(&r);
    assert!(pr.is_some());
    let pr = pr.get();
    assert!(pr.origin == Point2D(0, 0));
    assert!(pr.size == Size2D(3, 3));

    let qr = q.intersection(&r);
    assert!(qr.is_none());
}
<commit_msg>Update tests for new Rust<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use point::Point2D;
use size::Size2D;
use std::cmp::{Eq, Ord};

#[deriving(Eq, Clone)]
pub struct Rect<T> {
    origin: Point2D<T>,
    size: Size2D<T>,
}

pub fn Rect<T:Clone + Ord + Add<T,T> + Sub<T,T>>(origin: Point2D<T>,
                                                 size: Size2D<T>)
        -> Rect<T> {
    return Rect {
        origin: origin,
        size: size
    }
}

impl<T: Clone + Ord + Add<T,T> + Sub<T,T>> Rect<T> {
    pub fn intersects(&self, other: &Rect<T>) -> bool {
        self.origin.x < other.origin.x + other.size.width &&
       other.origin.x <  self.origin.x + self.size.width &&
        self.origin.y < other.origin.y + other.size.height &&
       other.origin.y <  self.origin.y + self.size.height
    }

    pub fn intersection(&self, other: &Rect<T>) -> Option<Rect<T>> {
        if !self.intersects(other) {
            return None;
        }

        let upper_left = Point2D(max(self.origin.x.clone(), other.origin.x.clone()),
                                 max(self.origin.y.clone(), other.origin.y.clone()));

        let lower_right = Point2D(min(self.origin.x + self.size.width,
                                      other.origin.x + other.size.width),
                                  min(self.origin.y + self.size.height,
                                      other.origin.y + other.size.height));

        Some(Rect(upper_left.clone(), Size2D(lower_right.x - upper_left.x,
                                             lower_right.y - upper_left.y)))
    }

    pub fn union(&self, other: &Rect<T>) -> Rect<T> {
        let upper_left = Point2D(min(self.origin.x.clone(), other.origin.x.clone()),
                                 min(self.origin.y.clone(), other.origin.y.clone()));

        let lower_right = Point2D(max(self.origin.x + self.size.width,
                                      other.origin.x + other.size.width),
                                  max(self.origin.y + self.size.height,
                                      other.origin.y + other.size.height));

        Rect {
            origin: upper_left.clone(),
            size: Size2D(lower_right.x - upper_left.x, lower_right.y - upper_left.y)
        }
    }

    pub fn translate(&self, other: &Point2D<T>) -> Rect<T> {
        Rect {
            origin: Point2D(self.origin.x + other.x, self.origin.y + other.y),
            size: self.size.clone()
        }
    }
}

pub fn min<T:Clone + Ord>(x: T, y: T) -> T {
    if x <= y { x } else { y }
}

pub fn max<T:Clone + Ord>(x: T, y: T) -> T {
    if x >= y { x } else { y }
}

#[test]
fn test_min_max() {
    assert!(min(0, 1) == 0);
    assert!(min(-1.0, 0.0) == -1.0);

    assert!(max(0, 1) == 1);
    assert!(max(-1.0, 0.0) == 0.0);
}

#[test]
fn test_translate() {
    let p = Rect(Point2D(0, 0), Size2D(50, 40));
    let pp = p.translate(&Point2D(10,15));

    assert!(pp.size.width == 50);
    assert!(pp.size.height == 40);
    assert!(pp.origin.x == 10);
    assert!(pp.origin.y == 15);

    let r = Rect(Point2D(-10, -5), Size2D(50, 40));
    let rr = r.translate(&Point2D(0,-10));

    assert!(rr.size.width == 50);
    assert!(rr.size.height == 40);
    assert!(rr.origin.x == -10);
    assert!(rr.origin.y == -15);
}

#[test]
fn test_union() {
    let p = Rect(Point2D(0,0), Size2D(50, 40));
    let q = Rect(Point2D(20,20), Size2D(5, 5));
    let r = Rect(Point2D(-15, -30), Size2D(200, 15));
    let s = Rect(Point2D(20, -15), Size2D(250, 200));

    let pq = p.union(&q);
    assert!(pq.origin == Point2D(0, 0));
    assert!(pq.size == Size2D(50, 40));

    let pr = p.union(&r);
    assert!(pr.origin == Point2D(-15, -30));
    assert!(pr.size == Size2D(200, 70));

    let ps = p.union(&s);
    assert!(ps.origin == Point2D(0, -15));
    assert!(ps.size == Size2D(270, 200));

}

#[test]
fn test_intersection() {
    let p = Rect(Point2D(0, 0), Size2D(10, 20));
    let q = Rect(Point2D(5, 15), Size2D(10, 10));
    let r = Rect(Point2D(-5, -5), Size2D(8, 8));

    let pq = p.intersection(&q);
    assert!(pq.is_some());
    let pq = pq.unwrap();
    assert!(pq.origin == Point2D(5, 15));
    assert!(pq.size == Size2D(5, 5));

    let pr = p.intersection(&r);
    assert!(pr.is_some());
    let pr = pr.unwrap();
    assert!(pr.origin == Point2D(0, 0));
    assert!(pr.size == Size2D(3, 3));

    let qr = q.intersection(&r);
    assert!(qr.is_none());
}
<|endoftext|>


<commit_before>// Copyright 2015, Paul Osborne <osbpau@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/license/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option.  This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(old_io)]
#![feature(io)]
#![feature(std_misc)]
#![allow(deprecated)] // old_io Timer replacement not stable

#[macro_use]
extern crate sysfs_gpio;

use sysfs_gpio::core::{Direction, Pin};
use std::time::Duration;
use std::old_io::Timer;
use std::io;

// export a GPIO for use.  This will not fail
// if already exported
fn blink_my_led(led : u64, duration_ms : i64, period_ms : i64) -> io::Result<()> {
    let my_led = Pin::new(led);

    try!(my_led.export());
    try_unexport!(my_led, my_led.set_direction(Direction::Low));
    let mut tmr = match Timer::new() {
        Ok(tmr) => tmr,
        Err(_) => panic!("Could not create timer!"),
    };
    let iterations = duration_ms / period_ms / 2;
    for _ in 0..iterations {
        try_unexport!(my_led, my_led.set_value(0));
        tmr.sleep(Duration::milliseconds(period_ms));
        try_unexport!(my_led, my_led.set_value(1));
        tmr.sleep(Duration::milliseconds(period_ms));
    }
    try_unexport!(my_led, my_led.set_value(0));
    try!(my_led.unexport());
    return Ok(());
}

fn main() {
    match blink_my_led(66, 5000, 200) {
        Ok(()) => println!("Blinking Complete!"),
        Err(err) => println!("I have a blinking problem! {}", err),
    }
}
<commit_msg>example: tweak example to take arguments for pin, duration, period<commit_after>// Copyright 2015, Paul Osborne <osbpau@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/license/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option.  This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(old_io)]
#![feature(io)]
#![feature(os)]
#![feature(std_misc)]
#![allow(deprecated)] // old_io Timer replacement not stable

#[macro_use]
extern crate sysfs_gpio;

use sysfs_gpio::core::{Direction, Pin};
use std::time::Duration;
use std::old_io::Timer;
use std::io;
use std::os;

struct Arguments {
    pin : u64,
    duration_ms : i64,
    period_ms : i64,
}

// export a GPIO for use.  This will not fail
// if already exported
fn blink_my_led(led : u64, duration_ms : i64, period_ms : i64) -> io::Result<()> {
    let my_led = Pin::new(led);

    try!(my_led.export());
    try_unexport!(my_led, my_led.set_direction(Direction::Low));
    let mut tmr = match Timer::new() {
        Ok(tmr) => tmr,
        Err(_) => panic!("Could not create timer!"),
    };
    let iterations = duration_ms / period_ms / 2;
    println!("./blinky {} {} {}", led, duration_ms, period_ms);
    println!("Iterations: {}", iterations);
    for _ in 0..iterations {
        try_unexport!(my_led, my_led.set_value(0));
        tmr.sleep(Duration::milliseconds(period_ms));
        try_unexport!(my_led, my_led.set_value(1));
        tmr.sleep(Duration::milliseconds(period_ms));
    }
    try_unexport!(my_led, my_led.set_value(0));
    try!(my_led.unexport());
    return Ok(());
}

fn print_usage() {
    println!("Usage: ./blinky <pin> <duration_ms> <period_ms>");
}

fn get_args() -> Option<Arguments> {
    let args = os::args();
    if args.len() != 4 { return None; }
    let pin = match args[1].parse::<u64>() { Ok(pin) => pin, Err(_) => return None, };
    let duration_ms = match args[2].parse::<i64>() { Ok(ms) => ms, Err(_) => return None, };
    let period_ms = match args[3].parse::<i64>() { Ok(ms) => ms, Err(_) => return None, };
    Some(Arguments { pin: pin, duration_ms: duration_ms, period_ms: period_ms, })
}

fn main() {
    match get_args() {
        None => print_usage(),
        Some(args) => {
            match blink_my_led(args.pin, args.duration_ms, args.period_ms) {
                Ok(()) => println!("Success!"),
                Err(err) => println!("We have a blinking problem: {}", err),
            }
        },
    }
}
<|endoftext|>


<commit_before>
extern crate getopts;
extern crate toml;

use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::path;

use getopts::Options;

const CONFIG: &'static str = ".plugwise.toml";
const CONFIG_HEAD: &'static str = "config";
const CONFIG_DEVICE: &'static str = "device";

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options] [mac|alias]", program);
    println!("{}", opts.usage(&brief));
}

fn load_config(configfile: &path::PathBuf) -> toml::Table {
    let mut config = String::new();
    if let Ok(mut file) = File::open(configfile) {
        file.read_to_string(&mut config).ok().expect(
            &format!("unable to read file `{}`", configfile.display()));
    } // errors are silently ignored (assuming file didn't exist)
    toml::Parser::new(&config).parse().expect(&format!("unable to parse `{}`", configfile.display()))
}

fn write_config(configfile: &path::PathBuf, config: &toml::Table) {
    let mut file = File::create(configfile).ok().expect(
        &format!("unable to create `{}`", configfile.display()));
    write!(file, "{}", toml::Value::Table(config.clone())).ok().expect(
        &format!("unable to write to `{}`", configfile.display()));
}

fn get_device_from_config<'a>(config: &'a toml::Table) -> Option<&'a str> {
    config.get(CONFIG_HEAD)
          .map_or(None, |item|item.as_table())
          .map_or(None, |table|table.get(CONFIG_DEVICE))
          .map_or(None, |string|string.as_str())
}

fn update_device_from_config<'a>(config: &'a toml::Table, device: &'a str) -> toml::Table {
    let mut config_table = config.get(CONFIG_HEAD)
                                 .map_or(None, |item|item.as_table())
                                 .map_or(toml::Table::new(), |table|table.clone());
    config_table.insert(CONFIG_DEVICE.to_string(), toml::Value::String(device.to_string()));
    config_table
}

fn remove_device_from_config<'a>(config: &'a toml::Table) -> toml::Table {
    let mut config_table = config.get(CONFIG_HEAD)
                                 .map_or(None, |item|item.as_table())
                                 .map_or(toml::Table::new(), |table|table.clone());
    config_table.remove(CONFIG_DEVICE);
    config_table
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();

    opts.optopt("s", "serial", "configure serial-port", "DEVICE")
        .optflag("t", "stub", "configure to use stub implementation")
        .optopt("a", "alias", "assign a alias to Mac", "NAME") // XXX
        .optflag("u", "unalias", "forget alias") // XXX
        .optflag("l", "list", "list aliassed circles") // XXX
        .optflag("r", "relaystatus", "print the relay status of a circle") // XXX
        .optflag("e", "enable", "enable the relay of a circle") // XXX
        .optflag("d", "disable", "disable the relay of a circle") // XXX
        .optflag("p", "powerusage", "print the actual power usage of a circle") // XXX
        .optopt("o", "powersince", "print the total power usage of a given number of days", "DAYS") // XXX
        .optflag("c", "clock", "print the internal clock value of a circle") // XXX
        .optflag("j", "updateclock", "update the internal clock of a circle using Internet time") // XXX
        .optflag("h", "help", "print this help menu") // XXX
        .optflag("v", "verbose", "print debug information"); // XXX

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m },
        Err(f) => { panic!(f.to_string()) }
    };

    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }

    let mut configfile = env::home_dir().expect("unable to find home/user directory");
    configfile.push(CONFIG);

    let mut config = load_config(&configfile);
    let mut update_config = false;

    if let Some(new_device) = matches.opt_str("s") {
        // client has provided new device; update (any) loaded configuration
        let new_config = update_device_from_config(&config, &new_device);
        config.insert(CONFIG_HEAD.to_string(), toml::Value::Table(new_config));
        update_config = true;
    } else if matches.opt_present("t") {
        // client has indicated to use stub
        let new_config = remove_device_from_config(&config);
        config.insert(CONFIG_HEAD.to_string(), toml::Value::Table(new_config));
        update_config = true;
    }

    let device = get_device_from_config(&config);

    println!("{:?}", device); // FIXME: remove this
    // FIXME: implement more options

    if update_config {
        write_config(&configfile, &config);
    }

}
<commit_msg>circle: initial aliases support<commit_after>
extern crate getopts;
extern crate toml;

use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::path;
use std::collections::HashMap;

use getopts::Options;

const CONFIG: &'static str = ".plugwise.toml";
const CONFIG_HEAD: &'static str = "config";
const CONFIG_DEVICE: &'static str = "device";
const ALIAS_MAC: &'static str = "mac";

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options] [mac|alias]", program);
    println!("{}", opts.usage(&brief));
}

fn load_config(configfile: &path::PathBuf) -> toml::Table {
    let mut config = String::new();
    if let Ok(mut file) = File::open(configfile) {
        file.read_to_string(&mut config).ok().expect(
            &format!("unable to read file `{}`", configfile.display()));
    } // errors are silently ignored (assuming file didn't exist)
    toml::Parser::new(&config).parse().expect(&format!("unable to parse `{}`", configfile.display()))
}

fn write_config(configfile: &path::PathBuf, config: &toml::Table) {
    let mut file = File::create(configfile).ok().expect(
        &format!("unable to create `{}`", configfile.display()));
    write!(file, "{}", toml::Value::Table(config.clone())).ok().expect(
        &format!("unable to write to `{}`", configfile.display()));
}

fn get_device_from_config<'a>(config: &'a toml::Table) -> Option<&'a str> {
    config.get(CONFIG_HEAD)
          .map_or(None, |item|item.as_table())
          .map_or(None, |table|table.get(CONFIG_DEVICE))
          .map_or(None, |string|string.as_str())
}

fn get_aliases<'a>(config: &'a toml::Table) -> HashMap<String, u64> {
    let mut aliases = HashMap::new();

    for key in config.keys().filter(|&k|k != CONFIG_HEAD) {
        let mac = config.get(key)
                        .map_or(None, |item|item.as_table())
                        .map_or(None, |table|table.get(ALIAS_MAC))
                        .map_or(None, |string|string.as_str());
        if let Some(mac) = mac {
            if mac.len() == 16 {
                let mac = u64::from_str_radix(&mac, 16);
                if let Ok(mac) = mac {
                    aliases.insert(key.to_string(), mac);
                }
            }
        }
    }

    aliases
}

fn update_device_from_config<'a>(config: &'a toml::Table, device: &'a str) -> toml::Table {
    let mut config_table = config.get(CONFIG_HEAD)
                                 .map_or(None, |item|item.as_table())
                                 .map_or(toml::Table::new(), |table|table.clone());
    config_table.insert(CONFIG_DEVICE.to_string(), toml::Value::String(device.to_string()));
    config_table
}

fn remove_device_from_config<'a>(config: &'a toml::Table) -> toml::Table {
    let mut config_table = config.get(CONFIG_HEAD)
                                 .map_or(None, |item|item.as_table())
                                 .map_or(toml::Table::new(), |table|table.clone());
    config_table.remove(CONFIG_DEVICE);
    config_table
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();

    opts.optopt("s", "serial", "configure serial-port", "DEVICE")
        .optflag("t", "stub", "configure to use stub implementation")
        .optopt("a", "alias", "assign a alias to Mac", "NAME") // XXX
        .optflag("u", "unalias", "forget alias") // XXX
        .optflag("l", "list", "list aliassed circles") // XXX
        .optflag("r", "relaystatus", "print the relay status of a circle") // XXX
        .optflag("e", "enable", "enable the relay of a circle") // XXX
        .optflag("d", "disable", "disable the relay of a circle") // XXX
        .optflag("p", "powerusage", "print the actual power usage of a circle") // XXX
        .optopt("o", "powersince", "print the total power usage of a given number of days", "DAYS") // XXX
        .optflag("c", "clock", "print the internal clock value of a circle") // XXX
        .optflag("j", "updateclock", "update the internal clock of a circle using Internet time") // XXX
        .optflag("h", "help", "print this help menu") // XXX
        .optflag("v", "verbose", "print debug information"); // XXX

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m },
        Err(f) => { panic!(f.to_string()) }
    };

    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }

    let mut configfile = env::home_dir().expect("unable to find home/user directory");
    configfile.push(CONFIG);

    let mut config = load_config(&configfile);
    let mut update_config = false;

    if let Some(new_device) = matches.opt_str("s") {
        // client has provided new device; update (any) loaded configuration
        let new_config = update_device_from_config(&config, &new_device);
        config.insert(CONFIG_HEAD.to_string(), toml::Value::Table(new_config));
        update_config = true;
    } else if matches.opt_present("t") {
        // client has indicated to use stub
        let new_config = remove_device_from_config(&config);
        config.insert(CONFIG_HEAD.to_string(), toml::Value::Table(new_config));
        update_config = true;
    }

    let serial = get_device_from_config(&config);
    let aliases = get_aliases(&config);

    println!("{:?}", serial); // FIXME: remove this
    // FIXME: implement more options

    if update_config {
        write_config(&configfile, &config);
    }

}
<|endoftext|>


<commit_before>extern crate sdl2;

fn main() {
    let sdl_context = sdl2::init().unwrap();
    let joystick_subsystem = sdl_context.joystick().unwrap();
    let haptic_subsystem = sdl_context.haptic().unwrap();

    let available =
        match joystick_subsystem.num_joysticks() {
            Ok(n)  => n,
            Err(e) => panic!("can't enumerate joysticks: {}", e),
        };

    println!("{} joysticks available", available);

    let mut joystick = None;

    // Iterate over all available joysticks and stop once we manage to
    // open one.
    for id in 0..available {
        match joystick_subsystem.open(id) {
            Ok(c) => {
                println!("Success: opened \"{}\"", c.name());
                joystick = Some(c);
                break;
            },
            Err(e) => println!("failed: {:?}", e),
        }
    }

    if joystick.is_none() {
        panic!("Couldn't open any joystick");
    };

    let joystick = joystick.unwrap();

    let mut haptic = haptic_subsystem.open_from_joystick_id(joystick.instance_id()).unwrap();

    for event in sdl_context.event_pump().unwrap().wait_iter() {
        use sdl2::event::Event;

        match event {
            Event::JoyAxisMotion{ axis_idx, value: val, .. } => {
                // Axis motion is an absolute value in the range
                // [-32768, 32767]. Let's simulate a very rough dead
                // zone to ignore spurious events.
                let dead_zone = 10000;
                if val > dead_zone || val < -dead_zone {
                    println!("Axis {} moved to {}", axis_idx, val);
                }
            }
            Event::JoyButtonDown{ button_idx, .. } =>{
                println!("Button {} down", button_idx);
                haptic.rumble_play(0.5, 500);
            },
            Event::JoyButtonUp{ button_idx, .. } =>
                println!("Button {} up", button_idx),
            Event::JoyHatMotion{ hat_idx, state, .. } =>
                println!("Hat {} moved to {:?}", hat_idx, state),
            Event::Quit{..} => break,
            _ => (),
        }
    }
}
<commit_msg>Update haptic example to use joystick index<commit_after>extern crate sdl2;

fn main() {
    let sdl_context = sdl2::init().unwrap();
    let joystick_subsystem = sdl_context.joystick().unwrap();
    let haptic_subsystem = sdl_context.haptic().unwrap();

    let available =
        match joystick_subsystem.num_joysticks() {
            Ok(n)  => n,
            Err(e) => panic!("can't enumerate joysticks: {}", e),
        };

    println!("{} joysticks available", available);

    let mut joystick_index = None;

    // Iterate over all available joysticks and stop once we manage to
    // open one.
    for id in 0..available {
        match joystick_subsystem.open(id) {
            Ok(c) => {
                println!("Success: opened \"{}\"", c.name());
                joystick_index = Some(id);
                break;
            },
            Err(e) => println!("failed: {:?}", e),
        }
    }

    if joystick_index.is_none() {
        panic!("Couldn't open any joystick");
    };

    let mut haptic = haptic_subsystem.open_from_joystick_id(joystick_index.unwrap()).unwrap();

    for event in sdl_context.event_pump().unwrap().wait_iter() {
        use sdl2::event::Event;

        match event {
            Event::JoyAxisMotion{ axis_idx, value: val, .. } => {
                // Axis motion is an absolute value in the range
                // [-32768, 32767]. Let's simulate a very rough dead
                // zone to ignore spurious events.
                let dead_zone = 10000;
                if val > dead_zone || val < -dead_zone {
                    println!("Axis {} moved to {}", axis_idx, val);
                }
            }
            Event::JoyButtonDown{ button_idx, .. } =>{
                println!("Button {} down", button_idx);
                haptic.rumble_play(0.5, 500);
            },
            Event::JoyButtonUp{ button_idx, .. } =>
                println!("Button {} up", button_idx),
            Event::JoyHatMotion{ hat_idx, state, .. } =>
                println!("Hat {} moved to {:?}", hat_idx, state),
            Event::Quit{..} => break,
            _ => (),
        }
    }
}
<|endoftext|>


<commit_before>#![allow(non_snake_case)]

//! A few linear algebra operations on two-dimensional arrays, just for demo
//! purposes.

extern crate ndarray;
extern crate num_traits;
extern crate num_complex;

use num_traits::{Num, Zero, One};
use num_traits::Float;
use num_complex::Complex;
use std::ops::{Add, Sub, Mul, Div};

use ndarray::{RcArray, Ix};
use ndarray::{rcarr1, rcarr2};
use ndarray::LinalgScalar;

/// Column vector.
pub type Col = RcArray;
/// Rectangular matrix.
pub type Mat = RcArray;

/// Trait union for a ring with 1.
pub trait Ring : Clone + Zero + Add<Output=Self> + Sub<Output=Self>
    + One + Mul<Output=Self> { }
impl<A: Clone + Zero + Add<Output=A> + Sub<Output=A> + One + Mul<Output=A>> Ring for A { }

/// Trait union for a field.
pub trait Field : Ring + Div<Output=Self> { }
impl<A: Ring + Div<Output=A>> Field for A { }

/// A real or complex number.
pub trait ComplexField : LinalgScalar
{
    #[inline]
    fn conjugate(self) -> Self { self }
    fn sqrt_real(self) -> Self;
    #[inline]
    fn is_complex() -> bool { false }
}

impl ComplexField for f32
{
    #[inline]
    fn sqrt_real(self) -> f32 { self.sqrt() }
}

impl ComplexField for f64
{
    #[inline]
    fn sqrt_real(self) -> f64 { self.sqrt() }
}

impl ComplexField for Complex
{
    #[inline]
    fn conjugate(self) -> Complex { self.conj() }
    fn sqrt_real(self) -> Complex { Complex::new(self.re.sqrt(), A::zero()) }
    #[inline]
    fn is_complex() -> bool { true }
}

// Some examples.
fn main() {
    chol();
    subst();
    lst_squares();
}

fn chol()
{
    let _ = rcarr2(&[[1., 2.], [3., 4.]]); // not pos. def.
    let a = rcarr2(&[[10., 14.], [14., 20.]]); // aT a is pos def

    let chol = cholesky(a);
    let ans =
        rcarr2(&[[3.16227770, 0.00000000],
                 [4.42718887, 0.63245525]]);

    assert!(ans.all_close(&chol, 0.001));

    // Compute bT b for a pos def matrix
    let b = RcArray::linspace(0f32, 8., 9).reshape((3, 3));
    let mut bt = b.clone();
    bt.swap_axes(0, 1);
    let bpd = bt.dot(&b).into_shared();
    println!("bpd=\n{:?}", bpd);
    let chol = cholesky(bpd);
    println!("chol=\n{:.8?}", chol);

    let ans =
        rcarr2(&[[6.70820379, 0.00000000, 0.00000000],
                 [8.04984474, 1.09544373, 0.00000000],
                 [9.39148617, 2.19088745, 0.00000000]]);
    assert!(ans.all_close(&chol, 0.001));

    let a =
        rcarr2(&[[ 0.05201001,  0.22982409,  0.1014132 ],
                 [ 0.22982409,  1.105822  ,  0.37946544],
                 [ 0.1014132 ,  0.37946544,  1.16199134]]);
    let chol = cholesky(a);

    let ans =
        rcarr2(&[[ 0.22805704,  0.        ,  0.        ],
                 [ 1.00774829,  0.30044197,  0.        ],
                 [ 0.44468348, -0.2285419 ,  0.95499557]]);
    assert!(ans.all_close(&chol, 0.001));
}

fn subst()
{
    let lll =
        rcarr2(&[[ 0.22805704,  0.        ,  0.        ],
                 [ 1.00774829,  0.30044197,  0.        ],
                 [ 0.44468348, -0.2285419 ,  0.95499557]]);
    let ans = rcarr1::<f32>(&[4.384868, -8.050947, -0.827078]);

    assert!(ans.all_close(&subst_fw(&lll, &rcarr1(&[1., 2., 3.])),
                         0.001));
}

fn lst_squares()
{
    let xs =
        rcarr2(&[[ 2.,  3.],
                 [-2., -1.],
                 [ 1.,  5.],
                 [-1.,  2.]]);
    let b = rcarr1(&[1., -1., 2., 1.]);
    let x_lstsq = least_squares(&xs, &b);
    let ans = rcarr1(&[0.070632, 0.390335]);
    assert!(x_lstsq.all_close(&ans, 0.001));
}

/// Solve *a x = b* with linear least squares approximation.
///
/// It is used to find the best fit for an overdetermined system,
/// i.e. the number of rows in *a* is larger than the number of
/// unknowns *x*.
///
/// Return best fit for *x*.
pub fn least_squares(a: &Mat, b: &Col) -> Col
{
    // Using transpose: a.T a x = a.T b;
    // a.T a being square gives naive solution
    // x_lstsq = inv(a.T a) a.T b
    //
    // Solve using cholesky decomposition
    // aT a x = aT b
    //
    // Factor aT a into L L.T
    //
    // L L.T x = aT b
    //
    // => L z = aT b
    //  fw subst for z
    // => L.T x = z
    //  bw subst for x estimate
    //
    let mut aT = a.clone();
    aT.swap_axes(0, 1);
    if ::is_complex() {
        // conjugate transpose
        for elt in aT.iter_mut() {
            *elt = elt.conjugate();
        }
    }

    let aT_a = aT.dot(a).into_shared();
    let mut L = cholesky(aT_a);
    let rhs = aT.dot(b).into_shared();

    // Solve L z = aT b
    let z = subst_fw(&L, &rhs);

    // Solve L.T x = z
    if ::is_complex() {
        // conjugate transpose
        // only elements below the diagonal have imag part
        let (m, _) = L.dim();
        for i in 1..m {
            for j in 0..i {
                let elt = &mut L[[i, j]];
                *elt = elt.conjugate();
            }
        }
    }
    L.swap_axes(0, 1);

    // => x_lstsq
    subst_bw(&L, &z)
}

/// Factor *a = L LT*.
///
/// *a* should be a square matrix, hermitian and positive definite.
///
/// https://en.wikipedia.org/wiki/Cholesky_decomposition
///
/// “The Cholesky decomposition is mainly used for the numerical solution of
/// linear equations Ax = b.
///
/// If A is symmetric and positive definite, then we can solve Ax = b by first
/// computing the Cholesky decomposition A = LL*, then solving Ly = b for y by
/// forward substitution, and finally solving L*x = y for x by back
/// substitution.”
///
/// Return L.
pub fn cholesky(a: Mat) -> Mat
{
    let z = A::zero();
    let (m, n) = a.dim();
    assert!(m == n);
    // Perform the operation in-place on `a`
    let mut L = a;
    for i in 0..m {
        // Entries 0 .. i before the diagonal
        for j in 0..i {
            // A = (
            // L²_1,1
            // L_2,1 L_1,1  L²_2,1 + L²_2,2
            // L_3,1 L_1,1  L_3,1 L_2,1 + L_3,2 L_2,2  L²_3,1 + L²_3,2 + L²_3,3
            // .. )
            let mut lik_ljk_sum = z;
            {
                // L_ik for k = 0 .. j
                // L_jk for k = 0 .. j
                let Lik = L.row(i).into_iter();
                let Ljk = L.row(j).into_iter();
                for (&lik, &ljk) in Lik.zip(Ljk).take(j as usize) {
                    lik_ljk_sum = lik_ljk_sum + lik * ljk.conjugate();
                }
            }

            // L_ij = [ A_ij - Sum(k = 1 .. j) L_ik L_jk ] / L_jj
            L[[i, j]] = (L[[i, j]] - lik_ljk_sum) / L[[j, j]];
        }

        // Diagonal where i == j
        // L_jj = Sqrt[ A_jj - Sum(k = 1 .. j) L_jk L_jk ]
        let j = i;
        let mut ljk_sum = z;
        // L_jk for k = 0 .. j
        for &ljk in L.row(j).into_iter().take(j as usize) {
            ljk_sum = ljk_sum + ljk * ljk.conjugate();
        }
        L[[j, j]] = (L[[j, j]] - ljk_sum).sqrt_real();

        // After the diagonal
        // L_ij = 0 for j > i
        for j in i + 1..n {
            L[[i, j]] = z;
        }
    }
    L
}

/// Solve *L x = b* where *L* is a lower triangular matrix.
pub fn subst_fw(l: &Mat, b: &Col) -> Col
{
    let (m, n) = l.dim();
    assert!(m == n);
    assert!(m == b.dim());
    let mut x = Col::zeros(m);
    for i in 0..m {
        // b_lx_sum = b[i] - Sum(for j = 0 .. i) L_ij x_j
        let mut b_lx_sum = b[i];
        for j in 0..i {
            b_lx_sum = b_lx_sum - l[[i, j]] * x[j];
        }
        x[i] = b_lx_sum / l[[i, i]];
    }
    x
}

/// Solve *U x = b* where *U* is an upper triangular matrix.
pub fn subst_bw(u: &Mat, b: &Col) -> Col
{
    let (m, n) = u.dim();
    assert!(m == n);
    assert!(m == b.dim());
    let mut x = Col::zeros(m);
    for i in (0..m).rev() {
        // b_ux_sum = b[i] - Sum(for j = i .. m) U_ij x_j
        let mut b_ux_sum = b[i];
        for j in i..m {
            b_ux_sum = b_ux_sum - u[[i, j]] * x[j];
        }
        x[i] = b_ux_sum / u[[i, i]];
    }
    x
}
<commit_msg>Update examples/linalg.rs<commit_after>#![allow(non_snake_case)]

//! A few linear algebra operations on two-dimensional arrays, just for demo
//! purposes.

extern crate ndarray;
extern crate num_traits;
extern crate num_complex;

use num_traits::{Num, Zero, One};
use num_traits::Float;
use num_complex::Complex;
use std::ops::{Add, Sub, Mul, Div};

use ndarray::{RcArray, Ix1, Ix2};
use ndarray::{rcarr1, rcarr2};
use ndarray::LinalgScalar;

/// Column vector.
pub type Col = RcArray;
/// Rectangular matrix.
pub type Mat = RcArray;

/// Trait union for a ring with 1.
pub trait Ring : Clone + Zero + Add<Output=Self> + Sub<Output=Self>
    + One + Mul<Output=Self> { }
impl<A: Clone + Zero + Add<Output=A> + Sub<Output=A> + One + Mul<Output=A>> Ring for A { }

/// Trait union for a field.
pub trait Field : Ring + Div<Output=Self> { }
impl<A: Ring + Div<Output=A>> Field for A { }

/// A real or complex number.
pub trait ComplexField : LinalgScalar
{
    #[inline]
    fn conjugate(self) -> Self { self }
    fn sqrt_real(self) -> Self;
    #[inline]
    fn is_complex() -> bool { false }
}

impl ComplexField for f32
{
    #[inline]
    fn sqrt_real(self) -> f32 { self.sqrt() }
}

impl ComplexField for f64
{
    #[inline]
    fn sqrt_real(self) -> f64 { self.sqrt() }
}

impl ComplexField for Complex
{
    #[inline]
    fn conjugate(self) -> Complex { self.conj() }
    fn sqrt_real(self) -> Complex { Complex::new(self.re.sqrt(), A::zero()) }
    #[inline]
    fn is_complex() -> bool { true }
}

// Some examples.
fn main() {
    chol();
    subst();
    lst_squares();
}

fn chol()
{
    let _ = rcarr2(&[[1., 2.], [3., 4.]]); // not pos. def.
    let a = rcarr2(&[[10., 14.], [14., 20.]]); // aT a is pos def

    let chol = cholesky(a);
    let ans =
        rcarr2(&[[3.16227770, 0.00000000],
                 [4.42718887, 0.63245525]]);

    assert!(ans.all_close(&chol, 0.001));

    // Compute bT b for a pos def matrix
    let b = RcArray::linspace(0f32, 8., 9).reshape((3, 3));
    let mut bt = b.clone();
    bt.swap_axes(0, 1);
    let bpd = bt.dot(&b).into_shared();
    println!("bpd=\n{:?}", bpd);
    let chol = cholesky(bpd);
    println!("chol=\n{:.8?}", chol);

    let ans =
        rcarr2(&[[6.70820379, 0.00000000, 0.00000000],
                 [8.04984474, 1.09544373, 0.00000000],
                 [9.39148617, 2.19088745, 0.00000000]]);
    assert!(ans.all_close(&chol, 0.001));

    let a =
        rcarr2(&[[ 0.05201001,  0.22982409,  0.1014132 ],
                 [ 0.22982409,  1.105822  ,  0.37946544],
                 [ 0.1014132 ,  0.37946544,  1.16199134]]);
    let chol = cholesky(a);

    let ans =
        rcarr2(&[[ 0.22805704,  0.        ,  0.        ],
                 [ 1.00774829,  0.30044197,  0.        ],
                 [ 0.44468348, -0.2285419 ,  0.95499557]]);
    assert!(ans.all_close(&chol, 0.001));
}

fn subst()
{
    let lll =
        rcarr2(&[[ 0.22805704,  0.        ,  0.        ],
                 [ 1.00774829,  0.30044197,  0.        ],
                 [ 0.44468348, -0.2285419 ,  0.95499557]]);
    let ans = rcarr1::<f32>(&[4.384868, -8.050947, -0.827078]);

    assert!(ans.all_close(&subst_fw(&lll, &rcarr1(&[1., 2., 3.])),
                         0.001));
}

fn lst_squares()
{
    let xs =
        rcarr2(&[[ 2.,  3.],
                 [-2., -1.],
                 [ 1.,  5.],
                 [-1.,  2.]]);
    let b = rcarr1(&[1., -1., 2., 1.]);
    let x_lstsq = least_squares(&xs, &b);
    let ans = rcarr1(&[0.070632, 0.390335]);
    assert!(x_lstsq.all_close(&ans, 0.001));
}

/// Solve *a x = b* with linear least squares approximation.
///
/// It is used to find the best fit for an overdetermined system,
/// i.e. the number of rows in *a* is larger than the number of
/// unknowns *x*.
///
/// Return best fit for *x*.
pub fn least_squares(a: &Mat, b: &Col) -> Col
{
    // Using transpose: a.T a x = a.T b;
    // a.T a being square gives naive solution
    // x_lstsq = inv(a.T a) a.T b
    //
    // Solve using cholesky decomposition
    // aT a x = aT b
    //
    // Factor aT a into L L.T
    //
    // L L.T x = aT b
    //
    // => L z = aT b
    //  fw subst for z
    // => L.T x = z
    //  bw subst for x estimate
    //
    let mut aT = a.clone();
    aT.swap_axes(0, 1);
    if ::is_complex() {
        // conjugate transpose
        for elt in aT.iter_mut() {
            *elt = elt.conjugate();
        }
    }

    let aT_a = aT.dot(a).into_shared();
    let mut L = cholesky(aT_a);
    let rhs = aT.dot(b).into_shared();

    // Solve L z = aT b
    let z = subst_fw(&L, &rhs);

    // Solve L.T x = z
    if ::is_complex() {
        // conjugate transpose
        // only elements below the diagonal have imag part
        let (m, _) = L.dim_tuple();
        for i in 1..m {
            for j in 0..i {
                let elt = &mut L[[i, j]];
                *elt = elt.conjugate();
            }
        }
    }
    L.swap_axes(0, 1);

    // => x_lstsq
    subst_bw(&L, &z)
}

/// Factor *a = L LT*.
///
/// *a* should be a square matrix, hermitian and positive definite.
///
/// https://en.wikipedia.org/wiki/Cholesky_decomposition
///
/// “The Cholesky decomposition is mainly used for the numerical solution of
/// linear equations Ax = b.
///
/// If A is symmetric and positive definite, then we can solve Ax = b by first
/// computing the Cholesky decomposition A = LL*, then solving Ly = b for y by
/// forward substitution, and finally solving L*x = y for x by back
/// substitution.”
///
/// Return L.
pub fn cholesky(a: Mat) -> Mat
{
    let z = A::zero();
    let (m, n) = a.dim_tuple();
    assert!(m == n);
    // Perform the operation in-place on `a`
    let mut L = a;
    for i in 0..m {
        // Entries 0 .. i before the diagonal
        for j in 0..i {
            // A = (
            // L²_1,1
            // L_2,1 L_1,1  L²_2,1 + L²_2,2
            // L_3,1 L_1,1  L_3,1 L_2,1 + L_3,2 L_2,2  L²_3,1 + L²_3,2 + L²_3,3
            // .. )
            let mut lik_ljk_sum = z;
            {
                // L_ik for k = 0 .. j
                // L_jk for k = 0 .. j
                let Lik = L.row(i).into_iter();
                let Ljk = L.row(j).into_iter();
                for (&lik, &ljk) in Lik.zip(Ljk).take(j as usize) {
                    lik_ljk_sum = lik_ljk_sum + lik * ljk.conjugate();
                }
            }

            // L_ij = [ A_ij - Sum(k = 1 .. j) L_ik L_jk ] / L_jj
            L[[i, j]] = (L[[i, j]] - lik_ljk_sum) / L[[j, j]];
        }

        // Diagonal where i == j
        // L_jj = Sqrt[ A_jj - Sum(k = 1 .. j) L_jk L_jk ]
        let j = i;
        let mut ljk_sum = z;
        // L_jk for k = 0 .. j
        for &ljk in L.row(j).into_iter().take(j as usize) {
            ljk_sum = ljk_sum + ljk * ljk.conjugate();
        }
        L[[j, j]] = (L[[j, j]] - ljk_sum).sqrt_real();

        // After the diagonal
        // L_ij = 0 for j > i
        for j in i + 1..n {
            L[[i, j]] = z;
        }
    }
    L
}

/// Solve *L x = b* where *L* is a lower triangular matrix.
pub fn subst_fw(l: &Mat, b: &Col) -> Col
{
    let (m, n) = l.dim_tuple();
    assert!(m == n);
    assert!(m == b.len());
    let mut x = Col::zeros(m);
    for i in 0..m {
        // b_lx_sum = b[i] - Sum(for j = 0 .. i) L_ij x_j
        let mut b_lx_sum = b[i];
        for j in 0..i {
            b_lx_sum = b_lx_sum - l[[i, j]] * x[j];
        }
        x[i] = b_lx_sum / l[[i, i]];
    }
    x
}

/// Solve *U x = b* where *U* is an upper triangular matrix.
pub fn subst_bw(u: &Mat, b: &Col) -> Col
{
    let (m, n) = u.dim_tuple();
    assert!(m == n);
    assert!(m == b.len());
    let mut x = Col::zeros(m);
    for i in (0..m).rev() {
        // b_ux_sum = b[i] - Sum(for j = i .. m) U_ij x_j
        let mut b_ux_sum = b[i];
        for j in i..m {
            b_ux_sum = b_ux_sum - u[[i, j]] * x[j];
        }
        x[i] = b_ux_sum / u[[i, i]];
    }
    x
}
<|endoftext|>


<commit_before>// Copyright (c) 2020 DDN. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use crate::{generated::css_classes::C, Msg};
use chrono::{offset::Local, Datelike};
use iml_wire_types::{Branding, Conf};
use seed::{prelude::*, *};

pub fn view(conf: &Conf) -> impl View<Msg> {
    let year = Local::now().year();

    let footer_string = match conf.branding {
        Branding::Whamcloud => format!(
            "Integrated Manager for Lustre software {} is Copyright © ",
            conf.version
        ),
        _ => {
            if let Some(version) = &conf.exa_version {
                format!("Exascaler software {} is Copyright © ", version)
            } else {
                "Exascaler software is Copyright © ".to_string()
            }
        }
    };

    footer![
        class![C.h_5, C.flex, C.justify_center],
        div![
            class![C.px_5, C.text_sm, C.items_center,],
            footer_string,
            &year.to_string(),
            " DDN. All rights reserved.",
        ]
    ]
}
<commit_msg>Update footer branding (#1982)<commit_after>// Copyright (c) 2020 DDN. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use crate::{generated::css_classes::C, Msg};
use chrono::{offset::Local, Datelike};
use iml_wire_types::{Branding, Conf};
use seed::{prelude::*, *};

pub fn view(conf: &Conf) -> impl View<Msg> {
    let year = Local::now().year();

    let footer_string = match conf.branding {
        Branding::Whamcloud => format!(
            "Integrated Manager for Lustre software {} is Copyright © ",
            conf.version
        ),
        _ => {
            if let Some(version) = &conf.exa_version {
                format!("DDN EXAScaler v{} ", version)
            } else {
                "DDN EXAScaler ".to_string()
            }
        }
    };

    let footer_text =  match conf.branding {
        Branding::Whamcloud => div![
            footer_string,
            year.to_string(),
            " DDN. All rights reserved.".to_string(),
        ],
        _ => div![footer_string]
    };

    footer![
        class![C.h_5, C.flex, C.justify_center],
        div![
            class![C.px_5, C.text_sm, C.items_center,],
            footer_text
        ]
    ]
}
<|endoftext|>


<commit_before>// Copyright (c) 2018, Alessandro Ghedini
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#[macro_use]
extern crate log;
extern crate mio;
extern crate rand;
extern crate docopt;
extern crate quiche;
extern crate env_logger;

use std::fs;
use std::io;
use std::net;
use std::path;

use std::collections::hash_map;
use std::collections::HashMap;

use docopt::Docopt;

use rand::Rng;

const LOCAL_CONN_ID_LEN: usize = 16;

const TRANSPORT_PARAMS: quiche::TransportParams = quiche::TransportParams {
    idle_timeout: 30,
    initial_max_data: 10_000_000,
    initial_max_bidi_streams: 100,
    initial_max_uni_streams: 100,
    max_packet_size: 1500,
    ack_delay_exponent: 3,
    disable_migration: true,
    max_ack_delay: 25,
    initial_max_stream_data_bidi_local: 1_000_000,
    initial_max_stream_data_bidi_remote: 1_000_000,
    initial_max_stream_data_uni: 1_000_000,
    stateless_reset_token_present: true,
    stateless_reset_token: [0xba; 16],
};

const USAGE: &str = "Usage: server [options]

Options:
  -h --help         Show this screen.
  --listen <addr>   Listen on the given IP:port [default: 127.0.0.1:4433]
  --cert <file>     TLS certificate path [default: examples/cert.crt]
  --key <file>      TLS certificate key path [default: examples/cert.key]
  --root <dir>      Root directory [default: examples/root/]
  --name <str>      Name of the server [default: quic.tech]
";

fn main() {
    let mut buf = [0; TRANSPORT_PARAMS.max_packet_size as usize];
    let mut out = [0; TRANSPORT_PARAMS.max_packet_size as usize];

    env_logger::init();

    let args = Docopt::new(USAGE)
                      .and_then(|dopt| dopt.parse())
                      .unwrap_or_else(|e| e.exit());

    let socket = net::UdpSocket::bind(args.get_str("--listen")).unwrap();

    let poll = mio::Poll::new().unwrap();
    let mut events = mio::Events::with_capacity(1024);

    let socket = mio::net::UdpSocket::from_socket(socket).unwrap();
    poll.register(&socket, mio::Token(0),
                  mio::Ready::readable(),
                  mio::PollOpt::edge()).unwrap();

    let mut connections: HashMap<net::SocketAddr, Box<quiche::Connection>> =
        HashMap::new();

    loop {
        // Garbage collect closed connections.
        connections.retain(|_, ref mut c| {
            debug!("Collecting garbage");

            if c.is_closed() {
                debug!("{} connection collected", c.trace_id());
            }

            !c.is_closed()
        });

        poll.poll(&mut events, None).unwrap();

        'read: loop {
            let (len, src) = match socket.recv_from(&mut buf) {
                Ok(v) => v,

                 Err(e) => {
                    if e.kind() == io::ErrorKind::WouldBlock {
                        warn!("recv() would block");
                        break 'read;
                    }

                    panic!("recv() failed: {:?}", e);
                },
            };

            let buf = &mut buf[..len];

            let hdr = match quiche::Header::from_slice(buf, LOCAL_CONN_ID_LEN) {
                Ok(v) => v,

                Err(e) => {
                    error!("Parsing packet header failed: {:?}", e);
                    continue
                }
            };

            if hdr.ty == quiche::Type::VersionNegotiation {
                error!("Version negotiation invalid on the server");
                continue;
            }

            let conn = match connections.entry(src) {
                hash_map::Entry::Vacant(v) => {
                    if hdr.version != quiche::VERSION_DRAFT15 {
                        warn!("Doing version negotiation");

                        let len = quiche::Connection::negotiate_version(&hdr, &mut out)
                                               .unwrap();
                        let out = &out[..len];

                        socket.send_to(out, &src).unwrap();
                        continue;
                    }

                    if hdr.ty != quiche::Type::Initial {
                        error!("Packet is not Initial");
                        continue;
                    }

                    let mut scid: [u8; LOCAL_CONN_ID_LEN] = [0; LOCAL_CONN_ID_LEN];
                    rand::thread_rng().fill(&mut scid[..]);

                    let config = quiche::Config {
                        version: quiche::VERSION_DRAFT15,

                        local_conn_id: &scid,

                        local_transport_params: &TRANSPORT_PARAMS,

                        tls_server_name: args.get_str("--name"),
                        tls_certificate: args.get_str("--cert"),
                        tls_certificate_key: args.get_str("--key"),
                    };

                    debug!("New connection: dcid={} scid={} lcid={}",
                           hex_dump(&hdr.dcid),
                           hex_dump(&hdr.scid),
                           hex_dump(&scid));

                    let conn = quiche::Connection::new(config, true).unwrap();

                    v.insert(conn)
                },

                hash_map::Entry::Occupied(v) => v.into_mut(),
            };

            let mut left = len;

            // Process potentially coalesced packets.
            while left > 0 {
                let read = match conn.recv(&mut buf[len - left..len]) {
                    Ok(v)  => v,

                    Err(e) => {
                        error!("{} recv failed: {:?}", conn.trace_id(), e);
                        conn.close(false, e.to_wire(), b"fail").unwrap();
                        break 'read;
                    },
                };

                left -= read;

                debug!("{} read {} bytes", conn.trace_id(), read);
            }

            let streams: Vec<u64> = conn.stream_iter().collect();
            for s in streams {
                info!("{} stream {} is readable", conn.trace_id(), s);
                handle_stream(conn, s, &args);
            }
        }

        for (src, conn) in &mut connections {
            loop {
                let write = match conn.send(&mut out) {
                    Ok(v) => v,

                    Err(quiche::Error::NothingToDo) => {
                        debug!("{} done writing", conn.trace_id());
                        break;
                    },

                    Err(e) => {
                        error!("{} send failed: {:?}", conn.trace_id(), e);
                        conn.close(false, e.to_wire(), b"fail").unwrap();
                        break;
                    },
                };

                // TODO: coalesce packets.
                socket.send_to(&out[..write], &src).unwrap();

                debug!("{} written {} bytes", conn.trace_id(), write);
            }
        }
    }
}

fn handle_stream(conn: &mut quiche::Connection, stream: u64, args: &docopt::ArgvMap) {
    let stream_data = match conn.stream_recv(stream) {
        Ok(v) => v,

        Err(quiche::Error::NothingToDo) => return,

        Err(e) => panic!("{} stream recv failed {:?}",
                         conn.trace_id(), e),
    };

    if &stream_data[..4] == b"GET " {
        let uri = &stream_data[4..stream_data.len()];
        let uri = String::from_utf8(uri.to_vec()).unwrap();
        let uri = String::from(uri.lines().next().unwrap());
        let uri = path::Path::new(&uri);
        let mut path = path::PathBuf::from(args.get_str("--root"));

        for c in uri.components() {
            if let path::Component::Normal(v) = c {
                path.push(v)
            }
        }

        info!("{} got GET request for {:?} on stream {}",
              conn.trace_id(), path, stream);

        let data = fs::read(path.as_path())
                      .unwrap_or_else(|_| Vec::from(String::from("Not Found!")));

        info!("{} sending response of size {} on stream {}",
              conn.trace_id(), data.len(), stream);

        if let Err(e) = conn.stream_send(stream, &data, true) {
            error!("{} stream send failed {:?}", conn.trace_id(), e);
        }
    }
}

fn hex_dump(buf: &[u8]) -> String {
    let vec: Vec<String> = buf.iter()
                              .map(|b| format!("{:02x}", b))
                              .collect();

    vec.join("")
}
<commit_msg>server: add trailing new line to not found body<commit_after>// Copyright (c) 2018, Alessandro Ghedini
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#[macro_use]
extern crate log;
extern crate mio;
extern crate rand;
extern crate docopt;
extern crate quiche;
extern crate env_logger;

use std::fs;
use std::io;
use std::net;
use std::path;

use std::collections::hash_map;
use std::collections::HashMap;

use docopt::Docopt;

use rand::Rng;

const LOCAL_CONN_ID_LEN: usize = 16;

const TRANSPORT_PARAMS: quiche::TransportParams = quiche::TransportParams {
    idle_timeout: 30,
    initial_max_data: 10_000_000,
    initial_max_bidi_streams: 100,
    initial_max_uni_streams: 100,
    max_packet_size: 1500,
    ack_delay_exponent: 3,
    disable_migration: true,
    max_ack_delay: 25,
    initial_max_stream_data_bidi_local: 1_000_000,
    initial_max_stream_data_bidi_remote: 1_000_000,
    initial_max_stream_data_uni: 1_000_000,
    stateless_reset_token_present: true,
    stateless_reset_token: [0xba; 16],
};

const USAGE: &str = "Usage: server [options]

Options:
  -h --help         Show this screen.
  --listen <addr>   Listen on the given IP:port [default: 127.0.0.1:4433]
  --cert <file>     TLS certificate path [default: examples/cert.crt]
  --key <file>      TLS certificate key path [default: examples/cert.key]
  --root <dir>      Root directory [default: examples/root/]
  --name <str>      Name of the server [default: quic.tech]
";

fn main() {
    let mut buf = [0; TRANSPORT_PARAMS.max_packet_size as usize];
    let mut out = [0; TRANSPORT_PARAMS.max_packet_size as usize];

    env_logger::init();

    let args = Docopt::new(USAGE)
                      .and_then(|dopt| dopt.parse())
                      .unwrap_or_else(|e| e.exit());

    let socket = net::UdpSocket::bind(args.get_str("--listen")).unwrap();

    let poll = mio::Poll::new().unwrap();
    let mut events = mio::Events::with_capacity(1024);

    let socket = mio::net::UdpSocket::from_socket(socket).unwrap();
    poll.register(&socket, mio::Token(0),
                  mio::Ready::readable(),
                  mio::PollOpt::edge()).unwrap();

    let mut connections: HashMap<net::SocketAddr, Box<quiche::Connection>> =
        HashMap::new();

    loop {
        // Garbage collect closed connections.
        connections.retain(|_, ref mut c| {
            debug!("Collecting garbage");

            if c.is_closed() {
                debug!("{} connection collected", c.trace_id());
            }

            !c.is_closed()
        });

        poll.poll(&mut events, None).unwrap();

        'read: loop {
            let (len, src) = match socket.recv_from(&mut buf) {
                Ok(v) => v,

                 Err(e) => {
                    if e.kind() == io::ErrorKind::WouldBlock {
                        warn!("recv() would block");
                        break 'read;
                    }

                    panic!("recv() failed: {:?}", e);
                },
            };

            let buf = &mut buf[..len];

            let hdr = match quiche::Header::from_slice(buf, LOCAL_CONN_ID_LEN) {
                Ok(v) => v,

                Err(e) => {
                    error!("Parsing packet header failed: {:?}", e);
                    continue
                }
            };

            if hdr.ty == quiche::Type::VersionNegotiation {
                error!("Version negotiation invalid on the server");
                continue;
            }

            let conn = match connections.entry(src) {
                hash_map::Entry::Vacant(v) => {
                    if hdr.version != quiche::VERSION_DRAFT15 {
                        warn!("Doing version negotiation");

                        let len = quiche::Connection::negotiate_version(&hdr, &mut out)
                                               .unwrap();
                        let out = &out[..len];

                        socket.send_to(out, &src).unwrap();
                        continue;
                    }

                    if hdr.ty != quiche::Type::Initial {
                        error!("Packet is not Initial");
                        continue;
                    }

                    let mut scid: [u8; LOCAL_CONN_ID_LEN] = [0; LOCAL_CONN_ID_LEN];
                    rand::thread_rng().fill(&mut scid[..]);

                    let config = quiche::Config {
                        version: quiche::VERSION_DRAFT15,

                        local_conn_id: &scid,

                        local_transport_params: &TRANSPORT_PARAMS,

                        tls_server_name: args.get_str("--name"),
                        tls_certificate: args.get_str("--cert"),
                        tls_certificate_key: args.get_str("--key"),
                    };

                    debug!("New connection: dcid={} scid={} lcid={}",
                           hex_dump(&hdr.dcid),
                           hex_dump(&hdr.scid),
                           hex_dump(&scid));

                    let conn = quiche::Connection::new(config, true).unwrap();

                    v.insert(conn)
                },

                hash_map::Entry::Occupied(v) => v.into_mut(),
            };

            let mut left = len;

            // Process potentially coalesced packets.
            while left > 0 {
                let read = match conn.recv(&mut buf[len - left..len]) {
                    Ok(v)  => v,

                    Err(e) => {
                        error!("{} recv failed: {:?}", conn.trace_id(), e);
                        conn.close(false, e.to_wire(), b"fail").unwrap();
                        break 'read;
                    },
                };

                left -= read;

                debug!("{} read {} bytes", conn.trace_id(), read);
            }

            let streams: Vec<u64> = conn.stream_iter().collect();
            for s in streams {
                info!("{} stream {} is readable", conn.trace_id(), s);
                handle_stream(conn, s, &args);
            }
        }

        for (src, conn) in &mut connections {
            loop {
                let write = match conn.send(&mut out) {
                    Ok(v) => v,

                    Err(quiche::Error::NothingToDo) => {
                        debug!("{} done writing", conn.trace_id());
                        break;
                    },

                    Err(e) => {
                        error!("{} send failed: {:?}", conn.trace_id(), e);
                        conn.close(false, e.to_wire(), b"fail").unwrap();
                        break;
                    },
                };

                // TODO: coalesce packets.
                socket.send_to(&out[..write], &src).unwrap();

                debug!("{} written {} bytes", conn.trace_id(), write);
            }
        }
    }
}

fn handle_stream(conn: &mut quiche::Connection, stream: u64, args: &docopt::ArgvMap) {
    let stream_data = match conn.stream_recv(stream) {
        Ok(v) => v,

        Err(quiche::Error::NothingToDo) => return,

        Err(e) => panic!("{} stream recv failed {:?}",
                         conn.trace_id(), e),
    };

    if &stream_data[..4] == b"GET " {
        let uri = &stream_data[4..stream_data.len()];
        let uri = String::from_utf8(uri.to_vec()).unwrap();
        let uri = String::from(uri.lines().next().unwrap());
        let uri = path::Path::new(&uri);
        let mut path = path::PathBuf::from(args.get_str("--root"));

        for c in uri.components() {
            if let path::Component::Normal(v) = c {
                path.push(v)
            }
        }

        info!("{} got GET request for {:?} on stream {}",
              conn.trace_id(), path, stream);

        let data = fs::read(path.as_path())
                      .unwrap_or_else(|_| Vec::from(String::from("Not Found!\r\n")));

        info!("{} sending response of size {} on stream {}",
              conn.trace_id(), data.len(), stream);

        if let Err(e) = conn.stream_send(stream, &data, true) {
            error!("{} stream send failed {:?}", conn.trace_id(), e);
        }
    }
}

fn hex_dump(buf: &[u8]) -> String {
    let vec: Vec<String> = buf.iter()
                              .map(|b| format!("{:02x}", b))
                              .collect();

    vec.join("")
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use any_pointer;
use MessageSize;
use capability::{Params, Request, RemotePromise, Results};

pub trait ResponseHook {
    fn get<'a>(&'a self) -> ::Result<any_pointer::Reader<'a>>;
}

pub trait RequestHook {
    fn init<'a>(&'a mut self) -> any_pointer::Builder<'a>;
    fn send<'a>(self : Box<Self>) -> RemotePromise<any_pointer::Owned>;
}

pub trait ClientHook {
    fn add_ref(&self) -> Box<ClientHook>;
    fn new_call(&self,
                interface_id: u64,
                method_id: u16,
                size_hint: Option<MessageSize>)
                -> Request<any_pointer::Owned, any_pointer::Owned>;

    fn call(&self, interface_id: u64, method_id: u16,
            params: Box<ParamsHook>, results: Box<ResultsHook>);

    fn get_brand(&self) -> usize;

    // HACK
    fn get_descriptor(&self) -> Box<::std::any::Any>;
}

#[cfg(feature = "rpc")]
pub trait ServerHook: 'static {
    fn new_client(server: Box<::capability::Server>) -> ::capability::Client;
}

pub trait ResultsHook {
    fn get<'a>(&'a mut self) -> any_pointer::Builder<'a>;
    fn fail(self: Box<Self>, message: String);
    fn unimplemented(self: Box<Self>);
    fn disconnected(self: Box<Self>);
    fn overloaded(self: Box<Self>);
}

pub trait ParamsHook {
    fn get<'a>(&'a self) -> any_pointer::Reader<'a>;
}

// Where should this live?
pub fn internal_get_typed_params<T>(typeless: Params<any_pointer::Owned>) -> Params<T> {
    Params { hook: typeless.hook, marker: ::std::marker::PhantomData }
}

pub fn internal_get_typed_results<T>(typeless: Results<any_pointer::Owned>) -> Results<T> {
    Results { hook: typeless.hook, marker: ::std::marker::PhantomData }
}

pub trait PipelineHook {
    fn add_ref(&self) -> Box<PipelineHook>;
    fn get_pipelined_cap(&self, ops: &[PipelineOp]) -> Box<ClientHook>;

    /// Version of get_pipelined_cap() passing the array by move. May avoid a copy in some cases.
    /// Default implementation just calls the other version.
    fn get_pipelined_cap_move(&self, ops: Vec<PipelineOp>) -> Box<ClientHook> {
        self.get_pipelined_cap(&ops)
    }
}

#[derive(Clone, Copy)]
pub enum PipelineOp {
    Noop,
    GetPointerField(u16),
}

<commit_msg>impl Clone for Box<ClientHook><commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use any_pointer;
use MessageSize;
use capability::{Params, Request, RemotePromise, Results};

pub trait ResponseHook {
    fn get<'a>(&'a self) -> ::Result<any_pointer::Reader<'a>>;
}

pub trait RequestHook {
    fn init<'a>(&'a mut self) -> any_pointer::Builder<'a>;
    fn send<'a>(self : Box<Self>) -> RemotePromise<any_pointer::Owned>;
}

pub trait ClientHook {
    fn add_ref(&self) -> Box<ClientHook>;
    fn new_call(&self,
                interface_id: u64,
                method_id: u16,
                size_hint: Option<MessageSize>)
                -> Request<any_pointer::Owned, any_pointer::Owned>;

    fn call(&self, interface_id: u64, method_id: u16,
            params: Box<ParamsHook>, results: Box<ResultsHook>);

    fn get_brand(&self) -> usize;

    // HACK
    fn get_descriptor(&self) -> Box<::std::any::Any>;
}

impl Clone for Box<ClientHook> {
    fn clone(&self) -> Box<ClientHook> {
        self.add_ref()
    }
}

#[cfg(feature = "rpc")]
pub trait ServerHook: 'static {
    fn new_client(server: Box<::capability::Server>) -> ::capability::Client;
}

pub trait ResultsHook {
    fn get<'a>(&'a mut self) -> any_pointer::Builder<'a>;
    fn fail(self: Box<Self>, message: String);
    fn unimplemented(self: Box<Self>);
    fn disconnected(self: Box<Self>);
    fn overloaded(self: Box<Self>);
}

pub trait ParamsHook {
    fn get<'a>(&'a self) -> any_pointer::Reader<'a>;
}

// Where should this live?
pub fn internal_get_typed_params<T>(typeless: Params<any_pointer::Owned>) -> Params<T> {
    Params { hook: typeless.hook, marker: ::std::marker::PhantomData }
}

pub fn internal_get_typed_results<T>(typeless: Results<any_pointer::Owned>) -> Results<T> {
    Results { hook: typeless.hook, marker: ::std::marker::PhantomData }
}

pub trait PipelineHook {
    fn add_ref(&self) -> Box<PipelineHook>;
    fn get_pipelined_cap(&self, ops: &[PipelineOp]) -> Box<ClientHook>;

    /// Version of get_pipelined_cap() passing the array by move. May avoid a copy in some cases.
    /// Default implementation just calls the other version.
    fn get_pipelined_cap_move(&self, ops: Vec<PipelineOp>) -> Box<ClientHook> {
        self.get_pipelined_cap(&ops)
    }
}

#[derive(Clone, Copy)]
pub enum PipelineOp {
    Noop,
    GetPointerField(u16),
}

<|endoftext|>


<commit_before>// Copyright 2018 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

#![feature(
    test,
    arbitrary_self_types,
    integer_atomics,
    async_await,
    proc_macro_hygiene
)]

extern crate test;

use futures::{compat::Executor01CompatExt, future, prelude::*};
use test::stats::Stats;
use rpc::{
    client, context,
    server::{Handler, Server},
};
use std::{
    io,
    time::{Duration, Instant},
};

mod ack {
    tarpc::service! {
        rpc ack();
    }
}

#[derive(Clone)]
struct Serve;

impl ack::Service for Serve {
    type AckFut = future::Ready<()>;

    fn ack(self, _: context::Context) -> Self::AckFut {
        future::ready(())
    }
}

async fn bench() -> io::Result<()> {
    let listener = bincode_transport::listen(&"0.0.0.0:0".parse().unwrap())?
        .filter_map(|r| future::ready(r.ok()));
    let addr = listener.get_ref().local_addr();

    tokio_executor::spawn(
        Server::default()
            .incoming(listener)
            .take(1)
            .respond_with(ack::serve(Serve))
            .unit_error()
            .boxed()
            .compat(),
    );

    let conn = bincode_transport::connect(&addr).await?;
    let mut client = ack::new_stub(client::Config::default(), conn).await?;

    let total = 10_000usize;
    let mut successful = 0u32;
    let mut unsuccessful = 0u32;
    let mut durations = vec![];
    for _ in 1..=total {
        let now = Instant::now();
        let response = client.ack(context::current()).await;
        let elapsed = now.elapsed();

        match response {
            Ok(_) => successful += 1,
            Err(_) => unsuccessful += 1,
        };
        durations.push(elapsed);
    }

    let durations_nanos = durations
        .iter()
        .map(|duration| duration.as_secs() as f64 * 1E9 + duration.subsec_nanos() as f64)
        .collect::<Vec<_>>();

    let (lower, median, upper) = durations_nanos.quartiles();

    println!("Of {:?} runs:", durations_nanos.len());
    println!("\tSuccessful: {:?}", successful);
    println!("\tUnsuccessful: {:?}", unsuccessful);
    println!(
        "\tMean: {:?}",
        Duration::from_nanos(durations_nanos.mean() as u64)
    );
    println!("\tMedian: {:?}", Duration::from_nanos(median as u64));
    println!(
        "\tStd Dev: {:?}",
        Duration::from_nanos(durations_nanos.std_dev() as u64)
    );
    println!(
        "\tMin: {:?}",
        Duration::from_nanos(durations_nanos.min() as u64)
    );
    println!(
        "\tMax: {:?}",
        Duration::from_nanos(durations_nanos.max() as u64)
    );
    println!(
        "\tQuartiles: ({:?}, {:?}, {:?})",
        Duration::from_nanos(lower as u64),
        Duration::from_nanos(median as u64),
        Duration::from_nanos(upper as u64)
    );

    println!("done");
    Ok(())
}

#[test]
fn bench_small_packet() {
    env_logger::init();
    tarpc::init(tokio::executor::DefaultExecutor::current().compat());

    tokio::run(bench().map_err(|e| panic!(e.to_string())).boxed().compat())
}
<commit_msg>Move bench outside crate.<commit_after><|endoftext|>