<commit_before>use std::collections::HashMap;

pub fn puzzle(input: &str) -> usize {
    0
}

pub enum BotOrOutput {
    Bot,
    Output
}

impl<'a> From<&'a str> for BotOrOutput {
    fn from(s: &'a str) -> BotOrOutput {
        match s {
            "bot" => BotOrOutput::Bot,
            "output" => BotOrOutput::Output,
            _ => panic!("Unknown string given to BotOrOutput"),
        }
    }
}

pub struct Command {
    low_value_type: BotOrOutput,
    low_value_key: usize,
    high_value_type: BotOrOutput,
    high_value_key: usize,
}

pub struct BotCommandCenter {
    bots: HashMap<usize, Bot>,
    outputs: HashMap<usize, Vec<usize>>,
    saved_commands: HashMap<usize, Command>,
    bots_to_check: Vec<usize>,
}

impl BotCommandCenter {
    pub fn new() -> BotCommandCenter {
        BotCommandCenter {
            bots: HashMap::new(),
            outputs: HashMap::new(),
            saved_commands: HashMap::new(),
            bots_to_check: vec![],
        }
    }

    pub fn exec_command(&mut self, input: &str) {
        println!("COMMAND: {}", input);
        let pieces: Vec<&str> = input.split_whitespace().collect();

        if pieces[0] == "value" {
            self.value_to_bot(
                pieces[5].parse().expect("can't parse bot key"),
                pieces[1].parse().expect("can't parse chip value")
            );
            self.process_bots();
        } else if pieces[0] == "bot" {
            self.command_to_bot(
                pieces[1].parse().expect("can't parse bot key"),
                pieces[5],
                pieces[6].parse().expect("can't parse low key"),
                pieces[10],
                pieces[11].parse().expect("can't parse high key"),
            );
        }
    }

    pub fn value_to_bot(&mut self, bot_key: usize, value: usize) {
        println!("COMMAND CTR sending value {} to bot {}", value, bot_key);
        self.bots
            .entry(bot_key)
            .or_insert(Bot::new(bot_key))
            .receive_chip(value);
        self.bots_to_check.push(bot_key);
    }

    pub fn value_to_output(&mut self, output_key: usize, value: usize) {
        println!("COMMAND CTR sending value {} to output {}", value, output_key);
        self.outputs
            .entry(output_key)
            .or_insert(vec![])
            .push(value);
    }

    pub fn get_next_bot_to_check(&mut self) -> usize {
        let check_bot_key = self.bots_to_check.iter().next().unwrap();
        *check_bot_key
    }

    pub fn bot_has_two_chips(&mut self, check_bot_key: usize) -> bool {
        let bot = self.bots.entry(check_bot_key)
                           .or_insert(Bot::new(check_bot_key));
        bot.has_two_chips()
    }

    pub fn bot_low_high(&mut self, check_bot_key: usize) -> (usize, usize) {
        let bot = self.bots.entry(check_bot_key)
                           .or_insert(Bot::new(check_bot_key));
        bot.low_high()
    }

    pub fn process_bots(&mut self) {
        while !self.bots_to_check.is_empty() {
            let check_bot_key = self.get_next_bot_to_check();
            if self.bot_has_two_chips(check_bot_key) {
                let command = self.saved_commands.remove(&check_bot_key)
                    .expect("no saved command for a bot with two chips");
                let (low_value, high_value) = self.bot_low_high(check_bot_key);

                match command.low_value_type {
                    BotOrOutput::Bot => self.value_to_bot(
                        command.low_value_key,
                        low_value
                    ),
                    BotOrOutput::Output => self.value_to_output(
                        command.low_value_key,
                        low_value
                    ),
                }

                match command.high_value_type {
                    BotOrOutput::Bot => self.value_to_bot(
                        command.high_value_key,
                        high_value
                    ),
                    BotOrOutput::Output => self.value_to_output(
                        command.high_value_key,
                        high_value
                    ),
                }
            }
        }
    }

    pub fn command_to_bot(&mut self, bot_key: usize,
                              low_bot_or_output: &str, low_key: usize,
                              high_bot_or_output: &str, high_key: usize) {

        let command = Command {
            low_value_type: low_bot_or_output.into(),
            low_value_key: low_key,
            high_value_type: high_bot_or_output.into(),
            high_value_key: high_key,
        };
        self.saved_commands.insert(bot_key, command);
    }
}

pub struct Bot {
    key: usize,
    chip1: Option<usize>,
    chip2: Option<usize>,
}

impl Bot {
    pub fn new(key: usize) -> Bot {
        Bot {
            key: key,
            chip1: None, chip2: None,
        }
    }

    pub fn has_two_chips(&self) -> bool {
        match (self.chip1, self.chip2) {
            (Some(_), Some(_)) => true,
            _ => false,
        }
    }

    pub fn receive_chip(&mut self, chip: usize) {
        if self.chip1.is_none() {
            println!("bot {}, chip1 = {}", self.key, chip);
            self.chip1 = Some(chip);
        } else if self.chip2.is_none() {
            println!("bot {}, chip2 = {}", self.key, chip);
            self.chip2 = Some(chip);
        } else {
            panic!("Cannot hold more than two chips");
        }
    }

    pub fn low_high(&mut self) -> (usize, usize) {
        let (low, high) = match (self.chip1, self.chip2) {
            (Some(c1), Some(c2)) => {
                if c1 < c2 {
                    (c1, c2)
                } else {
                    (c2, c1)
                }
            }
            _ => panic!("Tried to get low and high from bot, something is wrong"),
        };
        self.chip1 = None;
        self.chip2 = None;
        (low, high)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::collections::HashMap;

    #[test]
    fn new_bot_does_not_have_two_chips() {
        let bot = Bot::new(0);
        assert!( ! bot.has_two_chips() );
    }

    #[test]
    fn bot_gets_a_chip_still_not_two() {
        let mut bot = Bot::new(0);
        bot.receive_chip(1);
        assert!( ! bot.has_two_chips() );
    }

    #[test]
    fn bot_gets_two_chips() {
        let mut bot = Bot::new(0);
        bot.receive_chip(1);
        bot.receive_chip(4);
        assert!(bot.has_two_chips());
    }

    #[test]
    fn test_sample() {
        let mut br = BotCommandCenter::new();

        br.exec_command("value 5 goes to bot 2");
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        br.exec_command("value 3 goes to bot 1");
        br.exec_command("bot 1 gives low to output 1 and high to bot 0");
        br.exec_command("bot 0 gives low to output 2 and high to output 0");
        br.exec_command("value 2 goes to bot 2");

        assert_eq!(
            br.outputs.get(&0),
            Some(&vec![5])
        );

        assert_eq!(
            br.outputs.get(&1),
            Some(&vec![2])
        );

        assert_eq!(
            br.outputs.get(&2),
            Some(&vec![3])
        );
    }
}
<commit_msg>Tests are passing again<commit_after>use std::collections::HashMap;

pub fn puzzle(input: &str) -> usize {
    0
}

#[derive(Debug)]
pub enum BotOrOutput {
    Bot,
    Output
}

impl<'a> From<&'a str> for BotOrOutput {
    fn from(s: &'a str) -> BotOrOutput {
        match s {
            "bot" => BotOrOutput::Bot,
            "output" => BotOrOutput::Output,
            _ => panic!("Unknown string given to BotOrOutput"),
        }
    }
}

#[derive(Debug)]
pub struct Command {
    low_value_type: BotOrOutput,
    low_value_key: usize,
    high_value_type: BotOrOutput,
    high_value_key: usize,
}

pub struct BotCommandCenter {
    bots: HashMap<usize, Bot>,
    outputs: HashMap<usize, Vec<usize>>,
    saved_commands: HashMap<usize, Command>,
    bots_to_check: Vec<usize>,
}

impl BotCommandCenter {
    pub fn new() -> BotCommandCenter {
        BotCommandCenter {
            bots: HashMap::new(),
            outputs: HashMap::new(),
            saved_commands: HashMap::new(),
            bots_to_check: vec![],
        }
    }

    pub fn exec_command(&mut self, input: &str) {
        println!("COMMAND: {}", input);
        let pieces: Vec<&str> = input.split_whitespace().collect();

        if pieces[0] == "value" {
            self.value_to_bot(
                pieces[5].parse().expect("can't parse bot key"),
                pieces[1].parse().expect("can't parse chip value")
            );
            self.process_bots();
        } else if pieces[0] == "bot" {
            self.command_to_bot(
                pieces[1].parse().expect("can't parse bot key"),
                pieces[5],
                pieces[6].parse().expect("can't parse low key"),
                pieces[10],
                pieces[11].parse().expect("can't parse high key"),
            );
        }
    }

    pub fn value_to_bot(&mut self, bot_key: usize, value: usize) {
        println!("COMMAND CTR sending value {} to bot {}", value, bot_key);
        self.bots
            .entry(bot_key)
            .or_insert(Bot::new(bot_key))
            .receive_chip(value);
        self.bots_to_check.push(bot_key);
        println!("COMMAND CTR bots to check = {:?}", self.bots_to_check);
    }

    pub fn value_to_output(&mut self, output_key: usize, value: usize) {
        println!("COMMAND CTR sending value {} to output {}", value, output_key);
        self.outputs
            .entry(output_key)
            .or_insert(vec![])
            .push(value);
    }

    pub fn get_next_bot_to_check(&mut self) -> usize {
        self.bots_to_check.remove(0)
    }

    pub fn bot_has_two_chips(&mut self, check_bot_key: usize) -> bool {
        let bot = self.bots.entry(check_bot_key)
                           .or_insert(Bot::new(check_bot_key));
        bot.has_two_chips()
    }

    pub fn bot_low_high(&mut self, check_bot_key: usize) -> (usize, usize) {
        let bot = self.bots.entry(check_bot_key)
                           .or_insert(Bot::new(check_bot_key));
        bot.low_high()
    }

    pub fn process_bots(&mut self) {
        while !self.bots_to_check.is_empty() {
            println!("COMMAND CTR process_bots, {} bots to process", self.bots_to_check.len());
            let check_bot_key = self.get_next_bot_to_check();
            println!("COMMAND CTR processing bot {}", check_bot_key);
            if self.bot_has_two_chips(check_bot_key) {
                println!("COMMAND CTR found bot {} has two chips", check_bot_key);
                let command = self.saved_commands.remove(&check_bot_key)
                    .expect("no saved command for a bot with two chips");
                println!("COMMAND CTR found command: {:?}", command);
                let (low_value, high_value) = self.bot_low_high(check_bot_key);
                println!("COMMAND CTR found low = {}, high = {}", low_value, high_value);
                match command.low_value_type {
                    BotOrOutput::Bot => self.value_to_bot(
                        command.low_value_key,
                        low_value
                    ),
                    BotOrOutput::Output => self.value_to_output(
                        command.low_value_key,
                        low_value
                    ),
                }

                match command.high_value_type {
                    BotOrOutput::Bot => self.value_to_bot(
                        command.high_value_key,
                        high_value
                    ),
                    BotOrOutput::Output => self.value_to_output(
                        command.high_value_key,
                        high_value
                    ),
                }
            }
        }
        println!("COMMAND CTR bots_to_check is empty");
    }

    pub fn command_to_bot(&mut self, bot_key: usize,
                              low_bot_or_output: &str, low_key: usize,
                              high_bot_or_output: &str, high_key: usize) {

        let command = Command {
            low_value_type: low_bot_or_output.into(),
            low_value_key: low_key,
            high_value_type: high_bot_or_output.into(),
            high_value_key: high_key,
        };
        self.saved_commands.insert(bot_key, command);
    }
}

pub struct Bot {
    key: usize,
    chip1: Option<usize>,
    chip2: Option<usize>,
}

impl Bot {
    pub fn new(key: usize) -> Bot {
        Bot {
            key: key,
            chip1: None, chip2: None,
        }
    }

