<commit_before>use alloc::rc::Rc;
use spin::RwLock;
use core::hash::{Hash, Hasher};
// Compiler warns about a field not exported in core.
#[allow(deprecated)]
use core::hash::SipHasher;
use collections::vec::Vec;
use core::cmp;

enum HashMapMember<K: Hash + cmp::PartialEq, V> {
    None,
    Tombstone,
    Bucket(Bucket<K, V>)
}

struct Bucket<K: Hash + cmp::PartialEq, V> {
    key: K,
    value: Rc<V>,
}

pub struct HashMap<K: Hash + cmp::PartialEq, V> {
    count: usize,
    table: RwLock<Vec<HashMapMember<K, V>>>
}

impl<K: Hash + cmp::PartialEq, V> Bucket<K, V> {
    fn new(key: K, value: V) -> Self {
        Bucket{ key: key, value: Rc::new(value) }
    }
}

impl<K: Hash + cmp::PartialEq, V> HashMap<K, V> {

    pub fn new(size: usize) -> Self {
        let mut table = vec![];
        for _ in 0..size {
            table.push(HashMapMember::None);
        }
        HashMap{ count: 0, table: RwLock::new(table) }
    }

    // Compiler warns about a field not exported in core.
    #[allow(deprecated)]
    fn get_index(&self, key: &K) -> usize {
        let mut hasher = SipHasher::new();
        key.hash(&mut hasher);
        (hasher.finish() as usize) % self.table.read().len()
    }

    pub fn remove(&mut self, key: K) {
        let index = self.get_index(&key);

        for i in index..self.table.write().len() {
            match self.table.write()[i] {
                HashMapMember::Tombstone => continue,
                HashMapMember::None => return,
                HashMapMember::Bucket(ref mut b) => {
                    if b.key == key {
                        self.table.write()[i] = HashMapMember::Tombstone;
                        return;
                    } else {
                        continue;
                    }
                }
            }
        }

        for i in 0..index {
            match self.table.write()[i] {
                HashMapMember::Tombstone => continue,
                HashMapMember::None => return,
                HashMapMember::Bucket(ref mut b) => {
                    if b.key == key {
                        self.table.write()[i] = HashMapMember::Tombstone;
                        return;
                    } else {
                        continue;
                    }
                }
            }
        }
    }

    pub fn insert(&mut self, key: K, value: V) {
        let index = self.get_index(&key);
        extern crate std;

        for i in index..self.table.write().len() {
            match self.table.write()[i] {
                HashMapMember::Tombstone => continue,
                HashMapMember::None => {
                    self.table.write()[i] = HashMapMember::Bucket(Bucket::new(key, value));
                    return;
                }
                HashMapMember::Bucket(ref mut b) => {
                    if b.key == key {
                        b.value = Rc::new(value);
                        self.count += 1;
                        return;
                    } else {
                        continue;
                    }
                }
            }
        }

        for i in 0..index {
            match self.table.write()[i] {
                HashMapMember::Tombstone => continue,
                HashMapMember::None => {
                    self.table.write()[i] = HashMapMember::Bucket(Bucket::new(key, value));
                    return;
                }
                HashMapMember::Bucket(ref mut b) => {
                    if b.key == key {
                        b.value = Rc::new(value);
                        self.count += 1;
                        return;
                    } else {
                        continue;
                    }
                }
            }
        }
    }

    pub fn contains(&self, key: &K) -> bool {
        let index = self.get_index(key);

        for i in index..self.table.read().len() {
            match self.table.read()[i] {
                HashMapMember::Tombstone => continue,
                HashMapMember::None => return false,
                HashMapMember::Bucket(ref b) => {
                    if &b.key == key {
                        return true;
                    } else {
                        continue;
                    }
                }
            }
        }

        for i in index..self.table.read().len() {
            match self.table.read()[i] {
                HashMapMember::Tombstone => continue,
                HashMapMember::None => return false,
                HashMapMember::Bucket(ref b) => {
                    if &b.key == key {
                        return true;
                    } else {
                        continue;
                    }
                }
            }
        }
        false
    }

    pub fn get(&self, key: &K) -> Option<Rc<V>> {
        let index = self.get_index(key);

        for i in index..self.table.read().len() {
            match self.table.read()[i] {
                HashMapMember::Tombstone => continue,
                HashMapMember::None => return None,
                HashMapMember::Bucket(ref b) => {
                    if &b.key == key {
                        return Some(b.value.clone());
                    } else {
                        continue;
                    }
                }
            }
        }

        for i in index..self.table.read().len() {
            match self.table.read()[i] {
                HashMapMember::Tombstone => continue,
                HashMapMember::None => return None,
                HashMapMember::Bucket(ref b) => {
                    if &b.key == key {
                        return Some(b.value.clone());
                    } else {
                        continue;
                    }
                }
            }
        }
        None
    }
}

#[cfg(test)]
mod tests {
    use alloc::rc::Rc;
    use super::HashMap;

    #[test]
    fn test_new() {
        let ht = HashMap::<i32, i32>::new(10);
        let length = ht.table.read().len();
        assert_eq!(length, 10);

        let ht1 = HashMap::<&str, &str>::new(100);
        let length = ht1.table.read().len();
        assert_eq!(length, 100);

        #[allow(unused)]
        struct Custom<'a> {
            int_field: i32,
            str_field: &'a str,
        }

        let ht2 = HashMap::<i32, Custom>::new(1000);
        let length = ht2.table.read().len();
        assert_eq!(length, 1000);
    }

    #[test]
    fn test_basic_operations() {
        let mut ht = HashMap::<i32, i32>::new(10);
        ht.insert(42, 43);
        /*
        let k = 42;
        assert!(ht.contains(&k));
        assert_eq!(ht.get(&k), Some(Rc::new(43)));

        ht.remove(42);
        assert!(!ht.contains(&k));
        assert_eq!(ht.get(&k), None);

        ht.insert(42, 44);
        assert!(ht.contains(&k));
        assert_eq!(ht.get(&k), Some(Rc::new(44)));

        ht.insert(42, 45);
        assert!(ht.contains(&k));
        assert_eq!(ht.get(&k), Some(Rc::new(45)));
        */
    }
}
<commit_msg>Much improved and working hashtable<commit_after>use alloc::rc::Rc;
use spin::RwLock;
use core::hash::{Hash, Hasher};
// Compiler warns about a field not exported in core.
#[allow(deprecated)]
use core::hash::SipHasher;
use collections::vec::Vec;
use core::cmp;

enum HashMapMember<K: Hash + cmp::PartialEq, V> {
    None,
    Tombstone,
    Bucket(Bucket<K, V>)
}

struct Bucket<K: Hash + cmp::PartialEq, V> {
    key: K,
    value: Rc<V>,
}

pub struct HashMap<K: Hash + cmp::PartialEq, V> {
    count: usize,
    table: RwLock<Vec<HashMapMember<K, V>>>
}

impl<K: Hash + cmp::PartialEq, V> Bucket<K, V> {
    fn new(key: K, value: V) -> Self {
        Bucket{ key: key, value: Rc::new(value) }
    }
}

impl<K: Hash + cmp::PartialEq, V> HashMap<K, V> {

    pub fn new(size: usize) -> Self {
        let mut table = vec![];
        for _ in 0..size {
            table.push(HashMapMember::None);
        }
        HashMap{ count: 0, table: RwLock::new(table) }
    }

    // Compiler warns about a field not exported in core.
    #[allow(deprecated)]
    fn get_index(&self, key: &K) -> usize {
        let mut hasher = SipHasher::new();
        key.hash(&mut hasher);
        (hasher.finish() as usize) % self.table.read().len()
    }

    pub fn remove(&mut self, key: K) {
        let index = self.get_index(&key);
        let mut table = self.table.write();
        let (begin, end) = table.split_at_mut(index);
        for entry in end.iter_mut().chain(begin) {
            match entry {
                &mut HashMapMember::Tombstone => continue,
                &mut HashMapMember::None => return,
                &mut HashMapMember::Bucket(ref mut b) if b.key != key => continue,
                loc @ &mut HashMapMember::Bucket(_) => {
                    *loc = HashMapMember::Tombstone;
                    return;
                }
            }
        }
    }

    pub fn insert(&mut self, key: K, value: V) {
        let index = self.get_index(&key);
        let mut table = self.table.write();
        let (begin, end) = table.split_at_mut(index);
        for entry in end.iter_mut().chain(begin) {
             match entry {
                &mut HashMapMember::Tombstone => continue,
                loc @ &mut HashMapMember::None =>  {
                    *loc = HashMapMember::Bucket(Bucket::new(key, value));
                    return;
                }
                &mut HashMapMember::Bucket(ref mut b) => {
                    if b.key == key {
                        b.value = Rc::new(value);
                        self.count += 1;
                        return;
                    } else {
                        continue;
                    }
                }
            }
        }
    }

    pub fn contains(&self, key: &K) -> bool {
        let index = self.get_index(&key);
        let table = self.table.read();
        let (begin, end) = table.split_at(index);
        for entry in end.iter().chain(begin) {
            match entry {
                &HashMapMember::Tombstone => continue,
                &HashMapMember::None => return false,
                &HashMapMember::Bucket(ref b) => {
                    if &b.key == key {
                        return true;
                    } else {
                        continue;
                    }
                }
            }
        }
       false
    }

    pub fn get(&self, key: &K) -> Option<Rc<V>> {
        let index = self.get_index(&key);
        let mut table = self.table.write();
        let (begin, end) = table.split_at_mut(index);
        for entry in end.iter_mut().chain(begin) {
            match entry {
                &mut HashMapMember::Tombstone => continue,
                &mut HashMapMember::None => return None,
                &mut HashMapMember::Bucket(ref b) => {
                    if &b.key == key {
                        return Some(b.value.clone());
                    } else {
                        continue;
                    }
                }
            }
        }
        None
    }
}

#[cfg(test)]
mod tests {
    use alloc::rc::Rc;
    use super::HashMap;

    #[test]
    fn test_new() {
        let ht = HashMap::<i32, i32>::new(10);
        let length = ht.table.read().len();
        assert_eq!(length, 10);

        let ht1 = HashMap::<&str, &str>::new(100);
        let length = ht1.table.read().len();
        assert_eq!(length, 100);

        #[allow(unused)]
        struct Custom<'a> {
            int_field: i32,
            str_field: &'a str,
        }

