<commit_before>import stackwalk::Word;
import libc::size_t;
import send_map::linear::LinearMap;

extern mod rustrt {
    fn rust_annihilate_box(ptr: *Word);

    #[rust_stack]
    fn rust_gc_metadata() -> *Word;

    #[rust_stack]
    fn rust_call_tydesc_glue(root: *Word, tydesc: *Word, field: size_t);
}

type SafePoint = { sp_meta: *Word, fn_meta: *Word };

unsafe fn is_safe_point(pc: *Word) -> Option<SafePoint> {
    let module_meta = rustrt::rust_gc_metadata();
    let num_safe_points_ptr: *u32 = unsafe::reinterpret_cast(&module_meta);
    let num_safe_points = *num_safe_points_ptr as Word;
    let safe_points: *Word =
        ptr::offset(unsafe::reinterpret_cast(&module_meta), 1);

    if ptr::is_null(pc) {
        return None;
    }

    let mut sp = 0 as Word;
    while sp < num_safe_points {
        let sp_loc = *ptr::offset(safe_points, sp*3) as *Word;
        if sp_loc == pc {
            return Some(
                {sp_meta: *ptr::offset(safe_points, sp*3 + 1) as *Word,
                 fn_meta: *ptr::offset(safe_points, sp*3 + 2) as *Word});
        }
        sp += 1;
    }
    return None;
}

type Visitor = fn(root: **Word, tydesc: *Word) -> bool;

unsafe fn walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) {
    let fp_bytes: *u8 = unsafe::reinterpret_cast(&fp);
    let sp_meta_u32s: *u32 = unsafe::reinterpret_cast(&sp.sp_meta);

    let num_stack_roots = *sp_meta_u32s as uint;
    let num_reg_roots = *ptr::offset(sp_meta_u32s, 1) as uint;

    let stack_roots: *u32 =
        unsafe::reinterpret_cast(&ptr::offset(sp_meta_u32s, 2));
    let reg_roots: *u8 =
        unsafe::reinterpret_cast(&ptr::offset(stack_roots, num_stack_roots));
    let addrspaces: *Word =
        unsafe::reinterpret_cast(&ptr::offset(reg_roots, num_reg_roots));
    let tydescs: ***Word =
        unsafe::reinterpret_cast(&ptr::offset(addrspaces, num_stack_roots));

    // Stack roots
    let mut sri = 0;
    while sri < num_stack_roots {
        if *ptr::offset(addrspaces, sri) >= 1 {
            let root =
                ptr::offset(fp_bytes, *ptr::offset(stack_roots, sri) as Word)
                as **Word;
            let tydescpp = ptr::offset(tydescs, sri);
            let tydesc = if ptr::is_not_null(tydescpp) &&
                ptr::is_not_null(*tydescpp) {
                **tydescpp
            } else {
                ptr::null()
            };
            if !visitor(root, tydesc) { return; }
        }
        sri += 1;
    }

    // Register roots
    let mut rri = 0;
    while rri < num_reg_roots {
        if *ptr::offset(addrspaces, num_stack_roots + rri) == 1 {
            // FIXME(#2997): Need to find callee saved registers on the stack.
        }
        rri += 1;
    }
}

type Memory = uint;

const task_local_heap: Memory = 1;
const exchange_heap:   Memory = 2;
const stack:           Memory = 4;

const need_cleanup:    Memory = exchange_heap | stack;

unsafe fn walk_gc_roots(mem: Memory, visitor: Visitor) {
    let mut last_ret: *Word = ptr::null();
    for stackwalk::walk_stack |frame| {
        unsafe {
            if ptr::is_not_null(last_ret) {
                let sp = is_safe_point(last_ret);
                match sp {
                  Some(sp_info) => {
                    for walk_safe_point(frame.fp, sp_info) |root, tydesc| {
                        if ptr::is_null(tydesc) {
                            // Root is a generic box.
                            let refcount = **root;
                            if mem | task_local_heap != 0 && refcount != -1 {
                                if !visitor(root, tydesc) { return; }
                            } else if mem | exchange_heap != 0 {
                                if !visitor(root, tydesc) { return; }
                            }
                        } else {
                            // Root is a non-immediate.
                            if mem | stack != 0 {
                                if !visitor(root, tydesc) { return; }
                            }
                        }
                    }
                  }
                  None => ()
                }
            }
            last_ret = *ptr::offset(frame.fp, 1) as *Word;
        }
    }
}

fn gc() {
    unsafe {
        for walk_gc_roots(task_local_heap) |_root, _tydesc| {
            // FIXME(#2997): Walk roots and mark them.
            io::stdout().write([46]); // .
        }
    }
}

type RootSet = LinearMap<*Word,()>;

fn RootSet() -> RootSet {
    LinearMap()
}

// This should only be called from fail, as it will drop the roots
// which are *live* on the stack, rather than dropping those that are
// dead.
fn cleanup_stack_for_failure() {
    unsafe {
        let mut roots = ~RootSet();
        for walk_gc_roots(need_cleanup) |root, tydesc| {
            // Track roots to avoid double frees.
            if option::is_some(roots.find(&*root)) {
                again;
            }
            roots.insert(*root, ());

            if ptr::is_null(tydesc) {
                rustrt::rust_annihilate_box(*root);
            } else {
                rustrt::rust_call_tydesc_glue(*root, tydesc, 3 as size_t);
            }
        }
    }
}
<commit_msg>gc: Avoid freeing null pointers.<commit_after>import stackwalk::Word;
import libc::size_t;
import send_map::linear::LinearMap;

extern mod rustrt {
    fn rust_annihilate_box(ptr: *Word);

    #[rust_stack]
    fn rust_gc_metadata() -> *Word;

    #[rust_stack]
    fn rust_call_tydesc_glue(root: *Word, tydesc: *Word, field: size_t);
}

type SafePoint = { sp_meta: *Word, fn_meta: *Word };

unsafe fn is_safe_point(pc: *Word) -> Option<SafePoint> {
    let module_meta = rustrt::rust_gc_metadata();
    let num_safe_points_ptr: *u32 = unsafe::reinterpret_cast(&module_meta);
    let num_safe_points = *num_safe_points_ptr as Word;
    let safe_points: *Word =
        ptr::offset(unsafe::reinterpret_cast(&module_meta), 1);

    if ptr::is_null(pc) {
        return None;
    }

    let mut sp = 0 as Word;
    while sp < num_safe_points {
        let sp_loc = *ptr::offset(safe_points, sp*3) as *Word;
        if sp_loc == pc {
            return Some(
                {sp_meta: *ptr::offset(safe_points, sp*3 + 1) as *Word,
                 fn_meta: *ptr::offset(safe_points, sp*3 + 2) as *Word});
        }
        sp += 1;
    }
    return None;
}

type Visitor = fn(root: **Word, tydesc: *Word) -> bool;

unsafe fn walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) {
    let fp_bytes: *u8 = unsafe::reinterpret_cast(&fp);
    let sp_meta_u32s: *u32 = unsafe::reinterpret_cast(&sp.sp_meta);

    let num_stack_roots = *sp_meta_u32s as uint;
    let num_reg_roots = *ptr::offset(sp_meta_u32s, 1) as uint;

    let stack_roots: *u32 =
        unsafe::reinterpret_cast(&ptr::offset(sp_meta_u32s, 2));
    let reg_roots: *u8 =
        unsafe::reinterpret_cast(&ptr::offset(stack_roots, num_stack_roots));
    let addrspaces: *Word =
        unsafe::reinterpret_cast(&ptr::offset(reg_roots, num_reg_roots));
    let tydescs: ***Word =
        unsafe::reinterpret_cast(&ptr::offset(addrspaces, num_stack_roots));

    // Stack roots
    let mut sri = 0;
    while sri < num_stack_roots {
        if *ptr::offset(addrspaces, sri) >= 1 {
            let root =
                ptr::offset(fp_bytes, *ptr::offset(stack_roots, sri) as Word)
                as **Word;
            let tydescpp = ptr::offset(tydescs, sri);
            let tydesc = if ptr::is_not_null(tydescpp) &&
                ptr::is_not_null(*tydescpp) {
                **tydescpp
            } else {
                ptr::null()
            };
            if !visitor(root, tydesc) { return; }
        }
        sri += 1;
    }

    // Register roots
    let mut rri = 0;
    while rri < num_reg_roots {
        if *ptr::offset(addrspaces, num_stack_roots + rri) == 1 {
            // FIXME(#2997): Need to find callee saved registers on the stack.
        }
        rri += 1;
    }
}

type Memory = uint;

const task_local_heap: Memory = 1;
const exchange_heap:   Memory = 2;
const stack:           Memory = 4;

const need_cleanup:    Memory = exchange_heap | stack;

unsafe fn walk_gc_roots(mem: Memory, visitor: Visitor) {
    let mut last_ret: *Word = ptr::null();
    for stackwalk::walk_stack |frame| {
        unsafe {
            if ptr::is_not_null(last_ret) {
                let sp = is_safe_point(last_ret);
                match sp {
                  Some(sp_info) => {
                    for walk_safe_point(frame.fp, sp_info) |root, tydesc| {
                        // Skip null pointers, which can occur when a
                        // unique pointer has already been freed.
                        if ptr::is_null(*root) {
                            again;
                        }

                        if ptr::is_null(tydesc) {
                            // Root is a generic box.
                            let refcount = **root;
                            if mem | task_local_heap != 0 && refcount != -1 {
                                if !visitor(root, tydesc) { return; }
                            } else if mem | exchange_heap != 0 {
                                if !visitor(root, tydesc) { return; }
                            }
                        } else {
                            // Root is a non-immediate.
                            if mem | stack != 0 {
                                if !visitor(root, tydesc) { return; }
                            }
                        }
                    }
                  }
                  None => ()
                }
            }
            last_ret = *ptr::offset(frame.fp, 1) as *Word;
        }
    }
}

fn gc() {
    unsafe {
        for walk_gc_roots(task_local_heap) |_root, _tydesc| {
            // FIXME(#2997): Walk roots and mark them.
            io::stdout().write([46]); // .
        }
    }
}

type RootSet = LinearMap<*Word,()>;

fn RootSet() -> RootSet {
    LinearMap()
}

// This should only be called from fail, as it will drop the roots
// which are *live* on the stack, rather than dropping those that are
// dead.
fn cleanup_stack_for_failure() {
    unsafe {
        let mut roots = ~RootSet();
        for walk_gc_roots(need_cleanup) |root, tydesc| {
            // Track roots to avoid double frees.
            if option::is_some(roots.find(&*root)) {
                again;
            }
            roots.insert(*root, ());

            if ptr::is_null(tydesc) {
                rustrt::rust_annihilate_box(*root);
            } else {
                rustrt::rust_call_tydesc_glue(*root, tydesc, 3 as size_t);
            }
        }
    }
}
<|endoftext|>


<commit_before>use byteorder::{ReadBytesExt, LittleEndian};
use rwinstructs::timestamp::{WinTimestamp};
use lnkpkg::flags::{DataFlags,FileFlags};
use lnkpkg::errors::{LnkError};
use std::io::Read;

#[derive(Clone, Debug)]
pub struct Guid(pub [u8;16]);

#[derive(Debug)]
// 76 bytes long
pub struct ShellLinkHeader {
    pub header_size: u32,
    pub guid: Guid,
    pub data_flags: DataFlags,
    pub file_flags: FileFlags,
    pub created: WinTimestamp,
    pub accessed: WinTimestamp,
    pub modified: WinTimestamp,
    pub file_size: u32,
    pub icon_offset: i32,
    pub window_flag: u32,
    pub hot_key: u16,
    pub unknown1: u16,
    pub unknown2: u32,
    pub unknown3: u32
}