    pub fn has_two_chips(&self) -> bool {
        match (self.chip1, self.chip2) {
            (Some(_), Some(_)) => true,
            _ => false,
        }
    }

    pub fn receive_chip(&mut self, chip: usize) {
        if self.chip1.is_none() {
            println!("bot {}, chip1 = {}", self.key, chip);
            self.chip1 = Some(chip);
        } else if self.chip2.is_none() {
            println!("bot {}, chip2 = {}", self.key, chip);
            self.chip2 = Some(chip);
        } else {
            panic!("Cannot hold more than two chips");
        }
    }

    pub fn low_high(&mut self) -> (usize, usize) {
        let (low, high) = match (self.chip1, self.chip2) {
            (Some(c1), Some(c2)) => {
                if c1 < c2 {
                    (c1, c2)
                } else {
                    (c2, c1)
                }
            }
            _ => panic!("Tried to get low and high from bot, something is wrong"),
        };
        self.chip1 = None;
        self.chip2 = None;
        (low, high)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::collections::HashMap;

    #[test]
    fn new_bot_does_not_have_two_chips() {
        let bot = Bot::new(0);
        assert!( ! bot.has_two_chips() );
    }

    #[test]
    fn bot_gets_a_chip_still_not_two() {
        let mut bot = Bot::new(0);
        bot.receive_chip(1);
        assert!( ! bot.has_two_chips() );
    }

    #[test]
    fn bot_gets_two_chips() {
        let mut bot = Bot::new(0);
        bot.receive_chip(1);
        bot.receive_chip(4);
        assert!(bot.has_two_chips());
    }

    #[test]
    fn test_sample() {
        let mut br = BotCommandCenter::new();

        br.exec_command("value 5 goes to bot 2");
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        br.exec_command("value 3 goes to bot 1");
        br.exec_command("bot 1 gives low to output 1 and high to bot 0");
        br.exec_command("bot 0 gives low to output 2 and high to output 0");
        br.exec_command("value 2 goes to bot 2");

        assert_eq!(
            br.outputs.get(&0),
            Some(&vec![5])
        );

        assert_eq!(
            br.outputs.get(&1),
            Some(&vec![2])
        );

        assert_eq!(
            br.outputs.get(&2),
            Some(&vec![3])
        );
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2014  Josh Stone
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! # GitFS: a FUSE filesystem for Git objects

#![deny(missing_doc)]

#![feature(if_let)]

#![feature(phase)]
#[phase(plugin)]
extern crate probe;

extern crate fuse;
extern crate git2;
extern crate libc;
extern crate time;

use std::collections::hashmap;
use std::default::Default;
use std::io;
use std::u64;

mod inode;
mod blob;
mod tree;
mod reference;
mod root;

static TTY: time::Timespec = time::Timespec { sec: 1, nsec: 0 };

/// The main object implementing a FUSE filesystem.
pub struct GitFS<'a> {
    repo: git2::Repository,
    epoch: time::Timespec,
    uid: u32,
    gid: u32,
    mapper: inode::InodeMapper,
    inodes: inode::InodeContainer<'a>,
    mountdir: Option<DirHandle>,
}

impl<'a> GitFS<'a> {
    /// Create a GitFS referencing the given GIT_DIR.
    pub fn new(git_dir: &Path) -> Result<GitFS<'a>, git2::Error> {
        Ok(GitFS {
            repo: try!(git2::Repository::open(git_dir)),
            epoch: time::get_time(),
            uid: unsafe { libc::getuid() },
            gid: unsafe { libc::getgid() },
            mapper: Default::default(),
            inodes: Default::default(),
            mountdir: None,
        })
    }

    /// Get the resolved GIT_DIR.
    pub fn git_dir(&self) -> Path {
        self.repo.path()
    }

    fn mount_options(&self) -> Vec<u8> {
        let mut options = b"-oro,default_permissions,fsname=".to_vec();
        options.push_all(self.repo.path().as_vec()); // FIXME escape commas?
        options
    }

    /// Mount the filesystem and wait until the path is unmounted, e.g. with the command
    /// `fusermount -u PATH`.
    pub fn mount(mut self, mountpoint: &Path) {
        // Create/remove the mount point if it doesn't exist
        self.mountdir = DirHandle::new(mountpoint);

        let options = self.mount_options();
        fuse::mount(self, mountpoint, &[options.as_slice()])
    }

    /// Mount the filesystem in the background.  It will remain mounted until the returned session
    /// object is dropped, or an external umount is issued.
    pub fn spawn_mount(mut self, mountpoint: &Path) -> fuse::BackgroundSession {
        // Create/remove the mount point if it doesn't exist
        self.mountdir = DirHandle::new(mountpoint);

        let options = self.mount_options();
        fuse::spawn_mount(self, mountpoint, &[options.as_slice()])
    }

    fn defattr(&self, ino: u64) -> fuse::FileAttr {
        fuse::FileAttr {
            ino: ino,
            size: 0,
            blocks: 0,
            atime: self.epoch,
            mtime: self.epoch,
            ctime: self.epoch,
            crtime: self.epoch,
            kind: io::TypeUnknown,
            perm: Default::default(),
            nlink: 1,
            uid: self.uid,
            gid: self.gid,
            rdev: 0,
            flags: 0,
        }
    }
}

impl<'a> fuse::Filesystem for GitFS<'a> {
    fn init (&mut self, _req: &fuse::Request) -> Result<(), libc::c_int> {
        let root_ino = self.mapper.new_ino();
        let refs_ino = self.mapper.new_ino();
        assert_eq!(fuse::FUSE_ROOT_ID, root_ino);

        let root = root::Root::new(&self.repo, inode::Ino(refs_ino));
        self.inodes.insert(root_ino, root);

        let refs = reference::RefDir::new();
        self.inodes.insert(refs_ino, refs);

        Ok(())
    }

    fn lookup(&mut self, _req: &fuse::Request, parent: u64, name: &PosixPath,
              reply: fuse::ReplyEntry) {
        probe!(gitfs, lookup, parent, name.to_c_str().as_ptr());

        let repo = &self.repo;
        let id = {
            let inode = self.inodes.find_mut(parent);
            match inode.and_then(|inode| inode.lookup(repo, name)) {
                Ok(id) => id,
                Err(rc) => return reply.error(rc),
            }
        };
        let ino = self.mapper.get_ino(id);

        if let hashmap::Vacant(entry) = self.inodes.entry(ino) {
            if let Some(oid) = self.mapper.get_oid(ino) {
                if let Some(inode) = inode::new_inode(&self.repo, oid) {
                    entry.set(inode);
                }
            }
        }

        let attr = self.defattr(ino);
        let inode = self.inodes.find_mut(ino);
        match inode.and_then(|inode| inode.getattr(repo, attr)) {
            Ok(attr) => reply.entry(&TTY, &attr, 1),
            Err(rc) => reply.error(rc),
        }
    }

    fn forget (&mut self, _req: &fuse::Request, _ino: u64, _nlookup: uint) {
        probe!(gitfs, forget, _ino, _nlookup);

        // TODO could probably drop Oid inodes, since they're easily recreated
    }

    fn getattr (&mut self, _req: &fuse::Request, ino: u64,
                reply: fuse::ReplyAttr) {
        probe!(gitfs, getattr, ino);

        let attr = self.defattr(ino);
        let repo = &self.repo;
        let inode = self.inodes.find_mut(ino);
        match inode.and_then(|inode| inode.getattr(repo, attr)) {
            Ok(attr) => reply.attr(&TTY, &attr),
            Err(rc) => reply.error(rc),
        }
    }

    fn open (&mut self, _req: &fuse::Request, ino: u64, flags: uint, reply: fuse::ReplyOpen) {
        probe!(gitfs, open, ino, flags);

        let repo = &self.repo;
        let inode = self.inodes.find_mut(ino);
        match inode.and_then(|inode| inode.open(repo, flags)) {
            Ok(flags) => reply.opened(0, flags),
            Err(rc) => reply.error(rc),
        }
    }
    fn read (&mut self, _req: &fuse::Request, ino: u64, _fh: u64, offset: u64, size: uint,
             reply: fuse::ReplyData) {
        probe!(gitfs, read, ino, offset, size);

        let repo = &self.repo;
        let inode = self.inodes.find_mut(ino);
        match inode.and_then(|inode| inode.read(repo, offset, size)) {
            Ok(data) => reply.data(data),
            Err(rc) => reply.error(rc),
        }
    }

    fn release (&mut self, _req: &fuse::Request, ino: u64, _fh: u64, _flags: uint,
                _lock_owner: u64, _flush: bool, reply: fuse::ReplyEmpty) {
        probe!(gitfs, release, ino);

        let repo = &self.repo;
        let inode = self.inodes.find_mut(ino);
        match inode.and_then(|inode| inode.release(repo)) {
            Ok(()) => reply.ok(),
            Err(rc) => reply.error(rc),
        }
    }

    fn readdir (&mut self, _req: &fuse::Request, ino: u64, _fh: u64, mut offset: u64,
                mut reply: fuse::ReplyDirectory) {
        probe!(gitfs, readdir, ino, offset);

        let mapper = &mut self.mapper;
        let repo = &self.repo;
        let inode = self.inodes.find_mut(ino);
        match inode.and_then(|inode| {
            if offset == 0 {
                offset += 1;
                reply.add(u64::MAX, offset, io::TypeDirectory, &PosixPath::new("."));
            }
            if offset == 1 {
                offset += 1;
                reply.add(u64::MAX, offset, io::TypeDirectory, &PosixPath::new(".."));
            }
            inode.readdir(repo, offset - 2, |id, kind, path| {
                offset += 1;
                reply.add(mapper.get_ino(id), offset, kind, path)
            })
        }) {
            Ok(()) => reply.ok(),
            Err(rc) => reply.error(rc),
        }
    }
}

/// Helper for mkdir, ensuring rmdir when dropped
struct DirHandle {
    path: Path,
}

impl DirHandle {
    fn new(path: &Path) -> Option<DirHandle> {
        io::fs::mkdir(path, io::USER_DIR).ok()
            .map(|()| DirHandle { path: path.clone() })
    }
}

impl Drop for DirHandle {
    fn drop(&mut self) {
        io::fs::rmdir(&self.path).ok();
    }
}
<commit_msg>Make TTY a const<commit_after>// Copyright (C) 2014  Josh Stone
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! # GitFS: a FUSE filesystem for Git objects

#![deny(missing_doc)]

#![feature(if_let)]

#![feature(phase)]
#[phase(plugin)]
extern crate probe;

extern crate fuse;
extern crate git2;
extern crate libc;
extern crate time;

use std::collections::hashmap;
use std::default::Default;
use std::io;
use std::u64;

mod inode;
mod blob;
mod tree;
mod reference;
mod root;

const TTY: time::Timespec = time::Timespec { sec: 1, nsec: 0 };

/// The main object implementing a FUSE filesystem.
pub struct GitFS<'a> {
    repo: git2::Repository,
    epoch: time::Timespec,
    uid: u32,
    gid: u32,
    mapper: inode::InodeMapper,
    inodes: inode::InodeContainer<'a>,
    mountdir: Option<DirHandle>,
}

impl<'a> GitFS<'a> {
    /// Create a GitFS referencing the given GIT_DIR.
    pub fn new(git_dir: &Path) -> Result<GitFS<'a>, git2::Error> {
        Ok(GitFS {
            repo: try!(git2::Repository::open(git_dir)),
            epoch: time::get_time(),
            uid: unsafe { libc::getuid() },
            gid: unsafe { libc::getgid() },
            mapper: Default::default(),
            inodes: Default::default(),
            mountdir: None,
        })
    }