        let ht2 = HashMap::<i32, Custom>::new(1000);
        let length = ht2.table.read().len();
        assert_eq!(length, 1000);
    }

    #[test]
    fn test_basic_operations() {
        let mut ht = HashMap::<i32, i32>::new(10);
        let k = 42;
        ht.insert(k, 43);
        assert!(ht.contains(&k));
        assert_eq!(ht.get(&k), Some(Rc::new(43)));

        ht.remove(42);
        assert!(!ht.contains(&k));
        assert_eq!(ht.get(&k), None);

        ht.insert(42, 44);
        assert!(ht.contains(&k));
        assert_eq!(ht.get(&k), Some(Rc::new(44)));

        ht.insert(42, 45);
        assert!(ht.contains(&k));
        assert_eq!(ht.get(&k), Some(Rc::new(45)));
    }
}
<|endoftext|>


<commit_before>//! The module implements the framing layer of HTTP/2 and exposes an API for using it.
use std::io;
use std::convert::From;
use std::error::Error;

use hpack::decoder::DecoderError;

pub mod frame;
pub mod transport;
pub mod connection;
pub mod session;

/// An alias for the type that represents the ID of an HTTP/2 stream
pub type StreamId = u32;
/// An alias for the type that represents HTTP/2 haders. For now we only alias
/// the tuple of byte vectors instead of going with a full struct representation.
pub type Header = (Vec<u8>, Vec<u8>);

/// A set of protocol names that the library should use to indicate that HTTP/2
/// is supported during protocol negotiation (NPN or ALPN).
/// We include some of the drafts' protocol names, since there is basically no
/// difference for all intents and purposes (and some servers out there still
/// only officially advertise draft support).
/// TODO: Eventually only use "h2".
pub const ALPN_PROTOCOLS: &'static [&'static [u8]] = &[
    b"h2",
    b"h2-16",
    b"h2-15",
    b"h2-14",
];

/// An enum representing errors that can arise when performing operations
/// involving an HTTP/2 connection.
#[derive(Debug)]
pub enum HttpError {
    IoError(io::Error),
    InvalidFrame,
    CompressionError(DecoderError),
    UnknownStreamId,
    UnableToConnect,
    MalformedResponse,
}

/// Implement the trait that allows us to automatically convert `io::Error`s
/// into an `HttpError` by wrapping the given `io::Error` into an `HttpError::IoError` variant.
impl From<io::Error> for HttpError {
    fn from(err: io::Error) -> HttpError {
        HttpError::IoError(err)
    }
}

/// Implementation of the `PartialEq` trait as a convenience for tests.
#[cfg(test)]
impl PartialEq for HttpError {
    fn eq(&self, other: &HttpError) -> bool {
        match (self, other) {
            (&HttpError::IoError(ref e1), &HttpError::IoError(ref e2)) => {
                e1.kind() == e2.kind() && e1.description() == e2.description()
            },
            (&HttpError::InvalidFrame, &HttpError::InvalidFrame) => true,
            (&HttpError::CompressionError(ref e1), &HttpError::CompressionError(ref e2)) => {
                e1 == e2
            },
            (&HttpError::UnknownStreamId, &HttpError::UnknownStreamId) => true,
            (&HttpError::UnableToConnect, &HttpError::UnableToConnect) => true,
            (&HttpError::MalformedResponse, &HttpError::MalformedResponse) => true,
            _ => false,
        }
    }
}

/// A convenience `Result` type that has the `HttpError` type as the error
/// type and a generic Ok result type.
pub type HttpResult<T> = Result<T, HttpError>;

/// An enum representing the two possible HTTP schemes.
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum HttpScheme {
    /// The variant corresponding to `http://`
    Http,
    /// The variant corresponding to `https://`
    Https,
}

impl HttpScheme {
    /// Returns a byte string representing the scheme.
    #[inline]
    pub fn as_bytes(&self) -> &'static [u8] {
        match *self {
            HttpScheme::Http => b"http",
            HttpScheme::Https => b"https",
        }
    }
}

/// A struct representing the full raw response received on an HTTP/2 connection.
///
/// The full body of the response is included, regardless how large it may be.
/// The headers contain both the meta-headers, as well as the actual headers.
#[derive(Clone)]
pub struct Response {
    /// The ID of the stream to which the response is associated. HTTP/1.1 does
    /// not really have an equivalent to this.
    pub stream_id: StreamId,
    /// Exposes *all* the raw response headers, including the meta-headers.
    /// (For now the only meta header allowed in HTTP/2 responses is the
    /// `:status`.)
    pub headers: Vec<Header>,
    /// The full body of the response as an uninterpreted sequence of bytes.
    pub body: Vec<u8>,
}

impl Response {
    /// Creates a new `Response` with all the components already provided.
    pub fn new(stream_id: StreamId, headers: Vec<Header>, body: Vec<u8>)
            -> Response {
        Response {
            stream_id: stream_id,
            headers: headers,
            body: body,
        }
    }

    /// Gets the response status code from the pseudo-header. If the response
    /// does not contain the response as the first pseuo-header, an error is
    /// returned as such a response is malformed.
    pub fn status_code(&self) -> HttpResult<u16> {
        // Since pseudo-headers MUST be found before any regular header fields
        // and the *only* pseudo-header defined for responses is the `:status`
        // field, the `:status` MUST be the first header; otherwise, the
        // response is malformed.
        if self.headers.len() < 1 {
            return Err(HttpError::MalformedResponse)
        }
        if &self.headers[0].0 != &b":status" {
            Err(HttpError::MalformedResponse)
        } else {
            Ok(try!(Response::parse_status_code(&self.headers[0].1)))
        }
    }

    /// A helper function that parses a given buffer as a status code and
    /// returns it as a `u16`, if it is valid.
    fn parse_status_code(buf: &[u8]) -> HttpResult<u16> {
        // "The status-code element is a three-digit integer code [...]"
        if buf.len() != 3 {
            return Err(HttpError::MalformedResponse);
        }

        // "There are five values for the first digit"
        if buf[0] < b'1' || buf[0] > b'5' {
            return Err(HttpError::MalformedResponse);
        }

        // The rest of them just have to be digits
        if buf[1] < b'0' || buf[1] > b'9' || buf[2] < b'0' || buf[2] > b'9' {
            return Err(HttpError::MalformedResponse);
        }

        // Finally, we can merge them into an integer
        Ok(100 * ((buf[0] - b'0') as u16) +
           10 * ((buf[1] - b'0') as u16) +
           1 * ((buf[2] - b'0') as u16))
    }
}

/// A struct representing a full HTTP/2 request, along with the full body, as a
/// sequence of bytes.
#[derive(Clone)]
pub struct Request {
    pub stream_id: u32,
    pub headers: Vec<Header>,
    pub body: Vec<u8>,
}

#[cfg(test)]
mod tests {
    use super::{Response, HttpError, HttpScheme};

    /// Tests that the `Response` struct correctly parses a status code from
    /// its headers list.
    #[test]
    fn test_parse_status_code_response() {
        {
            // Only status => Ok
            let resp = Response::new(
                1,
                vec![(b":status".to_vec(), b"200".to_vec())],
                vec![]);
            assert_eq!(resp.status_code().ok().unwrap(), 200);
        }
        {
            // Extra headers => still works
            let resp = Response::new(
                1,
                vec![(b":status".to_vec(), b"200".to_vec()),
                     (b"key".to_vec(), b"val".to_vec())],
                vec![]);
            assert_eq!(resp.status_code().ok().unwrap(), 200);
        }
        {
            // Status is not the first header => malformed
            let resp = Response::new(
                1,
                vec![(b"key".to_vec(), b"val".to_vec()),
                     (b":status".to_vec(), b"200".to_vec())],
                vec![]);
            assert_eq!(resp.status_code().err().unwrap(),
                       HttpError::MalformedResponse);
        }
        {
            // No headers at all => Malformed
            let resp = Response::new(1, vec![], vec![]);
            assert_eq!(resp.status_code().err().unwrap(),
                       HttpError::MalformedResponse);
        }
    }

    /// Tests that the `HttpScheme` enum returns the correct scheme strings for
    /// the two variants.
    #[test]
    fn test_scheme_string() {
        assert_eq!(HttpScheme::Http.as_bytes(), b"http");
        assert_eq!(HttpScheme::Https.as_bytes(), b"https");
    }
}
<commit_msg>Docs: Fix typo<commit_after>//! The module implements the framing layer of HTTP/2 and exposes an API for using it.
use std::io;
use std::convert::From;
use std::error::Error;

use hpack::decoder::DecoderError;

pub mod frame;
pub mod transport;
pub mod connection;
pub mod session;

/// An alias for the type that represents the ID of an HTTP/2 stream
pub type StreamId = u32;
/// An alias for the type that represents HTTP/2 headers. For now we only alias
/// the tuple of byte vectors instead of going with a full struct representation.
pub type Header = (Vec<u8>, Vec<u8>);

/// A set of protocol names that the library should use to indicate that HTTP/2
/// is supported during protocol negotiation (NPN or ALPN).
/// We include some of the drafts' protocol names, since there is basically no
/// difference for all intents and purposes (and some servers out there still
/// only officially advertise draft support).
/// TODO: Eventually only use "h2".
pub const ALPN_PROTOCOLS: &'static [&'static [u8]] = &[
    b"h2",
    b"h2-16",
    b"h2-15",
    b"h2-14",
];

/// An enum representing errors that can arise when performing operations
/// involving an HTTP/2 connection.
#[derive(Debug)]
pub enum HttpError {
    IoError(io::Error),
    InvalidFrame,
    CompressionError(DecoderError),
    UnknownStreamId,
    UnableToConnect,
    MalformedResponse,
}

/// Implement the trait that allows us to automatically convert `io::Error`s
/// into an `HttpError` by wrapping the given `io::Error` into an `HttpError::IoError` variant.
impl From<io::Error> for HttpError {
    fn from(err: io::Error) -> HttpError {
        HttpError::IoError(err)
    }
}

/// Implementation of the `PartialEq` trait as a convenience for tests.
#[cfg(test)]
impl PartialEq for HttpError {
    fn eq(&self, other: &HttpError) -> bool {
        match (self, other) {
            (&HttpError::IoError(ref e1), &HttpError::IoError(ref e2)) => {
                e1.kind() == e2.kind() && e1.description() == e2.description()
            },
            (&HttpError::InvalidFrame, &HttpError::InvalidFrame) => true,
            (&HttpError::CompressionError(ref e1), &HttpError::CompressionError(ref e2)) => {
                e1 == e2
            },
            (&HttpError::UnknownStreamId, &HttpError::UnknownStreamId) => true,
            (&HttpError::UnableToConnect, &HttpError::UnableToConnect) => true,
            (&HttpError::MalformedResponse, &HttpError::MalformedResponse) => true,
            _ => false,
        }
    }
}