impl ShellLinkHeader {
    pub fn new<R: Read>(mut reader: R) -> Result<ShellLinkHeader,LnkError> {
        let header_size = reader.read_u32::<LittleEndian>()?;
        let mut guid = Guid([0; 16]);
        reader.read_exact(&mut guid.0)?;

        let data_flags = DataFlags::from_bits_truncate(
            reader.read_u32::<LittleEndian>()?
        );

        let file_flags = FileFlags::from_bits_truncate(
            reader.read_u32::<LittleEndian>()?
        );
        let created = WinTimestamp(reader.read_u64::<LittleEndian>()?);
        let accessed = WinTimestamp(reader.read_u64::<LittleEndian>()?);
        let modified = WinTimestamp(reader.read_u64::<LittleEndian>()?);
        let file_size = reader.read_u32::<LittleEndian>()?;
        let icon_offset = reader.read_i32::<LittleEndian>()?;
        let window_flag = reader.read_u32::<LittleEndian>()?;
        let hot_key = reader.read_u16::<LittleEndian>()?;
        let unknown1 = reader.read_u16::<LittleEndian>()?;
        let unknown2 = reader.read_u32::<LittleEndian>()?;
        let unknown3 = reader.read_u32::<LittleEndian>()?;

        Ok(
            ShellLinkHeader {
                header_size: header_size,
                guid: guid,
                data_flags: data_flags,
                file_flags: file_flags,
                created: created,
                accessed: accessed,
                modified: modified,
                file_size: file_size,
                icon_offset: icon_offset,
                window_flag: window_flag,
                hot_key: hot_key,
                unknown1: unknown1,
                unknown2: unknown2,
                unknown3: unknown3
            }
        )
    }
}

pub struct TargetIdList {
    pub list_size: u16
}

impl TargetIdList{
    pub fn new<R: Read>(mut reader: R) -> Result<TargetIdList, LnkError> {
        let list_size = reader.read_u16::<LittleEndian>()?;

        Ok(
            TargetIdList {
                list_size: list_size
            }
        )
    }
}

pub struct Lnk {
    pub header: ShellLinkHeader
}

impl Lnk {
    pub fn new<R: Read>(mut reader: R) -> Result<Lnk,LnkError> {
        let header = ShellLinkHeader::new(reader)?;

        Ok(
            Lnk {
                header: header
            }
        )
    }
}
<commit_msg>added LocationInfo struct<commit_after>use byteorder::{ReadBytesExt, LittleEndian};
use rwinstructs::timestamp::{WinTimestamp};
use lnkpkg::flags::{DataFlags,FileFlags};
use lnkpkg::errors::{LnkError};
use std::io::Read;

#[derive(Clone, Debug)]
pub struct Guid(pub [u8;16]);

#[derive(Debug)]
// 76 bytes long
pub struct ShellLinkHeader {
    pub header_size: u32,
    pub guid: Guid,
    pub data_flags: DataFlags,
    pub file_flags: FileFlags,
    pub created: WinTimestamp,
    pub accessed: WinTimestamp,
    pub modified: WinTimestamp,
    pub file_size: u32,
    pub icon_offset: i32,
    pub window_flag: u32,
    pub hot_key: u16,
    pub unknown1: u16,
    pub unknown2: u32,
    pub unknown3: u32
}

impl ShellLinkHeader {
    pub fn new<R: Read>(mut reader: R) -> Result<ShellLinkHeader,LnkError> {
        let header_size = reader.read_u32::<LittleEndian>()?;
        let mut guid = Guid([0; 16]);
        reader.read_exact(&mut guid.0)?;

        let data_flags = DataFlags::from_bits_truncate(
            reader.read_u32::<LittleEndian>()?
        );

        let file_flags = FileFlags::from_bits_truncate(
            reader.read_u32::<LittleEndian>()?
        );
        let created = WinTimestamp(reader.read_u64::<LittleEndian>()?);
        let accessed = WinTimestamp(reader.read_u64::<LittleEndian>()?);
        let modified = WinTimestamp(reader.read_u64::<LittleEndian>()?);
        let file_size = reader.read_u32::<LittleEndian>()?;
        let icon_offset = reader.read_i32::<LittleEndian>()?;
        let window_flag = reader.read_u32::<LittleEndian>()?;
        let hot_key = reader.read_u16::<LittleEndian>()?;
        let unknown1 = reader.read_u16::<LittleEndian>()?;
        let unknown2 = reader.read_u32::<LittleEndian>()?;
        let unknown3 = reader.read_u32::<LittleEndian>()?;

        Ok(
            ShellLinkHeader {
                header_size: header_size,
                guid: guid,
                data_flags: data_flags,
                file_flags: file_flags,
                created: created,
                accessed: accessed,
                modified: modified,
                file_size: file_size,
                icon_offset: icon_offset,
                window_flag: window_flag,
                hot_key: hot_key,
                unknown1: unknown1,
                unknown2: unknown2,
                unknown3: unknown3
            }
        )
    }
}

pub struct TargetIdList {
    pub list_size: u16
}

impl TargetIdList{
    pub fn new<R: Read>(mut reader: R) -> Result<TargetIdList, LnkError> {
        let list_size = reader.read_u16::<LittleEndian>()?;

        Ok(
            TargetIdList {
                list_size: list_size
            }
        )
    }
}

pub struct LocationInfo {
    pub info_size: u32,
    pub header_size: u32,
    pub flags: u32,
    pub offset_vol_info: u32,
    pub offset_loc_path: u32,
    pub offset_net_share: u32,
    pub offset_common_path: u32
}
impl LocationInfo {
    pub fn new<R: Read>(mut reader: R) -> Result<LocationInfo,LnkError> {
        let info_size = reader.read_u32::<LittleEndian>()?;
        let header_size = reader.read_u32::<LittleEndian>()?;
        let flags = reader.read_u32::<LittleEndian>()?;
        let offset_vol_info = reader.read_u32::<LittleEndian>()?;
        let offset_loc_path = reader.read_u32::<LittleEndian>()?;
        let offset_net_share = reader.read_u32::<LittleEndian>()?;
        let offset_common_path = reader.read_u32::<LittleEndian>()?;

        Ok (
            LocationInfo {
                info_size: info_size,
                header_size: header_size,
                flags: flags,
                offset_vol_info: offset_vol_info,
                offset_loc_path: offset_loc_path,
                offset_net_share: offset_net_share,
                offset_common_path: offset_common_path
            }
        )
    }
}

pub struct Lnk {
    pub header: ShellLinkHeader,
    pub target_list: TargetIdList,
    pub location_info: LocationInfo
}

impl Lnk {
    pub fn new<R: Read>(mut reader: R) -> Result<Lnk,LnkError> {
        let header = ShellLinkHeader::new(reader)?;

        Ok(
            Lnk {
                header: header
            }
        )
    }
}
<|endoftext|>


<commit_before>use std::io::{self, Cursor};
use bytes::{BytesMut, BufMut};
use tokio_io::codec::{Encoder, Decoder};

use mqtt3::{Packet, MqttWrite, MqttRead};

pub struct MqttCodec;

impl Decoder for MqttCodec {
    type Item = Packet;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<Packet>> {
        let (packet, len) = {
            let mut buf_ref = buf.as_ref();
            match buf_ref.read_packet_with_len() {
                Err(..) => return Ok(None),
                Ok(v) => v,
            }
        };

        buf.split_to(len);
        // println!("{:?}, {:?}", len, packet);
        Ok(Some(packet))
    }
}

impl Encoder for MqttCodec {
    type Item = Packet;
    type Error = io::Error;

    fn encode(&mut self, msg: Packet, buf: &mut BytesMut) -> io::Result<()> {
        let mut stream = Cursor::new(Vec::new());

        // TODO: Implement `write_packet` for `&mut BytesMut`
        if let Err(_) = stream.write_packet(&msg) {
            // println!("{:?}", e);
            return Err(io::Error::new(io::ErrorKind::Other, "Unable to encode!"));
        }

        for i in stream.get_ref() {
            buf.put(*i);
        }
        Ok(())
    }
}
<commit_msg>fix assertion failed: self.remaining_mut() >= src.remaining() bug<commit_after>use std::io::{self, Cursor};
use bytes::{BytesMut, BufMut};
use tokio_io::codec::{Encoder, Decoder};

use mqtt3::{Packet, MqttWrite, MqttRead};

pub struct MqttCodec;

impl Decoder for MqttCodec {
    type Item = Packet;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<Packet>> {
        let (packet, len) = {
            let mut buf_ref = buf.as_ref();
            match buf_ref.read_packet_with_len() {
                Err(..) => return Ok(None),
                Ok(v) => v,
            }
        };

        buf.split_to(len);
        // println!("{:?}, {:?}", len, packet);
        Ok(Some(packet))
    }
}

impl Encoder for MqttCodec {
    type Item = Packet;
    type Error = io::Error;