    /// Get the resolved GIT_DIR.
    pub fn git_dir(&self) -> Path {
        self.repo.path()
    }

    fn mount_options(&self) -> Vec<u8> {
        let mut options = b"-oro,default_permissions,fsname=".to_vec();
        options.push_all(self.repo.path().as_vec()); // FIXME escape commas?
        options
    }

    /// Mount the filesystem and wait until the path is unmounted, e.g. with the command
    /// `fusermount -u PATH`.
    pub fn mount(mut self, mountpoint: &Path) {
        // Create/remove the mount point if it doesn't exist
        self.mountdir = DirHandle::new(mountpoint);

        let options = self.mount_options();
        fuse::mount(self, mountpoint, &[options.as_slice()])
    }

    /// Mount the filesystem in the background.  It will remain mounted until the returned session
    /// object is dropped, or an external umount is issued.
    pub fn spawn_mount(mut self, mountpoint: &Path) -> fuse::BackgroundSession {
        // Create/remove the mount point if it doesn't exist
        self.mountdir = DirHandle::new(mountpoint);

        let options = self.mount_options();
        fuse::spawn_mount(self, mountpoint, &[options.as_slice()])
    }

    fn defattr(&self, ino: u64) -> fuse::FileAttr {
        fuse::FileAttr {
            ino: ino,
            size: 0,
            blocks: 0,
            atime: self.epoch,
            mtime: self.epoch,
            ctime: self.epoch,
            crtime: self.epoch,
            kind: io::TypeUnknown,
            perm: Default::default(),
            nlink: 1,
            uid: self.uid,
            gid: self.gid,
            rdev: 0,
            flags: 0,
        }
    }
}

impl<'a> fuse::Filesystem for GitFS<'a> {
    fn init (&mut self, _req: &fuse::Request) -> Result<(), libc::c_int> {
        let root_ino = self.mapper.new_ino();
        let refs_ino = self.mapper.new_ino();
        assert_eq!(fuse::FUSE_ROOT_ID, root_ino);

        let root = root::Root::new(&self.repo, inode::Ino(refs_ino));
        self.inodes.insert(root_ino, root);

        let refs = reference::RefDir::new();
        self.inodes.insert(refs_ino, refs);

        Ok(())
    }

    fn lookup(&mut self, _req: &fuse::Request, parent: u64, name: &PosixPath,
              reply: fuse::ReplyEntry) {
        probe!(gitfs, lookup, parent, name.to_c_str().as_ptr());

        let repo = &self.repo;
        let id = {
            let inode = self.inodes.find_mut(parent);
            match inode.and_then(|inode| inode.lookup(repo, name)) {
                Ok(id) => id,
                Err(rc) => return reply.error(rc),
            }
        };
        let ino = self.mapper.get_ino(id);

        if let hashmap::Vacant(entry) = self.inodes.entry(ino) {
            if let Some(oid) = self.mapper.get_oid(ino) {
                if let Some(inode) = inode::new_inode(&self.repo, oid) {
                    entry.set(inode);
                }
            }
        }

        let attr = self.defattr(ino);
        let inode = self.inodes.find_mut(ino);
        match inode.and_then(|inode| inode.getattr(repo, attr)) {
            Ok(attr) => reply.entry(&TTY, &attr, 1),
            Err(rc) => reply.error(rc),
        }
    }

    fn forget (&mut self, _req: &fuse::Request, _ino: u64, _nlookup: uint) {
        probe!(gitfs, forget, _ino, _nlookup);

        // TODO could probably drop Oid inodes, since they're easily recreated
    }

    fn getattr (&mut self, _req: &fuse::Request, ino: u64,
                reply: fuse::ReplyAttr) {
        probe!(gitfs, getattr, ino);

        let attr = self.defattr(ino);
        let repo = &self.repo;
        let inode = self.inodes.find_mut(ino);
        match inode.and_then(|inode| inode.getattr(repo, attr)) {
            Ok(attr) => reply.attr(&TTY, &attr),
            Err(rc) => reply.error(rc),
        }
    }

    fn open (&mut self, _req: &fuse::Request, ino: u64, flags: uint, reply: fuse::ReplyOpen) {
        probe!(gitfs, open, ino, flags);

        let repo = &self.repo;
        let inode = self.inodes.find_mut(ino);
        match inode.and_then(|inode| inode.open(repo, flags)) {
            Ok(flags) => reply.opened(0, flags),
            Err(rc) => reply.error(rc),
        }
    }
    fn read (&mut self, _req: &fuse::Request, ino: u64, _fh: u64, offset: u64, size: uint,
             reply: fuse::ReplyData) {
        probe!(gitfs, read, ino, offset, size);

        let repo = &self.repo;
        let inode = self.inodes.find_mut(ino);
        match inode.and_then(|inode| inode.read(repo, offset, size)) {
            Ok(data) => reply.data(data),
            Err(rc) => reply.error(rc),
        }
    }

    fn release (&mut self, _req: &fuse::Request, ino: u64, _fh: u64, _flags: uint,
                _lock_owner: u64, _flush: bool, reply: fuse::ReplyEmpty) {
        probe!(gitfs, release, ino);

        let repo = &self.repo;
        let inode = self.inodes.find_mut(ino);
        match inode.and_then(|inode| inode.release(repo)) {
            Ok(()) => reply.ok(),
            Err(rc) => reply.error(rc),
        }
    }

    fn readdir (&mut self, _req: &fuse::Request, ino: u64, _fh: u64, mut offset: u64,
                mut reply: fuse::ReplyDirectory) {
        probe!(gitfs, readdir, ino, offset);

        let mapper = &mut self.mapper;
        let repo = &self.repo;
        let inode = self.inodes.find_mut(ino);
        match inode.and_then(|inode| {
            if offset == 0 {
                offset += 1;
                reply.add(u64::MAX, offset, io::TypeDirectory, &PosixPath::new("."));
            }
            if offset == 1 {
                offset += 1;
                reply.add(u64::MAX, offset, io::TypeDirectory, &PosixPath::new(".."));
            }
            inode.readdir(repo, offset - 2, |id, kind, path| {
                offset += 1;
                reply.add(mapper.get_ino(id), offset, kind, path)
            })
        }) {
            Ok(()) => reply.ok(),
            Err(rc) => reply.error(rc),
        }
    }
}

/// Helper for mkdir, ensuring rmdir when dropped
struct DirHandle {
    path: Path,
}

impl DirHandle {
    fn new(path: &Path) -> Option<DirHandle> {
        io::fs::mkdir(path, io::USER_DIR).ok()
            .map(|()| DirHandle { path: path.clone() })
    }
}

impl Drop for DirHandle {
    fn drop(&mut self) {
        io::fs::rmdir(&self.path).ok();
    }
}
<|endoftext|>


<commit_before>//! # num_cpus
//!
//! A crate with utilities to determine the number of CPUs available on the
//! current system.
//!
//! ## Example
//!
//! ```
//! let cpus = num_cpus::get();
//! ```
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![allow(non_snake_case)]

#[cfg(not(windows))]
extern crate libc;

/// Returns the number of available CPUs of the current system.
///
/// # Note
///
/// This will check sched affinity on Linux.
#[inline]
pub fn get() -> usize {
    get_num_cpus()
}

/// Returns the number of physical cores of the current system.
///
/// If not possible on the particular architecture, returns same as `get()`
/// which is the logical CPUs.
#[inline]
pub fn get_physical() -> usize {
    get_num_physical_cpus()
}

#[cfg(not(any(target_os = "linux", target_os = "windows")))]
#[inline]
fn get_num_physical_cpus() -> usize {
    // Not implemented, fallback
    get_num_cpus()
}

#[cfg(target_os = "windows")]
fn get_num_physical_cpus() -> usize {
    match get_num_physical_cpus_windows() {
        Some(num) => num,
        None => get_num_cpus()
    }
}

#[cfg(target_os = "windows")]
fn get_num_physical_cpus_windows() -> Option<usize> {
    // Inspired by https://msdn.microsoft.com/en-us/library/ms683194

    use std::ptr;
    use std::mem;

    #[allow(non_upper_case_globals)]
    const RelationProcessorCore: u32 = 0;

    #[repr(C)]
    #[allow(non_camel_case_types)]
    struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION {
        mask: usize,
        relationship: u32,
        _unused: [u64; 2]
    }

    extern "system" {
        fn GetLogicalProcessorInformation(
            info: *mut SYSTEM_LOGICAL_PROCESSOR_INFORMATION,
            length: &mut u32
        ) -> u32;
    }

    // First we need to determine how much space to reserve.

    // The required size of the buffer, in bytes.
    let mut needed_size = 0;

    unsafe {
        GetLogicalProcessorInformation(ptr::null_mut(), &mut needed_size);
    }

    let struct_size = mem::size_of::<SYSTEM_LOGICAL_PROCESSOR_INFORMATION>() as u32;

    // Could be 0, or some other bogus size.
    if needed_size == 0 || needed_size < struct_size || needed_size % struct_size != 0 {
        return None;
    }

    let count = needed_size / struct_size;

    // Allocate some memory where we will store the processor info.
    let mut buf = Vec::with_capacity(count as usize);

    let result;

    unsafe {
        result = GetLogicalProcessorInformation(buf.as_mut_ptr(), &mut needed_size);
    }

    // Failed for any reason.
    if result == 0 {
        return None;
    }

    let count = needed_size / struct_size;

    unsafe {
        buf.set_len(count as usize);
    }

    let phys_proc_count = buf.iter()
        // Only interested in processor packages (physical processors.)
        .filter(|proc_info| proc_info.relationship == RelationProcessorCore)
        .count();

    if phys_proc_count == 0 {
        None
    } else {
        Some(phys_proc_count)
    }
}

#[cfg(target_os = "linux")]
fn get_num_physical_cpus() -> usize {
    use std::io::BufReader;
    use std::io::BufRead;
    use std::fs::File;
    use std::collections::HashSet;

    let file = match File::open("/proc/cpuinfo") {
        Ok(val) => val,
        Err(_) => {return get_num_cpus()},
    };
    let reader = BufReader::new(file);
    let mut set = HashSet::new();
    let mut coreid: u32 = 0;
    let mut physid: u32 = 0;
    let mut chgcount = 0;
    for line in reader.lines().filter_map(|result| result.ok()) {
        let parts: Vec<&str> = line.split(':').map(|s| s.trim()).collect();
        if parts.len() != 2 {
            continue
        }
        if parts[0] == "core id" || parts[0] == "physical id" {
            let value = match parts[1].trim().parse() {
              Ok(val) => val,
              Err(_) => break,
            };
            match parts[0] {
                "core id"     => coreid = value,
                "physical id" => physid = value,
                _ => {},
            }
            chgcount += 1;
        }
        if chgcount == 2 {
            set.insert((physid, coreid));
            chgcount = 0;
        }
    }
    let count = set.len();
    if count == 0 { get_num_cpus() } else { count }
}

#[cfg(windows)]
fn get_num_cpus() -> usize {
    #[repr(C)]
    struct SYSTEM_INFO {
        wProcessorArchitecture: u16,
        wReserved: u16,
        dwPageSize: u32,
        lpMinimumApplicationAddress: *mut u8,
        lpMaximumApplicationAddress: *mut u8,
        dwActiveProcessorMask: *mut u8,
        dwNumberOfProcessors: u32,
        dwProcessorType: u32,
        dwAllocationGranularity: u32,
        wProcessorLevel: u16,
        wProcessorRevision: u16,
    }

    extern "system" {
        fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
    }

    unsafe {
        let mut sysinfo: SYSTEM_INFO = std::mem::uninitialized();
        GetSystemInfo(&mut sysinfo);
        sysinfo.dwNumberOfProcessors as usize
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "netbsd"))]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    unsafe {
        cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
    }
    if cpus < 1 {
        let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
        unsafe {
            libc::sysctl(mib.as_mut_ptr(),
                         2,
                         &mut cpus as *mut _ as *mut _,
                         &mut cpus_size as *mut _ as *mut _,
                         0 as *mut _,
                         0);
        }
        if cpus < 1 {
            cpus = 1;
        }
    }
    cpus as usize
}

