<commit_before>//! Calculate the crc64 checksum of the given data, starting with the given crc.
//!
//! Implements the CRC64 used by Redis, which is the variant with "Jones" coefficients and init value of 0.
//!
//! Specification of this CRC64 variant follows:
//!
//! ```text
//! Name: crc-64-jones
//! Width: 64 bites
//! Poly: 0xad93d23594c935a9
//! Reflected In: True
//! Xor_In: 0xffffffffffffffff
//! Reflected_Out: True
//! Xor_Out: 0x0
//! Check("123456789"): 0xe9c6d914c4b8d9ca
//! ```
//!
//! Example:
//!
//! ```rust
//! let cksum = crc64::crc64(0, "123456789".as_bytes());
//! assert_eq!(16845390139448941002, cksum);
//! ```

use std::io::{self, Write};

use crc_table::CRC64_TAB;

mod crc_table;

fn to_u64(data: &[u8]) -> u64 {
    debug_assert!(data.len() == 8);
    let arr: [u8; 8] = data.try_into().expect("incorrect length");
    u64::from_le_bytes(arr)
}

pub fn crc64(crc: u64, data: &[u8]) -> u64 {
    let mut crc = crc;
    let mut len = data.len();
    let mut offset = 0usize;

    while len >= 8 {
        crc ^= to_u64(&data[offset..(offset + 8)]);
        crc = CRC64_TAB[7][(crc & 0xff) as usize]
            ^ CRC64_TAB[6][((crc >> 8) & 0xff) as usize]
            ^ CRC64_TAB[5][((crc >> 16) & 0xff) as usize]
            ^ CRC64_TAB[4][((crc >> 24) & 0xff) as usize]
            ^ CRC64_TAB[3][((crc >> 32) & 0xff) as usize]
            ^ CRC64_TAB[2][((crc >> 40) & 0xff) as usize]
            ^ CRC64_TAB[1][((crc >> 48) & 0xff) as usize]
            ^ CRC64_TAB[0][(crc >> 56) as usize];

        offset += 8;
        len -= 8;
    }

    while len > 0 {
        crc = CRC64_TAB[0][((crc ^ data[offset] as u64) & 0xff) as usize] ^ (crc >> 8);
        offset += 1;
        len -= 1;
    }

    crc
}

pub struct Crc64 {
    crc64: u64,
}

impl Crc64 {
    pub fn new() -> Crc64 {
        Crc64 { crc64: 0 }
    }
    pub fn get(&self) -> u64 {
        self.crc64
    }
}

impl Default for Crc64 {
    fn default() -> Self {
        Self::new()
    }
}

impl Write for Crc64 {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.crc64 = crc64(self.crc64, buf);
        Ok(buf.len())
    }
    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

#[test]
fn test_crc64_works() {
    assert_eq!(0xe9c6d914c4b8d9ca, crc64(0, "123456789".as_bytes()))
}

#[test]
fn test_crc64_write() {
    let step1 = "12345".as_bytes();
    let step2 = "6789".as_bytes();
    let value1 = 17326901458626182669;
    let value2 = 16845390139448941002;
    assert_eq!(value1, crc64(0, step1));
    assert_eq!(value2, crc64(value1, step2));

    let mut crc = Crc64::new();
    assert_eq!(crc.write(step1).unwrap(), step1.len());
    assert_eq!(value1, crc.get());
    assert_eq!(crc.write(step2).unwrap(), step2.len());
    assert_eq!(value2, crc.get());
}
<commit_msg>Add documentation<commit_after>//! Calculate the crc64 checksum of the given data, starting with the given crc.
//!
//! Implements the CRC64 used by Redis, which is the variant with "Jones" coefficients and init value of 0.
//!
//! Specification of this CRC64 variant follows:
//!
//! ```text
//! Name: crc-64-jones
//! Width: 64 bites
//! Poly: 0xad93d23594c935a9
//! Reflected In: True
//! Xor_In: 0xffffffffffffffff
//! Reflected_Out: True
//! Xor_Out: 0x0
//! Check("123456789"): 0xe9c6d914c4b8d9ca
//! ```
//!
//! Example:
//!
//! ```rust
//! let cksum = crc64::crc64(0, b"123456789");
//! assert_eq!(16845390139448941002, cksum);
//! ```

use std::io::{self, Write};

use crc_table::CRC64_TAB;

mod crc_table;

fn to_u64(data: &[u8]) -> u64 {
    debug_assert!(data.len() == 8);
    let arr: [u8; 8] = data.try_into().expect("incorrect length");
    u64::from_le_bytes(arr)
}

/// Calculate the Crc64 checksum over `data`, starting from `crc`.
///
/// ```rust
/// use crc64::crc64;
///
/// let cksum = crc64::crc64(0, b"123456789");
/// assert_eq!(16845390139448941002, cksum);
/// ```
pub fn crc64(crc: u64, data: &[u8]) -> u64 {
    let mut crc = crc;
    let mut len = data.len();
    let mut offset = 0usize;

    while len >= 8 {
        crc ^= to_u64(&data[offset..(offset + 8)]);
        crc = CRC64_TAB[7][(crc & 0xff) as usize]
            ^ CRC64_TAB[6][((crc >> 8) & 0xff) as usize]
            ^ CRC64_TAB[5][((crc >> 16) & 0xff) as usize]
            ^ CRC64_TAB[4][((crc >> 24) & 0xff) as usize]
            ^ CRC64_TAB[3][((crc >> 32) & 0xff) as usize]
            ^ CRC64_TAB[2][((crc >> 40) & 0xff) as usize]
            ^ CRC64_TAB[1][((crc >> 48) & 0xff) as usize]
            ^ CRC64_TAB[0][(crc >> 56) as usize];

        offset += 8;
        len -= 8;
    }

    while len > 0 {
        crc = CRC64_TAB[0][((crc ^ data[offset] as u64) & 0xff) as usize] ^ (crc >> 8);
        offset += 1;
        len -= 1;
    }

    crc
}

/// A checksummer.
///
/// You can write bytes to it to update the checksum.
///
/// ```rust
/// use std::io::Write;
/// use crc64::Crc64;
///
/// let mut cksum = Crc64::new();
/// cksum.write(&[0x1, 0x2, 0x3, 0x4, 0x5]);
/// assert_eq!(18087688510130107988, cksum.get());
/// ```
pub struct Crc64 {
    crc64: u64,
}

impl Crc64 {
    /// Creates a new checksummer.
    pub fn new() -> Crc64 {
        Crc64 { crc64: 0 }
    }

    /// Gets the current crc64 checksum.
    pub fn get(&self) -> u64 {
        self.crc64
    }
}

impl Default for Crc64 {
    fn default() -> Self {
        Self::new()
    }
}

impl Write for Crc64 {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.crc64 = crc64(self.crc64, buf);
        Ok(buf.len())
    }
    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

#[test]
fn test_crc64_works() {
    assert_eq!(0xe9c6d914c4b8d9ca, crc64(0, "123456789".as_bytes()))
}

#[test]
fn test_crc64_write() {
    let step1 = "12345".as_bytes();
    let step2 = "6789".as_bytes();
    let value1 = 17326901458626182669;
    let value2 = 16845390139448941002;
    assert_eq!(value1, crc64(0, step1));
    assert_eq!(value2, crc64(value1, step2));

    let mut crc = Crc64::new();
    assert_eq!(crc.write(step1).unwrap(), step1.len());
    assert_eq!(value1, crc.get());
    assert_eq!(crc.write(step2).unwrap(), step2.len());
    assert_eq!(value2, crc.get());
}
<|endoftext|>


<commit_before>extern crate flat_tree;

#[derive(Clone, Debug)]
pub struct Node {
    index: u64,
    parent: u64,
    hash: Vec<u8>,
    data: Option<Vec<u8>>,
    size: usize,
}

pub struct Generator {
    roots: Vec<Node>,
    blocks: u64,
    leaf: fn(&Node, &Vec<Node>) -> Vec<u8>,
    parent: fn(&Node, &Node) -> Vec<u8>,
}

impl Generator {
    pub fn new(leaf: fn(&Node, &Vec<Node>) -> Vec<u8>,
               parent: fn(&Node, &Node) -> Vec<u8>)
               -> Generator {
        Generator {
            roots: vec![],
            blocks: 0,
            leaf: leaf,
            parent: parent,
        }
    }

    pub fn next(&mut self, data: Vec<u8>) -> Vec<Node> {
        let mut nodes = vec![];
        let index = 2 * self.blocks;
        self.blocks += 1;
        let len = data.len();
        let mut leaf = Node {
            index: index,
            parent: flat_tree::parent(index),
            hash: vec![],
            data: Some(data),
            size: len,
        };
        let hash = (self.leaf)(&leaf, &self.roots);
        leaf.hash = hash;
        self.roots.push(leaf.clone());
        nodes.push(leaf.clone());

        while self.roots.len() > 1 {
            let ref left = self.roots[self.roots.len() - 2].clone();
            let ref right = self.roots[self.roots.len() - 1].clone();

            if left.parent != right.parent {
                break;
            }

            self.roots.pop();
            let leaf = Node {
                index: left.parent,
                parent: flat_tree::parent(left.parent),
                hash: (self.parent)(left, right),
                size: left.size + right.size,
                data: None,
            };
            let len = self.roots.len();
            self.roots[len - 1] = leaf.clone();
            nodes.push(leaf.clone());
        }

        nodes
    }
}

extern crate ring;

#[cfg(test)]
mod tests {
    use ring::digest;
    use super::{Generator, Node};

    #[test]
    fn it_works() {
        let mut gen = Generator::new(leaf, parent);
        let nodes = gen.next(b"Hello World".to_vec());
        assert!(nodes[0].index == 0);
        assert!(nodes[0].parent == 1);
        let data = nodes[0].data.clone().unwrap();
        assert!(data == b"Hello World");
        let hash = digest::digest(&digest::SHA256, b"Hello World").as_ref().to_vec();
        assert!(nodes[0].hash == hash);
    }

    fn parent(a: &Node, b: &Node) -> Vec<u8> {
        let mut data = a.data.clone().unwrap();
        data.append(&mut b.data.clone().unwrap());

        digest::digest(&digest::SHA256, data.as_slice())
            .as_ref()
            .to_vec()
    }

    fn leaf(leaf: &Node, roots: &Vec<Node>) -> Vec<u8> {
        let data = leaf.data.clone().unwrap();
        digest::digest(&digest::SHA256, data.as_slice()).as_ref().to_vec()
    }
}
<commit_msg>more test<commit_after>extern crate flat_tree;

#[derive(Clone, Debug)]
pub struct Node {
    index: u64,
    parent: u64,
    hash: Vec<u8>,
    data: Option<Vec<u8>>,
    size: usize,
}

pub struct Generator {
    roots: Vec<Node>,
    blocks: u64,
    leaf: fn(&Node, &Vec<Node>) -> Vec<u8>,
    parent: fn(&Node, &Node) -> Vec<u8>,
}

impl Generator {
    pub fn new(leaf: fn(&Node, &Vec<Node>) -> Vec<u8>,
               parent: fn(&Node, &Node) -> Vec<u8>)
               -> Generator {
        Generator {
            roots: vec![],
            blocks: 0,
            leaf: leaf,
            parent: parent,
        }
    }

    pub fn next(&mut self, data: Vec<u8>) -> Vec<Node> {
        let mut nodes = vec![];
        let index = 2 * self.blocks;
        self.blocks += 1;
        let len = data.len();
        let mut leaf = Node {
            index: index,
            parent: flat_tree::parent(index),
            hash: vec![],
            data: Some(data),
            size: len,
        };
        let hash = (self.leaf)(&leaf, &self.roots);
        leaf.hash = hash;
        self.roots.push(leaf.clone());
        nodes.push(leaf.clone());

        while self.roots.len() > 1 {
            let ref left = self.roots[self.roots.len() - 2].clone();
            let ref right = self.roots[self.roots.len() - 1].clone();

            if left.parent != right.parent {
                break;
            }

            self.roots.pop();
            let leaf = Node {
                index: left.parent,
                parent: flat_tree::parent(left.parent),
                hash: (self.parent)(left, right),
                size: left.size + right.size,
                data: None,
            };
            let len = self.roots.len();
            self.roots[len - 1] = leaf.clone();
            nodes.push(leaf.clone());
        }

        nodes
    }
}

extern crate ring;

#[cfg(test)]
mod tests {
    use ring::digest;
    use super::{Generator, Node};