    fn encode(&mut self, msg: Packet, buf: &mut BytesMut) -> io::Result<()> {
        let mut stream = Cursor::new(Vec::new());

        // TODO: Implement `write_packet` for `&mut BytesMut`
        if let Err(_) = stream.write_packet(&msg) {
            return Err(io::Error::new(io::ErrorKind::Other, "Unable to encode!"));
        }

        buf.extend(stream.get_ref());

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


<commit_before>const DATA: &'static str = include_str!("../data/input_24.txt");

pub fn main() -> Vec<String> {
    let v = DATA.lines().map(|l| l.parse::<u64>().unwrap()).collect::<Vec<u64>>();
    let weight = v.iter().sum::<u64>() / 3;
    let s1 = min_qe(&v, weight).to_string();

    let weight = v.iter().sum::<u64>() / 4;
    let s2 = min_qe(&v, weight).to_string();
    vec![s1, s2]
}

fn min_qe(data: &[u64], weight: u64) -> u64 {
    let ps = PowerSet::with_prune_condition(&data, move |ss| ss.iter().sum::<u64>() > weight);
    let subsets = ps.filter(|ss| ss.iter().sum::<u64>() == weight).collect::<Vec<_>>();
    let size = subsets.iter().map(|ss| ss.len()).min().unwrap();
    subsets.iter()
           .filter(|ss| ss.len() == size)
           .map(|ss| ss.iter().product::<u64>())
           .min()
           .unwrap()
}

struct PowerSet<'a, T>
    where T: 'a + Copy
{
    stack: Vec<(Vec<T>, &'a [T])>,
    stop: Box<Fn(&[T]) -> bool>,
}

impl<'a, T> PowerSet<'a, T> where T: 'a + Copy
{
    fn new(data: &'a [T]) -> PowerSet<'a, T> {
        let mut stack = Vec::new();
        if let Some((selected, remaining)) = data.split_last() {
            stack.push((vec![*selected], remaining));
            stack.push((vec![], remaining));
        } else {
            stack.push((vec![], data))
        }
        PowerSet {
            stack: stack,
            stop: box |_| false,
        }
    }

    fn with_prune_condition<F>(data: &'a [T], stop: F) -> PowerSet<'a, T>
        where F: 'static + Fn(&[T]) -> bool
    {
        PowerSet { stop: box stop, ..PowerSet::new(data) }
    }
}

impl<'a, T> Iterator for PowerSet<'a, T>
    where T: 'a + Copy,
{
    type Item = Vec<T>;

    fn next(&mut self) -> Option<Vec<T>> {
        if let Some((selected, remaining)) = self.stack.pop() {
            if let Some((sel, rem)) = remaining.split_last() {
                if !(self.stop)(&selected) {
                    let mut r = selected.clone();
                    r.push(*sel);
                    self.stack.push((r, rem));
                    self.stack.push((selected, rem));
                }
                self.next()
            } else {
                Some(selected)
            }
        } else {
            None
        }
    }
}
<commit_msg>day 24: performance improvement with better dynamic search limits<commit_after>const DATA: &'static str = include_str!("../data/input_24.txt");

use std::cmp;
use std::{u64, usize};
use std::cell::Cell;

pub fn main() -> Vec<String> {
    if let Ok(mut v) = DATA.lines()
                           .map(|l| l.parse::<u64>())
                           .collect::<Result<Vec<u64>, _>>() {
        v.sort_by(|a, b| b.cmp(a));

        let weight = v.iter().sum::<u64>() / 3;
        let s1 = min_qe(&v, weight).unwrap().to_string();

        let weight = v.iter().sum::<u64>() / 4;
        let s2 = min_qe(&v, weight).unwrap().to_string();

        vec![s1, s2]
    } else {
        vec![]
    }
}

fn min_qe(data: &[u64], weight: u64) -> Option<u64> {
    let best_size: Cell<usize> = Cell::new(usize::MAX);
    let best_qe: Cell<u64> = Cell::new(u64::MAX);
    let stop = |ss: &[u64]| {
        (ss.iter().sum::<u64>() > weight) ||
        (ss.iter().product::<u64>() > best_qe.get()) ||
        (ss.len() > best_size.get())
    };
    let ps = PowerSet::with_prune_condition(&data, stop);
    let subsets = ps.filter(|ss| ss.iter().sum::<u64>() == weight)
                    .inspect(|ss| {
                        best_size.set(cmp::min(best_size.get(), ss.len()));
                        best_qe.set(cmp::min(best_qe.get(), ss.iter().product()));
                    })
                    .collect::<Vec<_>>();
    subsets.iter()
           .filter(|ss| ss.len() == best_size.get())
           .map(|ss| ss.iter().product::<u64>())
           .min()
}

struct PowerSet<'a, T>
    where T: 'a + Copy
{
    stack: Vec<(Vec<T>, &'a [T])>,
    stop: Box<Fn(&[T]) -> bool + 'a>,
}

impl<'a, T> PowerSet<'a, T> where T: 'a + Copy
{
    fn new(data: &'a [T]) -> PowerSet<'a, T> {
        let mut stack = Vec::new();
        if let Some((selected, remaining)) = data.split_last() {
            stack.push((vec![*selected], remaining));
            stack.push((vec![], remaining));
        } else {
            stack.push((vec![], data))
        }
        PowerSet {
            stack: stack,
            stop: box |_| false,
        }
    }

    fn with_prune_condition<F>(data: &'a [T], stop: F) -> PowerSet<'a, T>
        where F: 'a + Fn(&[T]) -> bool
    {
        PowerSet { stop: box stop, ..PowerSet::new(data) }
    }
}

impl<'a, T> Iterator for PowerSet<'a, T> where T: 'a + Copy
{
    type Item = Vec<T>;

    fn next(&mut self) -> Option<Vec<T>> {
        if let Some((selected, remaining)) = self.stack.pop() {
            if let Some((sel, rem)) = remaining.split_last() {
                if !(self.stop)(&selected) {
                    let mut r = selected.clone();
                    r.push(*sel);
                    self.stack.push((r, rem));
                    self.stack.push((selected, rem));
                }
                self.next()
            } else {
                Some(selected)
            }
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>//! A `dmesg` command that is a simple demonstration program for using the [`libproc`](../libproc/index.html) library
//!
//! Usage
//! =
//!
//! `> sudo dmesg`
//!
//! ---
//!
//! NOTE: This must be run as `root`
//!

extern crate libproc;
extern crate libc;

use crate::libproc::libproc::kmesg_buffer;

fn main() {
    if let Ok(message) = kmesg_buffer::kmsgbuf() {
        println!("{}", message);
    }
}<commit_msg>small docs change<commit_after>//! A `dmesg` command that is a simple demonstration program for using the [`libproc`](../libproc/index.html) library
//!
//! Usage
//! =
//!
//! `> dmesg`
//!

extern crate libproc;
extern crate libc;

use crate::libproc::libproc::kmesg_buffer;

fn main() {
    if let Ok(message) = kmesg_buffer::kmsgbuf() {
        println!("{}", message);
    }
}<|endoftext|>


<commit_before>use crate::runtime::{yield_now, Arc, Mutex};
use crate::BatchFn;
use std::collections::{HashMap, HashSet};
use std::fmt::Debug;
use std::hash::Hash;

struct State<K, V, E> {
    completed: HashMap<K, Result<V, E>>,
    pending: HashSet<K>,
}

impl<K, V, E> State<K, V, E> {
    fn new() -> Self {
        State {
            completed: HashMap::new(),
            pending: HashSet::new(),
        }
    }
}

pub struct Loader<K, V, E, F>
where
    K: Eq + Hash + Clone,
    V: Clone,
    E: Clone,
    F: BatchFn<K, V, Error = E>,
{
    state: Arc<Mutex<State<K, V, E>>>,
    load_fn: Arc<Mutex<F>>,
    max_batch_size: usize,
    yield_count: usize,
}

impl<K, V, E, F> Clone for Loader<K, V, E, F>
where
    K: Eq + Hash + Clone,
    V: Clone,
    E: Clone,
    F: BatchFn<K, V, Error = E>,
{
    fn clone(&self) -> Self {
        Loader {
            state: self.state.clone(),
            max_batch_size: self.max_batch_size,
            load_fn: self.load_fn.clone(),
            yield_count: self.yield_count,
        }
    }
}

impl<K, V, E, F> Loader<K, V, E, F>
where
    K: Eq + Hash + Clone + Debug,
    V: Clone,
    E: Clone,
    F: BatchFn<K, V, Error = E>,
{
    pub fn new(load_fn: F) -> Loader<K, V, E, F> {
        Loader::with_yield_count(load_fn, 10)
    }

    pub fn with_yield_count(load_fn: F, yield_count: usize) -> Loader<K, V, E, F> {
        Loader {
            state: Arc::new(Mutex::new(State::new())),
            max_batch_size: load_fn.max_batch_size(),
            load_fn: Arc::new(Mutex::new(load_fn)),
            yield_count,
        }
    }

    pub async fn load(&self, key: K) -> Result<V, F::Error> {
        let mut state = self.state.lock().await;
        if let Some(v) = state.completed.get(&key) {
            return (*v).clone();
        }

        if state.pending.get(&key).is_none() {
            state.pending.insert(key.clone());
            if state.pending.len() >= self.max_batch_size {
                let keys = state.pending.drain().collect::<Vec<K>>();
                let load_fn = self.load_fn.lock().await;
                let load_ret = load_fn.load(keys.as_ref()).await;
                drop(load_fn);
                for (k, v) in load_ret.into_iter() {
                    state.completed.insert(k, v);
                }
                return state
                    .completed
                    .get(&key)
                    .cloned()
                    .unwrap_or_else(|| panic!("found key {:?} in load result", key));
            }
        }
        drop(state);

        // yield for other load to append request
        let mut i = 0;
        while i < self.yield_count {
            yield_now().await;
            i += 1;
        }

        let mut state = self.state.lock().await;
        if let Some(v) = state.completed.get(&key) {
            return (*v).clone();
        }

        if !state.pending.is_empty() {
            let keys = state.pending.drain().collect::<Vec<K>>();
            let load_fn = self.load_fn.lock().await;
            let load_ret = load_fn.load(keys.as_ref()).await;
            drop(load_fn);
            for (k, v) in load_ret.into_iter() {
                state.completed.insert(k, v);
            }
        }

        state
            .completed
            .get(&key)
            .cloned()
            .unwrap_or_else(|| panic!("found key {:?} in load result", key))
    }

    pub async fn load_many(&self, keys: Vec<K>) -> HashMap<K, Result<V, F::Error>> {
        let mut state = self.state.lock().await;
        let mut ret = HashMap::new();
        let mut rest = Vec::new();
        for key in keys.into_iter() {
            if let Some(v) = state.completed.get(&key).cloned() {
                ret.insert(key, v);
                continue;
            }
            if state.pending.get(&key).is_none() {
                state.pending.insert(key.clone());
                if state.pending.len() >= self.max_batch_size {
                    let keys = state.pending.drain().collect::<Vec<K>>();
                    let load_fn = self.load_fn.lock().await;
                    let load_ret = load_fn.load(keys.as_ref()).await;
                    drop(load_fn);
                    for (k, v) in load_ret.into_iter() {
                        state.completed.insert(k, v);
                    }
                }
            }
            rest.push(key);
        }
        drop(state);

        // yield for other load to append request
        let mut i = 0;
        while i < self.yield_count {
            yield_now().await;
            i += 1;
        }

        if !rest.is_empty() {
            let mut state = self.state.lock().await;
            if !state.pending.is_empty() {
                let keys = state.pending.drain().collect::<Vec<K>>();
                let load_fn = self.load_fn.lock().await;
                let load_ret = load_fn.load(keys.as_ref()).await;
                drop(load_fn);
                for (k, v) in load_ret.into_iter() {
                    state.completed.insert(k, v);
                }
            }

            for key in rest.into_iter() {
                let v = state
                    .completed
                    .get(&key)
                    .cloned()
                    .unwrap_or_else(|| panic!("found key {:?} in load result", key));
                ret.insert(key, v);
            }
        }

        ret
    }

    pub async fn prime(&self, key: K, val: V) {
        let mut state = self.state.lock().await;
        state.completed.insert(key, Ok(val));
    }
}
<commit_msg>Fix trait compile requirements for K in State::new<commit_after>use crate::runtime::{yield_now, Arc, Mutex};
use crate::BatchFn;
use std::collections::{HashMap, HashSet};
use std::fmt::Debug;
use std::hash::Hash;

struct State<K, V, E> {
    completed: HashMap<K, Result<V, E>>,
    pending: HashSet<K>,
}

impl<K: Eq + Hash, V, E> State<K, V, E> {
    fn new() -> Self {
        State {
            completed: HashMap::new(),
            pending: HashSet::new(),
        }
    }
}

pub struct Loader<K, V, E, F>
where
    K: Eq + Hash + Clone,
    V: Clone,
    E: Clone,
    F: BatchFn<K, V, Error = E>,
{
    state: Arc<Mutex<State<K, V, E>>>,
    load_fn: Arc<Mutex<F>>,
    max_batch_size: usize,
    yield_count: usize,
}

impl<K, V, E, F> Clone for Loader<K, V, E, F>
where
    K: Eq + Hash + Clone,
    V: Clone,
    E: Clone,
    F: BatchFn<K, V, Error = E>,
{
    fn clone(&self) -> Self {
        Loader {
            state: self.state.clone(),
            max_batch_size: self.max_batch_size,
            load_fn: self.load_fn.clone(),
            yield_count: self.yield_count,
        }
    }
}

impl<K, V, E, F> Loader<K, V, E, F>
where
    K: Eq + Hash + Clone + Debug,
    V: Clone,
    E: Clone,
    F: BatchFn<K, V, Error = E>,
{
    pub fn new(load_fn: F) -> Loader<K, V, E, F> {
        Loader::with_yield_count(load_fn, 10)
    }

    pub fn with_yield_count(
        load_fn: F,
        yield_count: usize,
    ) -> Loader<K, V, E, F> {
        Loader {
            state: Arc::new(Mutex::new(State::new())),
            max_batch_size: load_fn.max_batch_size(),
            load_fn: Arc::new(Mutex::new(load_fn)),
            yield_count,
        }
    }

    pub async fn load(&self, key: K) -> Result<V, F::Error> {
        let mut state = self.state.lock().await;
        if let Some(v) = state.completed.get(&key) {
            return (*v).clone();
        }

        if state.pending.get(&key).is_none() {
            state.pending.insert(key.clone());
            if state.pending.len() >= self.max_batch_size {
                let keys = state.pending.drain().collect::<Vec<K>>();
                let load_fn = self.load_fn.lock().await;
                let load_ret = load_fn.load(keys.as_ref()).await;
                drop(load_fn);
                for (k, v) in load_ret.into_iter() {
                    state.completed.insert(k, v);
                }
                return state.completed.get(&key).cloned().unwrap_or_else(
                    || panic!("found key {:?} in load result", key),
                );
            }
        }
        drop(state);

        // yield for other load to append request
        let mut i = 0;
        while i < self.yield_count {
            yield_now().await;
            i += 1;
        }

        let mut state = self.state.lock().await;
        if let Some(v) = state.completed.get(&key) {
            return (*v).clone();
        }

        if !state.pending.is_empty() {
            let keys = state.pending.drain().collect::<Vec<K>>();
            let load_fn = self.load_fn.lock().await;
            let load_ret = load_fn.load(keys.as_ref()).await;
            drop(load_fn);
            for (k, v) in load_ret.into_iter() {
                state.completed.insert(k, v);
            }
        }

        state
            .completed
            .get(&key)
            .cloned()
            .unwrap_or_else(|| panic!("found key {:?} in load result", key))
    }

    pub async fn load_many(
        &self,
        keys: Vec<K>,
    ) -> HashMap<K, Result<V, F::Error>> {
        let mut state = self.state.lock().await;
        let mut ret = HashMap::new();
        let mut rest = Vec::new();
        for key in keys.into_iter() {
            if let Some(v) = state.completed.get(&key).cloned() {
                ret.insert(key, v);
                continue;
            }
            if state.pending.get(&key).is_none() {
                state.pending.insert(key.clone());
                if state.pending.len() >= self.max_batch_size {
                    let keys = state.pending.drain().collect::<Vec<K>>();
                    let load_fn = self.load_fn.lock().await;
                    let load_ret = load_fn.load(keys.as_ref()).await;
                    drop(load_fn);
                    for (k, v) in load_ret.into_iter() {
                        state.completed.insert(k, v);
                    }
                }
            }
            rest.push(key);
        }
        drop(state);

        // yield for other load to append request
        let mut i = 0;
        while i < self.yield_count {
            yield_now().await;
            i += 1;
        }

        if !rest.is_empty() {
            let mut state = self.state.lock().await;
            if !state.pending.is_empty() {
                let keys = state.pending.drain().collect::<Vec<K>>();
                let load_fn = self.load_fn.lock().await;
                let load_ret = load_fn.load(keys.as_ref()).await;
                drop(load_fn);
                for (k, v) in load_ret.into_iter() {
                    state.completed.insert(k, v);
                }
            }

            for key in rest.into_iter() {
                let v =
                    state.completed.get(&key).cloned().unwrap_or_else(|| {
                        panic!("found key {:?} in load result", key)
                    });
                ret.insert(key, v);
            }
        }

        ret
    }

    pub async fn prime(&self, key: K, val: V) {
        let mut state = self.state.lock().await;
        state.completed.insert(key, Ok(val));
    }
}
<|endoftext|>


<commit_before>//! Cameras are used to view scenes from any point in the world.
//!
//! ## Projections
//!
//! ### Finite perspective
//!
//! Finite persepective projections are often used for 3D rendering. In a finite
//! perspective projection, objects moving away from the camera appear smaller and
//! are occluded by objects that are closer to the camera.
//!
//! Finite [`Perspective`] projections are created with the
//! [`Factory::perspective_camera`] method with a bounded range.
//!
//! ```rust,no_run
//! # let mut window = three::Window::new("");
//! # let _ = {
//! window.factory.perspective_camera(60.0, 0.1 .. 1.0);
//! # };
//! ```
//!
//! ### Infinite perspective
//!
//! Infinite perspective projections are perspective projections with `zfar` planes
//! at infinity. This means objects are never considered to be 'too far away' to be
//! visible by the camera.
//!
//! Infinite [`Perspective`] projections are created with the
//! [`Factory::perspective_camera`] method with an unbounded range.
//!
//! ```rust,no_run
//! # let mut window = three::Window::new("");
//! # let _ = {
//! window.factory.perspective_camera(60.0, 0.1 ..);
//! # };
//! ```
//!
//! ### Orthographic
//!
//! Orthographic projections are often used for 2D rendering. In an orthographic
//! projection, objects moving away from the camera retain their size but are
//! occluded by objects that are closer to the camera.
//!
//! [`Orthographic`] projections are created with the
//! [`Factory::orthographic_camera`] method.
//!
//! ```rust,no_run
//! # let mut window = three::Window::new("");
//! # let _ = {
//! window.factory.orthographic_camera([0.0, 0.0], 1.0, -1.0 .. 1.0)
//! # };
//! ```
//!
//! [`Factory::orthographic_camera`]: ../factory/struct.Factory.html#method.orthographic_camera
//! [`Factory::perspective_camera`]: ../factory/struct.Factory.html#method.perspective_camera
//! [`object::Base`]: ../object/struct.Base.html
//! [`Orthographic`]: struct.Orthographic.html
//! [`Perspective`]: struct.Perspective.html

use cgmath;
use mint;

use hub::{Hub, Operation, SubNode};
use object::{Base, DowncastObject, Object, ObjectType};
use scene::SyncGuard;

use std::ops;

/// The Z values of the near and far clipping planes of a camera's projection.
#[derive(Clone, Debug, PartialEq)]
pub enum ZRange {
    /// Z range for a finite projection.
    Finite(ops::Range<f32>),

    /// Z range for an infinite projection.
    Infinite(ops::RangeFrom<f32>),
}

impl From<ops::Range<f32>> for ZRange {
    fn from(range: ops::Range<f32>) -> ZRange {
        ZRange::Finite(range)
    }
}

impl From<ops::RangeFrom<f32>> for ZRange {
    fn from(range: ops::RangeFrom<f32>) -> ZRange {
        ZRange::Infinite(range)
    }
}

/// A camera's projection.
#[derive(Clone, Debug, PartialEq)]
pub enum Projection {
    /// An orthographic projection.
    Orthographic(Orthographic),
    /// A perspective projection.
    Perspective(Perspective),
}

/// Camera is used to render Scene with specific [`Projection`].
///
/// [`Projection`]: enum.Projection.html
#[derive(Clone, Debug, PartialEq)]
pub struct Camera {
    pub(crate) object: Base,
}

impl AsRef<Base> for Camera {
    fn as_ref(&self) -> &Base { &self.object }
}

impl Object for Camera {
    type Data = Projection;

    fn resolve_data(&self, sync_guard: &SyncGuard) -> Self::Data {
        match &sync_guard.hub[self].sub_node {
            SubNode::Camera(ref projection) => projection.clone(),
            sub_node @ _ => panic!("`Group` had a bad sub node type: {:?}", sub_node),
        }
    }
}

impl Camera {
    pub(crate) fn new(hub: &mut Hub, projection: Projection) -> Self {
        Camera {
            object: hub.spawn(SubNode::Camera(projection)),
        }
    }

    /// Sets the projection used by the camera.
    pub fn set_projection<P: Into<Projection>>(&self, projection: P) {
        self.as_ref().send(Operation::SetProjection(projection.into()));
    }
}

impl DowncastObject for Camera {
    fn downcast(object_type: ObjectType) -> Option<Self> {
        match object_type {
            ObjectType::Camera(camera) => Some(camera),
            _ => None,
        }
    }
}

impl Projection {
    /// Constructs an orthographic projection.
    pub fn orthographic<P>(
        center: P,
        extent_y: f32,
        range: ops::Range<f32>,
    ) -> Self
    where
        P: Into<mint::Point2<f32>>,
    {
        let center = center.into();
        Projection::Orthographic(Orthographic {
            center,
            extent_y,
            range,
        })
    }

    /// Constructs a perspective projection.
    pub fn perspective<R>(
        fov_y: f32,
        range: R,
    ) -> Self
    where
        R: Into<ZRange>,
    {
        Projection::Perspective(Perspective {
            fov_y,
            zrange: range.into(),
        })
    }

    /// Computes the projection matrix representing the camera's projection.
    pub fn matrix(
        &self,
        aspect_ratio: f32,
    ) -> mint::ColumnMatrix4<f32> {
        match *self {
            Projection::Orthographic(ref x) => x.matrix(aspect_ratio),
            Projection::Perspective(ref x) => x.matrix(aspect_ratio),
        }
    }
}

/// Orthographic projection parameters.
#[derive(Clone, Debug, PartialEq)]
pub struct Orthographic {
    /// The center of the projection.
    pub center: mint::Point2<f32>,
    /// Vertical extent from the center point. The height is double the extent.
    /// The width is derived from the height based on the current aspect ratio.
    pub extent_y: f32,
    /// Distance to the clipping planes.
    pub range: ops::Range<f32>,
}

impl Orthographic {
    /// Computes the projection matrix representing the camera's projection.
    pub fn matrix(
        &self,
        aspect_ratio: f32,
    ) -> mint::ColumnMatrix4<f32> {
        let extent_x = aspect_ratio * self.extent_y;
        cgmath::ortho(
            self.center.x - extent_x,
            self.center.x + extent_x,
            self.center.y - self.extent_y,
            self.center.y + self.extent_y,
            self.range.start,
            self.range.end,
        ).into()
    }
}

/// Perspective projection parameters.
#[derive(Clone, Debug, PartialEq)]
pub struct Perspective {
    /// Vertical field of view in degrees.
    /// Note: the horizontal FOV is computed based on the aspect.
    pub fov_y: f32,
    /// The distance to the clipping planes.
    pub zrange: ZRange,
}

impl Perspective {
    /// Computes the projection matrix representing the camera's projection.
    pub fn matrix(
        &self,
        aspect_ratio: f32,
    ) -> mint::ColumnMatrix4<f32> {
        match self.zrange {
            ZRange::Finite(ref range) => cgmath::perspective(
                cgmath::Deg(self.fov_y),
                aspect_ratio,
                range.start,
                range.end,
            ).into(),
            ZRange::Infinite(ref range) => {
                let m00 = 1.0 / (aspect_ratio * f32::tan(0.5 * self.fov_y));
                let m11 = 1.0 / f32::tan(0.5 * self.fov_y);
                let m22 = -1.0;
                let m23 = -2.0 * range.start;
                let m32 = -1.0;
                let m = [
                    [m00, 0.0, 0.0, 0.0],
                    [0.0, m11, 0.0, 0.0],
                    [0.0, 0.0, m22, m23],
                    [0.0, 0.0, m32, 0.0],
                ];
                m.into()
            }
        }
    }
}
<commit_msg>Fix the infinite perspective camera.<commit_after>//! Cameras are used to view scenes from any point in the world.
//!
//! ## Projections
//!
//! ### Finite perspective
//!
//! Finite persepective projections are often used for 3D rendering. In a finite
//! perspective projection, objects moving away from the camera appear smaller and
//! are occluded by objects that are closer to the camera.
//!
//! Finite [`Perspective`] projections are created with the
//! [`Factory::perspective_camera`] method with a bounded range.
//!
//! ```rust,no_run
//! # let mut window = three::Window::new("");
//! # let _ = {
//! window.factory.perspective_camera(60.0, 0.1 .. 1.0);
//! # };
//! ```
//!
//! ### Infinite perspective
//!
//! Infinite perspective projections are perspective projections with `zfar` planes
//! at infinity. This means objects are never considered to be 'too far away' to be
//! visible by the camera.
//!
//! Infinite [`Perspective`] projections are created with the
//! [`Factory::perspective_camera`] method with an unbounded range.
//!
//! ```rust,no_run
//! # let mut window = three::Window::new("");
//! # let _ = {
//! window.factory.perspective_camera(60.0, 0.1 ..);
//! # };
//! ```
//!
//! ### Orthographic
//!
//! Orthographic projections are often used for 2D rendering. In an orthographic
//! projection, objects moving away from the camera retain their size but are
//! occluded by objects that are closer to the camera.
//!
//! [`Orthographic`] projections are created with the
//! [`Factory::orthographic_camera`] method.
//!
//! ```rust,no_run
//! # let mut window = three::Window::new("");
//! # let _ = {
//! window.factory.orthographic_camera([0.0, 0.0], 1.0, -1.0 .. 1.0)
//! # };
//! ```
//!
//! [`Factory::orthographic_camera`]: ../factory/struct.Factory.html#method.orthographic_camera
//! [`Factory::perspective_camera`]: ../factory/struct.Factory.html#method.perspective_camera
//! [`object::Base`]: ../object/struct.Base.html
//! [`Orthographic`]: struct.Orthographic.html
//! [`Perspective`]: struct.Perspective.html

use cgmath;
use mint;

use hub::{Hub, Operation, SubNode};
use object::{Base, DowncastObject, Object, ObjectType};
use scene::SyncGuard;

use std::ops;

/// The Z values of the near and far clipping planes of a camera's projection.
#[derive(Clone, Debug, PartialEq)]
pub enum ZRange {
    /// Z range for a finite projection.
    Finite(ops::Range<f32>),

    /// Z range for an infinite projection.
    Infinite(ops::RangeFrom<f32>),
}

impl From<ops::Range<f32>> for ZRange {
    fn from(range: ops::Range<f32>) -> ZRange {
        ZRange::Finite(range)
    }
}

impl From<ops::RangeFrom<f32>> for ZRange {
    fn from(range: ops::RangeFrom<f32>) -> ZRange {
        ZRange::Infinite(range)
    }
}

/// A camera's projection.
#[derive(Clone, Debug, PartialEq)]
pub enum Projection {
    /// An orthographic projection.
    Orthographic(Orthographic),
    /// A perspective projection.
    Perspective(Perspective),
}

/// Camera is used to render Scene with specific [`Projection`].
///
/// [`Projection`]: enum.Projection.html
#[derive(Clone, Debug, PartialEq)]
pub struct Camera {
    pub(crate) object: Base,
}

impl AsRef<Base> for Camera {
    fn as_ref(&self) -> &Base { &self.object }
}

impl Object for Camera {
    type Data = Projection;

    fn resolve_data(&self, sync_guard: &SyncGuard) -> Self::Data {
        match &sync_guard.hub[self].sub_node {
            SubNode::Camera(ref projection) => projection.clone(),
            sub_node @ _ => panic!("`Group` had a bad sub node type: {:?}", sub_node),
        }
    }
}

impl Camera {
    pub(crate) fn new(hub: &mut Hub, projection: Projection) -> Self {
        Camera {
            object: hub.spawn(SubNode::Camera(projection)),
        }
    }

    /// Sets the projection used by the camera.
    pub fn set_projection<P: Into<Projection>>(&self, projection: P) {
        self.as_ref().send(Operation::SetProjection(projection.into()));
    }
}

impl DowncastObject for Camera {
    fn downcast(object_type: ObjectType) -> Option<Self> {
        match object_type {
            ObjectType::Camera(camera) => Some(camera),
            _ => None,
        }
    }
}

impl Projection {
    /// Constructs an orthographic projection.
    pub fn orthographic<P>(
        center: P,
        extent_y: f32,
        range: ops::Range<f32>,
    ) -> Self
    where
        P: Into<mint::Point2<f32>>,
    {
        let center = center.into();
        Projection::Orthographic(Orthographic {
            center,
            extent_y,
            range,
        })
    }

    /// Constructs a perspective projection.
    pub fn perspective<R>(
        fov_y: f32,
        range: R,
    ) -> Self
    where
        R: Into<ZRange>,
    {
        Projection::Perspective(Perspective {
            fov_y,
            zrange: range.into(),
        })
    }

    /// Computes the projection matrix representing the camera's projection.
    pub fn matrix(
        &self,
        aspect_ratio: f32,
    ) -> mint::ColumnMatrix4<f32> {
        match *self {
            Projection::Orthographic(ref x) => x.matrix(aspect_ratio),
            Projection::Perspective(ref x) => x.matrix(aspect_ratio),
        }
    }
}

/// Orthographic projection parameters.
#[derive(Clone, Debug, PartialEq)]
pub struct Orthographic {
    /// The center of the projection.
    pub center: mint::Point2<f32>,
    /// Vertical extent from the center point. The height is double the extent.
    /// The width is derived from the height based on the current aspect ratio.
    pub extent_y: f32,
    /// Distance to the clipping planes.
    pub range: ops::Range<f32>,
}

impl Orthographic {
    /// Computes the projection matrix representing the camera's projection.
    pub fn matrix(
        &self,
        aspect_ratio: f32,
    ) -> mint::ColumnMatrix4<f32> {
        let extent_x = aspect_ratio * self.extent_y;
        cgmath::ortho(
            self.center.x - extent_x,
            self.center.x + extent_x,
            self.center.y - self.extent_y,
            self.center.y + self.extent_y,
            self.range.start,
            self.range.end,
        ).into()
    }
}

/// Perspective projection parameters.
#[derive(Clone, Debug, PartialEq)]
pub struct Perspective {
    /// Vertical field of view in degrees.
    /// Note: the horizontal FOV is computed based on the aspect.
    pub fov_y: f32,
    /// The distance to the clipping planes.
    pub zrange: ZRange,
}

impl Perspective {
    /// Computes the projection matrix representing the camera's projection.
    pub fn matrix(
        &self,
        aspect_ratio: f32,
    ) -> mint::ColumnMatrix4<f32> {
        match self.zrange {
            ZRange::Finite(ref range) => cgmath::perspective(
                cgmath::Deg(self.fov_y),
                aspect_ratio,
                range.start,
                range.end,
            ).into(),
            ZRange::Infinite(ref range) => {
                let f = 1.0 / (0.5 * self.fov_y.to_radians()).tan();

                let m00 = f / aspect_ratio;
                let m11 = f;
                let m22 = -1.0;
                let m23 = -1.0;
                let m32 = -2.0 * range.start;

                let m = [
                    [m00, 0.0, 0.0, 0.0],
                    [0.0, m11, 0.0, 0.0],
                    [0.0, 0.0, m22, m23],
                    [0.0, 0.0, m32, 0.0],
                ];

                m.into()
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::sync::RwLock;
use std::error::Error;

use iron::prelude::*;
use iron::{status};
use iron::{AfterMiddleware, typemap};
use iron::modifier::Modifier;
use plugin::Plugin as PluginFor;
use iron::headers::ContentType;

use handlebars::{Handlebars, TemplateRenderError};
#[cfg(not(feature = "serde_type"))]
use serialize::json::{ToJson, Json};
#[cfg(feature = "serde_type")]
use serde::ser::Serialize as ToJson;
#[cfg(feature = "serde_type")]
use serde_json::value::{self, Value as Json};

use ::source::{Source, SourceError};
use ::sources::directory::{DirectorySource};

#[derive(Clone)]
pub struct Template {
    name: Option<String>,
    content: Option<String>,
    value: Json
}

#[cfg(not(feature = "serde_type"))]
impl Template {
    /// render some template from pre-registered templates
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: Some(name.to_string()),
            value: value.to_json(),
            content: None
        }
    }

    /// render some template with temporary template string
    pub fn with<T: ToJson>(content: &str, value: T) -> Template {
        Template {
            name: None,
            value: value.to_json(),
            content: Some(content.to_string())
        }
    }
}

#[cfg(feature = "serde_type")]
impl Template {
    /// render some template from pre-registered templates
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: name.to_string(),
            value: value::to_value(&value),
            content: None
        }
    }

    /// render some template with temporary template string
    pub fn with<T: ToJson>(content: &str, value: T) -> Template {
        Template {
            name: None,
            value: value::to_value(&value),
            content: Some(content.to_string())
        }
    }
}

pub struct HandlebarsEngine {
    pub sources: Vec<Box<Source + Send + Sync>>,
    pub registry: RwLock<Box<Handlebars>>
}

impl typemap::Key for HandlebarsEngine {
    type Value = Template;
}

impl Modifier<Response> for Template {
    fn modify(self, resp: &mut Response) {
        resp.extensions.insert::<HandlebarsEngine>(self);
    }
}

impl PluginFor<Response> for HandlebarsEngine {
    type Error = ();

    fn eval(resp: &mut Response) -> Result<Template, ()> {
        match resp.extensions.get::<HandlebarsEngine>(){
            Some(t) => Ok(t.clone()),
            None => Err(())
        }
    }
}

impl HandlebarsEngine {
    /// #[Deprecated], for backward compaitibility only
    pub fn new(prefix: &str, suffix: &str) -> HandlebarsEngine {
        let mut hbs = HandlebarsEngine::new2();
        hbs.add(Box::new(DirectorySource::new(prefix, suffix)));
        match hbs.reload() {
            Ok(_) => hbs,
            Err(e) => {
                panic!("Failed to init from directory: {}", e.description())
            }
        }
    }

    /// #[Deprecated], for backward compaitibility only
    pub fn from(prefix: &str, suffix: &str, custom: Handlebars) -> HandlebarsEngine {
        let mut hbs = HandlebarsEngine::from2(custom);
        hbs.add(Box::new(DirectorySource::new(prefix, suffix)));
        match hbs.reload() {
            Ok(_) => hbs,
            Err(e) => {
                panic!("Failed to init from directory: {}", e.description())
            }
        }
    }

    pub fn new2() -> HandlebarsEngine {
        HandlebarsEngine {
            sources: Vec::new(),
            registry: RwLock::new(Box::new(Handlebars::new()))
        }
    }

    pub fn from2(reg: Handlebars) -> HandlebarsEngine {
        HandlebarsEngine {
            sources: Vec::new(),
            registry: RwLock::new(Box::new(reg))
        }
    }

    pub fn add(&mut self, source: Box<Source + Send + Sync>) {
        self.sources.push(source);
    }

    pub fn reload(&self) -> Result<(), SourceError> {
        let mut hbs = self.registry.write().unwrap();
        hbs.clear_templates();
        for s in self.sources.iter() {
            try!(s.load(&mut hbs))
        }
        Ok(())
    }
}

impl AfterMiddleware for HandlebarsEngine {
    fn after(&self, _: &mut Request, r: Response) -> IronResult<Response> {
        let mut resp = r;
        let page_wrapper = resp.extensions.get::<HandlebarsEngine>().as_ref()
            .and_then(|h| {
                let hbs = self.registry.read().unwrap();
                if let Some(ref name) = h.name {
                    return Some(hbs.render(name, &h.value).map_err(TemplateRenderError::from));
                } else if let Some(ref content) = h.content {
                    return Some(hbs.template_render(content, &h.value));
                } else {
                    unreachable!();
                }
            });

        match page_wrapper {
            Some(page_result) => {
                match page_result {
                    Ok(page) => {
                        if !resp.headers.has::<ContentType>() {
                            resp.headers.set(ContentType::html());
                        }
                        resp.set_mut(page);
                        Ok(resp)
                    }
                    Err(e) => {
                        info!("{}", e.description());
                        Err(IronError::new(e, status::InternalServerError))
                    }
                }
            }
            None => {
                Ok(resp)
            }
        }
    }
}

#[cfg(test)]
mod test {
    use std::collections::BTreeMap;
    use iron::prelude::*;
    use middleware::*;
    use handlebars::{Handlebars, RenderError, RenderContext, Helper, Context};

    fn hello_world() -> IronResult<Response> {
        let resp = Response::new();

        let mut data = BTreeMap::new();
        data.insert("title".to_owned(), "Handlebars on Iron".to_owned());

        Ok(resp.set(Template::new("index", data)))
    }

    fn hello_world2() -> IronResult<Response> {
        let resp = Response::new();

        let mut data = BTreeMap::new();
        data.insert("title".to_owned(), "Handlebars on Iron".to_owned());

        Ok(resp.set(Template::with("{{title}}", data)))
    }

    #[test]
    fn test_resp_set() {
        let mut resp = hello_world().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.name.unwrap(), "index".to_string());
                assert_eq!(h.value.as_object().unwrap()
                           .get(&"title".to_string()).unwrap()
                           .as_string().unwrap(),
                           "Handlebars on Iron");
            },
            _ => panic!("template expected")
        }
    }

    #[test]
    fn test_resp_set2() {
        let mut resp = hello_world2().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.content.unwrap(), "{{title}}".to_string());
                assert_eq!(h.value.as_object().unwrap()
                           .get(&"title".to_string()).unwrap()
                           .as_string().unwrap(),
                           "Handlebars on Iron");
            },
            _ => panic!("template expected")
        }
    }

    #[test]
    fn test_register_helper() {
        let hbs = HandlebarsEngine::new2();
        let mut reg = hbs.registry.write().unwrap();
        reg.register_helper("ignore", Box::new(|_: &Context, _: &Helper, _: &Handlebars, _: &mut RenderContext| -> Result<(), RenderError> {
            Ok(())
        }));
    }
}
<commit_msg>(fix) fix mismatched types<commit_after>use std::sync::RwLock;
use std::error::Error;

use iron::prelude::*;
use iron::{status};
use iron::{AfterMiddleware, typemap};
use iron::modifier::Modifier;
use plugin::Plugin as PluginFor;
use iron::headers::ContentType;

use handlebars::{Handlebars, TemplateRenderError};
#[cfg(not(feature = "serde_type"))]
use serialize::json::{ToJson, Json};
#[cfg(feature = "serde_type")]
use serde::ser::Serialize as ToJson;
#[cfg(feature = "serde_type")]
use serde_json::value::{self, Value as Json};

use ::source::{Source, SourceError};
use ::sources::directory::{DirectorySource};

#[derive(Clone)]
pub struct Template {
    name: Option<String>,
    content: Option<String>,
    value: Json
}

#[cfg(not(feature = "serde_type"))]
impl Template {
    /// render some template from pre-registered templates
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: Some(name.to_string()),
            value: value.to_json(),
            content: None
        }
    }

    /// render some template with temporary template string
    pub fn with<T: ToJson>(content: &str, value: T) -> Template {
        Template {
            name: None,
            value: value.to_json(),
            content: Some(content.to_string())
        }
    }
}

#[cfg(feature = "serde_type")]
impl Template {
    /// render some template from pre-registered templates
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: Some(name.to_string()),
            value: value::to_value(&value),
            content: None
        }
    }

    /// render some template with temporary template string
    pub fn with<T: ToJson>(content: &str, value: T) -> Template {
        Template {
            name: None,
            value: value::to_value(&value),
            content: Some(content.to_string())
        }
    }
}

pub struct HandlebarsEngine {
    pub sources: Vec<Box<Source + Send + Sync>>,
    pub registry: RwLock<Box<Handlebars>>
}

impl typemap::Key for HandlebarsEngine {
    type Value = Template;
}

impl Modifier<Response> for Template {
    fn modify(self, resp: &mut Response) {
        resp.extensions.insert::<HandlebarsEngine>(self);
    }
}

impl PluginFor<Response> for HandlebarsEngine {
    type Error = ();