#[cfg(target_os = "openbsd")]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);
    let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];

    unsafe {
        libc::sysctl(mib.as_mut_ptr(),
                     2,
                     &mut cpus as *mut _ as *mut _,
                     &mut cpus_size as *mut _ as *mut _,
                     0 as *mut _,
                     0);
    }
    if cpus < 1 {
        cpus = 1;
    }
    cpus as usize
}

#[cfg(target_os = "linux")]
fn get_num_cpus() -> usize {
    let mut set:  libc::cpu_set_t = unsafe { std::mem::zeroed() };
    if unsafe { libc::sched_getaffinity(0, std::mem::size_of::<libc::cpu_set_t>(), &mut set) } == 0 {
        let mut count: u32 = 0;
        for i in 0..libc::CPU_SETSIZE as usize {
            if unsafe { libc::CPU_ISSET(i, &set) } {
                count += 1
            }
        }
        count as usize
    } else {
        let cpus = unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) };
        if cpus < 1 {
            1
        } else {
            cpus as usize
        }
    }
}

#[cfg(any(
    target_os = "nacl",
    target_os = "macos",
    target_os = "ios",
    target_os = "android",
    target_os = "solaris",
    target_os = "fuchsia")
)]
fn get_num_cpus() -> usize {
    let cpus = unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) };
    if cpus < 1 {
        1
    } else {
        cpus as usize
    }
}

#[cfg(any(target_os = "emscripten", target_os = "redox", target_os = "haiku"))]
fn get_num_cpus() -> usize {
    1
}

#[cfg(test)]
mod tests {
    fn env_var(name: &'static str) -> Option<usize> {
        ::std::env::var(name).ok().map(|val| val.parse().unwrap())
    }

    #[test]
    fn test_get() {
        let num = super::get();
        if let Some(n) = env_var("NUM_CPUS_TEST_GET") {
            assert_eq!(num, n);
        } else {
            assert!(num > 0);
            assert!(num < 236_451);
        }
    }

    #[test]
    fn test_get_physical() {
        let num = super::get_physical();
        if let Some(n) = env_var("NUM_CPUS_TEST_GET_PHYSICAL") {
            assert_eq!(num, n);
        } else {
            assert!(num > 0);
            assert!(num < 236_451);
        }
    }
}
<commit_msg>Implement get_physical() for macOS using the libc::sysctlbyname API.<commit_after>//! # num_cpus
//!
//! A crate with utilities to determine the number of CPUs available on the
//! current system.
//!
//! ## Example
//!
//! ```
//! let cpus = num_cpus::get();
//! ```
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![allow(non_snake_case)]

#[cfg(not(windows))]
extern crate libc;

/// Returns the number of available CPUs of the current system.
///
/// # Note
///
/// This will check sched affinity on Linux.
#[inline]
pub fn get() -> usize {
    get_num_cpus()
}

/// Returns the number of physical cores of the current system.
///
/// If not possible on the particular architecture, returns same as `get()`
/// which is the logical CPUs.
#[inline]
pub fn get_physical() -> usize {
    get_num_physical_cpus()
}

#[cfg(not(any(target_os = "linux", target_os = "windows", target_os="macos")))]
#[inline]
fn get_num_physical_cpus() -> usize {
    // Not implemented, fallback
    get_num_cpus()
}

#[cfg(target_os = "windows")]
fn get_num_physical_cpus() -> usize {
    match get_num_physical_cpus_windows() {
        Some(num) => num,
        None => get_num_cpus()
    }
}

#[cfg(target_os = "windows")]
fn get_num_physical_cpus_windows() -> Option<usize> {
    // Inspired by https://msdn.microsoft.com/en-us/library/ms683194

    use std::ptr;
    use std::mem;

    #[allow(non_upper_case_globals)]
    const RelationProcessorCore: u32 = 0;

    #[repr(C)]
    #[allow(non_camel_case_types)]
    struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION {
        mask: usize,
        relationship: u32,
        _unused: [u64; 2]
    }

    extern "system" {
        fn GetLogicalProcessorInformation(
            info: *mut SYSTEM_LOGICAL_PROCESSOR_INFORMATION,
            length: &mut u32
        ) -> u32;
    }

    // First we need to determine how much space to reserve.

    // The required size of the buffer, in bytes.
    let mut needed_size = 0;

    unsafe {
        GetLogicalProcessorInformation(ptr::null_mut(), &mut needed_size);
    }

    let struct_size = mem::size_of::<SYSTEM_LOGICAL_PROCESSOR_INFORMATION>() as u32;

    // Could be 0, or some other bogus size.
    if needed_size == 0 || needed_size < struct_size || needed_size % struct_size != 0 {
        return None;
    }

    let count = needed_size / struct_size;

    // Allocate some memory where we will store the processor info.
    let mut buf = Vec::with_capacity(count as usize);

    let result;

    unsafe {
        result = GetLogicalProcessorInformation(buf.as_mut_ptr(), &mut needed_size);
    }

    // Failed for any reason.
    if result == 0 {
        return None;
    }

    let count = needed_size / struct_size;

    unsafe {
        buf.set_len(count as usize);
    }

    let phys_proc_count = buf.iter()
        // Only interested in processor packages (physical processors.)
        .filter(|proc_info| proc_info.relationship == RelationProcessorCore)
        .count();

    if phys_proc_count == 0 {
        None
    } else {
        Some(phys_proc_count)
    }
}

#[cfg(target_os = "linux")]
fn get_num_physical_cpus() -> usize {
    use std::io::BufReader;
    use std::io::BufRead;
    use std::fs::File;
    use std::collections::HashSet;

    let file = match File::open("/proc/cpuinfo") {
        Ok(val) => val,
        Err(_) => {return get_num_cpus()},
    };
    let reader = BufReader::new(file);
    let mut set = HashSet::new();
    let mut coreid: u32 = 0;
    let mut physid: u32 = 0;
    let mut chgcount = 0;
    for line in reader.lines().filter_map(|result| result.ok()) {
        let parts: Vec<&str> = line.split(':').map(|s| s.trim()).collect();
        if parts.len() != 2 {
            continue
        }
        if parts[0] == "core id" || parts[0] == "physical id" {
            let value = match parts[1].trim().parse() {
              Ok(val) => val,
              Err(_) => break,
            };
            match parts[0] {
                "core id"     => coreid = value,
                "physical id" => physid = value,
                _ => {},
            }
            chgcount += 1;
        }
        if chgcount == 2 {
            set.insert((physid, coreid));
            chgcount = 0;
        }
    }
    let count = set.len();
    if count == 0 { get_num_cpus() } else { count }
}

#[cfg(windows)]
fn get_num_cpus() -> usize {
    #[repr(C)]
    struct SYSTEM_INFO {
        wProcessorArchitecture: u16,
        wReserved: u16,
        dwPageSize: u32,
        lpMinimumApplicationAddress: *mut u8,
        lpMaximumApplicationAddress: *mut u8,
        dwActiveProcessorMask: *mut u8,
        dwNumberOfProcessors: u32,
        dwProcessorType: u32,
        dwAllocationGranularity: u32,
        wProcessorLevel: u16,
        wProcessorRevision: u16,
    }

    extern "system" {
        fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
    }

    unsafe {
        let mut sysinfo: SYSTEM_INFO = std::mem::uninitialized();
        GetSystemInfo(&mut sysinfo);
        sysinfo.dwNumberOfProcessors as usize
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "netbsd"))]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    unsafe {
        cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
    }
    if cpus < 1 {
        let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
        unsafe {
            libc::sysctl(mib.as_mut_ptr(),
                         2,
                         &mut cpus as *mut _ as *mut _,
                         &mut cpus_size as *mut _ as *mut _,
                         0 as *mut _,
                         0);
        }
        if cpus < 1 {
            cpus = 1;
        }
    }
    cpus as usize
}

#[cfg(target_os = "openbsd")]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);
    let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];

    unsafe {
        libc::sysctl(mib.as_mut_ptr(),
                     2,
                     &mut cpus as *mut _ as *mut _,
                     &mut cpus_size as *mut _ as *mut _,
                     0 as *mut _,
                     0);
    }
    if cpus < 1 {
        cpus = 1;
    }
    cpus as usize
}

#[cfg(target_os = "macos")]
fn get_num_physical_cpus() -> usize {
    use std::ffi::CStr;
    use std::ptr;

    let mut cpus: i32 = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    let sysctl_name = CStr::from_bytes_with_nul(b"hw.physicalcpu\0")
        .expect("byte literal is missing NUL");

    unsafe {
        if 0 != libc::sysctlbyname(sysctl_name.as_ptr(),
                                   &mut cpus as *mut _ as *mut _,
                                   &mut cpus_size as *mut _ as *mut _,
                                   ptr::null_mut(),
                                   0) {
            return get_num_cpus();
        }
    }
    cpus as usize
}

#[cfg(target_os = "linux")]
fn get_num_cpus() -> usize {
    let mut set:  libc::cpu_set_t = unsafe { std::mem::zeroed() };
    if unsafe { libc::sched_getaffinity(0, std::mem::size_of::<libc::cpu_set_t>(), &mut set) } == 0 {
        let mut count: u32 = 0;
        for i in 0..libc::CPU_SETSIZE as usize {
            if unsafe { libc::CPU_ISSET(i, &set) } {
                count += 1
            }
        }
        count as usize
    } else {
        let cpus = unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) };
        if cpus < 1 {
            1
        } else {
            cpus as usize
        }
    }
}

#[cfg(any(
    target_os = "nacl",
    target_os = "macos",
    target_os = "ios",
    target_os = "android",
    target_os = "solaris",
    target_os = "fuchsia")
)]
fn get_num_cpus() -> usize {
    let cpus = unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) };
    if cpus < 1 {
        1
    } else {
        cpus as usize
    }
}

#[cfg(any(target_os = "emscripten", target_os = "redox", target_os = "haiku"))]
fn get_num_cpus() -> usize {
    1
}

#[cfg(test)]
mod tests {
    fn env_var(name: &'static str) -> Option<usize> {
        ::std::env::var(name).ok().map(|val| val.parse().unwrap())
    }

    #[test]
    fn test_get() {
        let num = super::get();
        if let Some(n) = env_var("NUM_CPUS_TEST_GET") {
            assert_eq!(num, n);
        } else {
            assert!(num > 0);
            assert!(num < 236_451);
        }
    }

    #[test]
    fn test_get_physical() {
        let num = super::get_physical();
        if let Some(n) = env_var("NUM_CPUS_TEST_GET_PHYSICAL") {
            assert_eq!(num, n);
        } else {
            assert!(num > 0);
            assert!(num < 236_451);
        }
    }

    #[test]
    fn test_physical_less_logical() {
        let logical = super::get();
        let physical = super::get_physical();
        println!("physical: {:?}, logical: {:?}", physical, logical);
        assert!(physical <= logical);
    }
}
<|endoftext|>


<commit_before>extern crate tokio_core;
extern crate hyper;
extern crate futures;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate quick_error;