/// A convenience `Result` type that has the `HttpError` type as the error
/// type and a generic Ok result type.
pub type HttpResult<T> = Result<T, HttpError>;

/// An enum representing the two possible HTTP schemes.
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum HttpScheme {
    /// The variant corresponding to `http://`
    Http,
    /// The variant corresponding to `https://`
    Https,
}

impl HttpScheme {
    /// Returns a byte string representing the scheme.
    #[inline]
    pub fn as_bytes(&self) -> &'static [u8] {
        match *self {
            HttpScheme::Http => b"http",
            HttpScheme::Https => b"https",
        }
    }
}

/// A struct representing the full raw response received on an HTTP/2 connection.
///
/// The full body of the response is included, regardless how large it may be.
/// The headers contain both the meta-headers, as well as the actual headers.
#[derive(Clone)]
pub struct Response {
    /// The ID of the stream to which the response is associated. HTTP/1.1 does
    /// not really have an equivalent to this.
    pub stream_id: StreamId,
    /// Exposes *all* the raw response headers, including the meta-headers.
    /// (For now the only meta header allowed in HTTP/2 responses is the
    /// `:status`.)
    pub headers: Vec<Header>,
    /// The full body of the response as an uninterpreted sequence of bytes.
    pub body: Vec<u8>,
}

impl Response {
    /// Creates a new `Response` with all the components already provided.
    pub fn new(stream_id: StreamId, headers: Vec<Header>, body: Vec<u8>)
            -> Response {
        Response {
            stream_id: stream_id,
            headers: headers,
            body: body,
        }
    }

    /// Gets the response status code from the pseudo-header. If the response
    /// does not contain the response as the first pseuo-header, an error is
    /// returned as such a response is malformed.
    pub fn status_code(&self) -> HttpResult<u16> {
        // Since pseudo-headers MUST be found before any regular header fields
        // and the *only* pseudo-header defined for responses is the `:status`
        // field, the `:status` MUST be the first header; otherwise, the
        // response is malformed.
        if self.headers.len() < 1 {
            return Err(HttpError::MalformedResponse)
        }
        if &self.headers[0].0 != &b":status" {
            Err(HttpError::MalformedResponse)
        } else {
            Ok(try!(Response::parse_status_code(&self.headers[0].1)))
        }
    }

    /// A helper function that parses a given buffer as a status code and
    /// returns it as a `u16`, if it is valid.
    fn parse_status_code(buf: &[u8]) -> HttpResult<u16> {
        // "The status-code element is a three-digit integer code [...]"
        if buf.len() != 3 {
            return Err(HttpError::MalformedResponse);
        }

        // "There are five values for the first digit"
        if buf[0] < b'1' || buf[0] > b'5' {
            return Err(HttpError::MalformedResponse);
        }

        // The rest of them just have to be digits
        if buf[1] < b'0' || buf[1] > b'9' || buf[2] < b'0' || buf[2] > b'9' {
            return Err(HttpError::MalformedResponse);
        }

        // Finally, we can merge them into an integer
        Ok(100 * ((buf[0] - b'0') as u16) +
           10 * ((buf[1] - b'0') as u16) +
           1 * ((buf[2] - b'0') as u16))
    }
}

/// A struct representing a full HTTP/2 request, along with the full body, as a
/// sequence of bytes.
#[derive(Clone)]
pub struct Request {
    pub stream_id: u32,
    pub headers: Vec<Header>,
    pub body: Vec<u8>,
}

#[cfg(test)]
mod tests {
    use super::{Response, HttpError, HttpScheme};

    /// Tests that the `Response` struct correctly parses a status code from
    /// its headers list.
    #[test]
    fn test_parse_status_code_response() {
        {
            // Only status => Ok
            let resp = Response::new(
                1,
                vec![(b":status".to_vec(), b"200".to_vec())],
                vec![]);
            assert_eq!(resp.status_code().ok().unwrap(), 200);
        }
        {
            // Extra headers => still works
            let resp = Response::new(
                1,
                vec![(b":status".to_vec(), b"200".to_vec()),
                     (b"key".to_vec(), b"val".to_vec())],
                vec![]);
            assert_eq!(resp.status_code().ok().unwrap(), 200);
        }
        {
            // Status is not the first header => malformed
            let resp = Response::new(
                1,
                vec![(b"key".to_vec(), b"val".to_vec()),
                     (b":status".to_vec(), b"200".to_vec())],
                vec![]);
            assert_eq!(resp.status_code().err().unwrap(),
                       HttpError::MalformedResponse);
        }
        {
            // No headers at all => Malformed
            let resp = Response::new(1, vec![], vec![]);
            assert_eq!(resp.status_code().err().unwrap(),
                       HttpError::MalformedResponse);
        }
    }

    /// Tests that the `HttpScheme` enum returns the correct scheme strings for
    /// the two variants.
    #[test]
    fn test_scheme_string() {
        assert_eq!(HttpScheme::Http.as_bytes(), b"http");
        assert_eq!(HttpScheme::Https.as_bytes(), b"https");
    }
}
<|endoftext|>


<commit_before>//! Basic types to build the parsers

use self::IResult::*;
use util::ErrorKind;

#[cfg(feature = "core")]
use std::prelude::v1::*;
use std::boxed::Box;

/// Contains the error that a parser can return
///
/// It can represent a linked list of errors, indicating the path taken in the parsing tree, with corresponding position in the input data.
/// It depends on P, the input position (for a &[u8] parser, it would be a &[u8]), and E, the custom error type (by default, u32)
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum Err<P,E=u32>{
  /// An error code, represented by an ErrorKind, which can contain a custom error code represented by E
  Code(ErrorKind<E>),
  /// An error code, and the next error
  Node(ErrorKind<E>, Box<Err<P,E>>),
  /// An error code, and the input position
  Position(ErrorKind<E>, P),
  /// An error code, the input position and the next error
  NodePosition(ErrorKind<E>, P, Box<Err<P,E>>)
}

/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug,PartialEq,Eq,Clone,Copy)]
pub enum Needed {
  /// needs more data, but we do not know how much
  Unknown,
  /// contains the required data size
  Size(usize)
}

/// Holds the result of parsing functions
///
/// It depends on I, the input type, O, the output type, and E, the error type (by default u32)
///
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum IResult<I,O,E=u32> {
   /// indicates a correct parsing, the first field containing the rest of the unparsed data, the second field contains the parsed data
  Done(I,O),
  /// contains a Err, an enum that can indicate an error code, a position in the input, and a pointer to another error, making a list of errors in the parsing tree
  Error(Err<I,E>),
  /// Incomplete contains a Needed, an enum than can represent a known quantity of input data, or unknown
  Incomplete(Needed)
}

impl<I,O,E> IResult<I,O,E> {
  pub fn is_done(&self) -> bool {
    match *self {
      Done(_,_) => true,
      _         => false
    }
  }

  pub fn is_err(&self) -> bool {
    match *self {
      Error(_) => true,
      _        => false
    }
  }

  pub fn is_incomplete(&self) -> bool {
    match *self {
      Incomplete(_) => true,
      _             => false
    }
  }

  #[inline]
  pub fn map<N, F: FnOnce(O) -> N>(self, f: F) -> IResult<I, N, E> {
    match self {
      Done(i, o)    => Done(i, f(o)),
      Error(e)      => Error(e),
      Incomplete(n) => Incomplete(n),
    }
  }
}

pub trait GetInput<I> {
  fn remaining_input(&self) -> Option<I>;
}

pub trait GetOutput<O> {
  fn output(&self) -> Option<O>;
}

impl<'a,I,O,E> GetInput<&'a[I]> for IResult<&'a[I],O,E> {
  fn remaining_input(&self) -> Option<&'a[I]> {
    match *self {
      Done(ref i,_) => Some(*i),
      _             => None
    }
  }
}

impl<O,E> GetInput<()> for IResult<(),O,E> {
  fn remaining_input(&self) -> Option<()> {
    match *self {
      Done((),_) => Some(()),
      _          => None
    }
  }
}

impl<'a,O,E> GetInput<&'a str> for IResult<&'a str,O,E> {
  fn remaining_input(&self) -> Option<&'a str> {
    match *self {
      Done(ref i,_) => Some(*i),
      _          => None
    }
  }
}

impl<'a,I,O,E> GetOutput<&'a[O]> for IResult<I,&'a[O],E> {
  fn output(&self) -> Option<&'a[O]> {
    match *self {
      Done(_, ref o) => Some(*o),
      _              => None
    }
  }
}

impl<I,E> GetOutput<()> for IResult<I,(),E> {
  fn output(&self) -> Option<()> {
    match *self {
      Done(_,()) => Some(()),
      _          => None
    }
  }
}

impl<'a,I,E> GetOutput<&'a str> for IResult<I,&'a str,E> {
  fn output(&self) -> Option<&'a str> {
    match *self {
      Done(_,ref o) => Some(*o),
      _          => None
    }
  }
}
<commit_msg>Add `IResult::map_err` for error manipulation<commit_after>//! Basic types to build the parsers

use self::IResult::*;
use util::ErrorKind;

#[cfg(feature = "core")]
use std::prelude::v1::*;
use std::boxed::Box;

/// Contains the error that a parser can return
///
/// It can represent a linked list of errors, indicating the path taken in the parsing tree, with corresponding position in the input data.
/// It depends on P, the input position (for a &[u8] parser, it would be a &[u8]), and E, the custom error type (by default, u32)
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum Err<P,E=u32>{
  /// An error code, represented by an ErrorKind, which can contain a custom error code represented by E
  Code(ErrorKind<E>),
  /// An error code, and the next error
  Node(ErrorKind<E>, Box<Err<P,E>>),
  /// An error code, and the input position
  Position(ErrorKind<E>, P),
  /// An error code, the input position and the next error
  NodePosition(ErrorKind<E>, P, Box<Err<P,E>>)
}

/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug,PartialEq,Eq,Clone,Copy)]
pub enum Needed {
  /// needs more data, but we do not know how much
  Unknown,
  /// contains the required data size
  Size(usize)
}