    fn eval(resp: &mut Response) -> Result<Template, ()> {
        match resp.extensions.get::<HandlebarsEngine>(){
            Some(t) => Ok(t.clone()),
            None => Err(())
        }
    }
}

impl HandlebarsEngine {
    /// #[Deprecated], for backward compaitibility only
    pub fn new(prefix: &str, suffix: &str) -> HandlebarsEngine {
        let mut hbs = HandlebarsEngine::new2();
        hbs.add(Box::new(DirectorySource::new(prefix, suffix)));
        match hbs.reload() {
            Ok(_) => hbs,
            Err(e) => {
                panic!("Failed to init from directory: {}", e.description())
            }
        }
    }

    /// #[Deprecated], for backward compaitibility only
    pub fn from(prefix: &str, suffix: &str, custom: Handlebars) -> HandlebarsEngine {
        let mut hbs = HandlebarsEngine::from2(custom);
        hbs.add(Box::new(DirectorySource::new(prefix, suffix)));
        match hbs.reload() {
            Ok(_) => hbs,
            Err(e) => {
                panic!("Failed to init from directory: {}", e.description())
            }
        }
    }

    pub fn new2() -> HandlebarsEngine {
        HandlebarsEngine {
            sources: Vec::new(),
            registry: RwLock::new(Box::new(Handlebars::new()))
        }
    }