    #[test]
    fn gen1() {
        let mut gen = Generator::new(leaf, parent);
        let nodes = gen.next(b"Hello World".to_vec());
        assert!(nodes[0].index == 0);
        assert!(nodes[0].parent == 1);
        let data = nodes[0].data.clone().unwrap();
        assert!(data == b"Hello World");
        let hash = digest::digest(&digest::SHA256, b"Hello World").as_ref().to_vec();
        assert!(nodes[0].hash == hash);
    }

    #[test]
    fn gen2() {
        let mut gen = Generator::new(leaf, parent);
        let nodes = gen.next(b"Hello".to_vec());
        let n1 = nodes[0].clone();
        assert!(nodes[0].index == 0);
        assert!(nodes[0].parent == 1);
        let data = nodes[0].data.clone().unwrap();
        assert!(data == b"Hello");
        let hash = digest::digest(&digest::SHA256, b"Hello").as_ref().to_vec();
        assert!(nodes[0].hash == hash);

        let nodes = gen.next(b"World".to_vec());
        let n2 = nodes[0].clone();
        assert!(nodes[0].index == 2);
        assert!(nodes[0].parent == 1);
        let data = nodes[0].data.clone().unwrap();
        assert!(data == b"World");
        let hash = digest::digest(&digest::SHA256, b"World").as_ref().to_vec();
        assert!(nodes[0].hash == hash);

        assert!(nodes[1].index == 1);
        assert!(nodes[1].parent == 3);
        assert!(nodes[1].data.is_none());
        let data = concat(&n1, &n2);

        let hash = digest::digest(&digest::SHA256, data.as_slice()).as_ref().to_vec();
        assert!(nodes[1].hash == hash);
    }

    fn parent(a: &Node, b: &Node) -> Vec<u8> {
        let data = concat(a, b);

        digest::digest(&digest::SHA256, data.as_slice())
            .as_ref()
            .to_vec()
    }

    fn leaf(leaf: &Node, roots: &Vec<Node>) -> Vec<u8> {
        let data = leaf.data.clone().unwrap();
        digest::digest(&digest::SHA256, data.as_slice()).as_ref().to_vec()
    }

    // concat helper
    fn concat(a: &Node, b: &Node) -> Vec<u8> {
        let mut data = a.data.clone().unwrap();
        data.append(&mut b.data.clone().unwrap());

        data
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Dawid Ciężarkiewicz
// See LICENSE-MPL
//
// Non-thread-shareable, simple and efficient Circular Buffer
// implementation that can store N elements when full (typical circular
// buffer implementations store N-1) without using separate flags.
//
// Uses only `core` so can be used in `#[no_std]` projects by using
// `no_std` feature.
//
#![no_std]
#![feature(const_fn)]
#![feature(test)]

use core::option::Option::{self, Some, None};
use core::marker::PhantomData;

extern crate test as test;

const CBUF_DATA_BIT: usize = !((usize::max_value() << 1) >> 1);

/// Circular Buffer
///
/// Turns a slice into a Circular buffer with head and tail indexes.
#[derive(Debug)]
pub struct CBuf<'a, T: 'a> {
    buf: &'a mut [T],
    ctrl: CBufControl<T>,
}

/// Circular Buffer Control
///
/// Implements the actual logic of Circular Buffer, but requires passing &[T]
/// to `get` and `put`.
#[derive(Debug)]
pub struct CBufControl<T> {
    head: usize,
    tail: usize,
    phantom: PhantomData<T>,
}

#[cfg(not(feature = "no_std"))]
impl<'a, T: Clone> CBuf<'a, T>
    where T: Clone
{
    /// Create new CBuf
    ///
    /// Length (not capacity) will be used to store elements
    /// in the circular buffer.
    pub fn new(buf: &'a mut [T]) -> CBuf<T> {
        debug_assert!(buf.len() < CBUF_DATA_BIT);

        CBuf {
            buf: buf,
            ctrl: CBufControl::new(),
        }
    }

    /// Is buffer full?
    #[inline]
    pub fn is_full(&self) -> bool {
        let CBuf { ref ctrl, .. } = *self;

        ctrl.is_full()
    }

    /// Is buffer empty?
    #[inline]
    pub fn is_empty(&self) -> bool {
        let CBuf { ref ctrl, .. } = *self;

        ctrl.is_empty()
    }

    /// Peek next element from the CBuf without removing it
    ///
    /// Returns `None` if buffer is empty.
    #[inline]
    pub fn peek(&mut self) -> Option<T> {
        let CBuf { ref mut ctrl, ref buf } = *self;

        ctrl.get(buf)
    }

    /// Peek next element from the CBuf without removing it
    ///
    /// Makes the buffer misbehave if it's empty.
    #[inline]
    pub fn peek_unchecked(&mut self) -> T {
        let CBuf { ref mut ctrl, ref buf } = *self;

        ctrl.peek_unchecked(buf)
    }

    /// Remove one element from the CBuf
    ///
    /// Returns `None` if buffer is empty.
    #[inline]
    pub fn get(&mut self) -> Option<T> {
        let CBuf { ref mut ctrl, ref buf } = *self;

        ctrl.get(buf)
    }

    /// Remove one element from the CBuf
    ///
    /// Makes the buffer misbehave if it's empty.
    #[inline]
    pub fn get_unchecked(&mut self) -> T {
        let CBuf { ref mut ctrl, ref buf } = *self;

        ctrl.get_unchecked(buf)
    }

    /// Add element the buffer
    ///
    /// Ignores the write if buffer is full.
    #[inline]
    pub fn put(&mut self, val: T) {
        let CBuf { ref mut ctrl, ref mut buf } = *self;

        ctrl.put(buf, val)
    }

    /// Add element the buffer
    ///
    /// Makes the buffer misbehave if it's full.
    #[inline]
    pub fn put_unchecked(&mut self, val: T) {
        let CBuf { ref mut ctrl, ref mut buf } = *self;

        ctrl.put_unchecked(buf, val)
    }
}

impl<T: Clone> CBufControl<T> {
    pub fn new() -> CBufControl<T> {
        CBufControl {
            tail: 0,
            head: 0,
            phantom: PhantomData,
        }
    }

    /// See corresponding method of CBuf
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.head == self.tail
    }

    /// See corresponding method of CBuf
    #[inline]
    pub fn is_full(&self) -> bool {
        (self.head ^ self.tail) == CBUF_DATA_BIT
    }

    /// See corresponding method of CBuf
    pub fn get(&mut self, buf: &[T]) -> Option<T> {
        if self.is_empty() {
            return None;
        }
        Some(self.get_unchecked(buf))
    }

    /// See corresponding method of CBuf
    pub fn get_unchecked(&mut self, buf: &[T]) -> T {
        let val = buf[self.tail & !CBUF_DATA_BIT].clone();

        self.tail += 1;

        if (self.tail & !CBUF_DATA_BIT) >= buf.len() {
            self.tail = (self.tail - buf.len()) ^ CBUF_DATA_BIT;
        }

        val
    }

    /// See corresponding method of CBuf
    pub fn peek(&mut self, buf: &[T]) -> Option<T> {
        if self.is_empty() {
            return None;
        }
        Some(self.peek_unchecked(buf))
    }

    /// See corresponding method of CBuf
    pub fn peek_unchecked(&mut self, buf: &[T]) -> T {
        buf[self.tail & !CBUF_DATA_BIT].clone()
    }

    /// See corresponding method of CBuf
    pub fn put(&mut self, buf: &mut [T], val: T) {
        if self.is_full() {
            return;
        }
        self.put_unchecked(buf, val)
    }

    /// See corresponding method of CBuf
    pub fn put_unchecked(&mut self, buf: &mut [T], val: T) {
        buf[self.head & !CBUF_DATA_BIT] = val;

        self.head += 1;

        if (self.head & !CBUF_DATA_BIT) >= buf.len() {
            self.head = (self.head - buf.len()) ^ CBUF_DATA_BIT;
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use test::Bencher;
    use test;

    #[test]
    fn basic_ctl() {
        let mut buf = [0u8, 2];
        let mut cbuf = CBufControl::<u8>::new();

        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());

        cbuf.put(&mut buf, 0);
        cbuf.put(&mut buf, 0);
        assert!(!cbuf.is_empty());
        assert!(cbuf.is_full());

        cbuf.get(&buf);
        cbuf.get(&buf);
        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());
    }

    #[test]
    fn basic_cbuf() {
        let mut buf = &mut [0u8, 0u8];
        let mut cbuf = CBuf::new(buf);

        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());

        cbuf.put(0);
        cbuf.put(0);
        assert!(!cbuf.is_empty());
        assert!(cbuf.is_full());

        cbuf.get();
        cbuf.get();
        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());
    }

    #[test]
    fn patterns() {
        let mut buf = [0u8, 7];
        let mut cbuf = CBufControl::<u8>::new();

        let mut cur_len = 0;
        let mut put_val = 0;
        let mut get_val = 0;

        for pattern in 0..256 {
            if cur_len == 0 {
                assert!(cbuf.is_empty());
            }
            if cur_len == buf.len() {
                assert!(cbuf.is_full());
            }

            for bit_i in 0..8 {
                match pattern & (1 << bit_i) == 0 {
                    true => {
                        if cbuf.is_empty() {
                            assert!(cbuf.peek(&buf).is_none());
                            assert!(cbuf.get(&buf).is_none());
                        } else {
                            assert!(cbuf.peek(&buf).unwrap() == get_val);
                            let val = cbuf.get(&buf).unwrap();
                            assert!(val == get_val);
                            get_val = get_val.wrapping_add(1);
                            cur_len -= 1;
                        }
                    }
                    false => {
                        if cbuf.is_full() {
                            cbuf.put(&mut buf, put_val);
                            assert!(cbuf.is_full());
                        } else {
                            cbuf.put(&mut buf, put_val);
                            put_val = put_val.wrapping_add(1);
                            cur_len += 1;
                        }
                    }
                }
            }
        }
    }

    #[bench]
    pub fn put_and_get(b: &mut Bencher) {
        let buf = &mut [0u8; 256];
        let mut cbuf = CBuf::new(buf);

        b.iter(|| {
            cbuf.put(0u8);
            cbuf.get();
        });

        test::black_box(cbuf.get());
    }

    #[bench]
    pub fn put_unchecked_and_get(b: &mut Bencher) {
        let buf = &mut [0u8; 256];
        let mut cbuf = CBuf::new(buf);

        b.iter(|| {
            cbuf.put_unchecked(0u8);
            cbuf.get_unchecked();
        });

        test::black_box(cbuf.get());
    }
}
<commit_msg>simplify, fix bug, add unit test<commit_after>//! Modified 2016 Garrett Berg <vitiral@gmail.com>
//! Copyright 2015 Dawid Ciężarkiewicz
//! See LICENSE-MPL
//!
//! Non-thread-shareable, simple and efficient Circular Buffer
//! implementation that can store N elements when full (typical circular
//! buffer implementations store N-1) without using separate flags.
//!
//! Uses only `core` so can be used in `#[no_std]` projects by using
//! `no_std` feature.
#![no_std]
#![feature(const_fn)]
#![feature(test)]

use core::option::Option::{self, Some, None};
use core::marker::PhantomData;

extern crate test as test;

const CBUF_DATA_BIT: usize = !((usize::max_value() << 1) >> 1);

/// Circular Buffer
///
/// Turns a slice into a Circular buffer with head and tail indexes.
#[derive(Debug)]
pub struct CBuf<'a, T: 'a> {
    buf: &'a mut [T],
    ctrl: CBufControl<T>,
}

/// Circular Buffer Control
///
/// Implements the actual logic of Circular Buffer, but requires passing &[T]
/// to `get` and `put`.
#[derive(Debug)]
pub struct CBufControl<T> {
    head: usize,
    tail: usize,
    phantom: PhantomData<T>,
}