/// Holds the result of parsing functions
///
/// It depends on I, the input type, O, the output type, and E, the error type (by default u32)
///
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum IResult<I,O,E=u32> {
   /// indicates a correct parsing, the first field containing the rest of the unparsed data, the second field contains the parsed data
  Done(I,O),
  /// contains a Err, an enum that can indicate an error code, a position in the input, and a pointer to another error, making a list of errors in the parsing tree
  Error(Err<I,E>),
  /// Incomplete contains a Needed, an enum than can represent a known quantity of input data, or unknown
  Incomplete(Needed)
}

impl<I,O,E> IResult<I,O,E> {
  pub fn is_done(&self) -> bool {
    match *self {
      Done(_,_) => true,
      _         => false
    }
  }

  pub fn is_err(&self) -> bool {
    match *self {
      Error(_) => true,
      _        => false
    }
  }

  pub fn is_incomplete(&self) -> bool {
    match *self {
      Incomplete(_) => true,
      _             => false
    }
  }

  #[inline]
  pub fn map<N, F: FnOnce(O) -> N>(self, f: F) -> IResult<I, N, E> {
    match self {
      Done(i, o)    => Done(i, f(o)),
      Error(e)      => Error(e),
      Incomplete(n) => Incomplete(n),
    }
  }

  #[inline]
  pub fn map_err<N, F>(self, f: F) -> IResult<I, O, N>
   where F: FnOnce(Err<I, E>) -> Err<I, N> {
    match self {
      Error(e)      => Error(f(e)),
      Incomplete(n) => Incomplete(n),
      Done(i, o)    => Done(i, o),
    }
  }
}

pub trait GetInput<I> {
  fn remaining_input(&self) -> Option<I>;
}

pub trait GetOutput<O> {
  fn output(&self) -> Option<O>;
}

impl<'a,I,O,E> GetInput<&'a[I]> for IResult<&'a[I],O,E> {
  fn remaining_input(&self) -> Option<&'a[I]> {
    match *self {
      Done(ref i,_) => Some(*i),
      _             => None
    }
  }
}

impl<O,E> GetInput<()> for IResult<(),O,E> {
  fn remaining_input(&self) -> Option<()> {
    match *self {
      Done((),_) => Some(()),
      _          => None
    }
  }
}

impl<'a,O,E> GetInput<&'a str> for IResult<&'a str,O,E> {
  fn remaining_input(&self) -> Option<&'a str> {
    match *self {
      Done(ref i,_) => Some(*i),
      _          => None
    }
  }
}

impl<'a,I,O,E> GetOutput<&'a[O]> for IResult<I,&'a[O],E> {
  fn output(&self) -> Option<&'a[O]> {
    match *self {
      Done(_, ref o) => Some(*o),
      _              => None
    }
  }
}

impl<I,E> GetOutput<()> for IResult<I,(),E> {
  fn output(&self) -> Option<()> {
    match *self {
      Done(_,()) => Some(()),
      _          => None
    }
  }
}

impl<'a,I,E> GetOutput<&'a str> for IResult<I,&'a str,E> {
  fn output(&self) -> Option<&'a str> {
    match *self {
      Done(_,ref o) => Some(*o),
      _          => None
    }
  }
}
<|endoftext|>


<commit_before>/*================================================================================================*/
// Copyright 2016 Kyle Finlay
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*================================================================================================*/

/*================================================================================================*/
//! The application module
//!
//! This module is the control center of ionCore.
//! It handles the initialization, updating, and destruction of all other modules,
//! as well as any inter-module communication.
/*================================================================================================*/

use ion_utils::logger::Logger;

/*================================================================================================*/
/*------APPVERSION STRUCT-------------------------------------------------------------------------*/
/*================================================================================================*/

/// The app version
///
/// This is a simple struct that stores the application version.
/// It is either set automatically (using cargo environment variables), via an app config file,
/// or manually using the AppBuilder.
///
/// Once set, it cannot be changed.
#[derive (Copy, Clone)]
pub struct AppVersion {

    // Public
    /// The major version of the application
    pub major : i32,
    /// The minor version of the application
    pub minor : i32,
    /// The patch version of the application
    pub patch : i32
}

/*================================================================================================*/
/*------APPVERSION PUBLIC METHODS-----------------------------------------------------------------*/
/*================================================================================================*/

impl AppVersion {

    /// Formats the version as a string
    pub fn to_string (&self) -> String {
        format! ("{}.{}.{}", self.major, self.minor, self.patch)
    }
}

/*================================================================================================*/
/*------APP STRUCT--------------------------------------------------------------------------------*/
/*================================================================================================*/

/// The app
///
/// This is the main control center of ionCore.
/// It is in charge of initialization, updating, and shutdown of all modules,
/// as well as the handing of any inter-module communication.
#[derive (Clone)]
pub struct App {

    // Private
    _name    : String,
    _version : AppVersion
}

/*================================================================================================*/
/*------APPVERSION PUBLIC METHODS-----------------------------------------------------------------*/
/*================================================================================================*/

impl App {

    /// Returns the name of the application
    pub fn get_name (&self) -> String {
        self._name.clone ()
    }

    /// Returns the version of the application
    pub fn get_version (&self) -> AppVersion {
        self._version
    }
}

/*================================================================================================*/
/*------APPBUILDER STRUCT-------------------------------------------------------------------------*/
/*================================================================================================*/

/// The app builder
///
/// The app builder provides an easy and straightforward way of creating and
/// configuring a new app instance.
#[derive (Clone)]
pub struct AppBuilder {

    // Private
    _name: String,
    _version: AppVersion
}

/*================================================================================================*/
/*------APPBUILDER PUBLIC METHODS-----------------------------------------------------------------*/
/*================================================================================================*/

impl AppBuilder {

    /// Builds the application
    pub fn build (&self) -> App {

        // Initalize the logger
        Logger::init ("ionCore.log", false).unwrap ();
        info! ("Initializing ionCore");

        App {_name: self._name.clone (),
             _version: self._version}
    }

    /// Sets the application name
    pub fn name (&mut self, name: String) -> &mut AppBuilder {

        self._name = name;
        self
    }

    /// Sets the version
    pub fn version (&mut self, major: i32, minor: i32, patch: i32) -> &mut AppBuilder {

        self._version.major = major;
        self._version.minor = minor;
        self._version.patch = patch;

        self
    }

    /// Sets the major version
    pub fn version_major (&mut self, major: i32) -> &mut AppBuilder {

        self._version.major = major;
        self
    }

    /// Sets the minor version
    pub fn version_minor (&mut self, minor: i32) -> &mut AppBuilder {

        self._version.minor = minor;
        self
    }

    /// Sets the patch version
    pub fn version_patch (&mut self, patch: i32) -> &mut AppBuilder {

        self._version.patch = patch;
        self
    }

/*================================================================================================*/
/*------APPBUILDER PUBLIC STATIC METHODS----------------------------------------------------------*/
/*================================================================================================*/

    /// Creates a new instance of the app builder
    pub fn new () -> AppBuilder {

        AppBuilder {_name: "Ion App".to_owned (),
                    _version: AppVersion {major: i32::from_str_radix (env! ("CARGO_PKG_VERSION_MAJOR"), 10).unwrap (),
                                          minor: i32::from_str_radix (env! ("CARGO_PKG_VERSION_MINOR"), 10).unwrap (),
                                          patch: i32::from_str_radix (env! ("CARGO_PKG_VERSION_PATCH"), 10).unwrap ()}}
    }
}
<commit_msg>'AppBuilder.build' now returns a std::result<commit_after>/*================================================================================================*/
// Copyright 2016 Kyle Finlay
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*================================================================================================*/

/*================================================================================================*/
//! The application module
//!
//! This module is the control center of ionCore.
//! It handles the initialization, updating, and destruction of all other modules,
//! as well as any inter-module communication.
/*================================================================================================*/

use ion_utils::logger::Logger;

/*================================================================================================*/
/*------APPVERSION STRUCT-------------------------------------------------------------------------*/
/*================================================================================================*/

/// The app version
///
/// This is a simple struct that stores the application version.
/// It is either set automatically (using cargo environment variables), via an app config file,
/// or manually using the AppBuilder.
///
/// Once set, it cannot be changed.
#[derive (Copy, Clone)]
pub struct AppVersion {

    // Public
    /// The major version of the application
    pub major : i32,
    /// The minor version of the application
    pub minor : i32,
    /// The patch version of the application
    pub patch : i32
}

/*================================================================================================*/
/*------APPVERSION PUBLIC METHODS-----------------------------------------------------------------*/
/*================================================================================================*/

impl AppVersion {

    /// Formats the version as a string
    pub fn to_string (&self) -> String {
        format! ("{}.{}.{}", self.major, self.minor, self.patch)
    }
}

/*================================================================================================*/
/*------APP STRUCT--------------------------------------------------------------------------------*/
/*================================================================================================*/

/// The app
///
/// This is the main control center of ionCore.
/// It is in charge of initialization, updating, and shutdown of all modules,
/// as well as the handing of any inter-module communication.
#[derive (Clone)]
pub struct App {

    // Private
    _name    : String,
    _version : AppVersion
}

/*================================================================================================*/
/*------APPVERSION PUBLIC METHODS-----------------------------------------------------------------*/
/*================================================================================================*/

impl App {

    /// Returns the name of the application
    pub fn get_name (&self) -> String {
        self._name.clone ()
    }

    /// Returns the version of the application
    pub fn get_version (&self) -> AppVersion {
        self._version
    }
}

/*================================================================================================*/
/*------APPBUILDER STRUCT-------------------------------------------------------------------------*/
/*================================================================================================*/

/// The app builder
///
/// The app builder provides an easy and straightforward way of creating and
/// configuring a new app instance.
#[derive (Clone)]
pub struct AppBuilder {

    // Private
    _name: String,
    _version: AppVersion
}

/*================================================================================================*/
/*------APPBUILDER PUBLIC METHODS-----------------------------------------------------------------*/
/*================================================================================================*/

impl AppBuilder {

    /// Builds the application
    pub fn build (&self) -> Result <App, &str> {

        // Initalize the logger
        Logger::init ("ionCore.log", false).unwrap ();
        info! ("Initializing ionCore");

        Ok (App {_name: self._name.clone (),
                 _version: self._version})
    }

    /// Sets the application name
    pub fn name (&mut self, name: String) -> &mut AppBuilder {

        self._name = name;
        self
    }