    pub fn from2(reg: Handlebars) -> HandlebarsEngine {
        HandlebarsEngine {
            sources: Vec::new(),
            registry: RwLock::new(Box::new(reg))
        }
    }

    pub fn add(&mut self, source: Box<Source + Send + Sync>) {
        self.sources.push(source);
    }

    pub fn reload(&self) -> Result<(), SourceError> {
        let mut hbs = self.registry.write().unwrap();
        hbs.clear_templates();
        for s in self.sources.iter() {
            try!(s.load(&mut hbs))
        }
        Ok(())
    }
}

impl AfterMiddleware for HandlebarsEngine {
    fn after(&self, _: &mut Request, r: Response) -> IronResult<Response> {
        let mut resp = r;
        let page_wrapper = resp.extensions.get::<HandlebarsEngine>().as_ref()
            .and_then(|h| {
                let hbs = self.registry.read().unwrap();
                if let Some(ref name) = h.name {
                    return Some(hbs.render(name, &h.value).map_err(TemplateRenderError::from));
                } else if let Some(ref content) = h.content {
                    return Some(hbs.template_render(content, &h.value));
                } else {
                    unreachable!();
                }
            });

        match page_wrapper {
            Some(page_result) => {
                match page_result {
                    Ok(page) => {
                        if !resp.headers.has::<ContentType>() {
                            resp.headers.set(ContentType::html());
                        }
                        resp.set_mut(page);
                        Ok(resp)
                    }
                    Err(e) => {
                        info!("{}", e.description());
                        Err(IronError::new(e, status::InternalServerError))
                    }
                }
            }
            None => {
                Ok(resp)
            }
        }
    }
}

#[cfg(test)]
mod test {
    use std::collections::BTreeMap;
    use iron::prelude::*;
    use middleware::*;
    use handlebars::{Handlebars, RenderError, RenderContext, Helper, Context};