#[cfg(not(feature = "no_std"))]
impl<'a, T: Clone> CBuf<'a, T>
    where T: Clone
{
    /// Create new CBuf
    ///
    /// Length (not capacity) will be used to store elements
    /// in the circular buffer.
    pub fn new(buf: &'a mut [T]) -> CBuf<T> {
        debug_assert!(buf.len() < CBUF_DATA_BIT);

        CBuf {
            buf: buf,
            ctrl: CBufControl::new(),
        }
    }

    /// Is buffer full?
    #[inline]
    pub fn is_full(&self) -> bool {
        self.ctrl.is_full()
    }

    /// Is buffer empty?
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.ctrl.is_empty()
    }

    /// Peek next element from the CBuf without removing it
    ///
    /// Returns `None` if buffer is empty.
    #[inline]
    pub fn peek(&mut self) -> Option<T> {
        self.ctrl.peek(self.buf)
    }

    /// Peek next element from the CBuf without removing it
    ///
    /// Makes the buffer misbehave if it's empty.
    #[inline]
    pub fn peek_unchecked(&mut self) -> T {
        self.ctrl.peek_unchecked(self.buf)
    }

    /// Remove one element from the CBuf
    ///
    /// Returns `None` if buffer is empty.
    #[inline]
    pub fn get(&mut self) -> Option<T> {
        self.ctrl.get(self.buf)
    }

    /// Remove one element from the CBuf
    ///
    /// Makes the buffer misbehave if it's empty.
    #[inline]
    pub fn get_unchecked(&mut self) -> T {
        self.ctrl.get_unchecked(self.buf)
    }

    /// Add element the buffer
    ///
    /// Ignores the write if buffer is full.
    #[inline]
    pub fn put(&mut self, val: T) {
        self.ctrl.put(self.buf, val)
    }

    /// Add element the buffer
    ///
    /// Makes the buffer misbehave if it's full.
    #[inline]
    pub fn put_unchecked(&mut self, val: T) {
        self.ctrl.put_unchecked(self.buf, val)
    }
}

impl<T: Clone> CBufControl<T> {
    pub fn new() -> CBufControl<T> {
        CBufControl {
            tail: 0,
            head: 0,
            phantom: PhantomData,
        }
    }

    /// See corresponding method of CBuf
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.head == self.tail
    }

    /// See corresponding method of CBuf
    #[inline]
    pub fn is_full(&self) -> bool {
        (self.head ^ self.tail) == CBUF_DATA_BIT
    }

    /// See corresponding method of CBuf
    pub fn get(&mut self, buf: &[T]) -> Option<T> {
        if self.is_empty() {
            return None;
        }
        Some(self.get_unchecked(buf))
    }

    /// See corresponding method of CBuf
    pub fn get_unchecked(&mut self, buf: &[T]) -> T {
        let val = buf[self.tail & !CBUF_DATA_BIT].clone();

        self.tail += 1;

        if (self.tail & !CBUF_DATA_BIT) >= buf.len() {
            self.tail = (self.tail - buf.len()) ^ CBUF_DATA_BIT;
        }

        val
    }

    /// See corresponding method of CBuf
    pub fn peek(&mut self, buf: &[T]) -> Option<T> {
        if self.is_empty() {
            return None;
        }
        Some(self.peek_unchecked(buf))
    }

    /// See corresponding method of CBuf
    pub fn peek_unchecked(&mut self, buf: &[T]) -> T {
        buf[self.tail & !CBUF_DATA_BIT].clone()
    }

    /// See corresponding method of CBuf
    pub fn put(&mut self, buf: &mut [T], val: T) {
        if self.is_full() {
            return;
        }
        self.put_unchecked(buf, val)
    }

    /// See corresponding method of CBuf
    pub fn put_unchecked(&mut self, buf: &mut [T], val: T) {
        buf[self.head & !CBUF_DATA_BIT] = val;

        self.head += 1;

        if (self.head & !CBUF_DATA_BIT) >= buf.len() {
            self.head = (self.head - buf.len()) ^ CBUF_DATA_BIT;
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use test::Bencher;
    use test;

    #[test]
    fn basic_ctl() {
        let mut buf = &mut [0u8, 2];
        let mut cbuf = CBufControl::<u8>::new();

        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());

        cbuf.put(buf, 3);
        cbuf.put(buf, 4);
        assert!(!cbuf.is_empty());
        assert!(cbuf.is_full());

        assert_eq!(cbuf.peek(buf).unwrap(), 3);
        cbuf.peek(buf).unwrap();
        assert!(!cbuf.is_empty());
        assert!(cbuf.is_full());

        assert_eq!(cbuf.get(buf).unwrap(), 3);
        assert_eq!(cbuf.get(buf).unwrap(), 4);
        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());
    }

    #[test]
    fn basic_cbuf() {
        let mut buf = &mut [0u8, 0u8];
        let mut cbuf = CBuf::new(buf);

        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());

        cbuf.put(3);
        cbuf.put(4);
        assert!(!cbuf.is_empty());
        assert!(cbuf.is_full());

        assert_eq!(cbuf.peek().unwrap(), 3);
        cbuf.peek().unwrap();
        assert!(!cbuf.is_empty());
        assert!(cbuf.is_full());

        assert_eq!(cbuf.get().unwrap(), 3);
        assert_eq!(cbuf.get().unwrap(), 4);
        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());
    }

    #[test]
    fn patterns() {
        let mut buf = [0u8, 7];
        let mut cbuf = CBufControl::<u8>::new();

        let mut cur_len = 0;
        let mut put_val = 0;
        let mut get_val = 0;

        for pattern in 0..256 {
            if cur_len == 0 {
                assert!(cbuf.is_empty());
            }
            if cur_len == buf.len() {
                assert!(cbuf.is_full());
            }

            for bit_i in 0..8 {
                match pattern & (1 << bit_i) == 0 {
                    true => {
                        if cbuf.is_empty() {
                            assert!(cbuf.peek(&buf).is_none());
                            assert!(cbuf.get(&buf).is_none());
                        } else {
                            assert!(cbuf.peek(&buf).unwrap() == get_val);
                            let val = cbuf.get(&buf).unwrap();
                            assert!(val == get_val);
                            get_val = get_val.wrapping_add(1);
                            cur_len -= 1;
                        }
                    }
                    false => {
                        if cbuf.is_full() {
                            cbuf.put(&mut buf, put_val);
                            assert!(cbuf.is_full());
                        } else {
                            cbuf.put(&mut buf, put_val);
                            put_val = put_val.wrapping_add(1);
                            cur_len += 1;
                        }
                    }
                }
            }
        }
    }

    #[bench]
    pub fn put_and_get(b: &mut Bencher) {
        let buf = &mut [0u8; 256];
        let mut cbuf = CBuf::new(buf);

        b.iter(|| {
            cbuf.put(0u8);
            cbuf.get();
        });

        test::black_box(cbuf.get());
    }

    #[bench]
    pub fn put_unchecked_and_get(b: &mut Bencher) {
        let buf = &mut [0u8; 256];
        let mut cbuf = CBuf::new(buf);

        b.iter(|| {
            cbuf.put_unchecked(0u8);
            cbuf.get_unchecked();
        });

        test::black_box(cbuf.get());
    }
}
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! swrite {
    // single tt rules ---------------------------------------------------------
    (@one $w:ident, ($e:expr)) => { write!($w, "{}", $e) };
    (@one $w:ident, [$e:expr]) => { write!($w, "{:?}", $e) };
    (@one $w:ident, {$e:tt : $($fmt:tt)*}) => {
        write!($w, concat!("{:", stringify!($($fmt)*), "}"), $e)
    };
    (@one $w:ident, {$($arg:tt)*}) => {
        write!($w, $($arg)*)
    };
    (@one $w:ident, $string:tt) => {
        write!($w, "{}", concat!($string))
    };

    // expression parsing (manually, because we can't use :expr before `{`)
    (@expr $w:ident {$($before:tt)*} ($($e:tt)*) {$($block:tt)*} $($rest:tt)* ) => {
        swrite!(@rec $w, $($before)* ($($e)*) {$($block)*} $($rest)*)
    };
    (@expr $w:ident {$($before:tt)*} ($($expr:tt)*) $tt:tt $($rest:tt)* ) => {
        swrite!(@expr $w {$($before)*} ($($expr)* $tt) $($rest)*)
    };

    // recursive parsing -------------------------------------------------------
    // for
    (@rec $w:ident, for $p:pat in ($e:expr) { $($body:tt)* } $($rest:tt)* ) => {
        {
            for $p in $e {
                swrite!(@rec $w, $($body)*);
            }
            swrite!(@rec $w, $($rest)*);
        }
    };
    (@rec $w:ident, for $p:pat in $($tt:tt)* ) => {
        swrite!(@expr $w { for $p in } () $($tt)*)
    };

    // match
    (@rec $w:ident, match ($e:expr) { $( $($p:pat)|+ $(if $g:expr)* => { $($body:tt)* } )* } $($rest:tt)* ) => {
        {
            match $e {
                $(
                    $($p)|+ $(if $g)* => {
                        swrite!(@rec $w, $($body)*)
                    }
                )*
            }
            swrite!(@rec $w, $($rest)*);
        }
    };
    (@rec $w:ident, match $($tt:tt)* ) => {
        swrite!(@expr $w { match } () $($tt)*)
    };

    // if let
    (@rec $w:ident, if let $p:pat = ($e:expr) { $($then:tt)* } else { $($els:tt)* } $($rest:tt)* ) => {
        {
            if let $p = $e {
                swrite!(@rec $w, $($then)*);
            } else {
                swrite!(@rec $w, $($els)*);
            }
            swrite!(@rec $w, $($rest)*);
        }
    };
    (@rec $w:ident, if let $p:pat = ($e:expr) { $($then:tt)* } else if $($rest:tt)* ) => {
        swrite!(@ifelseerror)
    };
    (@rec $w:ident, if let $p:pat = ($e:expr) { $($then:tt)* } $($rest:tt)* ) => {
        swrite!(@rec $w, if let $p = ($e) { $($then)* } else {} $($rest)*);
    };
    (@rec $w:ident, if let $p:pat = $($tt:tt)* ) => {
        swrite!(@expr $w { if let $p = } () $($tt)*)
    };

    // if
    (@rec $w:ident, if ($cond:expr) { $($then:tt)* } else { $($els:tt)* } $($rest:tt)* ) => {
        {
            if $cond {
                swrite!(@rec $w, $($then)*);
            } else {
                swrite!(@rec $w, $($els)*);
            }
            swrite!(@rec $w, $($rest)*);
        }
    };
    (@rec $w:ident, if ($cont:expr) { $($then:tt)* } else if $($rest:tt)* ) => {
        swrite!(@ifelseerror)
    };
    (@rec $w:ident, if ($cond:expr) { $($then:tt)* } $($rest:tt)* ) => {
        swrite!(@rec $w, if ($cond) { $($then)* } else {} $($rest)*);
    };
    (@rec $w:ident, if $($tt:tt)* ) => {
        swrite!(@expr $w { if } () $($tt)*)
    };

    // single tt
    (@rec $w:ident, $part:tt $($rest:tt)*) => {
        {
            match swrite!(@one $w, $part) {
                Ok(_) => (),
                error => return error,
            }
            swrite!(@rec $w, $($rest)*);
        }
    };

    // terminator
    (@rec $w:ident, ) => { () };

    (@ifelseerror) => {
        {
            let ERROR: () = "`else if` is unsupported";
            let NOTE: () = "use `match` or `else { if ... }` instead";
        }
    };

    // entry point -------------------------------------------------------------
    ($writer:expr, $($part:tt)*) => {
        (||{
            let mut _w = $writer;
            swrite!(@rec _w, $($part)*);
            Ok(())
        })()
    };
    ($writer:expr) => { swrite!($writer,) };
}

#[macro_export]
macro_rules! swriteln {
    ($($arg:tt)*) => { swrite!($($arg)* "\n") }
}

#[macro_export]
macro_rules! sprint {
    ($($arg:tt)*) => {
        {
            use ::std::io::Write;
            let o = ::std::io::stdout();
            swrite!(o.lock(), $($arg)*).unwrap();
        }
    }
}

#[macro_export]
macro_rules! sprintln {
    ($($arg:tt)*) => { sprint!($($arg)* "\n") }
}

#[macro_export]
macro_rules! sprerr {
    ($($arg:tt)*) => {
        {
            use ::std::io::Write;
            let o = ::std::io::stderr();
            swrite!(o.lock(), $($arg)*).unwrap();
        }
    }
}

#[macro_export]
macro_rules! sprerrln {
    ($($arg:tt)*) => { sprerr!($($arg)* "\n") }
}

#[macro_export]
macro_rules! sformat {
    () => { String::new() };
    ($($arg:tt)*) => {
        {
            use ::std::fmt::Write;
            let mut _s = String::new(); // TODO with capacity
            swrite!(&mut _s, $($arg)*).ok();
            _s
        }
    }
}