    /// Sets the version
    pub fn version (&mut self, major: i32, minor: i32, patch: i32) -> &mut AppBuilder {

        self._version.major = major;
        self._version.minor = minor;
        self._version.patch = patch;

        self
    }

    /// Sets the major version
    pub fn version_major (&mut self, major: i32) -> &mut AppBuilder {

        self._version.major = major;
        self
    }

    /// Sets the minor version
    pub fn version_minor (&mut self, minor: i32) -> &mut AppBuilder {

        self._version.minor = minor;
        self
    }

    /// Sets the patch version
    pub fn version_patch (&mut self, patch: i32) -> &mut AppBuilder {

        self._version.patch = patch;
        self
    }

/*================================================================================================*/
/*------APPBUILDER PUBLIC STATIC METHODS----------------------------------------------------------*/
/*================================================================================================*/

    /// Creates a new instance of the app builder
    pub fn new () -> AppBuilder {

        AppBuilder {_name: "Ion App".to_owned (),
                    _version: AppVersion {major: i32::from_str_radix (env! ("CARGO_PKG_VERSION_MAJOR"), 10).unwrap (),
                                          minor: i32::from_str_radix (env! ("CARGO_PKG_VERSION_MINOR"), 10).unwrap (),
                                          patch: i32::from_str_radix (env! ("CARGO_PKG_VERSION_PATCH"), 10).unwrap ()}}
    }
}
<|endoftext|>


<commit_before>//! Awesome compatibilty modules
use rlua::{self, Lua};
pub mod keygrabber;
pub mod mousegrabber;
pub mod awful;
mod awesome;
mod client;
mod screen;
mod button;
mod tag;
mod key;
mod drawin;
mod drawable;
mod mouse;
mod root;
mod signal;
mod object;
mod class;
mod property;

pub use self::object::Object;
pub use self::keygrabber::keygrabber_handle;
pub use self::mousegrabber::mousegrabber_handle;

use std::env;
use std::path::PathBuf;

pub fn init(lua: &Lua) -> rlua::Result<()> {
    set_up_awesome_path(lua)?;
    button::init(lua)?;
    awesome::init(lua)?;
    key::init(lua)?;
    client::init(lua)?;
    screen::init(lua)?;
    keygrabber::init(lua)?;
    root::init(lua)?;
    mouse::init(lua)?;
    tag::init(lua)?;
    drawin::init(lua)?;
    drawable::init(lua)?;
    mousegrabber::init(lua)?;
    awful::init(lua)?;
    Ok(())
}

fn set_up_awesome_path(lua: &Lua) -> rlua::Result<()> {
    let globals = lua.globals();
    let package: rlua::Table = globals.get("package")?;
    //let paths: String = package.get("path")?;
    // TODO Do this right, I'm too lazy and just scrapped from my awesome env
    let mut path = package.get::<_, String>("path")?;
    let mut cpath = package.get::<_, String>("cpath")?;
    let mut xdg_data_path: PathBuf = env::var("XDG_DATA_DIRS").unwrap_or("/usr/share".into()).into();
    xdg_data_path.push("awesome/lib");
    path.push_str(&format!(";{0}/?.lua;{0}/?/init.lua",
                             xdg_data_path.as_os_str().to_string_lossy()));
    package.set("path", path)?;
    let mut xdg_config_path: PathBuf = env::var("XDG_CONFIG_DIRS").unwrap_or("/etc/xdg".into()).into();
    xdg_config_path.push("awesome");
    cpath.push_str(&format!(";{}/?.so;{}/?.so",
                            xdg_config_path.into_os_string().to_string_lossy(),
                            xdg_data_path.into_os_string().to_string_lossy()));
    package.set("cpath", cpath)?;

    // NOTE The debug library does some powerful reflection that can do crazy things,
    // which is why it's unsafe to load.
    unsafe {
        lua.load_debug();
    }
    Ok(())
}

pub fn dummy<'lua>(_: &'lua Lua, _: rlua::Value) -> rlua::Result<()> { Ok(()) }
<commit_msg>Fixed comment<commit_after>//! Awesome compatibilty modules
use rlua::{self, Lua};
pub mod keygrabber;
pub mod mousegrabber;
pub mod awful;
mod awesome;
mod client;
mod screen;
mod button;
mod tag;
mod key;
mod drawin;
mod drawable;
mod mouse;
mod root;
mod signal;
mod object;
mod class;
mod property;

pub use self::object::Object;
pub use self::keygrabber::keygrabber_handle;
pub use self::mousegrabber::mousegrabber_handle;

use std::env;
use std::path::PathBuf;

pub fn init(lua: &Lua) -> rlua::Result<()> {
    set_up_awesome_path(lua)?;
    button::init(lua)?;
    awesome::init(lua)?;
    key::init(lua)?;
    client::init(lua)?;
    screen::init(lua)?;
    keygrabber::init(lua)?;
    root::init(lua)?;
    mouse::init(lua)?;
    tag::init(lua)?;
    drawin::init(lua)?;
    drawable::init(lua)?;
    mousegrabber::init(lua)?;
    awful::init(lua)?;
    Ok(())
}

fn set_up_awesome_path(lua: &Lua) -> rlua::Result<()> {
    let globals = lua.globals();
    let package: rlua::Table = globals.get("package")?;
    let mut path = package.get::<_, String>("path")?;
    let mut cpath = package.get::<_, String>("cpath")?;
    let mut xdg_data_path: PathBuf = env::var("XDG_DATA_DIRS").unwrap_or("/usr/share".into()).into();
    xdg_data_path.push("awesome/lib");
    path.push_str(&format!(";{0}/?.lua;{0}/?/init.lua",
                             xdg_data_path.as_os_str().to_string_lossy()));
    package.set("path", path)?;
    let mut xdg_config_path: PathBuf = env::var("XDG_CONFIG_DIRS").unwrap_or("/etc/xdg".into()).into();
    xdg_config_path.push("awesome");
    cpath.push_str(&format!(";{}/?.so;{}/?.so",
                            xdg_config_path.into_os_string().to_string_lossy(),
                            xdg_data_path.into_os_string().to_string_lossy()));
    package.set("cpath", cpath)?;

    // NOTE The debug library does some powerful reflection that can do crazy things,
    // which is why it's unsafe to load.
    unsafe {
        lua.load_debug();
    }
    Ok(())
}

pub fn dummy<'lua>(_: &'lua Lua, _: rlua::Value) -> rlua::Result<()> { Ok(()) }
<|endoftext|>


<commit_before>//! JSON and serialization
//!
//! # What is JSON?
//!
//! JSON (JavaScript Object Notation) is a way to write data in JavaScript.  Like XML, it allows to
//! encode structured data in a text format that can be easily read by humans.  Its simple syntax
//! and native compatibility with JavaScript have made it a widely used format.
//!
//! Data types that can be encoded are JavaScript types (see the `serde::json:Value` enum for more
//! details):
//!
//! * `Boolean`: equivalent to rust's `bool`
//! * `I64`: equivalent to rust's `i64`
//! * `U64`: equivalent to rust's `u64`
//! * `F64`: equivalent to rust's `i64`
//! * `String`: equivalent to rust's `String`
//! * `Array`: equivalent to rust's `Vec<T>`, but also allowing objects of different types in the
//!    same array
//! * `Object`: equivalent to rust's `BTreeMap<String, serde::json::Value>`
//! * `Null`
//!
//! An object is a series of string keys mapping to values, in `"key": value` format.  Arrays are
//! enclosed in square brackets ([ ... ]) and objects in curly brackets ({ ... }).  A simple JSON
//! document encoding a person, his/her age, address and phone numbers could look like
//!
//! ```ignore
//! {
//!     "FirstName": "John",
//!     "LastName": "Doe",
//!     "Age": 43,
//!     "Address": {
//!         "Street": "Downing Street 10",
//!         "City": "London",
//!         "Country": "Great Britain"
//!     },
//!     "PhoneNumbers": [
//!         "+44 1234567",
//!         "+44 2345678"
//!     ]
//! }
//! ```
//!
//! # Type-based Serialization and Deserialization
//!
//! Serde provides a mechanism for low boilerplate serialization & deserialization of values to and
//! from JSON via the serialization API.  To be able to serialize a piece of data, it must implement
//! the `serde::Serialize` trait.  To be able to deserialize a piece of data, it must implement the
//! `serde::Deserialize` trait.  Serde provides provides an annotation to automatically generate
//! the code for these traits: `#[derive(Serialize, Deserialize)]`.
//!
//! The JSON API also provides an enum `serde::json::Value` and a method `to_value` to serialize
//! objects.  A `serde::json::Value` value can be serialized as a string or buffer using the
//! functions described above.  You can also use the `json::Encoder` object, which implements the
//! `Encoder` trait.
//!
//! # Examples of use
//!
//! ## Using Autoserialization
//!
//! Create a struct called `TestStruct` and serialize and deserialize it to and from JSON using the
//! serialization API, using the derived serialization code.
//!
//! ```rust
//! // Required to use the annotations.
//! #![feature(custom_derive, plugin)]
//! #![plugin(serde_macros)]
//!
//! extern crate serde;
//!
//! use serde::json;
//!
//! // Automatically generate `Serialize` and `Deserialize` trait implementations
//! #[derive(Serialize, Deserialize)]
//! pub struct TestStruct  {
//!     data_int: u8,
//!     data_str: String,
//!     data_vector: Vec<u8>,
//! }
//!
//! fn main() {
//!     let object = TestStruct {
//!         data_int: 1,
//!         data_str: "homura".to_string(),
//!         data_vector: vec![2,3,4,5],
//!     };
//!
//!     // Serialize using `json::to_string`
//!     let serialized = json::to_string(&object).unwrap();
//!
//!     // Deserialize using `json::from_str`
//!     let deserialized: TestStruct = json::from_str(&serialized).unwrap();
//! }
//! ```
//!
//! ## Parsing a `str` to `Value` and reading the result
//!
//! ```rust
//! #![feature(custom_derive, plugin)]
//! #![plugin(serde_macros)]
//!
//! extern crate serde;
//!
//! use serde::json::{self, Value};
//!
//! fn main() {
//!     let data: Value = json::from_str("{\"foo\": 13, \"bar\": \"baz\"}").unwrap();
//!     println!("data: {:?}", data);
//!     // data: {"bar":"baz","foo":13}
//!     println!("object? {}", data.is_object());
//!     // object? true
//!
//!     let obj = data.as_object().unwrap();
//!     let foo = obj.get("foo").unwrap();
//!
//!     println!("array? {:?}", foo.as_array());
//!     // array? None
//!     println!("u64? {:?}", foo.as_u64());
//!     // u64? Some(13u64)
//!
//!     for (key, value) in obj.iter() {
//!         println!("{}: {}", key, match *value {
//!             Value::U64(v) => format!("{} (u64)", v),
//!             Value::String(ref v) => format!("{} (string)", v),
//!             _ => format!("other")
//!         });
//!     }
//!     // bar: baz (string)
//!     // foo: 13 (u64)
//! }
//! ```