use futures::{Future, Stream};
use futures::future::Either;
use hyper::client::{self, HttpConnector};
use tokio_core::reactor::Handle;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Url(error: hyper::error::ParseError) {
            description(error.description())
            display("Unable to parse URL: {}", error)
            from()
            cause(error)
        }
        Hyper(error: hyper::Error) {
            description(error.description())
            display("Unable to perform HTTP request: {}", error)
            from()
            cause(error)
        }
        Serde(error: serde_json::Error) {
            description(error.description())
            display("Unable to deserialize JSON: {}", error)
            from()
            cause(error)
        }
        BadRequest(what: String) {
            description("The InfluxDB server responded with an error")
            display("The InfluxDB server responded with an error: {}", what)
        }
    }
}

type Result<T> = ::std::result::Result<T, Error>;

pub struct AsyncDb {
    name: String,
    query_endpoint: hyper::Url,
    write_endpoint: hyper::Url,
    client: hyper::Client<HttpConnector>,
}

impl AsyncDb {
    pub fn new(handle: Handle, base_url: &str, name: &str) -> Result<Self> {
        let base_url = hyper::Url::parse(base_url)?;
        let query_endpoint = base_url.join("/query")?;
        let mut write_endpoint = base_url.join("/write")?;
        write_endpoint.query_pairs_mut()
            .append_pair("db", &name);

        let client = hyper::Client::configure().keep_alive(false).build(&handle);

        Ok(AsyncDb {
            name: name.into(),
            query_endpoint: query_endpoint,
            write_endpoint: write_endpoint,
            client: client,
        })
    }

    pub fn add_data(&self, data: &str) -> AddData {
        let mut request = client::Request::new(hyper::Method::Post, self.write_endpoint.clone());
        request.set_body(data.to_owned());

        let response =
            self.client.request(request)
            .map_err(Error::Hyper)
            .and_then(check_response_code)
            .map(|_| ());

        AddData(Box::new(response))
    }

    pub fn query(&self, query: &str) -> Query {
        let mut query_endpoint = self.query_endpoint.clone();
        query_endpoint.query_pairs_mut()
            .append_pair("db", &self.name)
            .append_pair("q", query);

        let response =
            self.client.get(query_endpoint)
            .map_err(Error::Hyper)
            .and_then(check_response_code)
            .and_then(response_to_json);

        Query(Box::new(response))
    }
}

fn check_response_code(resp: client::Response) -> Box<Future<Item = client::Response, Error = Error>> {
    let f = if resp.status().is_success() {
        Either::A(futures::future::ok(resp))
    } else {
        let e = response_to_json::<InfluxServerError>(resp)
            .and_then(|message| Err(Error::BadRequest(message.error)));
        Either::B(e)
    };

    Box::new(f)
}

fn response_to_json<T>(resp: client::Response) -> Box<Future<Item = T, Error = Error>>
    where T: serde::Deserialize + 'static,
{
    let f =
        resp.body()
        .map_err(Error::Hyper)
        .fold(Vec::new(), |mut acc, chunk| {
            // TODO: Is it the best idea to just build up a big `Vec`?
            acc.extend_from_slice(&*chunk);
            futures::future::ok::<_, Error>(acc)
        })
        .and_then(|body| serde_json::from_slice(&body).map_err(Error::Serde));

    Box::new(f)
}

#[must_use = "futures do nothing unless polled"]
pub struct AddData(Box<Future<Item = (), Error = Error>>);

impl Future for AddData {
    type Item = ();
    type Error = Error;

    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        self.0.poll()
    }
}

#[must_use = "futures do nothing unless polled"]
pub struct Query(Box<Future<Item = QueryResponse, Error = Error>>);

impl Future for Query {
    type Item = QueryResponse;
    type Error = Error;

    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        self.0.poll()
    }
}

#[derive(Debug, Deserialize)]
pub struct QueryResponse {
    pub results: Vec<QueryResult>,
}

#[derive(Debug, Deserialize)]
pub struct QueryResult {
    #[serde(default)]
    pub series: Vec<Series>,
    pub statement_id: usize, // TODO: correct integer type?
}

#[derive(Debug, Deserialize)]
pub struct Series {
    pub name: String,
    pub columns: Vec<String>, // TODO: `time` is always added?
    pub values: Vec<Vec<serde_json::Value>>, // TODO: matches with columns?
    // TODO: Don't expose serde types publically
}

#[derive(Debug, Deserialize)]
pub struct InfluxServerError {
    pub error: String,
}
<commit_msg>Add thoughts on potential optimization<commit_after>extern crate tokio_core;
extern crate hyper;
extern crate futures;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate quick_error;

use futures::{Future, Stream};
use futures::future::Either;
use hyper::client::{self, HttpConnector};
use tokio_core::reactor::Handle;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Url(error: hyper::error::ParseError) {
            description(error.description())
            display("Unable to parse URL: {}", error)
            from()
            cause(error)
        }
        Hyper(error: hyper::Error) {
            description(error.description())
            display("Unable to perform HTTP request: {}", error)
            from()
            cause(error)
        }
        Serde(error: serde_json::Error) {
            description(error.description())
            display("Unable to deserialize JSON: {}", error)
            from()
            cause(error)
        }
        BadRequest(what: String) {
            description("The InfluxDB server responded with an error")
            display("The InfluxDB server responded with an error: {}", what)
        }
    }
}

type Result<T> = ::std::result::Result<T, Error>;

pub struct AsyncDb {
    name: String,
    query_endpoint: hyper::Url,
    write_endpoint: hyper::Url,
    client: hyper::Client<HttpConnector>,
}

impl AsyncDb {
    pub fn new(handle: Handle, base_url: &str, name: &str) -> Result<Self> {
        let base_url = hyper::Url::parse(base_url)?;
        let query_endpoint = base_url.join("/query")?;
        let mut write_endpoint = base_url.join("/write")?;
        write_endpoint.query_pairs_mut()
            .append_pair("db", &name);

        let client = hyper::Client::configure().keep_alive(false).build(&handle);

        Ok(AsyncDb {
            name: name.into(),
            query_endpoint: query_endpoint,
            write_endpoint: write_endpoint,
            client: client,
        })
    }

    pub fn add_data(&self, data: &str) -> AddData {
        let mut request = client::Request::new(hyper::Method::Post, self.write_endpoint.clone());
        request.set_body(data.to_owned());

        let response =
            self.client.request(request)
            .map_err(Error::Hyper)
            .and_then(check_response_code)
            .map(|_| ());

        AddData(Box::new(response))
    }

    pub fn query(&self, query: &str) -> Query {
        let mut query_endpoint = self.query_endpoint.clone();
        query_endpoint.query_pairs_mut()
            .append_pair("db", &self.name)
            .append_pair("q", query);

        let response =
            self.client.get(query_endpoint)
            .map_err(Error::Hyper)
            .and_then(check_response_code)
            .and_then(response_to_json);

        Query(Box::new(response))
    }
}

fn check_response_code(resp: client::Response) -> Box<Future<Item = client::Response, Error = Error>> {
    let f = if resp.status().is_success() {
        Either::A(futures::future::ok(resp))
    } else {
        let e = response_to_json::<InfluxServerError>(resp)
            .and_then(|message| Err(Error::BadRequest(message.error)));
        Either::B(e)
    };

    Box::new(f)
}

fn response_to_json<T>(resp: client::Response) -> Box<Future<Item = T, Error = Error>>
    where T: serde::Deserialize + 'static,
{
    let f =
        resp.body()
        .map_err(Error::Hyper)
        .fold(Vec::new(), |mut acc, chunk| {
            // TODO: Is it the best idea to just build up a big `Vec`?
            // TODO: Is there some way of reusing the vector allocation?
            acc.extend_from_slice(&*chunk);
            futures::future::ok::<_, Error>(acc)
        })
        .and_then(|body| serde_json::from_slice(&body).map_err(Error::Serde));

    Box::new(f)
}

#[must_use = "futures do nothing unless polled"]
pub struct AddData(Box<Future<Item = (), Error = Error>>);

impl Future for AddData {
    type Item = ();
    type Error = Error;

    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        self.0.poll()
    }
}

#[must_use = "futures do nothing unless polled"]
pub struct Query(Box<Future<Item = QueryResponse, Error = Error>>);

impl Future for Query {
    type Item = QueryResponse;
    type Error = Error;

    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        self.0.poll()
    }
}

#[derive(Debug, Deserialize)]
pub struct QueryResponse {
    pub results: Vec<QueryResult>,
}

#[derive(Debug, Deserialize)]
pub struct QueryResult {
    #[serde(default)]
    pub series: Vec<Series>,
    pub statement_id: usize, // TODO: correct integer type?
}

#[derive(Debug, Deserialize)]
pub struct Series {
    pub name: String,
    pub columns: Vec<String>, // TODO: `time` is always added?
    pub values: Vec<Vec<serde_json::Value>>, // TODO: matches with columns?
    // TODO: Don't expose serde types publically
}

#[derive(Debug, Deserialize)]
pub struct InfluxServerError {
    pub error: String,
}
<|endoftext|>


<commit_before>#![cfg_attr(test, feature(io))]
#![cfg_attr(test, deny(warnings))]

extern crate "rustc-serialize" as rustc_serialize;

extern crate conduit;
extern crate "conduit-middleware" as middleware;
extern crate "conduit-utils" as utils;

use std::error::Error;
use rustc_serialize::Decodable;
use rustc_serialize::json::{self, Json};

use conduit::Request;
use utils::RequestDelegator;
use middleware::Middleware;

pub struct BodyReader<T>;

impl<T: Decodable + 'static> Middleware for BodyReader<T> {
    fn before(&self, req: &mut Request) -> Result<(), Box<Error+Send>> {
        let json: T = try!(decode::<T>(req.body()));

        req.mut_extensions().insert(json);
        Ok(())
    }
}

fn decode<T: Decodable>(reader: &mut Reader) -> Result<T, Box<Error+Send>> {
    let j = try!(Json::from_reader(reader).map_err(|e| Box::new(e) as Box<Error+Send>));
    let mut decoder = json::Decoder::new(j);
    Decodable::decode(&mut decoder).map_err(|e| Box::new(e) as Box<Error+Send>)
}