#[test]
fn basics() {
    let world = "World";
    assert_eq!(sformat!("Hello, "(world)"!"), "Hello, World!");
    let x = 3;
    assert_eq!(sformat!((x)" * 2 = "(x * 2)), "3 * 2 = 6");
}

#[test]
fn empty() {
    assert_eq!(sformat!(), "");
}

#[test]
fn vec() {
    let v = vec![1,2,3];
    assert_eq!(sformat!([v]), "[1, 2, 3]");
}

#[test]
fn write() {
    use std::io::Write;
    let mut v = Vec::new();
    swriteln!(&mut v, "hi" "!").unwrap();
    assert_eq!(v, "hi!\n".as_bytes());
}

#[test]
fn format() {
    assert_eq!( sformat!({5:02}), "05" );
    assert_eq!( sformat!({"{}-{}", 4, 2}), "4-2" );
}

#[test]
fn hello() {
    let foo = "foo";
    let x = 2;
    let y = 4;
    sprintln!("Bar "(foo)" and "(x));
    sprintln!( (x)" < "(y) );
    sprintln!( for x in (&[1,2,3]) { (x)" :: " } "nil" );
}

#[test]
fn matrix() {
    let matrix = vec![vec![0]];
    assert_eq!(
        sformat!( for row in &matrix { for x in row { {x:3} } "\n" } ),
        "  0\n"
    );
}

#[test]
fn boo() {
    let a = Some(5);
    sprintln!(if let Some(_) = a { "yes" });
}

#[test]
fn test_match() {
    let s = sformat!(
        match Some(5) {
            Some(x) if x > 3 => { (x) }
            Some(2) | None => {}
            _ => {}
        }
        "."
    );
    assert_eq!(s, "5.");
}
<commit_msg>split long lines<commit_after>#[macro_export]
macro_rules! swrite {
    // single tt rules ---------------------------------------------------------
    (@one $w:ident, ($e:expr)) => { write!($w, "{}", $e) };
    (@one $w:ident, [$e:expr]) => { write!($w, "{:?}", $e) };
    (@one $w:ident, {$e:tt : $($fmt:tt)*}) => {
        write!($w, concat!("{:", stringify!($($fmt)*), "}"), $e)
    };
    (@one $w:ident, {$($arg:tt)*}) => {
        write!($w, $($arg)*)
    };
    (@one $w:ident, $string:tt) => {
        write!($w, "{}", concat!($string))
    };

    // expression parsing (manually, because we can't use :expr before `{`)
    (@expr $w:ident {$($before:tt)*} ($($e:tt)*) {$($block:tt)*} $($rest:tt)* ) => {
        swrite!(@rec $w, $($before)* ($($e)*) {$($block)*} $($rest)*)
    };
    (@expr $w:ident {$($before:tt)*} ($($expr:tt)*) $tt:tt $($rest:tt)* ) => {
        swrite!(@expr $w {$($before)*} ($($expr)* $tt) $($rest)*)
    };

    // recursive parsing -------------------------------------------------------
    // for
    (@rec $w:ident, for $p:pat in ($e:expr) { $($body:tt)* } $($rest:tt)* ) => {
        {
            for $p in $e {
                swrite!(@rec $w, $($body)*);
            }
            swrite!(@rec $w, $($rest)*);
        }
    };
    (@rec $w:ident, for $p:pat in $($tt:tt)* ) => {
        swrite!(@expr $w { for $p in } () $($tt)*)
    };

    // match
    (
        @rec $w:ident,
        match ($e:expr) {
            $( $($p:pat)|+ $(if $g:expr)* => { $($body:tt)* } )*
        }
        $($rest:tt)*
    ) => {
        {
            match $e {
                $(
                    $($p)|+ $(if $g)* => {
                        swrite!(@rec $w, $($body)*)
                    }
                )*
            }
            swrite!(@rec $w, $($rest)*);
        }
    };
    (@rec $w:ident, match $($tt:tt)* ) => {
        swrite!(@expr $w { match } () $($tt)*)
    };

    // if let
    (
        @rec $w:ident,
        if let $p:pat = ($e:expr) { $($then:tt)* }
        else { $($els:tt)* }
        $($rest:tt)*
    ) => {
        {
            if let $p = $e {
                swrite!(@rec $w, $($then)*);
            } else {
                swrite!(@rec $w, $($els)*);
            }
            swrite!(@rec $w, $($rest)*);
        }
    };
    (
        @rec $w:ident,
        if let $p:pat = ($e:expr) { $($then:tt)* }
        else if $($rest:tt)*
    ) => {
        swrite!(@ifelseerror)
    };
    (
        @rec $w:ident,
        if let $p:pat = ($e:expr) { $($then:tt)* }
        $($rest:tt)*
    ) => {
        swrite!(@rec $w, if let $p = ($e) { $($then)* } else {} $($rest)*);
    };
    (@rec $w:ident, if let $p:pat = $($tt:tt)* ) => {
        swrite!(@expr $w { if let $p = } () $($tt)*)
    };

    // if
    (
        @rec $w:ident,
        if ($cond:expr) { $($then:tt)* }
        else { $($els:tt)* }
        $($rest:tt)*
    ) => {
        {
            if $cond {
                swrite!(@rec $w, $($then)*);
            } else {
                swrite!(@rec $w, $($els)*);
            }
            swrite!(@rec $w, $($rest)*);
        }
    };
    (
        @rec $w:ident,
        if ($cont:expr) { $($then:tt)* }
        else if $($rest:tt)*
    ) => {
        swrite!(@ifelseerror)
    };
    (@rec $w:ident, if ($cond:expr) { $($then:tt)* } $($rest:tt)* ) => {
        swrite!(@rec $w, if ($cond) { $($then)* } else {} $($rest)*);
    };
    (@rec $w:ident, if $($tt:tt)* ) => {
        swrite!(@expr $w { if } () $($tt)*)
    };

    // single tt
    (@rec $w:ident, $part:tt $($rest:tt)*) => {
        {
            match swrite!(@one $w, $part) {
                Ok(_) => (),
                error => return error,
            }
            swrite!(@rec $w, $($rest)*);
        }
    };

    // terminator
    (@rec $w:ident, ) => { () };

    (@ifelseerror) => {
        {
            let ERROR: () = "`else if` is unsupported";
            let NOTE: () = "use `match` or `else { if ... }` instead";
        }
    };

    // entry point -------------------------------------------------------------
    ($writer:expr, $($part:tt)*) => {
        (||{
            let mut _w = $writer;
            swrite!(@rec _w, $($part)*);
            Ok(())
        })()
    };
    ($writer:expr) => { swrite!($writer,) };
}

#[macro_export]
macro_rules! swriteln {
    ($($arg:tt)*) => { swrite!($($arg)* "\n") }
}

#[macro_export]
macro_rules! sprint {
    ($($arg:tt)*) => {
        {
            use ::std::io::Write;
            let o = ::std::io::stdout();
            swrite!(o.lock(), $($arg)*).unwrap();
        }
    }
}

#[macro_export]
macro_rules! sprintln {
    ($($arg:tt)*) => { sprint!($($arg)* "\n") }
}

#[macro_export]
macro_rules! sprerr {
    ($($arg:tt)*) => {
        {
            use ::std::io::Write;
            let o = ::std::io::stderr();
            swrite!(o.lock(), $($arg)*).unwrap();
        }
    }
}

#[macro_export]
macro_rules! sprerrln {
    ($($arg:tt)*) => { sprerr!($($arg)* "\n") }
}

#[macro_export]
macro_rules! sformat {
    () => { String::new() };
    ($($arg:tt)*) => {
        {
            use ::std::fmt::Write;
            let mut _s = String::new(); // TODO with capacity
            swrite!(&mut _s, $($arg)*).ok();
            _s
        }
    }
}

#[test]
fn basics() {
    let world = "World";
    assert_eq!(sformat!("Hello, "(world)"!"), "Hello, World!");
    let x = 3;
    assert_eq!(sformat!((x)" * 2 = "(x * 2)), "3 * 2 = 6");
}

#[test]
fn empty() {
    assert_eq!(sformat!(), "");
}

#[test]
fn vec() {
    let v = vec![1,2,3];
    assert_eq!(sformat!([v]), "[1, 2, 3]");
}

#[test]
fn write() {
    use std::io::Write;
    let mut v = Vec::new();
    swriteln!(&mut v, "hi" "!").unwrap();
    assert_eq!(v, "hi!\n".as_bytes());
}

#[test]
fn format() {
    assert_eq!( sformat!({5:02}), "05" );
    assert_eq!( sformat!({"{}-{}", 4, 2}), "4-2" );
}

#[test]
fn hello() {
    let foo = "foo";
    let x = 2;
    let y = 4;
    sprintln!("Bar "(foo)" and "(x));
    sprintln!( (x)" < "(y) );
    sprintln!( for x in (&[1,2,3]) { (x)" :: " } "nil" );
}

#[test]
fn matrix() {
    let matrix = vec![vec![0]];
    assert_eq!(
        sformat!( for row in &matrix { for x in row { {x:3} } "\n" } ),
        "  0\n"
    );
}

#[test]
fn boo() {
    let a = Some(5);
    sprintln!(if let Some(_) = a { "yes" });
}

#[test]
fn test_match() {
    let s = sformat!(
        match Some(5) {
            Some(x) if x > 3 => { (x) }
            Some(2) | None => {}
            _ => {}
        }
        "."
    );
    assert_eq!(s, "5.");
}
<|endoftext|>


<commit_before>extern crate libc;
/*
 * seccomp actions
 */
#[allow(non_camel_case_types)]
pub type scmp_filter_ctx = libc::c_void;

/**
 * Error retern value
 */
pub const __NR_SCMP_ERROR: libc::c_int = -1;

/**
 * Kill the calling thread
 */
pub const SCMP_ACT_KILL: u32  = 0x00000000;
/**
 * Kill the calling process
 */
pub const SCMP_ACT_KILL_PROCESS: u32 = 0x80000000;
/**
 * Throw a SIGSYS signal
 */
pub const SCMP_ACT_TRAP: u32 = 0x00030000;
/**
 * Return the specified error code
 */
#[allow(non_snake_case)]
pub fn SCMP_ACT_ERRNO(x: u32) -> u32 { 0x00050000 | ((x) & 0x0000ffff) }
/**
 * Notify a tracing process with the specified value
 */
#[allow(non_snake_case)]
pub fn SCMP_ACT_TRACE(x: u32) -> u32 { 0x7ff00000 | ((x) & 0x0000ffff) }
/**
 * Allow the syscall to be executed
 */
pub const SCMP_ACT_ALLOW: u32 = 0x7fff0000;

/**
 * Filter attributes
 */
#[allow(non_camel_case_types)]
#[derive(Debug,Clone,Copy)]
#[repr(C)]
pub enum scmp_filter_attr {
    _SCMP_FLTATR_MIN,
    SCMP_FLTATR_ACT_DEFAULT, /** default filter action */
    SCMP_FLTATR_ACT_BADARCH, /** bad architecture action */
    SCMP_FLTATR_CTL_NNP, /** set NO_NEW_PRIVS on filter load */
    _SCMP_FLTATR_MAX,
}

/**
 * Comparison operators
 */
#[allow(non_camel_case_types)]
#[derive(Debug,Clone,Copy)]
#[repr(C)]
pub enum scmp_compare {
        _SCMP_CMP_MIN = 0,
        SCMP_CMP_NE = 1,                /** not equal */
        SCMP_CMP_LT = 2,                /** less than */
        SCMP_CMP_LE = 3,                /** less than or equal */
        SCMP_CMP_EQ = 4,                /** equal */
        SCMP_CMP_GE = 5,                /** greater than or equal */
        SCMP_CMP_GT = 6,                /** greater than */
        SCMP_CMP_MASKED_EQ = 7,         /** masked equality */
        _SCMP_CMP_MAX,
}

/**
 * Architecutres
 */