    fn hello_world() -> IronResult<Response> {
        let resp = Response::new();

        let mut data = BTreeMap::new();
        data.insert("title".to_owned(), "Handlebars on Iron".to_owned());

        Ok(resp.set(Template::new("index", data)))
    }

    fn hello_world2() -> IronResult<Response> {
        let resp = Response::new();

        let mut data = BTreeMap::new();
        data.insert("title".to_owned(), "Handlebars on Iron".to_owned());

        Ok(resp.set(Template::with("{{title}}", data)))
    }

    #[test]
    fn test_resp_set() {
        let mut resp = hello_world().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.name.unwrap(), "index".to_string());
                assert_eq!(h.value.as_object().unwrap()
                           .get(&"title".to_string()).unwrap()
                           .as_string().unwrap(),
                           "Handlebars on Iron");
            },
            _ => panic!("template expected")
        }
    }

    #[test]
    fn test_resp_set2() {
        let mut resp = hello_world2().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.content.unwrap(), "{{title}}".to_string());
                assert_eq!(h.value.as_object().unwrap()
                           .get(&"title".to_string()).unwrap()
                           .as_string().unwrap(),
                           "Handlebars on Iron");
            },
            _ => panic!("template expected")
        }
    }

    #[test]
    fn test_register_helper() {
        let hbs = HandlebarsEngine::new2();
        let mut reg = hbs.registry.write().unwrap();
        reg.register_helper("ignore", Box::new(|_: &Context, _: &Helper, _: &Handlebars, _: &mut RenderContext| -> Result<(), RenderError> {
            Ok(())
        }));
    }
}
<|endoftext|>


<commit_before>
use message::Message;

pub struct TwitchClient {
	pub user: String,
	pub auth: String,
	pub default_channel: String,
	pub logging: bool,
}

impl TwitchClient {
	pub fn connect(&self) {
		// TODO: Connect!
	}

	pub fn recv_event(&self) -> Result<Event, &str> {

		Err("Not yet implemented")
	}

	fn parse_irc(irc: String) {
		// handle irc commands here

		// On Message Received

	}
}

pub enum Event {
	MessageReceived(Message),
}
<commit_msg>Adding basics for connecting to twitch's irc socket. Also added a ton of TODO comments<commit_after>

use ws::{connect, Handler, Sender, Handshake, Result, Message, CloseCode, Error};
use channel;
use message;
use std::error;

static DEFAULT_HOST: &'static str = "irc-ws.chat.twitch.tv";
const DEFAULT_PORT: i32 = 80;

pub struct TwitchClient {
	credentials: ConnectionCredentials,
	default_channel: String,
	logging: bool,

	channels: Vec<channel::Channel>,
}

impl TwitchClient {
	pub fn from(user: String, auth: String, channel: String, log: bool) -> TwitchClient {

		// TODO: add logging capabilities

		// TODO: add command identifiers for chat and whispers

		TwitchClient {
			credentials: ConnectionCredentials::from(user, auth),
			default_channel: channel,
			logging: log,

			channels: Vec::new(),
		}
	}

	pub fn connect(&self) {
		connect(format!("ws://{}:{}", self.credentials().host(), self.credentials().port()),
			|out| {
				WebClient {
					out: out
				}
			}
		);
	}

	pub fn recv_event(&self) -> Result<Event> {

		// TODO: return next event in queue
		Ok(Event::None)
	}

	pub fn credentials(&self) -> &ConnectionCredentials {
		&self.credentials
	}

	fn parse_irc(irc: String) {
		// TODO: handle irc commands here

		// On Message Received
	}
}

pub struct WebClient {

	out: Sender,
}

impl Handler for WebClient {

	fn on_open(&mut self, _: Handshake) -> Result<()> {

		// TODO: handle on open garbo
		Ok(())
	}

	fn on_message(&mut self, msg: Message) -> Result<()> {

		// TODO: handle on message garbo
		Ok(())
	}

	fn on_close(&mut self, code: CloseCode, reason: &str) {

		// TODO: handle on close garbo
	}

	fn on_error(&mut self, err: Error) {
		// TODO: handle error garbo
	}
}

pub struct ConnectionCredentials {
	user: String,
	auth: String,
	host: String,
	port: i32,
}

impl ConnectionCredentials {

	pub fn from(user: String, auth: String) -> ConnectionCredentials {
		ConnectionCredentials::from_host(user, auth, DEFAULT_HOST.to_owned(), DEFAULT_PORT)
	}

	pub fn from_host(
		user: String,
		auth: String,
		host: String,
		port: i32
	) -> ConnectionCredentials {

		ConnectionCredentials {
			user: user,
			auth: auth,
			host: host,
			port: port,
		}
	}

	pub fn user(&self) -> &String {
		&self.user
	}

	pub fn auth(&self) -> &String {
		&self.auth
	}

	pub fn host(&self) -> &String {
		&self.host
	}

	pub fn port(&self) -> &i32 {
		&self.port
	}
}

pub enum Event {
	None,

	// TODO: add all event types

	MessageReceived(message::Message),
}
<|endoftext|>


<commit_before>use std::net::{UdpSocket, SocketAddr};
use std::io::Error;
use std::str::FromStr;
use std::net::AddrParseError;
use std::collections::VecDeque;

extern crate clock_ticks;
extern crate rand;

#[derive(Debug)]
pub enum StatsdError {
    IoError(Error),
    AddrParseError(String),
}

impl From<AddrParseError> for StatsdError {
    fn from(_: AddrParseError) -> StatsdError {
        StatsdError::AddrParseError("Address parsing error".to_string())
    }
}

impl From<Error> for StatsdError {
    fn from(err: Error) -> StatsdError {
        StatsdError::IoError(err)
    }
}

/// Client socket for statsd servers.
///
/// After creating a metric you can use `Client`
/// to send metrics to the configured statsd server
///
/// # Example
///
/// Creating a client and sending metrics is easy.
///
/// ```ignore
/// use statsd::client::Client;
///
/// let client = Client::new("127.0.0.1:8125", "myapp.");
/// client.incr("some.metric.completed");
/// ```
pub struct Client {
    socket: UdpSocket,
    server_address: SocketAddr,
    prefix: String,
}

impl Client {
    /// Construct a new statsd client given an host/port & prefix
    pub fn new(host: &str, prefix: &str) -> Result<Client, StatsdError> {
        // Bind to a generic port as we'll only be writing on this
        // socket.
        let client_address = try!(SocketAddr::from_str("0.0.0.0:0"));
        let socket = try!(UdpSocket::bind(client_address));

        let server_address = try!(SocketAddr::from_str(host));
        Ok(Client {
            socket: socket,
            prefix: prefix.to_string(),
            server_address: server_address,
        })
    }

    /// Increment a metric by 1
    ///
    /// ```ignore
    /// # Increment a given metric by 1.
    /// client.incr("metric.completed");
    /// ```
    ///
    /// This modifies a counter with an effective sampling
    /// rate of 1.0.
    pub fn incr(&mut self, metric: &str) {
        self.count(metric, 1.0);
    }

    /// Decrement a metric by -1
    ///
    /// ```ignore
    /// # Decrement a given metric by 1
    /// client.decr("metric.completed");
    /// ```
    ///
    /// This modifies a counter with an effective sampling
    /// rate of 1.0.
    pub fn decr(&mut self, metric: &str) {
        self.count(metric, -1.0);
    }

    /// Modify a counter by `value`.
    ///
    /// Will increment or decrement a counter by `value` with
    /// a sampling rate of 1.0.
    ///
    /// ```ignore
    /// # Increment by 12
    /// client.count("metric.completed", 12);
    /// ```
    pub fn count(&mut self, metric: &str, value: f64) {
        let data = self.prepare(format!("{}:{}|c", metric, value));
        self.send(data);
    }

    /// Modify a counter by `value` only x% of the time.
    ///
    /// Will increment or decrement a counter by `value` with
    /// a custom sampling rate.
    ///
    ///
    /// ```ignore
    /// # Increment by 4 50% of the time.
    /// client.sampled_count("metric.completed", 4, 0.5);
    /// ```
    pub fn sampled_count(&mut self, metric: &str, value: f64, rate: f64) {
        if rand::random::<f64>() < rate {
            return;
        }
        let data = self.prepare(format!("{}:{}|c", metric, value));
        self.send(data);
    }

    /// Set a gauge value.
    ///
    /// ```ignore
    /// # set a gauge to 9001
    /// client.gauge("power_level.observed", 9001);
    /// ```
    pub fn gauge(&mut self, metric: &str, value: f64) {
        let data = self.prepare(format!("{}:{}|g", metric, value));
        self.send(data);
    }

    /// Send a timer value.
    ///
    /// The value is expected to be in ms.
    ///
    /// ```ignore
    /// # pass a duration value
    /// client.timer("response.duration", 10.123);
    /// ```
    pub fn timer(&mut self, metric: &str, value: f64) {
        let data = self.prepare(format!("{}:{}|ms", metric, value));
        self.send(data);
    }