pub fn json_params<'a, T: Decodable + 'static>(req: &'a Request) -> Option<&'a T> {
    req.extensions().find::<T>()
}

#[cfg(test)]
mod tests {
    extern crate "conduit-test" as conduit_test;

    use {json_params, BodyReader};

    use std::collections::HashMap;
    use std::error::Error;
    use std::old_io::MemReader;
    use rustc_serialize::json;

    use conduit::{Request, Response, Handler, Method};
    use middleware::MiddlewareBuilder;

    #[derive(PartialEq, RustcDecodable, RustcEncodable, Debug)]
    struct Person {
        name: String,
        location: String
    }

    fn handler(req: &mut Request) -> Result<Response, Box<Error+Send>> {
        let person = json_params::<Person>(req);
        let out = person.map(|p| json::encode(p).unwrap()).expect("No JSON");

        Ok(Response {
            status: (200, "OK"),
            headers: HashMap::new(),
            body: Box::new(MemReader::new(out.into_bytes()))
        })
    }

    #[test]
    fn test_body_params() {
        let mut req = conduit_test::MockRequest::new(Method::Get, "/");
        req.with_body(br#"{ "name": "Alex Crichton", "location": "San Francisco" }"#);

        let mut middleware = MiddlewareBuilder::new(handler);
        middleware.add(BodyReader::<Person>);

        let mut res = middleware.call(&mut req).ok().expect("No response");
        let person = super::decode::<Person>(&mut *res.body).ok().expect("No JSON response");
        assert_eq!(person, Person {
            name: "Alex Crichton".to_string(),
            location: "San Francisco".to_string()
        });
    }
}
<commit_msg>Update to rust master<commit_after>#![cfg_attr(test, feature(io))]
#![cfg_attr(test, deny(warnings))]

extern crate "rustc-serialize" as rustc_serialize;

extern crate conduit;
extern crate "conduit-middleware" as middleware;
extern crate "conduit-utils" as utils;

use std::error::Error;
use rustc_serialize::Decodable;
use rustc_serialize::json::{self, Json};

use conduit::Request;
use utils::RequestDelegator;
use middleware::Middleware;

pub struct BodyReader<T>;

impl<T: Decodable + 'static> Middleware for BodyReader<T> {
    fn before(&self, req: &mut Request) -> Result<(), Box<Error+Send>> {
        let json: T = try!(decode::<T>(req.body()));

        req.mut_extensions().insert(json);
        Ok(())
    }
}

fn decode<T: Decodable>(reader: &mut Reader) -> Result<T, Box<Error+Send>> {
    let j = try!(Json::from_reader(reader).map_err(|e| Box::new(e) as Box<Error+Send>));
    let mut decoder = json::Decoder::new(j);
    Decodable::decode(&mut decoder).map_err(|e| Box::new(e) as Box<Error+Send>)
}

pub fn json_params<'a, T: Decodable + 'static>(req: &'a Request) -> Option<&'a T> {
    req.extensions().find::<T>()
}

#[cfg(test)]
mod tests {
    extern crate "conduit-test" as conduit_test;

    use {json_params, BodyReader};

    use std::collections::HashMap;
    use std::old_io::{MemReader, IoError};
    use rustc_serialize::json;

    use conduit::{Request, Response, Handler, Method};
    use middleware::MiddlewareBuilder;

    #[derive(PartialEq, RustcDecodable, RustcEncodable, Debug)]
    struct Person {
        name: String,
        location: String
    }

    fn handler(req: &mut Request) -> Result<Response, IoError> {
        let person = json_params::<Person>(req);
        let out = person.map(|p| json::encode(p).unwrap()).expect("No JSON");

        Ok(Response {
            status: (200, "OK"),
            headers: HashMap::new(),
            body: Box::new(MemReader::new(out.into_bytes()))
        })
    }

    #[test]
    fn test_body_params() {
        let mut req = conduit_test::MockRequest::new(Method::Get, "/");
        req.with_body(br#"{ "name": "Alex Crichton", "location": "San Francisco" }"#);

        let mut middleware = MiddlewareBuilder::new(handler);
        middleware.add(BodyReader::<Person>);

        let mut res = middleware.call(&mut req).ok().expect("No response");
        let person = super::decode::<Person>(&mut *res.body).ok().expect("No JSON response");
        assert_eq!(person, Person {
            name: "Alex Crichton".to_string(),
            location: "San Francisco".to_string()
        });
    }
}
<|endoftext|>


<commit_before>#![feature(rustc_private)]
#![feature(map_first_last)]
#![feature(map_try_insert)]
#![feature(never_type)]
#![feature(try_blocks)]
#![feature(let_else)]
#![feature(io_error_more)]
#![feature(int_log)]
#![feature(variant_count)]
#![feature(yeet_expr)]
#![feature(is_some_with)]
#![feature(nonzero_ops)]
#![feature(local_key_cell_methods)]
// Configure clippy and other lints
#![allow(
    clippy::collapsible_else_if,
    clippy::collapsible_if,
    clippy::comparison_chain,
    clippy::enum_variant_names,
    clippy::field_reassign_with_default,
    clippy::manual_map,
    clippy::new_without_default,
    clippy::single_match,
    clippy::useless_format,
    clippy::derive_partial_eq_without_eq,
    clippy::derive_hash_xor_eq,
    clippy::too_many_arguments,
    clippy::type_complexity,
    clippy::single_element_loop,
    // We are not implementing queries here so it's fine
    rustc::potential_query_instability
)]
#![warn(
    rust_2018_idioms,
    clippy::cast_possible_wrap, // unsigned -> signed
    clippy::cast_sign_loss, // signed -> unsigned
    clippy::cast_lossless,
    clippy::cast_possible_truncation,
)]

extern crate rustc_apfloat;
extern crate rustc_ast;
#[macro_use]
extern crate rustc_middle;
extern crate rustc_const_eval;
extern crate rustc_data_structures;
extern crate rustc_hir;
extern crate rustc_index;
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_target;

mod concurrency;
mod diagnostics;
mod eval;
mod helpers;
mod intptrcast;
mod machine;
mod mono_hash_map;
mod operator;
mod range_map;
mod shims;
mod stacked_borrows;
pub mod thread;

// Establish a "crate-wide prelude": we often import `crate::*`.

// Make all those symbols available in the same place as our own.
pub use rustc_const_eval::interpret::*;
// Resolve ambiguity.
pub use rustc_const_eval::interpret::{self, AllocMap, PlaceTy, Provenance as _};

pub use crate::shims::dlsym::{Dlsym, EvalContextExt as _};
pub use crate::shims::env::{EnvVars, EvalContextExt as _};
pub use crate::shims::foreign_items::EvalContextExt as _;
pub use crate::shims::intrinsics::EvalContextExt as _;
pub use crate::shims::os_str::EvalContextExt as _;
pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as _};
pub use crate::shims::time::EvalContextExt as _;
pub use crate::shims::tls::{EvalContextExt as _, TlsData};
pub use crate::shims::EvalContextExt as _;

pub use crate::concurrency::data_race::{
    AtomicFenceOrd, AtomicReadOrd, AtomicRwOrd, AtomicWriteOrd,
    EvalContextExt as DataRaceEvalContextExt,
};
pub use crate::diagnostics::{
    EvalContextExt as DiagnosticsEvalContextExt, NonHaltingDiagnostic, register_diagnostic,
    report_error, TerminationInfo,
};
pub use crate::eval::{
    AlignmentCheck, BacktraceStyle, create_ecx, eval_entry, IsolatedOp, MiriConfig, RejectOpWith,
};
pub use crate::helpers::{CurrentSpan, EvalContextExt as HelpersEvalContextExt};
pub use crate::intptrcast::ProvenanceMode;
pub use crate::machine::{
    AllocExtra, Evaluator, FrameData, MiriEvalContext, MiriEvalContextExt, MiriMemoryKind,
    NUM_CPUS, PAGE_SIZE, Provenance, ProvenanceExtra, STACK_ADDR, STACK_SIZE,
};
pub use crate::mono_hash_map::MonoHashMap;
pub use crate::operator::EvalContextExt as OperatorEvalContextExt;
pub use crate::range_map::RangeMap;
pub use crate::stacked_borrows::{
    CallId, EvalContextExt as StackedBorEvalContextExt, Item, Permission, SbTag, Stack, Stacks,
};
pub use concurrency::sync::{CondvarId, EvalContextExt as SyncEvalContextExt, MutexId, RwLockId};
pub use crate::thread::{
    EvalContextExt as ThreadsEvalContextExt, SchedulingAction, ThreadId, ThreadManager, ThreadState,
};
/// Insert rustc arguments at the beginning of the argument list that Miri wants to be
/// set per default, for maximal validation power.
pub const MIRI_DEFAULT_ARGS: &[&str] = &[
    "-Zalways-encode-mir",
    "-Zmir-emit-retag",
    "-Zmir-opt-level=0",
    "--cfg=miri",
    "-Cdebug-assertions=on",
    "-Zextra-const-ub-checks",
];
<commit_msg>rustfmt<commit_after>#![feature(rustc_private)]
#![feature(map_first_last)]
#![feature(map_try_insert)]
#![feature(never_type)]
#![feature(try_blocks)]
#![feature(let_else)]
#![feature(io_error_more)]
#![feature(int_log)]
#![feature(variant_count)]
#![feature(yeet_expr)]
#![feature(is_some_with)]
#![feature(nonzero_ops)]
#![feature(local_key_cell_methods)]
// Configure clippy and other lints
#![allow(
    clippy::collapsible_else_if,
    clippy::collapsible_if,
    clippy::comparison_chain,
    clippy::enum_variant_names,
    clippy::field_reassign_with_default,
    clippy::manual_map,
    clippy::new_without_default,
    clippy::single_match,
    clippy::useless_format,
    clippy::derive_partial_eq_without_eq,
    clippy::derive_hash_xor_eq,
    clippy::too_many_arguments,
    clippy::type_complexity,
    clippy::single_element_loop,
    // We are not implementing queries here so it's fine
    rustc::potential_query_instability
)]
#![warn(
    rust_2018_idioms,
    clippy::cast_possible_wrap, // unsigned -> signed
    clippy::cast_sign_loss, // signed -> unsigned
    clippy::cast_lossless,
    clippy::cast_possible_truncation,
)]

extern crate rustc_apfloat;
extern crate rustc_ast;
#[macro_use]
extern crate rustc_middle;
extern crate rustc_const_eval;
extern crate rustc_data_structures;
extern crate rustc_hir;
extern crate rustc_index;
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_target;

mod concurrency;
mod diagnostics;
mod eval;
mod helpers;
mod intptrcast;
mod machine;
mod mono_hash_map;
mod operator;
mod range_map;
mod shims;
mod stacked_borrows;
pub mod thread;

// Establish a "crate-wide prelude": we often import `crate::*`.

// Make all those symbols available in the same place as our own.
pub use rustc_const_eval::interpret::*;
// Resolve ambiguity.
pub use rustc_const_eval::interpret::{self, AllocMap, PlaceTy, Provenance as _};

pub use crate::shims::dlsym::{Dlsym, EvalContextExt as _};
pub use crate::shims::env::{EnvVars, EvalContextExt as _};
pub use crate::shims::foreign_items::EvalContextExt as _;
pub use crate::shims::intrinsics::EvalContextExt as _;
pub use crate::shims::os_str::EvalContextExt as _;
pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as _};
pub use crate::shims::time::EvalContextExt as _;
pub use crate::shims::tls::{EvalContextExt as _, TlsData};
pub use crate::shims::EvalContextExt as _;

pub use crate::concurrency::data_race::{
    AtomicFenceOrd, AtomicReadOrd, AtomicRwOrd, AtomicWriteOrd,
    EvalContextExt as DataRaceEvalContextExt,
};
pub use crate::diagnostics::{
    register_diagnostic, report_error, EvalContextExt as DiagnosticsEvalContextExt,
    NonHaltingDiagnostic, TerminationInfo,
};
pub use crate::eval::{
    create_ecx, eval_entry, AlignmentCheck, BacktraceStyle, IsolatedOp, MiriConfig, RejectOpWith,
};
pub use crate::helpers::{CurrentSpan, EvalContextExt as HelpersEvalContextExt};
pub use crate::intptrcast::ProvenanceMode;
pub use crate::machine::{
    AllocExtra, Evaluator, FrameData, MiriEvalContext, MiriEvalContextExt, MiriMemoryKind,
    Provenance, ProvenanceExtra, NUM_CPUS, PAGE_SIZE, STACK_ADDR, STACK_SIZE,
};
pub use crate::mono_hash_map::MonoHashMap;
pub use crate::operator::EvalContextExt as OperatorEvalContextExt;
pub use crate::range_map::RangeMap;
pub use crate::stacked_borrows::{
    CallId, EvalContextExt as StackedBorEvalContextExt, Item, Permission, SbTag, Stack, Stacks,
};
pub use crate::thread::{
    EvalContextExt as ThreadsEvalContextExt, SchedulingAction, ThreadId, ThreadManager, ThreadState,
};
pub use concurrency::sync::{CondvarId, EvalContextExt as SyncEvalContextExt, MutexId, RwLockId};
/// Insert rustc arguments at the beginning of the argument list that Miri wants to be
/// set per default, for maximal validation power.
pub const MIRI_DEFAULT_ARGS: &[&str] = &[
    "-Zalways-encode-mir",
    "-Zmir-emit-retag",
    "-Zmir-opt-level=0",
    "--cfg=miri",
    "-Cdebug-assertions=on",
    "-Zextra-const-ub-checks",
];
<|endoftext|>