#[allow(non_camel_case_types)]
#[derive(Debug,Clone,Copy)]
#[repr(C)]
pub enum scmp_arch {
    SCMP_ARCH_NATIVE = 0x0,
    SCMP_ARCH_X86 = 0x40000003,
    SCMP_ARCH_X86_64 = 0xc000003e,
    SCMP_ARCH_X32 = 0x4000003e,
    SCMP_ARCH_ARM = 0x40000028,
    SCMP_ARCH_AARCH64 = 0xc00000b7,
    SCMP_ARCH_MIPS = 0x8,
    SCMP_ARCH_MIPS64 = 0x80000008,
    SCMP_ARCH_MIPS64N32 = 0xa0000008,
    SCMP_ARCH_MIPSEL = 0x40000008,
    SCMP_ARCH_MIPSEL64 = 0xc0000008,
    SCMP_ARCH_MIPSEL64N32 = 0xe0000008,
    SCMP_ARCH_PPC = 0x14,
    SCMP_ARCH_PPC64 = 0x80000015,
    SCMP_ARCH_PPC64LE = 0xc0000015,
    SCMP_ARCH_S390 = 0x16,
    SCMP_ARCH_S390X = 0x80000016,
}

/**
 * Argument datum
 */
#[allow(non_camel_case_types)]
pub type scmp_datum_t = u64;

/**
 * Argument / Value comparison definition
 */
#[derive(Debug)]
#[repr(C)]
pub struct scmp_arg_cmp {
        pub arg: libc::c_uint,        /** argument number, starting at 0 */
        pub op: scmp_compare,       /** the comparison op, e.g. SCMP_CMP_* */
        pub datum_a: scmp_datum_t,
        pub datum_b: scmp_datum_t,
}

#[link(name = "seccomp")]
extern {
    /**
     * Initialize the filter state
     *
     * @param def_action the default filter action
     *
     * This function initializes the internal seccomp filter state and should
     * be called before any other functions in this library to ensure the filter
     * state is initialized.  Returns a filter context on success, NULL on failure.
     *
     */
    pub fn seccomp_init(def_action: u32) -> *mut scmp_filter_ctx;
    /**
     * Reset the filter state
     *
     * @param ctx the filter context
     * @param def_action the default filter action
     *
     * This function resets the given seccomp filter state and ensures the
     * filter state is reinitialized.  This function does not reset any seccomp
     * filters already loaded into the kernel.  Returns zero on success, negative
     * values on failure.
     *
     */
    pub fn seccomp_reset(ctx: *mut scmp_filter_ctx, def_action: u32) -> libc::c_int;
    /**
     * Destroys the filter state and releases any resources
     *
     * @param ctx the filter context
     *
     * This functions destroys the given seccomp filter state and releases any
     * resources, including memory, associated with the filter state.  This
     * function does not reset any seccomp filters already loaded into the kernel.
     * The filter context can no longer be used after calling this function.
     *
     */
    pub fn seccomp_release(ctx: *mut scmp_filter_ctx);

    /**
     * Adds an architecture to the filter
     * @param ctx the filter context
     * @param arch_token the architecture token, e.g. SCMP_ARCH_*
     *
     * This function adds a new architecture to the given seccomp filter context.
     * Any new rules added after this function successfully returns will be added
     * to this architecture but existing rules will not be added to this
     * architecture.  If the architecture token is SCMP_ARCH_NATIVE then the native
     * architecture will be assumed.  Returns zero on success, negative values on
     * failure.
     *
     */
    pub fn seccomp_arch_add(ctx: *mut scmp_filter_ctx, arch_token: u32) -> libc::c_int;

    /**
     * Removes an architecture from the filter
     * @param ctx the filter context
     * @param arch_token the architecture token, e.g. SCMP_ARCH_*
     *
     * This function removes an architecture from the given seccomp filter context.
     * If the architecture token is SCMP_ARCH_NATIVE then the native architecture
     * will be assumed.  Returns zero on success, negative values on failure.
     *
     */
    pub fn seccomp_arch_remove(ctx: *mut scmp_filter_ctx, arch_token: u32)-> libc::c_int;

    /**
     * Loads the filter into the kernel
     *
     * @param ctx the filter context
     *
     * This function loads the given seccomp filter context into the kernel.  If
     * the filter was loaded correctly, the kernel will be enforcing the filter
     * when this function returns.  Returns zero on success, negative values on
     * error.
     *
     */
    pub fn seccomp_load(ctx: *const scmp_filter_ctx) -> libc::c_int;

    /**
     * Get the value of a filter attribute
     *
     * @param ctx the filter context
     * @param attr the filter attribute name
     * @param value the filter attribute value
     *
     * This function fetches the value of the given attribute name and returns it
     * via @value.  Returns zero on success, negative values on failure.
     *
     */
    pub fn seccomp_attr_get(ctx: *const scmp_filter_ctx,
                         attr: scmp_filter_attr, value: *mut u32) -> libc::c_int;

    /**
     * Set the value of a filter attribute
     *
     * @param ctx the filter context
     * @param attr the filter attribute name
     * @param value the filter attribute value
     *
     * This function sets the value of the given attribute.  Returns zero on
     * success, negative values on failure.
     *
     */
    pub fn seccomp_attr_set(ctx: *mut scmp_filter_ctx,
                         attr: scmp_filter_attr, value: u32) -> libc::c_int;

    /**
     * Resolve a syscall name to a number
     * @param name the syscall name
     *
     * Resolve the given syscall name to the syscall number.  Returns the syscall
     * number on success, including negative pseudo syscall numbers (e.g. __PNR_*);
     * returns __NR_SCMP_ERROR on failure.
     *
     */
    pub fn seccomp_syscall_resolve_name(name: *const libc::c_char) -> libc::c_int;

    /**
     * Set the priority of a given syscall
     *
     * @param ctx the filter context
     * @param syscall the syscall number
     * @param priority priority value, higher value == higher priority
     *
     * This function sets the priority of the given syscall; this value is used
     * when generating the seccomp filter code such that higher priority syscalls
     * will incur less filter code overhead than the lower priority syscalls in the
     * filter.  Returns zero on success, negative values on failure.
     *
     */
    pub fn seccomp_syscall_priority(ctx: *mut scmp_filter_ctx,
                                 syscall: libc::c_int, priority: u8) -> libc::c_int;

    /**
     * Add a new rule to the filter
     *
     * @param ctx the filter context
     * @param action the filter action
     * @param syscall the syscall number
     * @param arg_cnt the number of argument filters in the argument filter chain
     * @param ... scmp_arg_cmp structs (use of SCMP_ARG_CMP() recommended)
     *
     * This function adds a series of new argument/value checks to the seccomp
     * filter for the given syscall; multiple argument/value checks can be
     * specified and they will be chained together (AND'd together) in the filter.
     * If the specified rule needs to be adjusted due to architecture specifics it
     * will be adjusted without notification.  Returns zero on success, negative
     * values on failure.
     *
     */
    pub fn seccomp_rule_add(ctx: *mut scmp_filter_ctx,
                         action: u32, syscall: libc::c_int, arg_cnt: libc::c_uint, ...) -> libc::c_int;

    /**
     * Add a new rule to the filter
     *
     * @param ctx the filter context
     * @param action the filter action
     * @param syscall the syscall number
     * @param arg_cnt the number of elements in the arg_array parameter
     * @param arg_array array of scmp_arg_cmp structs
     *
     * This function adds a series of new argument/value checks to the seccomp
     * filter for the given syscall; multiple argument/value checks can be
     * specified and they will be chained together (AND'd together) in the filter.
     * If the specified rule needs to be adjusted due to architecture specifics it
     * will be adjusted without notification.  Returns zero on success, negative
     * values on failure.
     *
     */
    pub fn seccomp_rule_add_array(ctx: *mut scmp_filter_ctx,
        action: u32, syscall: libc::c_int, arg_cnt: libc::c_uint,
        arg_array: *const scmp_arg_cmp) -> libc::c_int;

    /**
     * Add a new rule to the filter
     *
     * @param ctx the filter context
     * @param action the filter action
     * @param syscall the syscall number
     * @param arg_cnt the number of argument filters in the argument filter chain
     * @param ... scmp_arg_cmp structs (use of SCMP_ARG_CMP() recommended)
     *
     * This function adds a series of new argument/value checks to the seccomp
     * filter for the given syscall; multiple argument/value checks can be
     * specified and they will be chained together (AND'd together) in the filter.
     * If the specified rule can not be represented on the architecture the
     * function will fail.  Returns zero on success, negative values on failure.
     *
     */
    pub fn seccomp_rule_add_exact(ctx: *mut scmp_filter_ctx, action: u32,
                               syscall: libc::c_int, arg_cnt: libc::c_uint, ...) -> libc::c_int;

    /**
     * Add a new rule to the filter
     *
     * @param ctx the filter context
     * @param action the filter action
     * @param syscall the syscall number
     * @param arg_cnt  the number of elements in the arg_array parameter
     * @param arg_array array of scmp_arg_cmp structs
     *
     * This function adds a series of new argument/value checks to the seccomp
     * filter for the given syscall; multiple argument/value checks can be
     * specified and they will be chained together (AND'd together) in the filter.
     * If the specified rule can not be represented on the architecture the
     * function will fail.  Returns zero on success, negative values on failure.
     *
     */
    pub fn seccomp_rule_add_exact_array(ctx: *mut scmp_filter_ctx,
                                        action: u32, syscall: libc::c_int, arg_cnt: libc::c_uint,
                                        arg_array: *const scmp_arg_cmp) -> libc::c_int;

    /**
     * Generate seccomp Pseudo Filter Code (PFC) and export it to a file
     *
     * @param ctx the filter context
     * @param fd the destination fd
     *
     * This function generates seccomp Pseudo Filter Code (PFC) and writes it to
     * the given fd.  Returns zero on success, negative values on failure.
     *
     */
    pub fn seccomp_export_pfc(ctx: *const scmp_filter_ctx, fd: libc::c_int) -> libc::c_int;

    /**
     * Generate seccomp Berkley Packet Filter (BPF) code and export it to a file
     *
     * @param ctx the filter context
     * @param fd the destination fd
     *
     * This function generates seccomp Berkley Packer Filter (BPF) code and writes
     * it to the given fd.  Returns zero on success, negative values on failure.
     *
     */
    pub fn seccomp_export_bpf(ctx: *const scmp_filter_ctx, fd: libc::c_int) -> libc::c_int;
}

#[test]
fn does_it_even_work() {
    unsafe {
        let context = seccomp_init(SCMP_ACT_ALLOW);
        let comparator = scmp_arg_cmp {
            arg: 0,
            op: scmp_compare::SCMP_CMP_EQ,
            datum_a: 1000,
            datum_b: 0,
        };
        assert!(seccomp_rule_add(context, SCMP_ACT_KILL, 105, 1, comparator) == 0);
        assert!(seccomp_load(context) == 0);
        //assert!(libc::setuid(1000) == 0);
    }
}
<commit_msg>Support to resolve syscall num to name<commit_after>extern crate libc;
/*
 * seccomp actions
 */
#[allow(non_camel_case_types)]
pub type scmp_filter_ctx = libc::c_void;

/**
 * Error retern value
 */
pub const __NR_SCMP_ERROR: libc::c_int = -1;

/**
 * Kill the calling thread
 */
pub const SCMP_ACT_KILL: u32  = 0x00000000;
/**
 * Kill the calling process
 */
pub const SCMP_ACT_KILL_PROCESS: u32 = 0x80000000;
/**
 * Throw a SIGSYS signal
 */
pub const SCMP_ACT_TRAP: u32 = 0x00030000;
/**
 * Return the specified error code
 */
#[allow(non_snake_case)]
pub fn SCMP_ACT_ERRNO(x: u32) -> u32 { 0x00050000 | ((x) & 0x0000ffff) }
/**
 * Notify a tracing process with the specified value
 */
#[allow(non_snake_case)]
pub fn SCMP_ACT_TRACE(x: u32) -> u32 { 0x7ff00000 | ((x) & 0x0000ffff) }
/**
 * Allow the syscall to be executed
 */
pub const SCMP_ACT_ALLOW: u32 = 0x7fff0000;

/**
 * Filter attributes
 */
#[allow(non_camel_case_types)]
#[derive(Debug,Clone,Copy)]
#[repr(C)]
pub enum scmp_filter_attr {
    _SCMP_FLTATR_MIN,
    SCMP_FLTATR_ACT_DEFAULT, /** default filter action */
    SCMP_FLTATR_ACT_BADARCH, /** bad architecture action */
    SCMP_FLTATR_CTL_NNP, /** set NO_NEW_PRIVS on filter load */
    _SCMP_FLTATR_MAX,
}

/**
 * Comparison operators
 */