    /// Time a block of code.
    ///
    /// The passed closure will be timed and executed. The block's
    /// duration will be sent as a metric.
    ///
    /// ```ignore
    /// # pass a duration value
    /// client.time("response.duration", || {
    ///   # Your code here.
    /// });
    /// ```
    pub fn time<F>(&mut self, metric: &str, callable: F)
        where F: Fn()
    {
        let start = clock_ticks::precise_time_ms();
        callable();
        let end = clock_ticks::precise_time_ms();
        let data = self.prepare(format!("{}:{}|ms", metric, end - start));
        self.send(data);
    }

    fn prepare<T: AsRef<str>>(&self, data: T) -> String {
        format!("{}.{}", self.prefix, data.as_ref())
    }

    /// Send data along the UDP socket.
    fn send(&mut self, data: String) {
        let _ = self.socket.send_to(data.as_bytes(), self.server_address);
    }

    pub fn pipeline(self) -> Pipeline {
        Pipeline::new(self)
    }
}

pub struct Pipeline {
    client: Client,
    stats: VecDeque<String>,
    max_udp_size: usize,
}

impl Pipeline {
    fn new(client: Client) -> Pipeline {
        Pipeline {
            client: client,
            stats: VecDeque::new(),
            max_udp_size: 512,
        }
    }

    /// Set max UDP packet size
    ///
    /// ```ignore
    /// let mut pipe = client.pipeline();
    /// pipe.set_max_udp_size(128);
    /// pipe.send();
    /// ```
    pub fn set_max_udp_size(&mut self, max_udp_size: usize) {
        self.max_udp_size = max_udp_size;
    }

    /// Increment a metric by 1
    ///
    /// ```ignore
    /// # Increment a given metric by 1.
    /// pipe = client.pipeline();
    /// pipe.incr("metric.completed");
    /// pipe.send();
    /// ```
    ///
    /// This modifies a counter with an effective sampling
    /// rate of 1.0.
    pub fn incr(&mut self, metric: &str) {
        self.count(metric, 1.0);
    }

    /// Decrement a metric by -1
    ///
    /// ```ignore
    /// # Decrement a given metric by 1
    /// pipe = client.pipeline();
    /// pipe.decr("metric.completed");
    /// pipe.send();
    /// ```
    ///
    /// This modifies a counter with an effective sampling
    /// rate of 1.0.
    pub fn decr(&mut self, metric: &str) {
        self.count(metric, -1.0);
    }

    /// Modify a counter by `value`.
    ///
    /// Will increment or decrement a counter by `value` with
    /// a sampling rate of 1.0.
    ///
    /// ```ignore
    /// # Increment by 12
    /// pipe = client.pipeline();
    /// pipe.count("metric.completed", 12);
    /// pipe.send();
    /// ```
    pub fn count(&mut self, metric: &str, value: f64) {
        let data = self.client.prepare(format!("{}:{}|c", metric, value));
        self.stats.push_back(data);
    }

    /// Modify a counter by `value` only x% of the time.
    ///
    /// Will increment or decrement a counter by `value` with
    /// a custom sampling rate.
    ///
    ///
    /// ```ignore
    /// # Increment by 4 50% of the time.
    /// pipe = client.pipeline();
    /// pipe.sampled_count("metric.completed", 4, 0.5);
    /// pipe.send();
    /// ```
    pub fn sampled_count(&mut self, metric: &str, value: f64, rate: f64) {
        if rand::random::<f64>() < rate {
            return;
        }
        let data = self.client.prepare(format!("{}:{}|c", metric, value));
        self.stats.push_back(data);
    }

    /// Set a gauge value.
    ///
    /// ```ignore
    /// # set a gauge to 9001
    /// pipe = client.pipeline();
    /// pipe.gauge("power_level.observed", 9001);
    /// pipe.send();
    /// ```
    pub fn gauge(&mut self, metric: &str, value: f64) {
        let data = self.client.prepare(format!("{}:{}|g", metric, value));
        self.stats.push_back(data);
    }

    /// Send a timer value.
    ///
    /// The value is expected to be in ms.
    ///
    /// ```ignore
    /// # pass a duration value
    /// pipe = client.pipeline();
    /// pipe.timer("response.duration", 10.123);
    /// pipe.send();
    /// ```
    pub fn timer(&mut self, metric: &str, value: f64) {
        let data = self.client.prepare(format!("{}:{}|ms", metric, value));
        self.stats.push_back(data);
    }

    /// Time a block of code.
    ///
    /// The passed closure will be timed and executed. The block's
    /// duration will be sent as a metric.
    ///
    /// ```ignore
    /// # pass a duration value
    /// pipe = client.pipeline();
    /// pipe.time("response.duration", || {
    ///   # Your code here.
    /// });
    /// pipe.send();
    /// ```
    pub fn time<F>(&mut self, metric: &str, callable: F)
        where F: Fn()
    {
        let start = clock_ticks::precise_time_ms();
        callable();
        let end = clock_ticks::precise_time_ms();
        let data = self.client.prepare(format!("{}:{}|ms", metric, end - start));
        self.stats.push_back(data);
    }

    /// Send data along the UDP socket.
    pub fn send(&mut self) {
        let mut _data = String::new();
        if let Some(data) = self.stats.pop_front() {
            _data = _data + &data;
            while !self.stats.is_empty() {
                let stat = self.stats.pop_front().unwrap();
                if data.len() + stat.len() + 1 > self.max_udp_size {
                    self.client.send(_data.clone());
                    _data.clear();
                    _data = _data + &stat;
                } else {
                    _data = _data + "\n";
                    _data = _data +&stat;
                }
            }
        }
        if !_data.is_empty() {
            self.client.send(_data);
        }
    }
}

#[cfg(test)]
mod test {
    extern crate rand;
    use super::*;
    use std::sync::mpsc::sync_channel;
    use std::net::{UdpSocket, SocketAddr};
    use std::str::FromStr;
    use self::rand::distributions::{IndependentSample, Range};
    use std::str;
    use std::thread;

    static PORT: u16 = 8125;

    // Generates random ports.
    // Having random ports helps tests not collide over
    // shared ports.
    fn next_test_ip4() -> String {
        let range = Range::new(0, 1000);
        let mut rng = rand::thread_rng();
        let port = PORT + range.ind_sample(&mut rng);
        format!("127.0.0.1:{}", port).to_string()
    }

    // Makes a udpsocket that acts as a statsd server.
    fn make_server(host: &str) -> UdpSocket {
        let addr = SocketAddr::from_str(host.as_ref()).unwrap();
        let server = UdpSocket::bind(addr).ok().unwrap();
        server
    }

    fn server_recv(server: UdpSocket) -> String {
        let (serv_tx, serv_rx) = sync_channel(1);
        let _t = thread::spawn(move || {
            let mut buf = [0; 128];
            let (len, _) = match server.recv_from(&mut buf) {
                Ok(r) => r,
                Err(_) => panic!("No response from test server."),
            };
            drop(server);
            let bytes = Vec::from(&buf[0..len]);
            serv_tx.send(bytes).unwrap();
        });

        let bytes = serv_rx.recv().ok().unwrap();
        str::from_utf8(&bytes).unwrap().to_string()
    }

    #[test]
    fn test_sending_gauge() {
        let host = next_test_ip4();
        let server = make_server(host.as_ref());
        let mut client = Client::new(host.as_ref(), "myapp").unwrap();

        client.gauge("metric", 9.1);

        let response = server_recv(server);
        assert_eq!("myapp.metric:9.1|g", response);
    }

    #[test]
    fn test_sending_incr() {
        let host = next_test_ip4();
        let server = make_server(host.as_ref());
        let mut client = Client::new(host.as_ref(), "myapp").unwrap();

        client.incr("metric");

        let response = server_recv(server);
        assert_eq!("myapp.metric:1|c", response);
    }

    #[test]
    fn test_sending_decr() {
        let host = next_test_ip4();
        let server = make_server(host.as_ref());
        let mut client = Client::new(host.as_ref(), "myapp").unwrap();

        client.decr("metric");

        let response = server_recv(server);
        assert_eq!("myapp.metric:-1|c", response);
    }

    #[test]
    fn test_sending_count() {
        let host = next_test_ip4();
        let server = make_server(host.as_ref());
        let mut client = Client::new(host.as_ref(), "myapp").unwrap();

        client.count("metric", 12.2);

        let response = server_recv(server);
        assert_eq!("myapp.metric:12.2|c", response);
    }

    #[test]
    fn test_sending_timer() {
        let host = next_test_ip4();
        let server = make_server(host.as_ref());
        let mut client = Client::new(host.as_ref(), "myapp").unwrap();

        client.timer("metric", 21.39);

        let response = server_recv(server);
        assert_eq!("myapp.metric:21.39|ms", response);
    }

    #[test]
    fn test_pipeline_sending_gauge() {
        let host = next_test_ip4();
        let server = make_server(host.as_ref());
        let client = Client::new(host.as_ref(), "myapp").unwrap();
        let mut pipeline = client.pipeline();
        pipeline.gauge("metric", 9.1);
        pipeline.send();

        let response = server_recv(server);
        assert_eq!("myapp.metric:9.1|g", response);
    }

    #[test]
    fn test_pipeline_sending_multiple_data() {
        let host = next_test_ip4();
        let server = make_server(host.as_ref());
        let client = Client::new(host.as_ref(), "myapp").unwrap();
        let mut pipeline = client.pipeline();
        pipeline.gauge("metric", 9.1);
        pipeline.count("metric", 12.2);
        pipeline.send();

        let response = server_recv(server);
        assert_eq!("myapp.metric:9.1|g\nmyapp.metric:12.2|c", response);
    }

    #[test]
    fn test_pipeline_set_max_udp_size() {
        let host = next_test_ip4();
        let server = make_server(host.as_ref());
        let client = Client::new(host.as_ref(), "myapp").unwrap();
        let mut pipeline = client.pipeline();
        pipeline.set_max_udp_size(20);
        pipeline.gauge("metric", 9.1);
        pipeline.count("metric", 12.2);
        pipeline.send();

        let response = server_recv(server);
        assert_eq!("myapp.metric:9.1|g", response);
    }
}
<commit_msg>Make pipeline take a client in send()<commit_after>use std::net::{UdpSocket, SocketAddr};
use std::io::Error;
use std::str::FromStr;
use std::net::AddrParseError;
use std::collections::VecDeque;

extern crate clock_ticks;
extern crate rand;

#[derive(Debug)]
pub enum StatsdError {
    IoError(Error),
    AddrParseError(String),
}

impl From<AddrParseError> for StatsdError {
    fn from(_: AddrParseError) -> StatsdError {
        StatsdError::AddrParseError("Address parsing error".to_string())
    }
}

impl From<Error> for StatsdError {
    fn from(err: Error) -> StatsdError {
        StatsdError::IoError(err)
    }
}

/// Client socket for statsd servers.
///
/// After creating a metric you can use `Client`
/// to send metrics to the configured statsd server
///
/// # Example
///
/// Creating a client and sending metrics is easy.
///
/// ```ignore
/// use statsd::client::Client;
///
/// let client = Client::new("127.0.0.1:8125", "myapp.");
/// client.incr("some.metric.completed");
/// ```
pub struct Client {
    socket: UdpSocket,
    server_address: SocketAddr,
    prefix: String,
}

impl Client {
    /// Construct a new statsd client given an host/port & prefix
    pub fn new(host: &str, prefix: &str) -> Result<Client, StatsdError> {
        // Bind to a generic port as we'll only be writing on this
        // socket.
        let client_address = try!(SocketAddr::from_str("0.0.0.0:0"));
        let socket = try!(UdpSocket::bind(client_address));

        let server_address = try!(SocketAddr::from_str(host));
        Ok(Client {
            socket: socket,
            prefix: prefix.to_string(),
            server_address: server_address,
        })
    }

    /// Increment a metric by 1
    ///
    /// ```ignore
    /// # Increment a given metric by 1.
    /// client.incr("metric.completed");
    /// ```
    ///
    /// This modifies a counter with an effective sampling
    /// rate of 1.0.
    pub fn incr(&mut self, metric: &str) {
        self.count(metric, 1.0);
    }

    /// Decrement a metric by -1
    ///
    /// ```ignore
    /// # Decrement a given metric by 1
    /// client.decr("metric.completed");
    /// ```
    ///
    /// This modifies a counter with an effective sampling
    /// rate of 1.0.
    pub fn decr(&mut self, metric: &str) {
        self.count(metric, -1.0);
    }