pub use self::de::{Deserializer, from_str};
pub use self::error::{Error, ErrorCode};
pub use self::ser::{
    Serializer,
    to_writer,
    to_writer_pretty,
    to_vec,
    to_vec_pretty,
    to_string,
    to_string_pretty,
    escape_str,
};
pub use self::value::{Value, to_value, from_value};

pub mod builder;
pub mod de;
pub mod error;
pub mod ser;
pub mod value;
<commit_msg>Remove the use of serde_macros from the doctests<commit_after>//! JSON and serialization
//!
//! # What is JSON?
//!
//! JSON (JavaScript Object Notation) is a way to write data in JavaScript.  Like XML, it allows to
//! encode structured data in a text format that can be easily read by humans.  Its simple syntax
//! and native compatibility with JavaScript have made it a widely used format.
//!
//! Data types that can be encoded are JavaScript types (see the `serde::json:Value` enum for more
//! details):
//!
//! * `Boolean`: equivalent to rust's `bool`
//! * `I64`: equivalent to rust's `i64`
//! * `U64`: equivalent to rust's `u64`
//! * `F64`: equivalent to rust's `i64`
//! * `String`: equivalent to rust's `String`
//! * `Array`: equivalent to rust's `Vec<T>`, but also allowing objects of different types in the
//!    same array
//! * `Object`: equivalent to rust's `BTreeMap<String, serde::json::Value>`
//! * `Null`
//!
//! An object is a series of string keys mapping to values, in `"key": value` format.  Arrays are
//! enclosed in square brackets ([ ... ]) and objects in curly brackets ({ ... }).  A simple JSON
//! document encoding a person, his/her age, address and phone numbers could look like
//!
//! ```ignore
//! {
//!     "FirstName": "John",
//!     "LastName": "Doe",
//!     "Age": 43,
//!     "Address": {
//!         "Street": "Downing Street 10",
//!         "City": "London",
//!         "Country": "Great Britain"
//!     },
//!     "PhoneNumbers": [
//!         "+44 1234567",
//!         "+44 2345678"
//!     ]
//! }
//! ```
//!
//! # Type-based Serialization and Deserialization
//!
//! Serde provides a mechanism for low boilerplate serialization & deserialization of values to and
//! from JSON via the serialization API.  To be able to serialize a piece of data, it must implement
//! the `serde::Serialize` trait.  To be able to deserialize a piece of data, it must implement the
//! `serde::Deserialize` trait.  Serde provides provides an annotation to automatically generate
//! the code for these traits: `#[derive(Serialize, Deserialize)]`.
//!
//! The JSON API also provides an enum `serde::json::Value` and a method `to_value` to serialize
//! objects.  A `serde::json::Value` value can be serialized as a string or buffer using the
//! functions described above.  You can also use the `json::Serializer` object, which implements the
//! `Serializer` trait.
//!
//! # Examples of use
//!
//! ## Parsing a `str` to `Value` and reading the result
//!
//! ```rust
//! //#![feature(custom_derive, plugin)]
//! //#![plugin(serde_macros)]
//!
//! extern crate serde;
//!
//! use serde::json::{self, Value};
//!
//! fn main() {
//!     let data: Value = json::from_str("{\"foo\": 13, \"bar\": \"baz\"}").unwrap();
//!     println!("data: {:?}", data);
//!     // data: {"bar":"baz","foo":13}
//!     println!("object? {}", data.is_object());
//!     // object? true
//!
//!     let obj = data.as_object().unwrap();
//!     let foo = obj.get("foo").unwrap();
//!
//!     println!("array? {:?}", foo.as_array());
//!     // array? None
//!     println!("u64? {:?}", foo.as_u64());
//!     // u64? Some(13u64)
//!
//!     for (key, value) in obj.iter() {
//!         println!("{}: {}", key, match *value {
//!             Value::U64(v) => format!("{} (u64)", v),
//!             Value::String(ref v) => format!("{} (string)", v),
//!             _ => format!("other")
//!         });
//!     }
//!     // bar: baz (string)
//!     // foo: 13 (u64)
//! }
//! ```

pub use self::de::{Deserializer, from_str};
pub use self::error::{Error, ErrorCode};
pub use self::ser::{
    Serializer,
    to_writer,
    to_writer_pretty,
    to_vec,
    to_vec_pretty,
    to_string,
    to_string_pretty,
    escape_str,
};
pub use self::value::{Value, to_value, from_value};

pub mod builder;
pub mod de;
pub mod error;
pub mod ser;
pub mod value;
<|endoftext|>


<commit_before>/*!
Window-wrangling, polygon-pushing and input-grabbing.

*/

pub use backend::canvas::{CanvasBuilder, Canvas};
pub use backend::canvas::{Image};
pub use backend::canvas_util::{CanvasUtil};
pub use backend::key::Key;
pub use backend::fonter::{Fonter, Align};
pub use backend::event::{Event, MouseButton};

mod canvas;
mod canvas_util;
mod event;
mod fonter;
mod key;
mod renderer;

#[cfg(target_os = "macos")]
mod scancode_macos;
#[cfg(target_os = "linux")]
mod scancode_linux;
#[cfg(target_os = "windows")]
mod scancode_windows;

mod scancode {
#[cfg(target_os = "macos")]
    pub use backend::scancode_macos::MAP;
#[cfg(target_os = "linux")]
    pub use backend::scancode_linux::MAP;
#[cfg(target_os = "windows")]
    pub use backend::scancode_windows::MAP;
}

/// How to scale up the graphics to a higher resolution
pub enum CanvasMagnify {
    /// Nearest-neighbor, fill the window, not pixel-perfect
    Nearest,
    /// Pixel-perfect nearest neighbor, only magnify to the largest full
    /// multiple of pixel size that fits on the window
    PixelPerfect,
    /// Use smooth filtering, may look blurry
    Smooth,
}

/// UI Widget static identifier, unique for a specific site in source code.
#[derive(Copy, Debug, PartialEq)]
pub struct WidgetId {
    filename: &'static str,
    line: usize,
    column: usize,
}

impl WidgetId {
    pub fn new(filename: &'static str, line: usize, column: usize) -> WidgetId {
        WidgetId {
            filename: filename,
            line: line,
            column: column,
        }
    }

    pub fn dummy() -> WidgetId {
        WidgetId {
            filename: "n/a",
            line: 666666,
            column: 666666,
        }
    }
}

#[macro_export]
/// Generate a static identifier for the current source code position. Used
/// with imgui API.
macro_rules! widget_id {
    () => {
        // XXX: Assuming the crate user renames 'calx_backend' to 'backend'
        // when declaring the extern crate, since the app that does use this
        // does that. This is extremely wrong and bad to assume. Don't know
        // how to do this right.
        backend::WidgetId::new(concat!(module_path!(), "/", file!()), line!(), column!())
    }
}
<commit_msg>Update imgui widget generation<commit_after>/*!
Window-wrangling, polygon-pushing and input-grabbing.

*/

pub use backend::canvas::{CanvasBuilder, Canvas};
pub use backend::canvas::{Image};
pub use backend::canvas_util::{CanvasUtil};
pub use backend::key::Key;
pub use backend::fonter::{Fonter, Align};
pub use backend::event::{Event, MouseButton};

mod canvas;
mod canvas_util;
mod event;
mod fonter;
mod key;
mod renderer;

#[cfg(target_os = "macos")]
mod scancode_macos;
#[cfg(target_os = "linux")]
mod scancode_linux;
#[cfg(target_os = "windows")]
mod scancode_windows;

mod scancode {
#[cfg(target_os = "macos")]
    pub use backend::scancode_macos::MAP;
#[cfg(target_os = "linux")]
    pub use backend::scancode_linux::MAP;
#[cfg(target_os = "windows")]
    pub use backend::scancode_windows::MAP;
}

/// How to scale up the graphics to a higher resolution
pub enum CanvasMagnify {
    /// Nearest-neighbor, fill the window, not pixel-perfect
    Nearest,
    /// Pixel-perfect nearest neighbor, only magnify to the largest full
    /// multiple of pixel size that fits on the window
    PixelPerfect,
    /// Use smooth filtering, may look blurry
    Smooth,
}

/// UI Widget static identifier, unique for a specific site in source code.
#[derive(Copy, Debug, PartialEq)]
pub struct WidgetId {
    filename: &'static str,
    line: u32,
    column: u32,
}

impl WidgetId {
    pub fn new(filename: &'static str, line: u32, column: u32) -> WidgetId {
        WidgetId {
            filename: filename,
            line: line,
            column: column,
        }
    }

    pub fn dummy() -> WidgetId {
        WidgetId {
            filename: "n/a",
            line: 666666,
            column: 666666,
        }
    }
}

#[macro_export]
/// Generate a static identifier for the current source code position. Used
/// with imgui API.
macro_rules! widget_id {
    () => {
        ::calx::backend::WidgetId::new(concat!(module_path!(), "/", file!()), line!(), column!())
    }
}
<|endoftext|>


<commit_before>import sys;
import ptr;
import unsafe;

export _chan;
export _port;

export mk_port;

native "rust" mod rustrt {
    type void;
    type rust_chan;
    type rust_port;

    fn new_chan(po : *rust_port) -> *rust_chan;
    fn del_chan(ch : *rust_chan);
    fn drop_chan(ch : *rust_chan);
    fn chan_send(ch: *rust_chan, v : *void);

    fn new_port(unit_sz : uint) -> *rust_port;
    fn del_port(po : *rust_port);
    fn drop_port(po : *rust_port);
}

native "rust-intrinsic" mod rusti {
    fn recv[T](port : *rustrt::rust_port) -> T;
}

resource chan_ptr(ch: *rustrt::rust_chan) {
    rustrt::drop_chan(ch);
    rustrt::drop_chan(ch); // FIXME: We shouldn't have to do this
                           // twice.
    rustrt::del_chan(ch);
}