#[allow(non_camel_case_types)]
#[derive(Debug,Clone,Copy)]
#[repr(C)]
pub enum scmp_compare {
        _SCMP_CMP_MIN = 0,
        SCMP_CMP_NE = 1,                /** not equal */
        SCMP_CMP_LT = 2,                /** less than */
        SCMP_CMP_LE = 3,                /** less than or equal */
        SCMP_CMP_EQ = 4,                /** equal */
        SCMP_CMP_GE = 5,                /** greater than or equal */
        SCMP_CMP_GT = 6,                /** greater than */
        SCMP_CMP_MASKED_EQ = 7,         /** masked equality */
        _SCMP_CMP_MAX,
}

/**
 * Architecutres
 */
#[allow(non_camel_case_types)]
#[derive(Debug,Clone,Copy)]
#[repr(C)]
pub enum scmp_arch {
    SCMP_ARCH_NATIVE = 0x0,
    SCMP_ARCH_X86 = 0x40000003,
    SCMP_ARCH_X86_64 = 0xc000003e,
    SCMP_ARCH_X32 = 0x4000003e,
    SCMP_ARCH_ARM = 0x40000028,
    SCMP_ARCH_AARCH64 = 0xc00000b7,
    SCMP_ARCH_MIPS = 0x8,
    SCMP_ARCH_MIPS64 = 0x80000008,
    SCMP_ARCH_MIPS64N32 = 0xa0000008,
    SCMP_ARCH_MIPSEL = 0x40000008,
    SCMP_ARCH_MIPSEL64 = 0xc0000008,
    SCMP_ARCH_MIPSEL64N32 = 0xe0000008,
    SCMP_ARCH_PPC = 0x14,
    SCMP_ARCH_PPC64 = 0x80000015,
    SCMP_ARCH_PPC64LE = 0xc0000015,
    SCMP_ARCH_S390 = 0x16,
    SCMP_ARCH_S390X = 0x80000016,
}

/**
 * Argument datum
 */
#[allow(non_camel_case_types)]
pub type scmp_datum_t = u64;

/**
 * Argument / Value comparison definition
 */
#[derive(Debug)]
#[repr(C)]
pub struct scmp_arg_cmp {
        pub arg: libc::c_uint,        /** argument number, starting at 0 */
        pub op: scmp_compare,       /** the comparison op, e.g. SCMP_CMP_* */
        pub datum_a: scmp_datum_t,
        pub datum_b: scmp_datum_t,
}

#[link(name = "seccomp")]
extern {
    /**
     * Initialize the filter state
     *
     * @param def_action the default filter action
     *
     * This function initializes the internal seccomp filter state and should
     * be called before any other functions in this library to ensure the filter
     * state is initialized.  Returns a filter context on success, NULL on failure.
     *
     */
    pub fn seccomp_init(def_action: u32) -> *mut scmp_filter_ctx;
    /**
     * Reset the filter state
     *
     * @param ctx the filter context
     * @param def_action the default filter action
     *
     * This function resets the given seccomp filter state and ensures the
     * filter state is reinitialized.  This function does not reset any seccomp
     * filters already loaded into the kernel.  Returns zero on success, negative
     * values on failure.
     *
     */
    pub fn seccomp_reset(ctx: *mut scmp_filter_ctx, def_action: u32) -> libc::c_int;
    /**
     * Destroys the filter state and releases any resources
     *
     * @param ctx the filter context
     *
     * This functions destroys the given seccomp filter state and releases any
     * resources, including memory, associated with the filter state.  This
     * function does not reset any seccomp filters already loaded into the kernel.
     * The filter context can no longer be used after calling this function.
     *
     */
    pub fn seccomp_release(ctx: *mut scmp_filter_ctx);

    /**
     * Adds an architecture to the filter
     * @param ctx the filter context
     * @param arch_token the architecture token, e.g. SCMP_ARCH_*
     *
     * This function adds a new architecture to the given seccomp filter context.
     * Any new rules added after this function successfully returns will be added
     * to this architecture but existing rules will not be added to this
     * architecture.  If the architecture token is SCMP_ARCH_NATIVE then the native
     * architecture will be assumed.  Returns zero on success, negative values on
     * failure.
     *
     */
    pub fn seccomp_arch_add(ctx: *mut scmp_filter_ctx, arch_token: u32) -> libc::c_int;

    /**
     * Removes an architecture from the filter
     * @param ctx the filter context
     * @param arch_token the architecture token, e.g. SCMP_ARCH_*
     *
     * This function removes an architecture from the given seccomp filter context.
     * If the architecture token is SCMP_ARCH_NATIVE then the native architecture
     * will be assumed.  Returns zero on success, negative values on failure.
     *
     */
    pub fn seccomp_arch_remove(ctx: *mut scmp_filter_ctx, arch_token: u32)-> libc::c_int;

    /**
     * Loads the filter into the kernel
     *
     * @param ctx the filter context
     *
     * This function loads the given seccomp filter context into the kernel.  If
     * the filter was loaded correctly, the kernel will be enforcing the filter
     * when this function returns.  Returns zero on success, negative values on
     * error.
     *
     */
    pub fn seccomp_load(ctx: *const scmp_filter_ctx) -> libc::c_int;

    /**
     * Get the value of a filter attribute
     *
     * @param ctx the filter context
     * @param attr the filter attribute name
     * @param value the filter attribute value
     *
     * This function fetches the value of the given attribute name and returns it
     * via @value.  Returns zero on success, negative values on failure.
     *
     */
    pub fn seccomp_attr_get(ctx: *const scmp_filter_ctx,
                         attr: scmp_filter_attr, value: *mut u32) -> libc::c_int;

    /**
     * Set the value of a filter attribute
     *
     * @param ctx the filter context
     * @param attr the filter attribute name
     * @param value the filter attribute value
     *
     * This function sets the value of the given attribute.  Returns zero on
     * success, negative values on failure.
     *
     */
    pub fn seccomp_attr_set(ctx: *mut scmp_filter_ctx,
                         attr: scmp_filter_attr, value: u32) -> libc::c_int;

    /**
     * Resolve a syscall name to a number
     * @param name the syscall name
     *
     * Resolve the given syscall name to the syscall number.  Returns the syscall
     * number on success, including negative pseudo syscall numbers (e.g. __PNR_*);
     * returns __NR_SCMP_ERROR on failure.
     *
     */
    pub fn seccomp_syscall_resolve_name(name: *const libc::c_char) -> libc::c_int;

    /**
     * Resolve a syscall number to a name
     * @param arch_token the architecture token, e.g. SCMP_ARCH_*
     * @param num the syscall number
     *
     * Resolve the given syscall number to the syscall name for the given
     * architecture; it is up to the caller to free the returned string.  Returns
     * the syscall name on success, NULL on failure.
     *
     */
    pub fn seccomp_syscall_resolve_num_arch(arch_token: u32, num: libc::c_int) -> *const libc::c_char;

    /**
     * Set the priority of a given syscall
     *
     * @param ctx the filter context
     * @param syscall the syscall number
     * @param priority priority value, higher value == higher priority
     *
     * This function sets the priority of the given syscall; this value is used
     * when generating the seccomp filter code such that higher priority syscalls
     * will incur less filter code overhead than the lower priority syscalls in the
     * filter.  Returns zero on success, negative values on failure.
     *
     */
    pub fn seccomp_syscall_priority(ctx: *mut scmp_filter_ctx,
                                 syscall: libc::c_int, priority: u8) -> libc::c_int;

    /**
     * Add a new rule to the filter
     *
     * @param ctx the filter context
     * @param action the filter action
     * @param syscall the syscall number
     * @param arg_cnt the number of argument filters in the argument filter chain
     * @param ... scmp_arg_cmp structs (use of SCMP_ARG_CMP() recommended)
     *
     * This function adds a series of new argument/value checks to the seccomp
     * filter for the given syscall; multiple argument/value checks can be
     * specified and they will be chained together (AND'd together) in the filter.
     * If the specified rule needs to be adjusted due to architecture specifics it
     * will be adjusted without notification.  Returns zero on success, negative
     * values on failure.
     *
     */
    pub fn seccomp_rule_add(ctx: *mut scmp_filter_ctx,
                         action: u32, syscall: libc::c_int, arg_cnt: libc::c_uint, ...) -> libc::c_int;

    /**
     * Add a new rule to the filter
     *
     * @param ctx the filter context
     * @param action the filter action
     * @param syscall the syscall number
     * @param arg_cnt the number of elements in the arg_array parameter
     * @param arg_array array of scmp_arg_cmp structs
     *
     * This function adds a series of new argument/value checks to the seccomp
     * filter for the given syscall; multiple argument/value checks can be
     * specified and they will be chained together (AND'd together) in the filter.
     * If the specified rule needs to be adjusted due to architecture specifics it
     * will be adjusted without notification.  Returns zero on success, negative
     * values on failure.
     *
     */
    pub fn seccomp_rule_add_array(ctx: *mut scmp_filter_ctx,
        action: u32, syscall: libc::c_int, arg_cnt: libc::c_uint,
        arg_array: *const scmp_arg_cmp) -> libc::c_int;

    /**
     * Add a new rule to the filter
     *
     * @param ctx the filter context
     * @param action the filter action
     * @param syscall the syscall number
     * @param arg_cnt the number of argument filters in the argument filter chain
     * @param ... scmp_arg_cmp structs (use of SCMP_ARG_CMP() recommended)
     *
     * This function adds a series of new argument/value checks to the seccomp
     * filter for the given syscall; multiple argument/value checks can be
     * specified and they will be chained together (AND'd together) in the filter.
     * If the specified rule can not be represented on the architecture the
     * function will fail.  Returns zero on success, negative values on failure.
     *
     */
    pub fn seccomp_rule_add_exact(ctx: *mut scmp_filter_ctx, action: u32,
                               syscall: libc::c_int, arg_cnt: libc::c_uint, ...) -> libc::c_int;

    /**
     * Add a new rule to the filter
     *
     * @param ctx the filter context
     * @param action the filter action
     * @param syscall the syscall number
     * @param arg_cnt  the number of elements in the arg_array parameter
     * @param arg_array array of scmp_arg_cmp structs
     *
     * This function adds a series of new argument/value checks to the seccomp
     * filter for the given syscall; multiple argument/value checks can be
     * specified and they will be chained together (AND'd together) in the filter.
     * If the specified rule can not be represented on the architecture the
     * function will fail.  Returns zero on success, negative values on failure.
     *
     */
    pub fn seccomp_rule_add_exact_array(ctx: *mut scmp_filter_ctx,
                                        action: u32, syscall: libc::c_int, arg_cnt: libc::c_uint,
                                        arg_array: *const scmp_arg_cmp) -> libc::c_int;

    /**
     * Generate seccomp Pseudo Filter Code (PFC) and export it to a file
     *
     * @param ctx the filter context
     * @param fd the destination fd
     *
     * This function generates seccomp Pseudo Filter Code (PFC) and writes it to
     * the given fd.  Returns zero on success, negative values on failure.
     *
     */
    pub fn seccomp_export_pfc(ctx: *const scmp_filter_ctx, fd: libc::c_int) -> libc::c_int;

    /**
     * Generate seccomp Berkley Packet Filter (BPF) code and export it to a file
     *
     * @param ctx the filter context
     * @param fd the destination fd
     *
     * This function generates seccomp Berkley Packer Filter (BPF) code and writes
     * it to the given fd.  Returns zero on success, negative values on failure.
     *
     */
    pub fn seccomp_export_bpf(ctx: *const scmp_filter_ctx, fd: libc::c_int) -> libc::c_int;
}

#[test]
fn does_it_even_work() {
    unsafe {
        let context = seccomp_init(SCMP_ACT_ALLOW);
        let comparator = scmp_arg_cmp {
            arg: 0,
            op: scmp_compare::SCMP_CMP_EQ,
            datum_a: 1000,
            datum_b: 0,
        };
        assert!(seccomp_rule_add(context, SCMP_ACT_KILL, 105, 1, comparator) == 0);
        assert!(seccomp_load(context) == 0);
        //assert!(libc::setuid(1000) == 0);
    }
}
<|endoftext|>


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

//! Net-utils library provides a configurable TCP/SSL client connection pool
#![crate_name = "net_utils"]
#![crate_type = "lib"]
#![warn(missing_docs)]
// #![allow(unstable)]
#![allow(unused_must_use)]

/// # Example
///
///Define the below dependency in Cargo.toml
///
///[dependencies.net-utils]
///git = "https://github.com/rohitjoshi/net-utils.git"
///
/// ```
/// extern crate "net-utils" as utils;
/// use std::default::Default;
/// use std::sync::{ Arc, Mutex };
/// use utils::net::config;
/// use utils::net::poolmgr;