<commit_before>//! # Slog -  Structured, composable logging for Rust

#![warn(missing_docs)]

extern crate crossbeam;
extern crate chrono;
extern crate rustc_serialize as serialize;

#[macro_use]
extern crate error_chain;

use std::sync::Arc;
use std::fmt;

/// Convenience function for building `&[OwnedKeyValue]`
///
/// ```
/// #[macro_use]
/// extern crate slog;
/// use slog::drain::IntoLogger;
///
/// fn main() {
///     let drain = slog::drain::discard();
///     let root = drain.into_logger(o!("key1" => "value1", "key2" => "value2"));
/// }
/// ```
#[macro_export]
macro_rules! o(
    () => {
        vec![]
    };
    ($($k:expr => $v:expr),*) => {
        {
        use std;
        vec![$(($k, std::sync::Arc::new($v) as std::sync::Arc<$crate::ser::SyncSerialize>)),*]
        }
    };
);

/// Log message of a given level
///
/// Use wrappers `error!`, `warn!` etc. instead
///
/// ```
/// #[macro_use]
/// extern crate slog;
/// use slog::drain::IntoLogger;
///
/// fn main() {
///     let drain = slog::drain::discard();
///     let root = drain.into_logger(o!("key1" => "value1", "key2" => "value2"));
///     info!(root, "test info log", "log-key" => true);
/// }
/// ```
#[macro_export]
macro_rules! log(
    ($l:expr, $lvl:expr, $msg:expr) => {
        $l.log(
            &$crate::RecordInfo::new(
                $lvl,
                &$msg,
                file!(),
                line!(),
                module_path!(),
                &[]
            )
        )
    };
    ($l:expr, $lvl:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        $l.log(
            &$crate::RecordInfo::new(
                $lvl,
                &$msg,
                file!(),
                line!(),
                module_path!(),
                &[$(($k, &$v)),*]
            )
    )
    };
);

/// Log critical level record
#[macro_export]
macro_rules! crit(
    ($l:expr, $msg:expr) => {
        log!($l, $crate::Level::Critical, $msg)
    };
    ($l:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        log!($l, $crate::Level::Critical, $msg, $($k => $v),*)
    };
);

/// Log error level record
#[macro_export]
macro_rules! error(
    ($l:expr, $msg:expr) => {
        log!($l, $crate::Level::Error, $msg)
    };
    ($l:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        log!($l, $crate::Level::Error, $msg, $($k => $v),*)
    };
);

/// Log warning level record
#[macro_export]
macro_rules! warn(
    ($l:expr, $msg:expr) => {
        log!($l, $crate::Level::Warning, $msg)
    };
    ($l:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        log!($l, $crate::Level::Warning, $msg, $($k => $v),*)
    };
);

/// Log info level record
#[macro_export]
macro_rules! info(
    ($l:expr, $msg:expr) => {
        log!($l, $crate::Level::Info, $msg)
    };
    ($l:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        log!($l, $crate::Level::Info, $msg, $($k => $v),*)
    };
);

/// Log debug level record
#[macro_export]
macro_rules! debug(
    ($l:expr, $msg:expr) => {
        log!($l, $crate::Level::Debug, $msg)
    };
    ($l:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        log!($l, $crate::Level::Debug, $msg, $($k => $v),*)
    };
);

/// Log trace level record
#[macro_export]
macro_rules! trace(
    ($l:expr, $msg:expr) => {
        log!($l, $crate::Level::Trace, $msg)
    };
    ($l:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        log!($l, $crate::Level::Trace, $msg, $($k => $v),*)
    };
);

/// Drains - logging outputs
pub mod drain;

/// Logger - logging handle
pub mod logger;

/// Serialization
pub mod ser;

/// Output formating
pub mod format;

pub use logger::Logger;
pub use logger::RecordInfo;

include!("_level.rs");

/// Key value pair that can be owned by `Logger`
pub type OwnedKeyValue = (&'static str, Arc<ser::SyncSerialize>);
/// Key value pair that can be part of each logging record
pub type BorrowedKeyValue<'a> = (&'static str, &'a ser::Serialize);

/// Values specific for this Logger and reference to it's parent values
#[derive(Clone)]
pub struct OwnedKeyValueNode {
    parent: Option<Arc<OwnedKeyValueNode>>,
    values: Vec<OwnedKeyValue>,
}

impl OwnedKeyValueNode {
    /// New `OwnedKeyValue` with a parent
    pub fn new(values: Vec<OwnedKeyValue>, parent: Arc<OwnedKeyValueNode>) -> Self {
        OwnedKeyValueNode {
            parent: Some(parent),
            values: values,
        }
    }

    /// New `OwnedKeyValue` without a parent (root)
    pub fn new_root(values: Vec<OwnedKeyValue>) -> Self {
        OwnedKeyValueNode {
            parent: None,
            values: values,
        }
    }

    /// Iterator over `OwnedKeyValue`-s
    pub fn iter(&self) -> OwnedKeyValueNodeIterator {
        OwnedKeyValueNodeIterator::new(self)
    }
}

/// Iterator over `OwnedKeyValue`-s
pub struct OwnedKeyValueNodeIterator<'a> {
    next_node: &'a Option<Arc<OwnedKeyValueNode>>,
    iter: std::slice::Iter<'a, OwnedKeyValue>,
}

impl<'a> OwnedKeyValueNodeIterator<'a> {
    fn new(node: &'a OwnedKeyValueNode) -> Self {
        OwnedKeyValueNodeIterator {
            next_node: &node.parent,
            iter: node.values.iter(),
        }
    }
}

impl<'a> Iterator for OwnedKeyValueNodeIterator<'a> {
    type Item = &'a OwnedKeyValue;
    fn next(&mut self) -> Option<Self::Item> {
        loop {
            match self.iter.next() {
                Some(x) => return Some(&*x),
                None => {
                    match self.next_node {
                        &Some(ref node) => {
                            self.iter = node.values.iter();
                            self.next_node = &node.parent;
                        }
                        &None => return None,
                    }
                }
            }
        }
    }
}

#[cfg(test)]
mod tests;
<commit_msg>Alternative names for `log!`<commit_after>//! # Slog -  Structured, composable logging for Rust

#![warn(missing_docs)]

extern crate crossbeam;
extern crate chrono;
extern crate rustc_serialize as serialize;

#[macro_use]
extern crate error_chain;

use std::sync::Arc;
use std::fmt;

/// Convenience function for building `&[OwnedKeyValue]`
///
/// ```
/// #[macro_use]
/// extern crate slog;
/// use slog::drain::IntoLogger;
///
/// fn main() {
///     let drain = slog::drain::discard();
///     let root = drain.into_logger(o!("key1" => "value1", "key2" => "value2"));
/// }
/// ```
#[macro_export]
macro_rules! o(
    () => {
        vec![]
    };
    ($($k:expr => $v:expr),*) => {
        {
        use std;
        vec![$(($k, std::sync::Arc::new($v) as std::sync::Arc<$crate::ser::SyncSerialize>)),*]
        }
    };
);

/// Log message of a given level
///
/// Use wrappers `error!`, `warn!` etc. instead
///
/// ```
/// #[macro_use]
/// extern crate slog;
/// use slog::drain::IntoLogger;
///
/// fn main() {
///     let drain = slog::drain::discard();
///     let root = drain.into_logger(o!("key1" => "value1", "key2" => "value2"));
///     info!(root, "test info log", "log-key" => true);
/// }
/// ```
#[macro_export]
macro_rules! log(
    ($l:expr, $lvl:expr, $msg:expr) => {
        $l.log(
            &$crate::RecordInfo::new(
                $lvl,
                &$msg,
                file!(),
                line!(),
                module_path!(),
                &[]
            )
        )
    };
    ($l:expr, $lvl:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        $l.log(
            &$crate::RecordInfo::new(
                $lvl,
                &$msg,
                file!(),
                line!(),
                module_path!(),
                &[$(($k, &$v)),*]
            )
    )
    };
);

/// Alias for `log`
///
/// Prefer shorter version, unless it clashes with
/// existing `log` crate macro.
#[macro_export]
macro_rules! slog_log(
    ($l:expr, $lvl:expr, $msg:expr) => {
        $l.log(
            &$crate::RecordInfo::new(
                $lvl,
                &$msg,
                file!(),
                line!(),
                module_path!(),
                &[]
            )
        )
    };
    ($l:expr, $lvl:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        $l.log(
            &$crate::RecordInfo::new(
                $lvl,
                &$msg,
                file!(),
                line!(),
                module_path!(),
                &[$(($k, &$v)),*]
            )
        )
    };
);

/// Log critical level record
#[macro_export]
macro_rules! crit(
    ($l:expr, $msg:expr) => {
        log!($l, $crate::Level::Critical, $msg)
    };
    ($l:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        log!($l, $crate::Level::Critical, $msg, $($k => $v),*)
    };
);

/// Log critical level record
///
/// Prefer shorter version, unless it clashes with
/// existing `log` crate macro.
#[macro_export]
macro_rules! slog_crit(
    ($l:expr, $msg:expr) => {
        slog_log!($l, $crate::Level::Critical, $msg)
    };
    ($l:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        slog_log!($l, $crate::Level::Critical, $msg, $($k => $v),*)
    };
);

/// Log error level record
#[macro_export]
macro_rules! error(
    ($l:expr, $msg:expr) => {
        log!($l, $crate::Level::Error, $msg)
    };
    ($l:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        log!($l, $crate::Level::Error, $msg, $($k => $v),*)
    };
);

/// Log error level record
///
/// Prefer shorter version, unless it clashes with
/// existing `log` crate macro.
#[macro_export]
macro_rules! slog_error(
    ($l:expr, $msg:expr) => {
        slog_log!($l, $crate::Level::Error, $msg)
    };
    ($l:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        slog_log!($l, $crate::Level::Error, $msg, $($k => $v),*)
    };
);

/// Log warning level record
#[macro_export]
macro_rules! warn(
    ($l:expr, $msg:expr) => {
        log!($l, $crate::Level::Warning, $msg)
    };
    ($l:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        log!($l, $crate::Level::Warning, $msg, $($k => $v),*)
    };
);

/// Log warning level record
///
/// Prefer shorter version, unless it clashes with
/// existing `log` crate macro.
#[macro_export]
macro_rules! slog_warn(
    ($l:expr, $msg:expr) => {
    slog_log!($l, $crate::Level::Warning, $msg)
};
($l:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        slog_log!($l, $crate::Level::Warning, $msg, $($k => $v),*)
    };
);

/// Log info level record
#[macro_export]
macro_rules! info(
    ($l:expr, $msg:expr) => {
        log!($l, $crate::Level::Info, $msg)
    };
    ($l:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        log!($l, $crate::Level::Info, $msg, $($k => $v),*)
    };
);

/// Log info level record
///
/// Prefer shorter version, unless it clashes with
/// existing `log` crate macro.
#[macro_export]
macro_rules! slog_info(
    ($l:expr, $msg:expr) => {
        slog_log!($l, $crate::Level::Info, $msg)
    };
    ($l:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        slog_log!($l, $crate::Level::Info, $msg, $($k => $v),*)
    };
);

/// Log debug level record
#[macro_export]
macro_rules! debug(
    ($l:expr, $msg:expr) => {
        log!($l, $crate::Level::Debug, $msg)
    };
    ($l:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        log!($l, $crate::Level::Debug, $msg, $($k => $v),*)
    };
);

/// Log debug level record
///
/// Prefer shorter version, unless it clashes with
/// existing `log` crate macro.
#[macro_export]
macro_rules! slog_debug(
    ($l:expr, $msg:expr) => {
        slog_log!($l, $crate::Level::Debug, $msg)
    };
    ($l:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        slog_log!($l, $crate::Level::Debug, $msg, $($k => $v),*)
    };
);