resource port_ptr(po: *rustrt::rust_port) {
    rustrt::drop_port(po);
    rustrt::del_port(po);
}

obj _chan[T](raw_chan : @chan_ptr) {
    fn send(v : &T) {
        rustrt::chan_send(**raw_chan,
                          unsafe::reinterpret_cast(ptr::addr_of(v)));
    }
}

obj _port[T](raw_port : @port_ptr) {
    fn mk_chan() -> _chan[T] {
        _chan(@chan_ptr(rustrt::new_chan(**raw_port)))
    }

    fn recv() -> T {
        ret rusti::recv(**raw_port)
    }
}

fn mk_port[T]() -> _port[T] {
    _port(@port_ptr(rustrt::new_port(sys::size_of[T]())))
}
<commit_msg>Removing an invalid operation in the attempt to restore valgrind cleanness.<commit_after>import sys;
import ptr;
import unsafe;

export _chan;
export _port;

export mk_port;

native "rust" mod rustrt {
    type void;
    type rust_chan;
    type rust_port;

    fn new_chan(po : *rust_port) -> *rust_chan;
    fn del_chan(ch : *rust_chan);
    fn drop_chan(ch : *rust_chan);
    fn chan_send(ch: *rust_chan, v : *void);

    fn new_port(unit_sz : uint) -> *rust_port;
    fn del_port(po : *rust_port);
    fn drop_port(po : *rust_port);
}

native "rust-intrinsic" mod rusti {
    fn recv[T](port : *rustrt::rust_port) -> T;
}

resource chan_ptr(ch: *rustrt::rust_chan) {
    rustrt::drop_chan(ch);
    rustrt::drop_chan(ch); // FIXME: We shouldn't have to do this
                           // twice.
}

resource port_ptr(po: *rustrt::rust_port) {
    rustrt::drop_port(po);
    rustrt::del_port(po);
}

obj _chan[T](raw_chan : @chan_ptr) {
    fn send(v : &T) {
        rustrt::chan_send(**raw_chan,
                          unsafe::reinterpret_cast(ptr::addr_of(v)));
    }
}

obj _port[T](raw_port : @port_ptr) {
    fn mk_chan() -> _chan[T] {
        _chan(@chan_ptr(rustrt::new_chan(**raw_port)))
    }

    fn recv() -> T {
        ret rusti::recv(**raw_port)
    }
}

fn mk_port[T]() -> _port[T] {
    _port(@port_ptr(rustrt::new_port(sys::size_of[T]())))
}
<|endoftext|>


<commit_before>#![feature(io)]

extern crate rustc_serialize;
extern crate docopt;
extern crate users;
extern crate glob;

use docopt::Docopt;
use std::env;
use std::fs;
use std::io::{stdin, stdout, Write, Read};
use std::fs::File;
use std::os::unix::fs::PermissionsExt;
use std::path::{PathBuf, Path};
use std::process::exit;
use std::ops::Deref;

static CRONTAB_DIR: &'static str = "/var/spool/cron";
static REBOOT_FILE: &'static str = "/run/crond.reboot";

static USAGE: &'static str = r#"
Usage: crontab [-u USER] -l
       crontab [-u USER] -e [FILE]
       crontab [-u USER] -s
       crontab [-u USER] -r [-i]
       crontab -h | --help

Maintain crontab files for individual users

Options:

  -h, --help            Show this help message and exit.
  -u USER, --user USER  It specifies the name of the user whose crontab is to
                        be tweaked. If this option is not given, crontab
                        examines "your" crontab, i.e., the crontab of the
                        person executing the command. Note that su(8) can
                        confuse crontab and that if you are running inside of
                        su(8) you should always use the -u option for safety's
                        sake. The first form of this command is used to
                        install a new crontab from some named file or standard
                        input if the pseudo-filename "-" is given.
  -l, --list            The current crontab will be displayed on standard
                        output.
  -r, --remove          The current crontab will be removed.
  -e, --edit            This option is used to edit the current crontab using
                        the editor specified by the VISUAL or EDITOR
                        environment variables. After you exit from the editor,
                        the modified crontab will be installed automatically.
  -s, --show            Show all users who have a crontab.
  -i, --ask             This option modifies the -r option to prompt the user
                        for a 'y/Y' response before actually removing the
                        crontab.
"#;

#[derive(Debug, RustcDecodable)]
#[allow(non_snake_case)]
struct Args {
    arg_FILE: Option<String>,
    flag_user: Option<String>,
    flag_list: bool,
    flag_remove: bool,
    flag_edit: bool,
    flag_show: bool,
    flag_ask: bool
}

fn get_editor() -> Option<String> {
    env::var("EDITOR").ok()
        .or_else(|| env::var("VISUAL").ok())
        .or_else(|| ["/usr/bin/editor", "/usr/bin/vim", "/usr/bin/nano", "/usr/bin/mcedit"].iter()
                 .filter(|editor| fs::metadata(editor).map(|meta| meta.is_file() && meta.permissions().mode() & 0o0111 != 0).unwrap_or(false))
                 .next()
                 .map(|&s| s.to_owned()))
}

fn confirm(msg: &str) -> bool {
    let mut stdin = stdin();
    let mut stdout = stdout();
    loop {
        stdout.write_all(msg.as_bytes()).unwrap();
        stdout.flush().unwrap();
        let mut buf = [0u8; 1024];
        match stdin.read(&mut buf) {
            Ok(n) if n > 0 && (buf[0] == 121 || buf[0] == 89) => return true,
            Ok(n) if n > 0 && (buf[0] == 110 || buf[0] == 78) => return false,
            _ => { stdout.write_all("Please reply \"y\" or \"n\"\n".as_bytes()).unwrap(); },
        }
    }
}

fn list(cron_file: &Path, args: &Args) {
    if let Err(e) = File::open(cron_file).map(|file| file.tee(stdout()).bytes().count()) {
        use std::io::ErrorKind::*;
        match e.kind() {
            NotFound => println!("no crontab for {}", args.flag_user.as_ref().map(String::deref).unwrap_or("???")),
            PermissionDenied => println!("you can not display {}'s crontab", args.flag_user.as_ref().map(String::deref).unwrap_or("???")),
            _ => println!("failed to read {}", cron_file.display()),
        }
        exit(1);
    }
}

fn remove(cron_file: &Path, args: &Args) {
    if !args.flag_ask || confirm(&*format!("Are you sure you want to delete {} (y/n)? ", cron_file.display())) {
        if let Err(e) = fs::remove_file(cron_file) {
            use std::io::ErrorKind::*;
            match e.kind() {
                NotFound => println!("no crontab for {}", args.flag_user.as_ref().map(String::deref).unwrap_or("???")),
                PermissionDenied => match args.flag_user {
                    ref user @ Some(_) if user != &users::get_current_username() => {
                        println!("you can not remove {}'s crontab", args.flag_user.as_ref().map(String::deref).unwrap_or("???"));
                    },
                    _ => match File::create(cron_file) {
                        Ok(_) => println!("couldn't remove {}, wiped it instead", cron_file.display()),
                        Err(_) => println!("failed to remove {}", cron_file.display()),
                    }
                },
                _ => println!("failed to remove {}", cron_file.display())
            }
            exit(1);
        }
    }
}

fn show(cron_file: &Path, args: &Args) {
    if users::get_current_uid() != 0 {
        return println!("must be privileged to use -s");
    }

    if let Ok(dir) = fs::read_dir(CRONTAB_DIR) {
        for entry in dir {
            let name = entry.ok().and_then(|e| e.path().file_name().map(|s| s.to_string_lossy().into_owned()));
            if let Some(user) = name {
                if users::get_user_by_name(&*user).is_some() {
                    println!("{}", user);
                } else {
                    println!("WARNING: crontab found with no matching user: {}", user)
                }
            }
        }
    }
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());

    let editor = get_editor();

    match fs::metadata(CRONTAB_DIR) {
        Ok(ref meta) if meta.is_dir() => (),
        Ok(_) => return println!("{} is not a directory!", CRONTAB_DIR),
        Err(_) => if let Err(_) = fs::create_dir_all(CRONTAB_DIR) {
            return println!("{} doesn't exist!", CRONTAB_DIR);
        }
    }

    let cron_file = PathBuf::from(CRONTAB_DIR).join(args.flag_user.clone().or_else(|| users::get_current_username()).unwrap());

    if args.flag_show {
        show(&*cron_file, &args);
    } else if args.flag_list {
        list(&*cron_file, &args);
    }

    //println!("{:?}", confirm("Yes or no? "));
    //println!("{:?}", cron_file);
    //println!("{:?}", editor);
    //println!("{:?}", args);
}
<commit_msg>crontab: stubs for all sub commands<commit_after>#![feature(io)]

extern crate rustc_serialize;
extern crate docopt;
extern crate users;
extern crate glob;

use docopt::Docopt;
use std::env;
use std::fs;
use std::io::{stdin, stdout, Write, Read};
use std::fs::File;
use std::os::unix::fs::PermissionsExt;
use std::path::{PathBuf, Path};
use std::process::exit;
use std::ops::Deref;

static CRONTAB_DIR: &'static str = "/var/spool/cron";
static REBOOT_FILE: &'static str = "/run/crond.reboot";

static USAGE: &'static str = r#"
Usage: crontab [-u USER] -l
       crontab [-u USER] -e [FILE]
       crontab [-u USER] -s
       crontab [-u USER] -r [-i]
       crontab -h | --help

Maintain crontab files for individual users

Options:

  -h, --help            Show this help message and exit.
  -u USER, --user USER  It specifies the name of the user whose crontab is to
                        be tweaked. If this option is not given, crontab
                        examines "your" crontab, i.e., the crontab of the
                        person executing the command. Note that su(8) can
                        confuse crontab and that if you are running inside of
                        su(8) you should always use the -u option for safety's
                        sake. The first form of this command is used to
                        install a new crontab from some named file or standard
                        input if the pseudo-filename "-" is given.
  -l, --list            The current crontab will be displayed on standard
                        output.
  -r, --remove          The current crontab will be removed.
  -e, --edit            This option is used to edit the current crontab using
                        the editor specified by the VISUAL or EDITOR
                        environment variables. After you exit from the editor,
                        the modified crontab will be installed automatically.
  -s, --show            Show all users who have a crontab.
  -i, --ask             This option modifies the -r option to prompt the user
                        for a 'y/Y' response before actually removing the
                        crontab.