/// fn main() {
///     let mut cfg : config::Config = Default::default();
///     //set port to 80
///     cfg.port= Some(80);
///     //set host to
///     cfg.server = Some("google.com".to_string());
///     let mut pool = poolmgr::ConnectionPool::new(2, 20, true, &cfg);
///     //get the connection
///     let mut conn = pool.aquire().unwrap();
///     conn.writer.write_str("GET google.com\r\n").unwrap();
///     conn.writer.flush().unwrap();
///     let r = conn.reader.read_line();
///     println!("Received {}", r);
///     pool.release(conn);
///}
/// ```
///
///Here is above example used in multi-threded environment
/// ```
/// extern crate "net-utils" as utils;
/// use std::default::Default;
/// use std::sync::{ Arc, Mutex };
/// use utils::net::config;
/// use utils::net::poolmgr;
///
/// fn main() {
///     let mut cfg : config::Config = Default::default();
///     //set port to 80
///     cfg.port= Some(80);
///     //set host to
///     cfg.server = Some("google.com".to_string());
///     let mut pool = poolmgr::ConnectionPool::new(2, 20, true, &cfg);
///     let pool = Arc::new(Mutex::new(pool));
///     for _ in range(0u, 2) {
///         let pool = pool.clone();
///         spawn(move || {
///             let mut conn = pool.lock().aquire().unwrap();
///             conn.writer.write_str("GET google.com\r\n").unwrap();
///             conn.writer.flush().unwrap();
///             let r = conn.reader.read_line();
///             println!("Received {}", r);
///             pool.lock().release(conn);
///        });
///     }
/// }
//# ```
#[cfg(feature = "ssl")]
extern crate openssl;
#[macro_use]
extern crate log;
#[macro_use]
extern crate time;
#[macro_use]
extern crate uuid;
/// module net provides the TCP/SSL connection and connection pool functionality
pub mod net;
<commit_msg>Update lib.rs<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Net-utils library provides a configurable TCP/SSL client connection pool
//! A simple, connection pool library.
#![crate_name = "net_utils"]
#![crate_type = "lib"]
#![warn(missing_docs)]
// #![allow(unstable)]
#![allow(unused_must_use)]
#[cfg(feature = "ssl")]
extern crate openssl;
#[macro_use]
extern crate log;
#[macro_use]
extern crate time;
//! module net provides the TCP/SSL connection and connection pool functionality
pub mod net;
<|endoftext|>


<commit_before>#![crate_name = "orbtk"]
#![crate_type = "lib"]

pub use dces::prelude::*;

#[macro_use]
extern crate lazy_static;

#[macro_use]
pub mod macros;

pub use crate::application::*;
pub use crate::backend::*;
pub use crate::enums::*;
pub use crate::event::*;
pub use crate::layout::*;
pub use crate::properties::*;
pub use crate::render_object::*;
pub use crate::structs::*;
pub use crate::styling::theme::{DEFAULT_THEME_CSS, LIGHT_THEME_EXTENSION_CSS};
pub use crate::styling::vector_graphics::*;
pub use crate::systems::*;
pub use crate::theme::*;
pub use crate::widget::*;

pub mod application;
pub mod backend;
pub mod enums;
pub mod event;
pub mod layout;
pub mod properties;
pub mod render_object;
pub mod structs;
pub mod styling;
pub mod systems;
pub mod theme;
pub mod widget;
<commit_msg>[fix] add reexport dces prelude.<commit_after>#![crate_name = "orbtk"]
#![crate_type = "lib"]

pub use dces::prelude::*;

#[macro_use]
extern crate lazy_static;

#[macro_use]
pub mod macros;

pub use crate::application::*;
pub use crate::backend::*;
pub use crate::enums::*;
pub use crate::event::*;
pub use crate::layout::*;
pub use crate::properties::*;
pub use crate::render_object::*;
pub use crate::structs::*;
pub use crate::styling::theme::{DEFAULT_THEME_CSS, LIGHT_THEME_EXTENSION_CSS};
pub use crate::styling::vector_graphics::*;
pub use crate::systems::*;
pub use crate::theme::*;
pub use crate::widget::*;

pub use dces::prelude::*;

pub mod application;
pub mod backend;
pub mod enums;
pub mod event;
pub mod layout;
pub mod properties;
pub mod render_object;
pub mod structs;
pub mod styling;
pub mod systems;
pub mod theme;
pub mod widget;
<|endoftext|>


<commit_before>// Code style
#![forbid(private_in_public)]
#![deny(unused_assignments)]

// Code style (development time)
#![allow(unused_macros)]
#![allow(dead_code)]

// Code style (temp)
#![allow(unused_variables)]
#![allow(unused_imports)]
#![allow(unused_parens)]
#![allow(unused_mut)]
#![allow(unused_unsafe)]
#![allow(unreachable_code)]

// Safety
#![deny(overflowing_literals)]
#![deny(safe_packed_borrows)]
#![deny(unused_must_use)]

#![no_std]

#![feature(lang_items)]
#![feature(core_intrinsics)]
#![feature(panic_info_message)]
#![feature(asm)]
#![feature(ptr_internals)]
#![feature(const_fn)]
#![feature(const_vec_new)]
#![feature(naked_functions)]
#![feature(box_syntax, box_patterns)]
#![feature(box_into_raw_non_null)]
#![feature(stmt_expr_attributes)]
#![feature(alloc)]
#![feature(allocator_api)]

use core::alloc::Layout;
use core::panic::PanicInfo;

extern crate volatile;
extern crate rlibc;
extern crate spin;
extern crate x86_64;
extern crate cpuio;
#[macro_use]
extern crate bitflags;
extern crate bit_field;
#[macro_use]
extern crate static_assertions;

extern crate d7alloc;
extern crate d7staticfs;
extern crate d7ramfs;

#[macro_use]
extern crate alloc;

// Hardware:
#[macro_use]
mod vga_buffer;
#[macro_use]
mod util;
mod mem_map;
mod paging;
mod acpi;
mod pic;
// mod apic;
mod cpuid;
mod interrupt;
mod keyboard;
mod pit;
mod memory;
mod pci;
mod virtio;
mod disk_io;
mod staticfs;
// mod ide;
// mod nic;

// Software:
mod elf_parser;
mod time;
mod multitasking;
mod syscall;
mod filesystem;
mod kernel_shell;