    /// Modify a counter by `value`.
    ///
    /// Will increment or decrement a counter by `value` with
    /// a sampling rate of 1.0.
    ///
    /// ```ignore
    /// // Increment by 12
    /// client.count("metric.completed", 12.0);
    /// ```
    pub fn count(&mut self, metric: &str, value: f64) {
        let data = self.prepare(format!("{}:{}|c", metric, value));
        self.send(data);
    }

    /// Modify a counter by `value` only x% of the time.
    ///
    /// Will increment or decrement a counter by `value` with
    /// a custom sampling rate.
    ///
    ///
    /// ```ignore
    /// // Increment by 4 50% of the time.
    /// client.sampled_count("metric.completed", 4, 0.5);
    /// ```
    pub fn sampled_count(&mut self, metric: &str, value: f64, rate: f64) {
        if rand::random::<f64>() < rate {
            return;
        }
        let data = self.prepare(format!("{}:{}|c", metric, value));
        self.send(data);
    }

    /// Set a gauge value.
    ///
    /// ```ignore
    /// // set a gauge to 9001
    /// client.gauge("power_level.observed", 9001.0);
    /// ```
    pub fn gauge(&mut self, metric: &str, value: f64) {
        let data = self.prepare(format!("{}:{}|g", metric, value));
        self.send(data);
    }

    /// Send a timer value.
    ///
    /// The value is expected to be in ms.
    ///
    /// ```ignore
    /// // pass a duration value
    /// client.timer("response.duration", 10.123);
    /// ```
    pub fn timer(&mut self, metric: &str, value: f64) {
        let data = self.prepare(format!("{}:{}|ms", metric, value));
        self.send(data);
    }

    /// Time a block of code.
    ///
    /// The passed closure will be timed and executed. The block's
    /// duration will be sent as a metric.
    ///
    /// ```ignore
    /// // pass a duration value
    /// client.time("response.duration", || {
    ///   // Your code here.
    /// });
    /// ```
    pub fn time<F>(&mut self, metric: &str, callable: F)
        where F: Fn()
    {
        let start = clock_ticks::precise_time_ms();
        callable();
        let end = clock_ticks::precise_time_ms();
        let data = self.prepare(format!("{}:{}|ms", metric, end - start));
        self.send(data);
    }

    fn prepare<T: AsRef<str>>(&self, data: T) -> String {
        format!("{}.{}", self.prefix, data.as_ref())
    }

    /// Send data along the UDP socket.
    fn send(&mut self, data: String) {
        let _ = self.socket.send_to(data.as_bytes(), self.server_address);
    }

    /// Get a pipeline struct that allows optimizes the number of UDP
    /// packets used to send multiple metrics
    ///
    /// ```ignore
    /// let mut pipeline = client.pipeline();
    /// pipeline.incr("some.metric", 1);
    /// pipeline.incr("other.metric", 1);
    /// pipeline.send(&client);
    /// ```
    pub fn pipeline(&self) -> Pipeline {
        Pipeline::new()
    }
}

pub struct Pipeline {
    stats: VecDeque<String>,
    max_udp_size: usize,
}

impl Pipeline {
    pub fn new() -> Pipeline {
        Pipeline {
            stats: VecDeque::new(),
            max_udp_size: 512,
        }
    }

    /// Set max UDP packet size
    ///
    /// ```
    /// use statsd::client::Pipeline;
    ///
    /// let mut pipe = Pipeline::new();
    /// pipe.set_max_udp_size(128);
    /// ```
    pub fn set_max_udp_size(&mut self, max_udp_size: usize) {
        self.max_udp_size = max_udp_size;
    }

    /// Increment a metric by 1
    ///
    /// ```
    /// use statsd::client::Pipeline;
    ///
    /// let mut pipe = Pipeline::new();
    /// // Increment a given metric by 1.
    /// pipe.incr("metric.completed");
    /// ```
    ///
    /// This modifies a counter with an effective sampling
    /// rate of 1.0.
    pub fn incr(&mut self, metric: &str) {
        self.count(metric, 1.0);
    }

    /// Decrement a metric by -1
    ///
    /// ```
    /// use statsd::client::Pipeline;
    ///
    /// let mut pipe = Pipeline::new();
    /// // Decrement a given metric by 1
    /// pipe.decr("metric.completed");
    /// ```
    ///
    /// This modifies a counter with an effective sampling
    /// rate of 1.0.
    pub fn decr(&mut self, metric: &str) {
        self.count(metric, -1.0);
    }

    /// Modify a counter by `value`.
    ///
    /// Will increment or decrement a counter by `value` with
    /// a sampling rate of 1.0.
    ///
    /// ```
    /// use statsd::client::Pipeline;
    ///
    /// let mut pipe = Pipeline::new();
    /// // Increment by 12
    /// pipe.count("metric.completed", 12.0);
    /// ```
    pub fn count(&mut self, metric: &str, value: f64) {
        let data = format!("{}:{}|c", metric, value);
        self.stats.push_back(data);
    }

    /// Modify a counter by `value` only x% of the time.
    ///
    /// Will increment or decrement a counter by `value` with
    /// a custom sampling rate.
    ///
    /// ```
    /// use statsd::client::Pipeline;
    ///
    /// let mut pipe = Pipeline::new();
    /// // Increment by 4 50% of the time.
    /// pipe.sampled_count("metric.completed", 4.0, 0.5);
    /// ```
    pub fn sampled_count(&mut self, metric: &str, value: f64, rate: f64) {
        if rand::random::<f64>() < rate {
            return;
        }
        let data = format!("{}:{}|c", metric, value);
        self.stats.push_back(data);
    }

    /// Set a gauge value.
    ///
    /// ```
    /// use statsd::client::Pipeline;
    ///
    /// let mut pipe = Pipeline::new();
    /// // set a gauge to 9001
    /// pipe.gauge("power_level.observed", 9001.0);
    /// ```
    pub fn gauge(&mut self, metric: &str, value: f64) {
        let data = format!("{}:{}|g", metric, value);
        self.stats.push_back(data);
    }

    /// Send a timer value.
    ///
    /// The value is expected to be in ms.
    ///
    /// ```
    /// use statsd::client::Pipeline;
    ///
    /// let mut pipe = Pipeline::new();
    /// // pass a duration value
    /// pipe.timer("response.duration", 10.123);
    /// ```
    pub fn timer(&mut self, metric: &str, value: f64) {
        let data = format!("{}:{}|ms", metric, value);
        self.stats.push_back(data);
    }

    /// Time a block of code.
    ///
    /// The passed closure will be timed and executed. The block's
    /// duration will be sent as a metric.
    ///
    /// ```
    /// use statsd::client::Pipeline;
    ///
    /// let mut pipe = Pipeline::new();
    /// // pass a duration value
    /// pipe.time("response.duration", || {
    ///   // Your code here.
    /// });
    /// ```
    pub fn time<F>(&mut self, metric: &str, callable: F)
        where F: Fn()
    {
        let start = clock_ticks::precise_time_ms();
        callable();
        let end = clock_ticks::precise_time_ms();
        let data = format!("{}:{}|ms", metric, end - start);
        self.stats.push_back(data);
    }

    /// Send data along the UDP socket.
    pub fn send(&mut self, mut client: Client) {
        let mut _data = String::new();
        if let Some(data) = self.stats.pop_front() {
            _data = _data + client.prepare(&data).as_ref();
            while !self.stats.is_empty() {
                let stat = client.prepare(self.stats.pop_front().unwrap());
                if data.len() + stat.len() + 1 > self.max_udp_size {
                    client.send(_data.clone());
                    _data.clear();
                    _data = _data + &stat;
                } else {
                    _data = _data + "\n";
                    _data = _data +&stat;
                }
            }
        }
        if !_data.is_empty() {
            client.send(_data);
        }
    }
}

#[cfg(test)]
mod test {
    extern crate rand;
    use super::*;
    use std::sync::mpsc::sync_channel;
    use std::net::{UdpSocket, SocketAddr};
    use std::str::FromStr;
    use self::rand::distributions::{IndependentSample, Range};
    use std::str;
    use std::thread;

    static PORT: u16 = 8125;

    // Generates random ports.
    // Having random ports helps tests not collide over
    // shared ports.
    fn next_test_ip4() -> String {
        let range = Range::new(0, 1000);
        let mut rng = rand::thread_rng();
        let port = PORT + range.ind_sample(&mut rng);
        format!("127.0.0.1:{}", port).to_string()
    }

    // Makes a udpsocket that acts as a statsd server.
    fn make_server(host: &str) -> UdpSocket {
        let addr = SocketAddr::from_str(host.as_ref()).unwrap();
        let server = UdpSocket::bind(addr).ok().unwrap();
        server
    }

    fn server_recv(server: UdpSocket) -> String {
        let (serv_tx, serv_rx) = sync_channel(1);
        let _t = thread::spawn(move || {
            let mut buf = [0; 128];
            let (len, _) = match server.recv_from(&mut buf) {
                Ok(r) => r,
                Err(_) => panic!("No response from test server."),
            };
            drop(server);
            let bytes = Vec::from(&buf[0..len]);
            serv_tx.send(bytes).unwrap();
        });

        let bytes = serv_rx.recv().ok().unwrap();
        str::from_utf8(&bytes).unwrap().to_string()
    }

    #[test]
    fn test_sending_gauge() {
        let host = next_test_ip4();
        let server = make_server(host.as_ref());
        let mut client = Client::new(host.as_ref(), "myapp").unwrap();

        client.gauge("metric", 9.1);

        let response = server_recv(server);
        assert_eq!("myapp.metric:9.1|g", response);
    }

    #[test]
    fn test_sending_incr() {
        let host = next_test_ip4();
        let server = make_server(host.as_ref());
        let mut client = Client::new(host.as_ref(), "myapp").unwrap();

        client.incr("metric");

        let response = server_recv(server);
        assert_eq!("myapp.metric:1|c", response);
    }

    #[test]
    fn test_sending_decr() {
        let host = next_test_ip4();
        let server = make_server(host.as_ref());
        let mut client = Client::new(host.as_ref(), "myapp").unwrap();

        client.decr("metric");

        let response = server_recv(server);
        assert_eq!("myapp.metric:-1|c", response);
    }

    #[test]
    fn test_sending_count() {
        let host = next_test_ip4();
        let server = make_server(host.as_ref());
        let mut client = Client::new(host.as_ref(), "myapp").unwrap();

        client.count("metric", 12.2);

        let response = server_recv(server);
        assert_eq!("myapp.metric:12.2|c", response);
    }

    #[test]
    fn test_sending_timer() {
        let host = next_test_ip4();
        let server = make_server(host.as_ref());
        let mut client = Client::new(host.as_ref(), "myapp").unwrap();

        client.timer("metric", 21.39);

        let response = server_recv(server);
        assert_eq!("myapp.metric:21.39|ms", response);
    }

    #[test]
    fn test_pipeline_sending_gauge() {
        let host = next_test_ip4();
        let server = make_server(host.as_ref());
        let client = Client::new(host.as_ref(), "myapp").unwrap();
        let mut pipeline = client.pipeline();
        pipeline.gauge("metric", 9.1);
        pipeline.send(client);

        let response = server_recv(server);
        assert_eq!("myapp.metric:9.1|g", response);
    }

    #[test]
    fn test_pipeline_sending_multiple_data() {
        let host = next_test_ip4();
        let server = make_server(host.as_ref());
        let client = Client::new(host.as_ref(), "myapp").unwrap();
        let mut pipeline = client.pipeline();
        pipeline.gauge("metric", 9.1);
        pipeline.count("metric", 12.2);
        pipeline.send(client);

        let response = server_recv(server);
        assert_eq!("myapp.metric:9.1|g\nmyapp.metric:12.2|c", response);
    }

    #[test]
    fn test_pipeline_set_max_udp_size() {
        let host = next_test_ip4();
        let server = make_server(host.as_ref());
        let client = Client::new(host.as_ref(), "myapp").unwrap();
        let mut pipeline = client.pipeline();
        pipeline.set_max_udp_size(20);
        pipeline.gauge("metric", 9.1);
        pipeline.count("metric", 12.2);
        pipeline.send(client);

        let response = server_recv(server);
        assert_eq!("myapp.metric:9.1|g", response);
    }
}
<|endoftext|>