"#;

#[derive(Debug, RustcDecodable)]
#[allow(non_snake_case)]
struct Args {
    arg_FILE: Option<String>,
    flag_user: Option<String>,
    flag_list: bool,
    flag_remove: bool,
    flag_edit: bool,
    flag_show: bool,
    flag_ask: bool
}

fn get_editor() -> Option<String> {
    env::var("EDITOR").ok()
        .or_else(|| env::var("VISUAL").ok())
        .or_else(|| ["/usr/bin/editor", "/usr/bin/vim", "/usr/bin/nano", "/usr/bin/mcedit"].iter()
                 .filter(|editor| fs::metadata(editor).map(|meta| meta.is_file() && meta.permissions().mode() & 0o0111 != 0).unwrap_or(false))
                 .next()
                 .map(|&s| s.to_owned()))
}

fn confirm(msg: &str) -> bool {
    let mut stdin = stdin();
    let mut stdout = stdout();
    loop {
        stdout.write_all(msg.as_bytes()).unwrap();
        stdout.flush().unwrap();
        let mut buf = [0u8; 1024];
        match stdin.read(&mut buf) {
            Ok(n) if n > 0 && (buf[0] == 121 || buf[0] == 89) => return true,
            Ok(n) if n > 0 && (buf[0] == 110 || buf[0] == 78) => return false,
            _ => { stdout.write_all("Please reply \"y\" or \"n\"\n".as_bytes()).unwrap(); },
        }
    }
}

fn list(cron_file: &Path, args: &Args) {
    if let Err(e) = File::open(cron_file).map(|file| file.tee(stdout()).bytes().count()) {
        use std::io::ErrorKind::*;
        match e.kind() {
            NotFound => println!("no crontab for {}", args.flag_user.as_ref().map(String::deref).unwrap_or("???")),
            PermissionDenied => println!("you can not display {}'s crontab", args.flag_user.as_ref().map(String::deref).unwrap_or("???")),
            _ => println!("failed to read {}", cron_file.display()),
        }
        exit(1);
    }
}

fn remove(cron_file: &Path, args: &Args) {
    if !args.flag_ask || confirm(&*format!("Are you sure you want to delete {} (y/n)? ", cron_file.display())) {
        if let Err(e) = fs::remove_file(cron_file) {
            use std::io::ErrorKind::*;
            match e.kind() {
                NotFound => println!("no crontab for {}", args.flag_user.as_ref().map(String::deref).unwrap_or("???")),
                PermissionDenied => match args.flag_user {
                    ref user @ Some(_) if user != &users::get_current_username() => {
                        println!("you can not remove {}'s crontab", args.flag_user.as_ref().map(String::deref).unwrap_or("???"));
                    },
                    _ => match File::create(cron_file) {
                        Ok(_) => println!("couldn't remove {}, wiped it instead", cron_file.display()),
                        Err(_) => println!("failed to remove {}", cron_file.display()),
                    }
                },
                _ => println!("failed to remove {}", cron_file.display())
            }
            exit(1);
        }
    }
}

fn show(cron_file: &Path, args: &Args) {
    if users::get_current_uid() != 0 {
        return println!("must be privileged to use -s");
    }

    if let Ok(dir) = fs::read_dir(CRONTAB_DIR) {
        for entry in dir {
            let name = entry.ok().and_then(|e| e.path().file_name().map(|s| s.to_string_lossy().into_owned()));
            if let Some(user) = name {
                if users::get_user_by_name(&*user).is_some() {
                    println!("{}", user);
                } else {
                    println!("WARNING: crontab found with no matching user: {}", user)
                }
            }
        }
    }
}

fn edit(cron_file: &Path, args: &Args) {
    // TODO
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());

    let editor = get_editor();

    match fs::metadata(CRONTAB_DIR) {
        Ok(ref meta) if meta.is_dir() => (),
        Ok(_) => return println!("{} is not a directory!", CRONTAB_DIR),
        Err(_) => if let Err(_) = fs::create_dir_all(CRONTAB_DIR) {
            return println!("{} doesn't exist!", CRONTAB_DIR);
        }
    }

    let cron_file = PathBuf::from(CRONTAB_DIR).join(args.flag_user.clone().or_else(|| users::get_current_username()).unwrap());

    if args.flag_show {
        show(&*cron_file, &args);
    } else if args.flag_list {
        list(&*cron_file, &args);
    } else if args.flag_edit {
        edit(&*cron_file, &args);
    } else if args.flag_remove {
        remove(&*cron_file, &args);
    }

    //println!("{:?}", confirm("Yes or no? "));
    //println!("{:?}", cron_file);
    //println!("{:?}", editor);
    //println!("{:?}", args);
}
<|endoftext|>


<commit_before>// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashMap;

use syn::Ident;

use crate::{
    conversion::{api::Api, error_reporter::convert_item_apis, ConvertError},
    types::{validate_ident_ok_for_cxx, QualifiedName},
};

use super::fun::FnAnalysis;

/// Do some final checks that the names we've come up with can be represented
/// within cxx.
pub(crate) fn check_names(apis: Vec<Api<FnAnalysis>>) -> Vec<Api<FnAnalysis>> {
    // If any items have names which can't be represented by cxx,
    // abort. This check should ideally be done at the times we fill in the
    // `name` field of each `api` in the first place, at parse time. TODO - move
    // to parsing phase.
    let mut intermediate = Vec::new();
    convert_item_apis(apis, &mut intermediate, |api| match api {
        Api::Typedef { ref name, .. }
        | Api::ForwardDeclaration { ref name, .. }
        | Api::Const { ref name, .. }
        | Api::Enum { ref name, .. }
        | Api::Struct { ref name, .. } => {
            validate_all_segments_ok_for_cxx(name.name.segment_iter())?;
            if let Some(ref cpp_name) = name.cpp_name {
                // The C++ name might itself be outer_type::inner_type and thus may
                // have multiple segments.
                validate_all_segments_ok_for_cxx(QualifiedName::new_from_cpp_name(cpp_name).segment_iter())?;
            }
            Ok(Some(api))
        }
        Api::Function { .. } // we don't handle functions here because
            // the function analysis does an equivalent check. Instead of just rejecting
            // the function, it creates a wrapper function instead with a more
            // palatable name. That's preferable to rejecting the API entirely.
        | Api::ConcreteType  { .. }
        | Api::CType { .. }
        | Api::StringConstructor { .. }
        | Api::IgnoredItem { .. } => Ok(Some(api)),
    });

    // Reject any names which are duplicates within the cxx bridge mod,
    // that has a flat namespace.
    let mut names_found: HashMap<Ident, usize> = HashMap::new();
    for api in &intermediate {
        let my_name = api.cxxbridge_name();
        if let Some(name) = my_name {
            let e = names_found.entry(name).or_default();
            *e += 1usize;
        }
    }
    let mut results = Vec::new();
    convert_item_apis(intermediate, &mut results, |api| {
        let my_name = api.cxxbridge_name();
        if let Some(name) = my_name {
            if *names_found.entry(name).or_default() > 1usize {
                Err(ConvertError::DuplicateCxxBridgeName)
            } else {
                Ok(Some(api))
            }
        } else {
            Ok(Some(api))
        }
    });
    results
}

fn validate_all_segments_ok_for_cxx(
    items: impl Iterator<Item = String>,
) -> Result<(), ConvertError> {
    for seg in items {
        validate_ident_ok_for_cxx(&seg)?;
    }
    Ok(())
}
<commit_msg>Comment update.<commit_after>// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashMap;

use syn::Ident;

use crate::{
    conversion::{api::Api, error_reporter::convert_item_apis, ConvertError},
    types::{validate_ident_ok_for_cxx, QualifiedName},
};

use super::fun::FnAnalysis;

/// Do some final checks that the names we've come up with can be represented
/// within cxx.
pub(crate) fn check_names(apis: Vec<Api<FnAnalysis>>) -> Vec<Api<FnAnalysis>> {
    // If any items have names which can't be represented by cxx,
    // abort. This check should ideally be done at the times we fill in the
    // `name` field of each `api` in the first place, at parse time, though
    // as the `name` field of each API may change during various analysis phases,
    // currently it seems better to do it here to ensure we respect
    // the output of any such changes.
    let mut intermediate = Vec::new();
    convert_item_apis(apis, &mut intermediate, |api| match api {
        Api::Typedef { ref name, .. }
        | Api::ForwardDeclaration { ref name, .. }
        | Api::Const { ref name, .. }
        | Api::Enum { ref name, .. }
        | Api::Struct { ref name, .. } => {
            validate_all_segments_ok_for_cxx(name.name.segment_iter())?;
            if let Some(ref cpp_name) = name.cpp_name {
                // The C++ name might itself be outer_type::inner_type and thus may
                // have multiple segments.
                validate_all_segments_ok_for_cxx(QualifiedName::new_from_cpp_name(cpp_name).segment_iter())?;
            }
            Ok(Some(api))
        }
        Api::Function { .. } // we don't handle functions here because
            // the function analysis does an equivalent check. Instead of just rejecting
            // the function, it creates a wrapper function instead with a more
            // palatable name. That's preferable to rejecting the API entirely.
        | Api::ConcreteType  { .. }
        | Api::CType { .. }
        | Api::StringConstructor { .. }
        | Api::IgnoredItem { .. } => Ok(Some(api)),
    });

    // Reject any names which are duplicates within the cxx bridge mod,
    // that has a flat namespace.
    let mut names_found: HashMap<Ident, usize> = HashMap::new();
    for api in &intermediate {
        let my_name = api.cxxbridge_name();
        if let Some(name) = my_name {
            let e = names_found.entry(name).or_default();
            *e += 1usize;
        }
    }
    let mut results = Vec::new();
    convert_item_apis(intermediate, &mut results, |api| {
        let my_name = api.cxxbridge_name();
        if let Some(name) = my_name {
            if *names_found.entry(name).or_default() > 1usize {
                Err(ConvertError::DuplicateCxxBridgeName)
            } else {
                Ok(Some(api))
            }
        } else {
            Ok(Some(api))
        }
    });
    results
}

fn validate_all_segments_ok_for_cxx(
    items: impl Iterator<Item = String>,
) -> Result<(), ConvertError> {
    for seg in items {
        validate_ident_ok_for_cxx(&seg)?;
    }
    Ok(())
}
<|endoftext|>