/// Log trace level record
#[macro_export]
macro_rules! trace(
    ($l:expr, $msg:expr) => {
        log!($l, $crate::Level::Trace, $msg)
    };
    ($l:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        log!($l, $crate::Level::Trace, $msg, $($k => $v),*)
    };
);

/// Log trace level record
///
/// Prefer shorter version, unless it clashes with
/// existing `log` crate macro.
#[macro_export]
macro_rules! slog_trace(
    ($l:expr, $msg:expr) => {
        slog_log!($l, $crate::Level::Trace, $msg)
    };
    ($l:expr, $msg:expr, $($k:expr => $v:expr),*) => {
        slog_log!($l, $crate::Level::Trace, $msg, $($k => $v),*)
    };
);

/// Drains - logging outputs
pub mod drain;

/// Logger - logging handle
pub mod logger;

/// Serialization
pub mod ser;

/// Output formating
pub mod format;

pub use logger::Logger;
pub use logger::RecordInfo;

include!("_level.rs");

/// Key value pair that can be owned by `Logger`
pub type OwnedKeyValue = (&'static str, Arc<ser::SyncSerialize>);
/// Key value pair that can be part of each logging record
pub type BorrowedKeyValue<'a> = (&'static str, &'a ser::Serialize);

/// Values specific for this Logger and reference to it's parent values
#[derive(Clone)]
pub struct OwnedKeyValueNode {
    parent: Option<Arc<OwnedKeyValueNode>>,
    values: Vec<OwnedKeyValue>,
}

impl OwnedKeyValueNode {
    /// New `OwnedKeyValue` with a parent
    pub fn new(values: Vec<OwnedKeyValue>, parent: Arc<OwnedKeyValueNode>) -> Self {
        OwnedKeyValueNode {
            parent: Some(parent),
            values: values,
        }
    }

    /// New `OwnedKeyValue` without a parent (root)
    pub fn new_root(values: Vec<OwnedKeyValue>) -> Self {
        OwnedKeyValueNode {
            parent: None,
            values: values,
        }
    }

    /// Iterator over `OwnedKeyValue`-s
    pub fn iter(&self) -> OwnedKeyValueNodeIterator {
        OwnedKeyValueNodeIterator::new(self)
    }
}

/// Iterator over `OwnedKeyValue`-s
pub struct OwnedKeyValueNodeIterator<'a> {
    next_node: &'a Option<Arc<OwnedKeyValueNode>>,
    iter: std::slice::Iter<'a, OwnedKeyValue>,
}

impl<'a> OwnedKeyValueNodeIterator<'a> {
    fn new(node: &'a OwnedKeyValueNode) -> Self {
        OwnedKeyValueNodeIterator {
            next_node: &node.parent,
            iter: node.values.iter(),
        }
    }
}

impl<'a> Iterator for OwnedKeyValueNodeIterator<'a> {
    type Item = &'a OwnedKeyValue;
    fn next(&mut self) -> Option<Self::Item> {
        loop {
            match self.iter.next() {
                Some(x) => return Some(&*x),
                None => {
                    match self.next_node {
                        &Some(ref node) => {
                            self.iter = node.values.iter();
                            self.next_node = &node.parent;
                        }
                        &None => return None,
                    }
                }
            }
        }
    }
}

#[cfg(test)]
mod tests;
<|endoftext|>


<commit_before>#![feature(core, plugin, step_by, test)]
#![cfg_attr(test, deny(missing_docs, warnings))]
#![plugin(regex_macros)]

extern crate byteorder;
extern crate flate2;
extern crate nbt;
extern crate regex;
extern crate regex_macros;
extern crate rustc_serialize;
extern crate test;
extern crate time;
extern crate uuid;

pub mod packet;
pub mod proto;
pub mod types;
mod util;
<commit_msg>Fix superfluous regex_macros import<commit_after>#![feature(core, plugin, step_by, test)]
#![cfg_attr(test, deny(missing_docs, warnings))]
#![plugin(regex_macros)]

extern crate byteorder;
extern crate flate2;
extern crate nbt;
extern crate regex;
extern crate rustc_serialize;
extern crate test;
extern crate time;
extern crate uuid;

pub mod packet;
pub mod proto;
pub mod types;
mod util;
<|endoftext|>


<commit_before>extern crate byteorder;

use std::io;

use byteorder::{WriteBytesExt};

pub struct Serializer<T> where T: io::Write {
    writer: T
}

impl<T> Serializer<T> where T: io::Write {
    pub fn new(writer: T) -> Serializer<T> {
        return Serializer {
            writer: writer,
        }
    }

    fn _write_length(&mut self, length: usize) -> Result<(), io::Error> {
        assert!(length < 128);
        try!(self.writer.write_u8(length as u8));
        return Ok(());
    }

    fn _write_with_tag<F>(&mut self, tag: u8, body: F) -> Result<(), io::Error>
            where F: Fn() -> Vec<u8> {
        try!(self.writer.write_u8(tag));
        let body = body();
        try!(self._write_length(body.len()));
        try!(self.writer.write_all(&body));
        return Ok(());
    }

    pub fn write_bool(&mut self, v: bool) -> Result<(), io::Error> {
        return self._write_with_tag(1, || {
            if v {
                return b"\xff".to_vec();
            } else {
                return b"\x00".to_vec();
            }
        })
    }

    fn _int_length(&self, v: i64) -> usize {
        let mut num_bytes = 1;
        let mut i = v;

        while i > 127 || i < -128 {
            num_bytes += 1;
            i >>= 8;
        }
        return num_bytes;
    }

    pub fn write_int(&mut self, v: i64) -> Result<(), io::Error> {
        let n = self._int_length(v);
        return self._write_with_tag(2, || {
            let mut result = Vec::with_capacity(n);
            for i in (1..n+1).rev() {
                result.push((v >> ((i - 1) * 8)) as u8);
            }
            return result;
        })
    }

    pub fn write_octet_string(&mut self, v: &Vec<u8>) -> Result<(), io::Error> {
        return self._write_with_tag(4, || {
            return v.to_vec();
        })
    }
}

#[cfg(test)]
mod tests {
    use super::{Serializer};

    fn assert_serializes<T, F>(values: Vec<(T, Vec<u8>)>, f: F)
            where F: Fn(&mut Serializer<&mut Vec<u8>>, T) {
        for (value, expected) in values {
            let mut out = Vec::new();
            {
                let mut serializer = Serializer::new(&mut out);
                f(&mut serializer, value);
            }
            assert_eq!(out, expected);
        }
    }

    #[test]
    fn test_write_bool() {
        assert_serializes(vec![
            (true, b"\x01\x01\xff".to_vec()),
            (false, b"\x01\x01\x00".to_vec()),
        ], |serializer, v| {
            serializer.write_bool(v).unwrap();
        });
    }

    #[test]
    fn test_write_int() {
        assert_serializes(vec![
            (0, b"\x02\x01\x00".to_vec()),
            (127, b"\x02\x01\x7f".to_vec()),
            (128, b"\x02\x02\x00\x80".to_vec()),
            (256, b"\x02\x02\x01\x00".to_vec()),
            (-128, b"\x02\x01\x80".to_vec()),
            (-129, b"\x02\x02\xff\x7f".to_vec()),
        ], |serializer, v| {
            serializer.write_int(v).unwrap();
        })
    }

    #[test]
    fn test_write_octet_string() {
        assert_serializes(vec![
            (b"\x01\x02\x03".to_vec(), b"\x04\x03\x01\x02\x03".to_vec()),
        ], |serializer, v| {
            serializer.write_octet_string(&v).unwrap();
        })
    }
}
<commit_msg>added write_sequence<commit_after>extern crate byteorder;

use std::io;

use byteorder::{WriteBytesExt};

pub struct Serializer<T> where T: io::Write {
    writer: T
}

impl<T> Serializer<T> where T: io::Write {
    pub fn new(writer: T) -> Serializer<T> {
        return Serializer {
            writer: writer,
        }
    }

    fn _write_length(&mut self, length: usize) -> Result<(), io::Error> {
        assert!(length < 128);
        try!(self.writer.write_u8(length as u8));
        return Ok(());
    }

    fn _write_with_tag<F>(&mut self, tag: u8, body: F) -> Result<(), io::Error>
            where F: Fn() -> Vec<u8> {
        try!(self.writer.write_u8(tag));
        let body = body();
        try!(self._write_length(body.len()));
        try!(self.writer.write_all(&body));
        return Ok(());
    }

    pub fn write_bool(&mut self, v: bool) -> Result<(), io::Error> {
        return self._write_with_tag(1, || {
            if v {
                return b"\xff".to_vec();
            } else {
                return b"\x00".to_vec();
            }
        })
    }

    fn _int_length(&self, v: i64) -> usize {
        let mut num_bytes = 1;
        let mut i = v;

        while i > 127 || i < -128 {
            num_bytes += 1;
            i >>= 8;
        }
        return num_bytes;
    }

    pub fn write_int(&mut self, v: i64) -> Result<(), io::Error> {
        let n = self._int_length(v);
        return self._write_with_tag(2, || {
            let mut result = Vec::with_capacity(n);
            for i in (1..n+1).rev() {
                result.push((v >> ((i - 1) * 8)) as u8);
            }
            return result;
        })
    }

    pub fn write_octet_string(&mut self, v: &Vec<u8>) -> Result<(), io::Error> {
        return self._write_with_tag(4, || {
            return v.to_vec();
        })
    }

    pub fn write_sequence<F>(&mut self, v: F) -> Result<(), io::Error>
            where F: Fn(&mut Serializer<&mut Vec<u8>>) {
        return self._write_with_tag(48, || {
            let mut out = Vec::new();
            {
                let mut s = Serializer::new(&mut out);
                v(&mut s);
            }
            return out;
        });
    }
}

#[cfg(test)]
mod tests {
    use super::{Serializer};

    fn assert_serializes<T, F>(values: Vec<(T, Vec<u8>)>, f: F)
            where F: Fn(&mut Serializer<&mut Vec<u8>>, T) {
        for (value, expected) in values {
            let mut out = Vec::new();
            {
                let mut serializer = Serializer::new(&mut out);
                f(&mut serializer, value);
            }
            assert_eq!(out, expected);
        }
    }

    #[test]
    fn test_write_bool() {
        assert_serializes(vec![
            (true, b"\x01\x01\xff".to_vec()),
            (false, b"\x01\x01\x00".to_vec()),
        ], |serializer, v| {
            serializer.write_bool(v).unwrap();
        });
    }

    #[test]
    fn test_write_int() {
        assert_serializes(vec![
            (0, b"\x02\x01\x00".to_vec()),
            (127, b"\x02\x01\x7f".to_vec()),
            (128, b"\x02\x02\x00\x80".to_vec()),
            (256, b"\x02\x02\x01\x00".to_vec()),
            (-128, b"\x02\x01\x80".to_vec()),
            (-129, b"\x02\x02\xff\x7f".to_vec()),
        ], |serializer, v| {
            serializer.write_int(v).unwrap();
        })
    }

    #[test]
    fn test_write_octet_string() {
        assert_serializes(vec![
            (b"\x01\x02\x03".to_vec(), b"\x04\x03\x01\x02\x03".to_vec()),
        ], |serializer, v| {
            serializer.write_octet_string(&v).unwrap();
        })
    }

    #[test]
    fn test_write_sequence() {
        assert_serializes(vec![
            ((1, 2), b"\x30\x06\x02\x01\x01\x02\x01\x02".to_vec()),
        ], |serializer, (x, y)| {
            serializer.write_sequence(|s| {
                s.write_int(x).unwrap();
                s.write_int(y).unwrap();
            }).unwrap();
        })
    }
}
<|endoftext|>