/// The kernel main function
#[no_mangle]
pub extern fn rust_main() {
    rreset!();
    rprintln!("Loading the system...\n");

    // Finish system setup

    // Interrupt controller
    pic::init();
    // apic::init();

    // Memory allocation
    memory::init();

    // Interrupt system
    interrupt::init();

    // PIT
    pit::init();

    // CPU data
    cpuid::init();

    // Filesystem
    // filesystem::init();

    // Keyboard
    // keyboard::init();

    // PCI
    pci::init();

    // Disk IO (ATA, IDE, VirtIO)
    disk_io::init();

    // NIC
    // nic::init();

    // rreset!();
    rprintln!("Kernel initialized.\n");

    // Load modules
    if let Some(bytes) = staticfs::read_file("README.md") {
        let mut lines = 3;
        for b in bytes {
            if b == 0x0a {
                lines -= 1;
                if lines == 0 {
                    break;
                }
            }
            if (0x20 <= b && b <= 0x7f)  || b == 0x0a {
                rprint!("{}", b as char);
            }
        }
    } else {
        rprintln!("File not found");
    }

    // use multitasking::PROCMAN;
    //
    // {
    //     let ref mut pm = PROCMAN.lock();
    //     rprintln!("Did not crash!");
    //     let pid = pm.spawn();
    //     rprintln!("PID: {}", pid);
    //     rprintln!("Did not crash!");
    // }

    kernel_shell::run();

    loop {
        use time::{SYSCLOCK, busy_sleep_until};
        busy_sleep_until(SYSCLOCK.lock().after_seconds(5));
        // rprintln!("Sleep done");

        let success: u64;
        let result: u64;
        unsafe {
            asm!("
                mov rax, 0x1
                mov rdi, 0x2
                mov rsi, 0x3
                int 0xd7
            " : "={rax}"(success), "={rdx}"(result) :: "eax", "rdx", "rdi", "rsi" : "intel");
        }
        // let _ = success;
        // let _ = result;
        rprintln!("{:?} {:?}", success, result);
    }
}

#[global_allocator]
static HEAP_ALLOCATOR: d7alloc::GlobAlloc = d7alloc::GlobAlloc::new(
    d7alloc::BumpAllocator::new(d7alloc::HEAP_START, d7alloc::HEAP_START + d7alloc::HEAP_SIZE)
);

#[lang = "oom"]
#[no_mangle]
extern fn rust_oom(_: Layout) -> ! {
    unsafe {
        asm!("cli"::::"intel","volatile");
        panic_indicator!(0x4f4D4f21); // !M as in "No memory"
        asm!("jmp panic"::::"intel","volatile");
   }
   loop {}
}

#[cfg(not(test))]
#[allow(non_snake_case)]
#[no_mangle]
pub extern "C" fn _Unwind_Resume() -> ! {loop {}}

#[cfg(not(test))]
#[lang = "eh_personality"]
extern "C" fn eh_personality() -> ! {loop {}}

#[cfg(not(test))]
#[panic_handler]
#[allow(unused_variables)]
#[no_mangle]
extern "C" fn panic(info: &PanicInfo) -> ! {
    unsafe {
        // asm!("jmp panic"::::"intel","volatile");

        asm!("cli"::::"intel","volatile");
        panic_indicator!(0x4f214f21); // !!

        if let Some(location) = info.location() {
            rprintln!("\nKernel Panic: file: '{}', line: {}", location.file(), location.line());
        } else {
            rprintln!("\nKernel Panic: Location unavailable");
        }
        if let Some(msg) = info.message() {
            rprintln!("  {:?}", msg);
        } else {
            rprintln!("  Info unavailable");
        }
        asm!("jmp panic"::::"intel","volatile");
    }
    loop {}
}
<commit_msg>Enable keyboard support againt<commit_after>// Code style
#![forbid(private_in_public)]
#![deny(unused_assignments)]

// Code style (development time)
#![allow(unused_macros)]
#![allow(dead_code)]

// Code style (temp)
#![allow(unused_variables)]
#![allow(unused_imports)]
#![allow(unused_parens)]
#![allow(unused_mut)]
#![allow(unused_unsafe)]
#![allow(unreachable_code)]

// Safety
#![deny(overflowing_literals)]
#![deny(safe_packed_borrows)]
#![deny(unused_must_use)]

#![no_std]

#![feature(lang_items)]
#![feature(core_intrinsics)]
#![feature(panic_info_message)]
#![feature(asm)]
#![feature(ptr_internals)]
#![feature(const_fn)]
#![feature(const_vec_new)]
#![feature(naked_functions)]
#![feature(box_syntax, box_patterns)]
#![feature(box_into_raw_non_null)]
#![feature(stmt_expr_attributes)]
#![feature(alloc)]
#![feature(allocator_api)]
#![feature(abi_x86_interrupt)]

use core::alloc::Layout;
use core::panic::PanicInfo;

extern crate volatile;
extern crate rlibc;
extern crate spin;
extern crate x86_64;
extern crate cpuio;
#[macro_use]
extern crate bitflags;
extern crate bit_field;
#[macro_use]
extern crate static_assertions;

extern crate d7alloc;
extern crate d7staticfs;
extern crate d7ramfs;

#[macro_use]
extern crate alloc;

// Hardware:
#[macro_use]
mod vga_buffer;
#[macro_use]
mod util;
mod mem_map;
mod paging;
mod acpi;
mod pic;
// mod apic;
mod cpuid;
mod interrupt;
mod keyboard;
mod pit;
mod memory;
mod pci;
mod virtio;
mod disk_io;
mod staticfs;
// mod ide;
// mod nic;

// Software:
mod elf_parser;
mod time;
mod multitasking;
mod syscall;
mod filesystem;
mod kernel_shell;

/// The kernel main function
#[no_mangle]
pub extern fn rust_main() {
    rreset!();
    rprintln!("Loading the system...\n");

    // Finish system setup

    // Interrupt controller
    pic::init();
    // apic::init();

    // Memory allocation
    memory::init();

    // Interrupt system
    interrupt::init();

    // PIT
    pit::init();

    // CPU data
    cpuid::init();

    // Filesystem
    // filesystem::init();

    // Keyboard
    keyboard::init();

    // PCI
    pci::init();

    // Disk IO (ATA, IDE, VirtIO)
    disk_io::init();

    // NIC
    // nic::init();

    // rreset!();
    rprintln!("Kernel initialized.\n");

    // Load modules
    if let Some(bytes) = staticfs::read_file("README.md") {
        let mut lines = 3;
        for b in bytes {
            if b == 0x0a {
                lines -= 1;
                if lines == 0 {
                    break;
                }
            }
            if (0x20 <= b && b <= 0x7f)  || b == 0x0a {
                rprint!("{}", b as char);
            }
        }
    } else {
        rprintln!("File not found");
    }

    // use multitasking::PROCMAN;
    //
    // {
    //     let ref mut pm = PROCMAN.lock();
    //     rprintln!("Did not crash!");
    //     let pid = pm.spawn();
    //     rprintln!("PID: {}", pid);
    //     rprintln!("Did not crash!");
    // }

    kernel_shell::run();

    loop {
        use time::{SYSCLOCK, busy_sleep_until};
        busy_sleep_until(SYSCLOCK.lock().after_seconds(5));
        // rprintln!("Sleep done");

        let success: u64;
        let result: u64;
        unsafe {
            asm!("
                mov rax, 0x1
                mov rdi, 0x2
                mov rsi, 0x3
                int 0xd7
            " : "={rax}"(success), "={rdx}"(result) :: "eax", "rdx", "rdi", "rsi" : "intel");
        }
        // let _ = success;
        // let _ = result;
        rprintln!("{:?} {:?}", success, result);
    }
}

#[global_allocator]
static HEAP_ALLOCATOR: d7alloc::GlobAlloc = d7alloc::GlobAlloc::new(
    d7alloc::BumpAllocator::new(d7alloc::HEAP_START, d7alloc::HEAP_START + d7alloc::HEAP_SIZE)
);

#[lang = "oom"]
#[no_mangle]
extern fn rust_oom(_: Layout) -> ! {
    unsafe {
        asm!("cli"::::"intel","volatile");
        panic_indicator!(0x4f4D4f21); // !M as in "No memory"
        asm!("jmp panic"::::"intel","volatile");
   }
   loop {}
}

#[cfg(not(test))]
#[allow(non_snake_case)]
#[no_mangle]
pub extern "C" fn _Unwind_Resume() -> ! {loop {}}

#[cfg(not(test))]
#[lang = "eh_personality"]
extern "C" fn eh_personality() -> ! {loop {}}

#[cfg(not(test))]
#[panic_handler]
#[allow(unused_variables)]
#[no_mangle]
extern "C" fn panic(info: &PanicInfo) -> ! {
    unsafe {
        // asm!("jmp panic"::::"intel","volatile");

        asm!("cli"::::"intel","volatile");
        panic_indicator!(0x4f214f21); // !!

        if let Some(location) = info.location() {
            rprintln!("\nKernel Panic: file: '{}', line: {}", location.file(), location.line());
        } else {
            rprintln!("\nKernel Panic: Location unavailable");
        }
        if let Some(msg) = info.message() {
            rprintln!("  {:?}", msg);
        } else {
            rprintln!("  Info unavailable");
        }
        asm!("jmp panic"::::"intel","volatile");
    }
    loop {}
}
<|endoftext|>


<commit_before>#![feature(old_io)]

extern crate "rustc-serialize" as rustc_serialize;
extern crate hyper;
extern crate mime;
extern crate url;

use hyper::Url;
use hyper::header::{ Accept, Authorization, ContentType, UserAgent, qitem };
use hyper::method::Method;
use mime::{ Attr, Mime, Value };
use mime::TopLevel::Application;
use mime::SubLevel::Json;
use rustc_serialize::json;
use std::old_io::IoError;
use std::result;

pub type Result<T> = result::Result<T, IoError>;

pub struct Client {
  host: String,
  token: Option<String>
}

#[derive(RustcDecodable)]
struct Status {
  ok: bool
}

#[derive(RustcDecodable)]
pub struct User {
  pub id: u32,
  pub login: String,
  pub avatar: String,
  pub email: Option<String>,
  pub name: Option<String>,
}

#[derive(RustcDecodable)]
struct Users {
  users: Vec<User>
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct Crate {
  pub name: String,
  pub description: Option<String>,
  pub max_version: String
}

#[derive(RustcEncodable)]
pub struct OwnersReq<'a> {
  users: &'a [&'a str]
}

#[derive(RustcDecodable)]
struct Crates {
  crates: Vec<Crate>
}

impl Client {
  pub fn new() -> Client {
    Client::host("https://crates.io")
  }

  pub fn host(addr: &str) -> Client {
    Client { host: addr.to_string(), token: None }
  }

  pub fn token(self, auth: &str) -> Client {
    Client {
      host: self.host,
      token: Some(auth.to_string())
    }
  }

  pub fn find(&mut self, query: &str) -> Result<Vec<Crate>> {
    let body = try!(self.get(format!("/crates?q={}", query)));
    Ok(json::decode::<Crates>(&body).unwrap().crates)
  }

  pub fn named(&mut self, name: &str) -> Result<String> { // can't decode this automagically because it contains the key "crate"!
    self.get(format!("/crates/{}", name))
  }

  pub fn add_owners(&mut self, krate: &str, owners: &[&str]) -> Result<()> {
    let body = json::encode(&OwnersReq { users: owners }).unwrap();
    try!(self.put(format!("/crates/{}/owners", krate),
                   body.as_bytes()));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn remove_owners(&mut self, krate: &str, owners: &[&str]) -> Result<()> {
    let body = json::encode(&OwnersReq { users: owners }).unwrap();
    try!(self.delete(format!("/crates/{}/owners", krate),
                     Some(body.as_bytes())));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn owners(&mut self, krate: &str) -> Result<Vec<User>> {
    let body = try!(self.get(format!("/crates/{}/owners", krate)));
    Ok(json::decode::<Users>(&body).unwrap().users)
  }

  // todo: https://github.com/rust-lang/crates.io/blob/dabd8778c1a515ea7572c59096da76e562afe2e2/src/lib.rs#L74-L96

  fn get(&mut self, path: String) -> Result<String> {
    self.req(path, None, Method::Get)
  }

  fn delete(&mut self, path: String, body: Option<&[u8]>) -> Result<String> {
    self.req(path, body, Method::Delete)
  }

  fn put(&mut self, path: String, b: &[u8]) -> Result<String> {
    self.req(path, Some(b), Method::Put)
  }

  fn req(&mut self, path: String, body: Option<&[u8]>, method: Method) -> Result<String> {
     let uri = Url::parse(&format!("{}/api/v1{}", self.host, path)).ok().expect("invalid url");
     let mut cli = hyper::Client::new();
     let bound = cli.request(method, uri)
        .header(UserAgent("cargopants/0.1.0".to_string()))
        .header(Accept(vec![qitem(Mime(Application, Json, vec![(Attr::Charset, Value::Utf8)]))]))
        .header(ContentType(Mime(Application, Json, vec![(Attr::Charset, Value::Utf8)])));
      let authenticated = match self.token.clone() {
        Some(auth) => bound.header(Authorization(auth)),
                 _ => bound
      };
      let embodied = match body {
        Some(data) => authenticated.body(data),
                 _ => authenticated
      };
      let mut res = match embodied.send() {
        Ok(r) => r,
        Err(err) => panic!("failed request: {:?}", err)
      };
      res.read_to_string()
  }
}

#[test]
fn it_works() {
}
<commit_msg>follows<commit_after>#![feature(old_io)]

extern crate "rustc-serialize" as rustc_serialize;
extern crate hyper;
extern crate mime;
extern crate url;

use hyper::Url;
use hyper::header::{ Accept, Authorization, ContentType, UserAgent, qitem };
use hyper::method::Method;
use mime::{ Attr, Mime, Value };
use mime::TopLevel::Application;
use mime::SubLevel::Json;
use rustc_serialize::json;
use std::old_io::IoError;
use std::result;

pub type Result<T> = result::Result<T, IoError>;

pub struct Client {
  host: String,
  token: Option<String>
}

#[derive(RustcDecodable)]
struct Status {
  ok: bool
}

#[derive(RustcDecodable)]
struct Following {
  following: bool
}

#[derive(RustcDecodable)]
pub struct User {
  pub id: u32,
  pub login: String,
  pub avatar: String,
  pub email: Option<String>,
  pub name: Option<String>,
}

#[derive(RustcDecodable)]
struct Users {
  users: Vec<User>
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct Crate {
  pub name: String,
  pub description: Option<String>,
  pub max_version: String
}

#[derive(RustcEncodable)]
pub struct OwnersReq<'a> {
  users: &'a [&'a str]
}

#[derive(RustcDecodable)]
struct Crates {
  crates: Vec<Crate>
}

impl Client {
  pub fn new() -> Client {
    Client::host("https://crates.io")
  }

  pub fn host(addr: &str) -> Client {
    Client { host: addr.to_string(), token: None }
  }

  pub fn token(self, auth: &str) -> Client {
    Client {
      host: self.host,
      token: Some(auth.to_string())
    }
  }

  // todo: soft (downloads|name), by letter/keyword/user_id/following
  pub fn find(&mut self, query: &str) -> Result<Vec<Crate>> {
    let body = try!(self.get(format!("/crates?q={}&sort={}", query, "name")));
    Ok(json::decode::<Crates>(&body).unwrap().crates)
  }

  pub fn named(&mut self, name: &str) -> Result<String> { // can't decode this automagically because it contains the key "crate"!
    self.get(format!("/crates/{}", name))
  }

  pub fn follow(&mut self, krate: &str) -> Result<()> {
    let body = try!(self.put(format!("/crates/{}/follow", krate), &vec![]));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn unfollow(&mut self, krate: &str) -> Result<()> {
    let body = try!(self.delete(format!("/crates/{}/follow", krate), None));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn following(&mut self, krate: &str) -> Result<()> {
    let body = try!(self.get(format!("/crates/{}/following", krate)));
    assert!(json::decode::<Following>(&body).unwrap().following);
    Ok(())
  }

  pub fn add_owners(&mut self, krate: &str, owners: &[&str]) -> Result<()> {
    let body = json::encode(&OwnersReq { users: owners }).unwrap();
    let body = try!(self.put(format!("/crates/{}/owners", krate),
                   body.as_bytes()));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn remove_owners(&mut self, krate: &str, owners: &[&str]) -> Result<()> {
    let body = json::encode(&OwnersReq { users: owners }).unwrap();
    let body = try!(self.delete(format!("/crates/{}/owners", krate),
                     Some(body.as_bytes())));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn owners(&mut self, krate: &str) -> Result<Vec<User>> {
    let body = try!(self.get(format!("/crates/{}/owners", krate)));
    Ok(json::decode::<Users>(&body).unwrap().users)
  }

  // todo: https://github.com/rust-lang/crates.io/blob/dabd8778c1a515ea7572c59096da76e562afe2e2/src/lib.rs#L74-L96

  fn get(&mut self, path: String) -> Result<String> {
    self.req(path, None, Method::Get)
  }

  fn delete(&mut self, path: String, body: Option<&[u8]>) -> Result<String> {
    self.req(path, body, Method::Delete)
  }

  fn put(&mut self, path: String, b: &[u8]) -> Result<String> {
    self.req(path, Some(b), Method::Put)
  }

  fn req(&mut self, path: String, body: Option<&[u8]>, method: Method) -> Result<String> {
     let uri = Url::parse(&format!("{}/api/v1{}", self.host, path)).ok().expect("invalid url");
     let mut cli = hyper::Client::new();
     let bound = cli.request(method, uri)
        .header(UserAgent("cargopants/0.1.0".to_string()))
        .header(Accept(vec![qitem(Mime(Application, Json, vec![(Attr::Charset, Value::Utf8)]))]))
        .header(ContentType(Mime(Application, Json, vec![(Attr::Charset, Value::Utf8)])));
      let authenticated = match self.token.clone() {
        Some(auth) => bound.header(Authorization(auth)),
                 _ => bound
      };
      let embodied = match body {
        Some(data) => authenticated.body(data),
                 _ => authenticated
      };
      let mut res = match embodied.send() {
        Ok(r) => r,
        Err(err) => panic!("failed request: {:?}", err)
      };
      res.read_to_string()
  }
}

#[test]
fn it_works() {
}
<|endoftext|>