<commit_before>//! Parse server.properties files

use std::fs::File;
use std::io::prelude::*;
use std::io::{self, BufReader, BufWriter};
use std::num::ParseIntError;
use std::path::Path;
use std::str::ParseBoolError;

macro_rules! parse {
    ($value:ident, String) => {
        $value.to_string()
    };
    ($value:ident, bool) => {
        try!($value.parse().map_err(|_: ParseBoolError| io::Error::new(io::ErrorKind::InvalidInput, "invalid bool value")))
    };
    ($value:ident, i32) => {
        try!($value.parse().map_err(|_: ParseIntError| io::Error::new(io::ErrorKind::InvalidInput, "invalid i32 value")))
    };
    ($value:ident, u16) => {
        try!($value.parse().map_err(|_: ParseIntError| io::Error::new(io::ErrorKind::InvalidInput, "invalid u16 value")))
    }
}

macro_rules! server_properties_impl {
    ($({ $field:ident, $hyphen:expr, $fty:ident, $default:expr})+) => {
        /// Vanilla server.properties
        ///
        /// Documentation of each filed here: http://minecraft.gamepedia.com/Server.properties
        #[derive(Debug)]
        pub struct Properties {
            $(pub $field: $fty),*
        }

        impl Properties {
            pub fn default() -> Properties {
                Properties{
                    $($field: $default),*
                }
            }

            /// Load and parse a server.properties file from `path`,
            pub fn load(path: &Path) -> io::Result<Properties> {
                let mut p = Properties::default();
                let file = try!(File::open(path));
                let file = BufReader::new(file);
                for line in file.lines().map(|l| l.unwrap()) {
                    // Ignore comment lines
                    if line.trim().starts_with("#") {
                        continue
                    }
                    let parts: Vec<&str> = line.trim().splitn(2, '=').collect();
                    let (prop, value) = (parts[0], parts[1]);
                    match prop {
                        $(stringify!($field) => p.$field = parse!(value, $fty),)*
                        prop => println!("Unknown property {}", prop)
                    }
                }
                Ok(p)
            }

            /// Saves a server.properties file into `path`. It creates the
            /// file if it does not exist, and will truncate it if it does.
            pub fn save(&self, path: &Path) -> io::Result<()> {
                let file = try!(File::create(path));
                let mut file = BufWriter::new(file);
                // Header
                try!(write!(&mut file, "#Minecraft server properties"));
                try!(write!(&mut file, "#(File modification datestamp)"));
                // Body. Vanilla MC does write 37 out of 40 properties by default, it
                // only writes the 3 left if they are not using default values. It
                // also writes them unsorted (possibly because they are stored in a
                // HashMap).
                $(try!(write!(&mut file, "{}={}\n", $hyphen, self.$field));)*
                Ok(())
            }
        }

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

            #[test]
            fn decode_default() {
                let props = Properties::default();
                $(assert_eq!(props.$field, $default));*
            }
        }
    }
}

server_properties_impl! {
    { allow_flight, "allow-flight", bool, false }
    { allow_nether, "allow-nether", bool, true }
    { announce_player_achievements, "announce-player-achievements", bool, true }
    { difficulty, "difficulty", i32, 1 }
    { enable_query, "enable-query", bool, false }
    { enable_rcon, "enable-rcon", bool, false }
    { enable_command_block, "enable-command-block", bool, false }
    { force_gamemode, "force-gamemode", bool, false }
    { gamemode, "gamemode", i32, 0 }
    { generate_structures, "generate-structures", bool, true }
    { generator_settings, "generator-settings", String, "".to_string() }
    { hardcore, "hardcore", bool, false }
    { level_name, "level-name", String, "world".to_string() }
    { level_seed, "level-seed", String, "".to_string() }
    { level_type, "level-type", String, "DEFAULT".to_string() }
    { max_build_height, "max-build-height", i32, 256 }
    { max_players, "max-players", i32, 20 }
    { max_tick_time, "max-tick-time", i32, 60000 }
    { max_world_size, "max-world-size", i32, 29999984 }
    { motd, "motd", String, "A Minecraft Server".to_string() }
    { network_compression_threshold, "network-compression-threshold", i32, 256 }
    { online_mode, "online-mode", bool, true }
    { op_permission_level, "op-permission-level", i32, 4 }
    { player_idle_timeout, "player-idle-timeout", i32, 0 }
    { pvp, "pvp", bool, true }
    { query_port, "query.port", i32, 25565 }
    { rcon_password, "rcon.password", String, "".to_string() }
    { rcon_port, "rcon.port", i32, 25575 }
    { resource_pack, "resource-pack", String, "".to_string() }
    { resource_pack_hash, "resource-pack-hash", String, "".to_string() }
    { server_ip, "server-ip", String, "".to_string() }
    { server_port, "server-port", u16, 25565 }
    { snooper_enabled, "snooper-enabled", bool, true }
    { spawn_animals, "spawn-animals", bool, true }
    { spawn_monsters, "spawn-monsters", bool, true }
    { spawn_npcs, "spawn-npcs", bool, true }
    { spawn_protection, "spawn-protection", i32, 16 }
    { use_native_transport, "use-native-transport", bool, true }
    { view_distance, "view-distance", i32, 10 }
    { white_list, "white-list", bool, false }
}
<commit_msg>Fix server.properties parsing<commit_after>//! Parse server.properties files

use std::fs::File;
use std::io::prelude::*;
use std::io::{self, BufReader, BufWriter};
use std::num::ParseIntError;
use std::path::Path;
use std::str::ParseBoolError;

macro_rules! parse {
    ($value:ident, String) => {
        $value.to_string()
    };
    ($value:ident, bool) => {
        try!($value.parse().map_err(|_: ParseBoolError| io::Error::new(io::ErrorKind::InvalidInput, "invalid bool value")))
    };
    ($value:ident, i32) => {
        try!($value.parse().map_err(|_: ParseIntError| io::Error::new(io::ErrorKind::InvalidInput, "invalid i32 value")))
    };
    ($value:ident, u16) => {
        try!($value.parse().map_err(|_: ParseIntError| io::Error::new(io::ErrorKind::InvalidInput, "invalid u16 value")))
    }
}

macro_rules! server_properties_impl {
    ($({ $field:ident, $hyphen:expr, $fty:ident, $default:expr})+) => {
        /// Vanilla server.properties
        ///
        /// Documentation of each filed here: http://minecraft.gamepedia.com/Server.properties
        #[derive(Debug)]
        pub struct Properties {
            $(pub $field: $fty),*
        }

        impl Properties {
            pub fn default() -> Properties {
                Properties{
                    $($field: $default),*
                }
            }

            /// Load and parse a server.properties file from `path`,
            pub fn load(path: &Path) -> io::Result<Properties> {
                let mut p = Properties::default();
                let file = try!(File::open(path));
                let file = BufReader::new(file);
                for line in file.lines().map(|l| l.unwrap()) {
                    // Ignore comment lines
                    if line.trim().starts_with("#") {
                        continue
                    }
                    let parts: Vec<&str> = line.trim().splitn(2, '=').collect();
                    let (prop, value) = (parts[0], parts[1]);
                    match prop {
                        $($hyphen => p.$field = parse!(value, $fty),)*
                        prop => println!("Unknown property {}", prop)
                    }
                }
                Ok(p)
            }

            /// Saves a server.properties file into `path`. It creates the
            /// file if it does not exist, and will truncate it if it does.
            pub fn save(&self, path: &Path) -> io::Result<()> {
                let file = try!(File::create(path));
                let mut file = BufWriter::new(file);
                // Header
                try!(write!(&mut file, "#Minecraft server properties"));
                try!(write!(&mut file, "#(File modification datestamp)"));
                // Body. Vanilla MC does write 37 out of 40 properties by default, it
                // only writes the 3 left if they are not using default values. It
                // also writes them unsorted (possibly because they are stored in a
                // HashMap).
                $(try!(write!(&mut file, "{}={}\n", $hyphen, self.$field));)*
                Ok(())
            }
        }

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

            #[test]
            fn decode_default() {
                let props = Properties::default();
                $(assert_eq!(props.$field, $default));*
            }
        }
    }
}

server_properties_impl! {
    { allow_flight, "allow-flight", bool, false }
    { allow_nether, "allow-nether", bool, true }
    { announce_player_achievements, "announce-player-achievements", bool, true }
    { difficulty, "difficulty", i32, 1 }
    { enable_query, "enable-query", bool, false }
    { enable_rcon, "enable-rcon", bool, false }
    { enable_command_block, "enable-command-block", bool, false }
    { force_gamemode, "force-gamemode", bool, false }
    { gamemode, "gamemode", i32, 0 }
    { generate_structures, "generate-structures", bool, true }
    { generator_settings, "generator-settings", String, "".to_string() }
    { hardcore, "hardcore", bool, false }
    { level_name, "level-name", String, "world".to_string() }
    { level_seed, "level-seed", String, "".to_string() }
    { level_type, "level-type", String, "DEFAULT".to_string() }
    { max_build_height, "max-build-height", i32, 256 }
    { max_players, "max-players", i32, 20 }
    { max_tick_time, "max-tick-time", i32, 60000 }
    { max_world_size, "max-world-size", i32, 29999984 }
    { motd, "motd", String, "A Minecraft Server".to_string() }
    { network_compression_threshold, "network-compression-threshold", i32, 256 }
    { online_mode, "online-mode", bool, true }
    { op_permission_level, "op-permission-level", i32, 4 }
    { player_idle_timeout, "player-idle-timeout", i32, 0 }
    { pvp, "pvp", bool, true }
    { query_port, "query.port", i32, 25565 }
    { rcon_password, "rcon.password", String, "".to_string() }
    { rcon_port, "rcon.port", i32, 25575 }
    { resource_pack, "resource-pack", String, "".to_string() }
    { resource_pack_hash, "resource-pack-hash", String, "".to_string() }
    { server_ip, "server-ip", String, "".to_string() }
    { server_port, "server-port", u16, 25565 }
    { snooper_enabled, "snooper-enabled", bool, true }
    { spawn_animals, "spawn-animals", bool, true }
    { spawn_monsters, "spawn-monsters", bool, true }
    { spawn_npcs, "spawn-npcs", bool, true }
    { spawn_protection, "spawn-protection", i32, 16 }
    { use_native_transport, "use-native-transport", bool, true }
    { view_distance, "view-distance", i32, 10 }
    { white_list, "white-list", bool, false }
}
<|endoftext|>


<commit_before>use std::convert::{From, Into, AsRef};
use std::fmt;
use std::result::Result as StdResult;
use std::str;

use error::{Result, Error};

mod string_collect {

    use utf8;
    use utf8::DecodeError;

    use error::{Error, Result};

    #[derive(Debug)]
    pub struct StringCollector {
        data: String,
        incomplete: Option<utf8::Incomplete>,
    }

    impl StringCollector {
        pub fn new() -> Self {
            StringCollector {
                data: String::new(),
                incomplete: None,
            }
        }

        pub fn len(&self) -> usize {
            self.data.len()
                .saturating_add(self.incomplete.map(|i| i.buffer_len as usize).unwrap_or(0))
        }

        pub fn extend<T: AsRef<[u8]>>(&mut self, tail: T) -> Result<()> {
            let mut input: &[u8] = tail.as_ref();

            if let Some(mut incomplete) = self.incomplete.take() {
                let fin = if let Some((result, rest)) = incomplete.try_complete(input) {
                    input = rest;
                    if let Ok(text) = result {
                        self.data.push_str(text);
                    } else {
                        return Err(Error::Utf8)
                    }
                    true
                } else {
                    input = &[];
                    false
                };
                if !fin {
                    self.incomplete = Some(incomplete)
                }
            }

            if !input.is_empty() {
                match utf8::decode(input) {
                    Ok(text) => {
                        self.data.push_str(text);
                        Ok(())
                    }
                    Err(DecodeError::Incomplete { valid_prefix, incomplete_suffix }) => {
                        self.data.push_str(valid_prefix);
                        self.incomplete = Some(incomplete_suffix);
                        Ok(())
                    }
                    Err(DecodeError::Invalid { valid_prefix, .. }) => {
                        self.data.push_str(valid_prefix);
                        Err(Error::Utf8)
                    }
                }
            } else {
                Ok(())
            }
        }

        pub fn into_string(self) -> Result<String> {
            if self.incomplete.is_some() {
                Err(Error::Utf8)
            } else {
                Ok(self.data)
            }
        }
    }

}

use self::string_collect::StringCollector;

/// A struct representing the incomplete message.
#[derive(Debug)]
pub struct IncompleteMessage {
    collector: IncompleteMessageCollector,
}

#[derive(Debug)]
enum IncompleteMessageCollector {
    Text(StringCollector),
    Binary(Vec<u8>),
}

impl IncompleteMessage {
    /// Create new.
    pub fn new(message_type: IncompleteMessageType) -> Self {
        IncompleteMessage {
            collector: match message_type {
                IncompleteMessageType::Binary =>
                    IncompleteMessageCollector::Binary(Vec::new()),
                IncompleteMessageType::Text =>
                    IncompleteMessageCollector::Text(StringCollector::new()),
            }
        }
    }

    /// Get the current filled size of the buffer.
    pub fn len(&self) -> usize {
        match self.collector {
            IncompleteMessageCollector::Text(ref t) => t.len(),
            IncompleteMessageCollector::Binary(ref b) => b.len(),
        }
    }

    /// Add more data to an existing message.
    pub fn extend<T: AsRef<[u8]>>(&mut self, tail: T, size_limit: Option<usize>) -> Result<()> {
        // Always have a max size. This ensures an error in case of concatenating two buffers
        // of more than `usize::max_value()` bytes in total.
        let max_size = size_limit.unwrap_or_else(usize::max_value);
        let my_size = self.len();
        let portion_size = tail.as_ref().len();
        // Be careful about integer overflows here.
        if my_size > max_size || portion_size > max_size - my_size {
            return Err(Error::Capacity(
                format!("Message too big: {} + {} > {}", my_size, portion_size, max_size).into()
            ))
        }

        match self.collector {
            IncompleteMessageCollector::Binary(ref mut v) => {
                v.extend(tail.as_ref());
                Ok(())
            }
            IncompleteMessageCollector::Text(ref mut t) => {
                t.extend(tail)
            }
        }
    }

    /// Convert an incomplete message into a complete one.
    pub fn complete(self) -> Result<Message> {
        match self.collector {
            IncompleteMessageCollector::Binary(v) => {
                Ok(Message::Binary(v))
            }
            IncompleteMessageCollector::Text(t) => {
                let text = t.into_string()?;
                Ok(Message::Text(text))
            }
        }
    }
}

/// The type of incomplete message.
pub enum IncompleteMessageType {
    Text,
    Binary,
}

/// An enum representing the various forms of a WebSocket message.
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum Message {
    /// A text WebSocket message
    Text(String),
    /// A binary WebSocket message
    Binary(Vec<u8>),
    /// A ping message with the specified payload
    ///
    /// The payload here must have a length less than 125 bytes
    Ping(Vec<u8>),
    /// A pong message with the specified payload
    ///
    /// The payload here must have a length less than 125 bytes
    Pong(Vec<u8>),
}

impl Message {

    /// Create a new text WebSocket message from a stringable.
    pub fn text<S>(string: S) -> Message
        where S: Into<String>
    {
        Message::Text(string.into())
    }

    /// Create a new binary WebSocket message by converting to Vec<u8>.
    pub fn binary<B>(bin: B) -> Message
        where B: Into<Vec<u8>>
    {
        Message::Binary(bin.into())
    }

    /// Indicates whether a message is a text message.
    pub fn is_text(&self) -> bool {
        match *self {
            Message::Text(_) => true,
            _ => false,
        }
    }

    /// Indicates whether a message is a binary message.
    pub fn is_binary(&self) -> bool {
        match *self {
            Message::Binary(_) => true,
            _ => false,
        }
    }

    /// Indicates whether a message is a ping message.
    pub fn is_ping(&self) -> bool {
        match *self {
            Message::Ping(_) => true,
            _ => false,
        }
    }

    /// Indicates whether a message is a pong message.
    pub fn is_pong(&self) -> bool {
        match *self {
            Message::Pong(_) => true,
            _ => false,
        }
    }

    /// Get the length of the WebSocket message.
    pub fn len(&self) -> usize {
        match *self {
            Message::Text(ref string) => string.len(),
            Message::Binary(ref data) |
            Message::Ping(ref data) |
            Message::Pong(ref data) => data.len(),
        }
    }

    /// Returns true if the WebSocket message has no content.
    /// For example, if the other side of the connection sent an empty string.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Consume the WebSocket and return it as binary data.
    pub fn into_data(self) -> Vec<u8> {
        match self {
            Message::Text(string) => string.into_bytes(),
            Message::Binary(data) |
            Message::Ping(data) |
            Message::Pong(data) => data,
        }
    }

    /// Attempt to consume the WebSocket message and convert it to a String.
    pub fn into_text(self) -> Result<String> {
        match self {
            Message::Text(string) => Ok(string),
            Message::Binary(data) |
            Message::Ping(data) |
            Message::Pong(data) => Ok(try!(
                String::from_utf8(data).map_err(|err| err.utf8_error()))),
        }
    }

    /// Attempt to get a &str from the WebSocket message,
    /// this will try to convert binary data to utf8.
    pub fn to_text(&self) -> Result<&str> {
        match *self {
            Message::Text(ref string) => Ok(string),
            Message::Binary(ref data) |
            Message::Ping(ref data) |
            Message::Pong(ref data) => Ok(try!(str::from_utf8(data))),
        }
    }

}

impl From<String> for Message {
    fn from(string: String) -> Message {
        Message::text(string)
    }
}

impl<'s> From<&'s str> for Message {
    fn from(string: &'s str) -> Message {
        Message::text(string)
    }
}

impl<'b> From<&'b [u8]> for Message {
    fn from(data: &'b [u8]) -> Message {
        Message::binary(data)
    }
}

impl From<Vec<u8>> for Message {
    fn from(data: Vec<u8>) -> Message {
        Message::binary(data)
    }
}

impl fmt::Display for Message {
    fn fmt(&self, f: &mut fmt::Formatter) -> StdResult<(), fmt::Error> {
        if let Ok(string) = self.to_text() {
            write!(f, "{}", string)
        } else {
            write!(f, "Binary Data<length={}>", self.len())
        }
    }
}

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

    #[test]
    fn display() {
        let t = Message::text(format!("test"));
        assert_eq!(t.to_string(), "test".to_owned());

        let bin = Message::binary(vec![0, 1, 3, 4, 241]);
        assert_eq!(bin.to_string(), "Binary Data<length=5>".to_owned());
    }

    #[test]
    fn binary_convert() {
        let bin = [6u8, 7, 8, 9, 10, 241];
        let msg = Message::from(&bin[..]);
        assert!(msg.is_binary());
        assert!(msg.into_text().is_err());
    }

    #[test]
    fn binary_convert_vec() {
        let bin = vec![6u8, 7, 8, 9, 10, 241];
        let msg = Message::from(bin);
        assert!(msg.is_binary());
        assert!(msg.into_text().is_err());
    }

    #[test]
    fn text_convert() {
        let s = "kiwotsukete";
        let msg = Message::from(s);
        assert!(msg.is_text());
    }
}
<commit_msg>feat: impl Into<Vec<u8>> for Message<commit_after>use std::convert::{From, Into, AsRef};
use std::fmt;
use std::result::Result as StdResult;
use std::str;

use error::{Result, Error};

mod string_collect {

    use utf8;
    use utf8::DecodeError;

    use error::{Error, Result};

    #[derive(Debug)]
    pub struct StringCollector {
        data: String,
        incomplete: Option<utf8::Incomplete>,
    }

    impl StringCollector {
        pub fn new() -> Self {
            StringCollector {
                data: String::new(),
                incomplete: None,
            }
        }

        pub fn len(&self) -> usize {
            self.data.len()
                .saturating_add(self.incomplete.map(|i| i.buffer_len as usize).unwrap_or(0))
        }

        pub fn extend<T: AsRef<[u8]>>(&mut self, tail: T) -> Result<()> {
            let mut input: &[u8] = tail.as_ref();

            if let Some(mut incomplete) = self.incomplete.take() {
                let fin = if let Some((result, rest)) = incomplete.try_complete(input) {
                    input = rest;
                    if let Ok(text) = result {
                        self.data.push_str(text);
                    } else {
                        return Err(Error::Utf8)
                    }
                    true
                } else {
                    input = &[];
                    false
                };
                if !fin {
                    self.incomplete = Some(incomplete)
                }
            }

            if !input.is_empty() {
                match utf8::decode(input) {
                    Ok(text) => {
                        self.data.push_str(text);
                        Ok(())
                    }
                    Err(DecodeError::Incomplete { valid_prefix, incomplete_suffix }) => {
                        self.data.push_str(valid_prefix);
                        self.incomplete = Some(incomplete_suffix);
                        Ok(())
                    }
                    Err(DecodeError::Invalid { valid_prefix, .. }) => {
                        self.data.push_str(valid_prefix);
                        Err(Error::Utf8)
                    }
                }
            } else {
                Ok(())
            }
        }

        pub fn into_string(self) -> Result<String> {
            if self.incomplete.is_some() {
                Err(Error::Utf8)
            } else {
                Ok(self.data)
            }
        }
    }

}

use self::string_collect::StringCollector;

/// A struct representing the incomplete message.
#[derive(Debug)]
pub struct IncompleteMessage {
    collector: IncompleteMessageCollector,
}

#[derive(Debug)]
enum IncompleteMessageCollector {
    Text(StringCollector),
    Binary(Vec<u8>),
}

impl IncompleteMessage {
    /// Create new.
    pub fn new(message_type: IncompleteMessageType) -> Self {
        IncompleteMessage {
            collector: match message_type {
                IncompleteMessageType::Binary =>
                    IncompleteMessageCollector::Binary(Vec::new()),
                IncompleteMessageType::Text =>
                    IncompleteMessageCollector::Text(StringCollector::new()),
            }
        }
    }

    /// Get the current filled size of the buffer.
    pub fn len(&self) -> usize {
        match self.collector {
            IncompleteMessageCollector::Text(ref t) => t.len(),
            IncompleteMessageCollector::Binary(ref b) => b.len(),
        }
    }

    /// Add more data to an existing message.
    pub fn extend<T: AsRef<[u8]>>(&mut self, tail: T, size_limit: Option<usize>) -> Result<()> {
        // Always have a max size. This ensures an error in case of concatenating two buffers
        // of more than `usize::max_value()` bytes in total.
        let max_size = size_limit.unwrap_or_else(usize::max_value);
        let my_size = self.len();
        let portion_size = tail.as_ref().len();
        // Be careful about integer overflows here.
        if my_size > max_size || portion_size > max_size - my_size {
            return Err(Error::Capacity(
                format!("Message too big: {} + {} > {}", my_size, portion_size, max_size).into()
            ))
        }

        match self.collector {
            IncompleteMessageCollector::Binary(ref mut v) => {
                v.extend(tail.as_ref());
                Ok(())
            }
            IncompleteMessageCollector::Text(ref mut t) => {
                t.extend(tail)
            }
        }
    }

    /// Convert an incomplete message into a complete one.
    pub fn complete(self) -> Result<Message> {
        match self.collector {
            IncompleteMessageCollector::Binary(v) => {
                Ok(Message::Binary(v))
            }
            IncompleteMessageCollector::Text(t) => {
                let text = t.into_string()?;
                Ok(Message::Text(text))
            }
        }
    }
}

/// The type of incomplete message.
pub enum IncompleteMessageType {
    Text,
    Binary,
}

/// An enum representing the various forms of a WebSocket message.
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum Message {
    /// A text WebSocket message
    Text(String),
    /// A binary WebSocket message
    Binary(Vec<u8>),
    /// A ping message with the specified payload
    ///
    /// The payload here must have a length less than 125 bytes
    Ping(Vec<u8>),
    /// A pong message with the specified payload
    ///
    /// The payload here must have a length less than 125 bytes
    Pong(Vec<u8>),
}

impl Message {

    /// Create a new text WebSocket message from a stringable.
    pub fn text<S>(string: S) -> Message
        where S: Into<String>
    {
        Message::Text(string.into())
    }

    /// Create a new binary WebSocket message by converting to Vec<u8>.
    pub fn binary<B>(bin: B) -> Message
        where B: Into<Vec<u8>>
    {
        Message::Binary(bin.into())
    }

    /// Indicates whether a message is a text message.
    pub fn is_text(&self) -> bool {
        match *self {
            Message::Text(_) => true,
            _ => false,
        }
    }

    /// Indicates whether a message is a binary message.
    pub fn is_binary(&self) -> bool {
        match *self {
            Message::Binary(_) => true,
            _ => false,
        }
    }

    /// Indicates whether a message is a ping message.
    pub fn is_ping(&self) -> bool {
        match *self {
            Message::Ping(_) => true,
            _ => false,
        }
    }

    /// Indicates whether a message is a pong message.
    pub fn is_pong(&self) -> bool {
        match *self {
            Message::Pong(_) => true,
            _ => false,
        }
    }

    /// Get the length of the WebSocket message.
    pub fn len(&self) -> usize {
        match *self {
            Message::Text(ref string) => string.len(),
            Message::Binary(ref data) |
            Message::Ping(ref data) |
            Message::Pong(ref data) => data.len(),
        }
    }

    /// Returns true if the WebSocket message has no content.
    /// For example, if the other side of the connection sent an empty string.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Consume the WebSocket and return it as binary data.
    pub fn into_data(self) -> Vec<u8> {
        match self {
            Message::Text(string) => string.into_bytes(),
            Message::Binary(data) |
            Message::Ping(data) |
            Message::Pong(data) => data,
        }
    }

    /// Attempt to consume the WebSocket message and convert it to a String.
    pub fn into_text(self) -> Result<String> {
        match self {
            Message::Text(string) => Ok(string),
            Message::Binary(data) |
            Message::Ping(data) |
            Message::Pong(data) => Ok(try!(
                String::from_utf8(data).map_err(|err| err.utf8_error()))),
        }
    }

    /// Attempt to get a &str from the WebSocket message,
    /// this will try to convert binary data to utf8.
    pub fn to_text(&self) -> Result<&str> {
        match *self {
            Message::Text(ref string) => Ok(string),
            Message::Binary(ref data) |
            Message::Ping(ref data) |
            Message::Pong(ref data) => Ok(try!(str::from_utf8(data))),
        }
    }

}

impl From<String> for Message {
    fn from(string: String) -> Message {
        Message::text(string)
    }
}

impl<'s> From<&'s str> for Message {
    fn from(string: &'s str) -> Message {
        Message::text(string)
    }
}

impl<'b> From<&'b [u8]> for Message {
    fn from(data: &'b [u8]) -> Message {
        Message::binary(data)
    }
}

impl From<Vec<u8>> for Message {
    fn from(data: Vec<u8>) -> Message {
        Message::binary(data)
    }
}

impl Into<Vec<u8>> for Message {
    fn into(self) -> Vec<u8> {
        self.into_data()
    }
}

impl fmt::Display for Message {
    fn fmt(&self, f: &mut fmt::Formatter) -> StdResult<(), fmt::Error> {
        if let Ok(string) = self.to_text() {
            write!(f, "{}", string)
        } else {
            write!(f, "Binary Data<length={}>", self.len())
        }
    }
}

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

    #[test]
    fn display() {
        let t = Message::text(format!("test"));
        assert_eq!(t.to_string(), "test".to_owned());

        let bin = Message::binary(vec![0, 1, 3, 4, 241]);
        assert_eq!(bin.to_string(), "Binary Data<length=5>".to_owned());
    }

    #[test]
    fn binary_convert() {
        let bin = [6u8, 7, 8, 9, 10, 241];
        let msg = Message::from(&bin[..]);
        assert!(msg.is_binary());
        assert!(msg.into_text().is_err());
    }

    #[test]
    fn binary_convert_vec() {
        let bin = vec![6u8, 7, 8, 9, 10, 241];
        let msg = Message::from(bin);
        assert!(msg.is_binary());
        assert!(msg.into_text().is_err());
    }

    #[test]
    fn binary_convert_into_vec() {
        let bin = vec![6u8, 7, 8, 9, 10, 241];
        let bin_copy = bin.clone();
        let msg = Message::from(bin);
        let serialized: Vec<u8> = msg.into();
        assert_eq!(bin_copy, serialized);
    }

    #[test]
    fn text_convert() {
        let s = "kiwotsukete";
        let msg = Message::from(s);
        assert!(msg.is_text());
    }
}
<|endoftext|>


<commit_before>mod joins;
mod select;

use types::{FromSqlRow, NativeSqlType};
use std::convert::Into;
pub use self::joins::{InnerJoinSource, LeftOuterJoinSource};
use self::select::SelectSqlQuerySource;

pub use self::joins::JoinTo;

pub trait Queriable<ST: NativeSqlType> {
    type Row: FromSqlRow<ST>;

    fn build(row: Self::Row) -> Self;
}

pub trait QuerySource: Sized {
    type SqlType: NativeSqlType;

    fn select_clause(&self) -> String;
    fn from_clause(&self) -> String;

    fn select<C, T, ST>(self, column: C) -> SelectSqlQuerySource<ST, Self> where
        ST: NativeSqlType,
        C: SelectableColumn<T, Self, ST>,
    {
        self.select_sql_inner(column.qualified_name())
    }

    fn select_sql<A: NativeSqlType>(self, columns: &str)
        -> SelectSqlQuerySource<A, Self>
    {
        self.select_sql_inner(columns)
    }

    fn select_sql_inner<A, S>(self, columns: S)
        -> SelectSqlQuerySource<A, Self> where
        A: NativeSqlType,
        S: Into<String>
    {
        SelectSqlQuerySource::new(columns.into(), self)
    }
}

pub trait Column<Table> {
    type SqlType: NativeSqlType;

    fn name(&self) -> String;

    fn qualified_name(&self) -> String;
}

pub trait Table: QuerySource {
    type PrimaryKey: Column<Self>;
    fn name(&self) -> &str;
    fn primary_key(&self) -> Self::PrimaryKey;

    fn inner_join<T>(self, other: T) -> InnerJoinSource<Self, T> where
        T: Table,
        Self: JoinTo<T>,
    {
        InnerJoinSource::new(self, other)
    }

    fn left_outer_join<T>(self, other: T) -> LeftOuterJoinSource<Self, T> where
        T: Table,
        Self: JoinTo<T>,
    {
        LeftOuterJoinSource::new(self, other)
    }
}

pub trait SelectableColumn<T, QS: QuerySource, SqlType: NativeSqlType = <Self as Column<T>>::SqlType>: Column<T> {
}

impl<T, C> SelectableColumn<T, T> for C where
    T: Table,
    C: Column<T>,
{
}
<commit_msg>Minor formatting changes<commit_after>mod joins;
mod select;

use types::{FromSqlRow, NativeSqlType};
use std::convert::Into;
pub use self::joins::{InnerJoinSource, LeftOuterJoinSource};
use self::select::SelectSqlQuerySource;

pub use self::joins::JoinTo;

pub trait Queriable<ST: NativeSqlType> {
    type Row: FromSqlRow<ST>;

    fn build(row: Self::Row) -> Self;
}

pub trait QuerySource: Sized {
    type SqlType: NativeSqlType;

    fn select_clause(&self) -> String;
    fn from_clause(&self) -> String;

    fn select<C, T, ST>(self, column: C) -> SelectSqlQuerySource<ST, Self> where
        ST: NativeSqlType,
        C: SelectableColumn<T, Self, ST>,
    {
        self.select_sql_inner(column.qualified_name())
    }

    fn select_sql<A: NativeSqlType>(self, columns: &str)
        -> SelectSqlQuerySource<A, Self>
    {
        self.select_sql_inner(columns)
    }

    fn select_sql_inner<A, S>(self, columns: S)
        -> SelectSqlQuerySource<A, Self> where
        A: NativeSqlType,
        S: Into<String>
    {
        SelectSqlQuerySource::new(columns.into(), self)
    }
}

pub trait Column<Table> {
    type SqlType: NativeSqlType;

    fn name(&self) -> String;

    fn qualified_name(&self) -> String;
}

pub trait Table: QuerySource {
    type PrimaryKey: Column<Self>;
    fn name(&self) -> &str;
    fn primary_key(&self) -> Self::PrimaryKey;

    fn inner_join<T>(self, other: T) -> InnerJoinSource<Self, T> where
        T: Table,
        Self: JoinTo<T>,
    {
        InnerJoinSource::new(self, other)
    }

    fn left_outer_join<T>(self, other: T) -> LeftOuterJoinSource<Self, T> where
        T: Table,
        Self: JoinTo<T>,
    {
        LeftOuterJoinSource::new(self, other)
    }
}

pub trait SelectableColumn<
    T,
    QS: QuerySource,
    SqlType: NativeSqlType = <Self as Column<T>>::SqlType,
>: Column<T> {
}

impl<T, C> SelectableColumn<T, T> for C where
    T: Table,
    C: Column<T>,
{
}
<|endoftext|>


<commit_before>// Helianto -- static website generator
// Copyright © 2015-2016 Mickaël RAYBAUD-ROIG
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use std::path::Path;
use std::fs::File;
use regex::Regex;
use std::io::Read;
use std::ascii::AsciiExt;
use pulldown_cmark::{Parser, Event, Tag};
use pulldown_cmark::{OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES};
use pulldown_cmark::html;
use super::{Metadata, Reader};
use super::super::{Error, Result, Settings};

#[derive(Debug, Clone)]
pub struct MarkdownReader;

static EXTENSIONS: &'static [&'static str] = &["markdown", "md", "mkd", "mdown"];

impl Reader for MarkdownReader {
    fn new(_settings: &Settings) -> MarkdownReader {
        MarkdownReader
    }

    fn extensions() -> &'static [&'static str] {
        EXTENSIONS
    }

    fn load(&self, path: &Path) -> Result<(String, Metadata)> {
        let mut input = String::new();
        try! {
            File::open(path)
                .and_then(|mut fd| fd.read_to_string(&mut input))
                .map_err(|err| Error::Reader {
                    path: path.into(),
                    cause: Box::new(err),
                }
            )
        };

        Ok(process_markdown(&input))
    }
}

#[derive(PartialEq, Eq, Debug)]
enum State {
    BeforeTitle,
    InsideTitle,
    BeforeMetadata,
    InsideMetadata,
    InsideBody,
}

struct MetadataExtractor<'a> {
    inner: Parser<'a>,
    regex: Regex,
    state: State,
    pub metadata: Metadata,
    buffer: Vec<Event<'a>>,
}

impl<'a> From<Parser<'a>> for MetadataExtractor<'a> {
    fn from(parser: Parser) -> MetadataExtractor {
        MetadataExtractor {
            inner: parser,
            regex: Regex::new(r"^[\w][\w\d_\x2D ]*\s*:").unwrap(),
            state: State::BeforeTitle,
            metadata: Metadata::new(),
            buffer: Vec::new(),
        }
    }
}

impl<'a> Iterator for MetadataExtractor<'a> {
    type Item = Event<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        use self::State::*;

        if self.state == State::InsideBody {
            if self.buffer.len() > 0 {
                return Some(self.buffer.remove(0));
            } else {
                return self.inner.next();
            }
        }

        let event = match self.inner.next() {
            Some(ev) => ev,
            None => return None,
        };

        println!("{:?} {:?}", self.state, event);
        match self.state {
            BeforeTitle => {
                match event {
                    Event::Start(Tag::Header(_)) => {
                        self.state = State::InsideTitle;
                        self.next()
                    },
                    Event::Start(Tag::Paragraph) => {
                        self.state = State::InsideMetadata;
                        self.buffer.push(event);
                        self.next()
                    },
                    _ => {
                        self.state = State::InsideBody;
                        Some(event)
                    }
                }
            },
            InsideTitle => {
                match event {
                    Event::Text(_) => {
                        self.metadata.insert("title".into(), get_event_text(&event));
                        self.next()
                    },
                    Event::End(Tag::Header(_)) => {
                        self.state = State::BeforeMetadata;
                        self.next()
                    },
                    _ => self.next(),
                }
            },
            BeforeMetadata => {
                match event {
                    Event::Start(Tag::Paragraph) => {
                        self.state = State::InsideMetadata;
                        self.buffer.push(event);
                        self.next()
                    },
                    _ => {
                        self.state = State::InsideBody;
                        Some(event)
                    }
                }
            },
            InsideMetadata => {
                match event {
                    Event::Text(_) => {
                        if ! self.regex.is_match(&get_event_text(&event)) {
                            self.state = State::InsideBody;
                            println!("metadata end: {}", get_event_text(&event));
                        }
                        self.buffer.push(event);
                        self.next()
                    },
                    Event::End(Tag::Paragraph) => {
                        self.metadata.extend(
                            self.buffer.drain(..).filter_map(|event| {
                                if let Event::Text(text) = event {
                                    let (key, value) = split_pair(&text);
                                    Some((key.to_ascii_lowercase(), value))
                                } else {
                                    None
                                }
                            })
                        );
                        self.state = State::InsideBody;
                        self.next()
                    },
                    Event::SoftBreak | Event::HardBreak => {
                        self.buffer.push(event);
                        self.next()
                    },
                    _ => {
                        self.buffer.push(event);
                        self.state = State::InsideBody;
                        self.next()
                    }
                }
            },
            InsideBody => unreachable!(),
        }
    }
}

fn split_pair<S: AsRef<str>>(input: &S) -> (String, String) {
    let mut split = input.as_ref().splitn(2, ':');
    let key: &str = split.next().unwrap_or("");
    let value: &str = split.next().unwrap_or("");
    (key.trim().into(), value.trim().into())
}

fn get_event_text<'a>(event: &Event<'a>) -> String {
    if let Event::Text(ref text) = *event {
        text.clone().into_owned()
    } else {
        panic!()
    }
}

fn process_markdown<S: AsRef<str>>(input: &S) -> (String, Metadata) {
    let mut parser = MetadataExtractor::from(
        Parser::new_ext(input.as_ref(), OPTION_ENABLE_TABLES | OPTION_ENABLE_FOOTNOTES)
    );
    let mut output = String::with_capacity(input.as_ref().len() * (3/2));
    html::push_html(&mut output, &mut parser);
    (output, parser.metadata.clone())
}

#[test]
fn extract_title() {
    let (output, metadata) = process_markdown(&"# Foo\nbar\nbaz");
    assert_eq!(metadata.get("title"), Some(&"Foo".into()));
    assert_eq!(output, "
bar\nbaz
\n");
}

#[test]
fn extract_metadata() {
    let (output, metadata) = process_markdown(&"# Foo\n\nBar: baz:quux\nFoo bar: qux baz\n\nfoo: bar");
    assert_eq!(metadata.get("title"), Some(&"Foo".into()));
    assert_eq!(metadata.get("bar"), Some(&"baz:quux".into()));
    assert_eq!(metadata.get("foo bar"), Some(&"qux baz".into()));
    assert_eq!(output, "
foo: bar
\n");
}

#[test]
fn can_skip_to_metadata() {
    let (output, metadata) = process_markdown(&"\n\n\nBar: baz:quux\nFoo bar: qux baz\n\nfoo: bar");
    assert_eq!(metadata.get("title"), None);
    assert_eq!(metadata.get("bar"), Some(&"baz:quux".into()));
    assert_eq!(metadata.get("foo bar"), Some(&"qux baz".into()));
    assert_eq!(output, "
foo: bar
\n");
}

#[test]
fn can_skip_to_body() {
    let (output, metadata) = process_markdown(&"\n\n\nBar: baz:quux\nFoo bar: qux baz  \nlol\n\nfoo: bar");
    assert_eq!(metadata.get("title"), None);
    assert_eq!(metadata.get("bar"), None);
    assert_eq!(metadata.get("foo bar"), None);
    assert_eq!(output, "
Bar: baz:quux\nFoo bar: qux baz
\nlol
\n
foo: bar
\n");
}

#[test]
fn can_skip_metadata() {
    let (output, metadata) = process_markdown(&"# Title\n\n\nBar: baz:quux\nFoo bar: qux baz  \nlol\n\nfoo: bar");
    assert_eq!(metadata.get("title"), Some(&String::from("Title")));
    assert_eq!(metadata.get("bar"), None);
    assert_eq!(metadata.get("foo bar"), None);
    assert_eq!(output, "
Bar: baz:quux\nFoo bar: qux baz
\nlol
\n
foo: bar
\n");
}<commit_msg>Auto merge of #2 - m-r-r:rust-stable, r=m-r-r<commit_after>// Helianto -- static website generator
// Copyright © 2015-2016 Mickaël RAYBAUD-ROIG
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use std::path::Path;
use std::fs::File;
use regex::Regex;
use std::io::Read;
use std::ascii::AsciiExt;
use std::mem::replace;
use pulldown_cmark::{Parser, Event, Tag};
use pulldown_cmark::{OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES};
use pulldown_cmark::html;
use super::{Metadata, Reader};
use super::super::{Error, Result, Settings};

#[derive(Debug, Clone)]
pub struct MarkdownReader;

static EXTENSIONS: &'static [&'static str] = &["markdown", "md", "mkd", "mdown"];

impl Reader for MarkdownReader {
    fn new(_settings: &Settings) -> MarkdownReader {
        MarkdownReader
    }

    fn extensions() -> &'static [&'static str] {
        EXTENSIONS
    }

    fn load(&self, path: &Path) -> Result<(String, Metadata)> {
        let mut input = String::new();
        try! {
            File::open(path)
                .and_then(|mut fd| fd.read_to_string(&mut input))
                .map_err(|err| Error::Reader {
                    path: path.into(),
                    cause: Box::new(err),
                }
            )
        };

        Ok(process_markdown(&input))
    }
}

#[derive(PartialEq, Eq, Debug)]
enum State {
    BeforeTitle,
    InsideTitle,
    BeforeMetadata,
    InsideMetadata,
    InsideBody,
}

struct MetadataExtractor<'a> {
    inner: Parser<'a>,
    regex: Regex,
    state: State,
    pub metadata: Metadata,
    buffer: Vec<Event<'a>>,
}

impl<'a> From<Parser<'a>> for MetadataExtractor<'a> {
    fn from(parser: Parser) -> MetadataExtractor {
        MetadataExtractor {
            inner: parser,
            regex: Regex::new(r"^[\w][\w\d_\x2D ]*\s*:").unwrap(),
            state: State::BeforeTitle,
            metadata: Metadata::new(),
            buffer: Vec::new(),
        }
    }
}

impl<'a> Iterator for MetadataExtractor<'a> {
    type Item = Event<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        use self::State::*;

        if self.state == State::InsideBody {
            if self.buffer.len() > 0 {
                return Some(self.buffer.remove(0));
            } else {
                return self.inner.next();
            }
        }

        let event = match self.inner.next() {
            Some(ev) => ev,
            None => return None,
        };

        println!("{:?} {:?}", self.state, event);
        match self.state {
            BeforeTitle => {
                match event {
                    Event::Start(Tag::Header(_)) => {
                        self.state = State::InsideTitle;
                        self.next()
                    },
                    Event::Start(Tag::Paragraph) => {
                        self.state = State::InsideMetadata;
                        self.buffer.push(event);
                        self.next()
                    },
                    _ => {
                        self.state = State::InsideBody;
                        Some(event)
                    }
                }
            },
            InsideTitle => {
                match event {
                    Event::Text(_) => {
                        self.metadata.insert("title".into(), get_event_text(&event));
                        self.next()
                    },
                    Event::End(Tag::Header(_)) => {
                        self.state = State::BeforeMetadata;
                        self.next()
                    },
                    _ => self.next(),
                }
            },
            BeforeMetadata => {
                match event {
                    Event::Start(Tag::Paragraph) => {
                        self.state = State::InsideMetadata;
                        self.buffer.push(event);
                        self.next()
                    },
                    _ => {
                        self.state = State::InsideBody;
                        Some(event)
                    }
                }
            },
            InsideMetadata => {
                match event {
                    Event::Text(_) => {
                        if ! self.regex.is_match(&get_event_text(&event)) {
                            self.state = State::InsideBody;
                            println!("metadata end: {}", get_event_text(&event));
                        }
                        self.buffer.push(event);
                        self.next()
                    },
                    Event::End(Tag::Paragraph) => {
                        self.metadata.extend(
                            replace(&mut self.buffer, Vec::new()).into_iter().filter_map(|event| {
                                if let Event::Text(text) = event {
                                    let (key, value) = split_pair(&text);
                                    Some((key.to_ascii_lowercase(), value))
                                } else {
                                    None
                                }
                            })
                        );
                        self.state = State::InsideBody;
                        self.next()
                    },
                    Event::SoftBreak | Event::HardBreak => {
                        self.buffer.push(event);
                        self.next()
                    },
                    _ => {
                        self.buffer.push(event);
                        self.state = State::InsideBody;
                        self.next()
                    }
                }
            },
            InsideBody => unreachable!(),
        }
    }
}

fn split_pair<S: AsRef<str>>(input: &S) -> (String, String) {
    let mut split = input.as_ref().splitn(2, ':');
    let key: &str = split.next().unwrap_or("");
    let value: &str = split.next().unwrap_or("");
    (key.trim().into(), value.trim().into())
}

fn get_event_text<'a>(event: &Event<'a>) -> String {
    if let Event::Text(ref text) = *event {
        text.clone().into_owned()
    } else {
        panic!()
    }
}

fn process_markdown<S: AsRef<str>>(input: &S) -> (String, Metadata) {
    let mut parser = MetadataExtractor::from(
        Parser::new_ext(input.as_ref(), OPTION_ENABLE_TABLES | OPTION_ENABLE_FOOTNOTES)
    );
    let mut output = String::with_capacity(input.as_ref().len() * (3/2));
    html::push_html(&mut output, &mut parser);
    (output, parser.metadata.clone())
}

#[test]
fn extract_title() {
    let (output, metadata) = process_markdown(&"# Foo\nbar\nbaz");
    assert_eq!(metadata.get("title"), Some(&"Foo".into()));
    assert_eq!(output, "
bar\nbaz
\n");
}

#[test]
fn extract_metadata() {
    let (output, metadata) = process_markdown(&"# Foo\n\nBar: baz:quux\nFoo bar: qux baz\n\nfoo: bar");
    assert_eq!(metadata.get("title"), Some(&"Foo".into()));
    assert_eq!(metadata.get("bar"), Some(&"baz:quux".into()));
    assert_eq!(metadata.get("foo bar"), Some(&"qux baz".into()));
    assert_eq!(output, "
foo: bar
\n");
}

#[test]
fn can_skip_to_metadata() {
    let (output, metadata) = process_markdown(&"\n\n\nBar: baz:quux\nFoo bar: qux baz\n\nfoo: bar");
    assert_eq!(metadata.get("title"), None);
    assert_eq!(metadata.get("bar"), Some(&"baz:quux".into()));
    assert_eq!(metadata.get("foo bar"), Some(&"qux baz".into()));
    assert_eq!(output, "
foo: bar
\n");
}

#[test]
fn can_skip_to_body() {
    let (output, metadata) = process_markdown(&"\n\n\nBar: baz:quux\nFoo bar: qux baz  \nlol\n\nfoo: bar");
    assert_eq!(metadata.get("title"), None);
    assert_eq!(metadata.get("bar"), None);
    assert_eq!(metadata.get("foo bar"), None);
    assert_eq!(output, "
Bar: baz:quux\nFoo bar: qux baz
\nlol
\n
foo: bar
\n");
}

#[test]
fn can_skip_metadata() {
    let (output, metadata) = process_markdown(&"# Title\n\n\nBar: baz:quux\nFoo bar: qux baz  \nlol\n\nfoo: bar");
    assert_eq!(metadata.get("title"), Some(&String::from("Title")));
    assert_eq!(metadata.get("bar"), None);
    assert_eq!(metadata.get("foo bar"), None);
    assert_eq!(output, "
Bar: baz:quux\nFoo bar: qux baz
\nlol
\n
foo: bar
\n");
}
<|endoftext|>


<commit_before>use nom::{be_u8, be_u16};

use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
use std::convert::AsMut;
use std::convert::From;

use network::protocol::proxy_protocol::header::*;

const PROTOCOL_SIGNATURE_V2: [u8; 12] = [0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A];

named!(read_and_verify_ver_and_command<u8>, verify!(be_u8, |ver_and_cmd: u8| (ver_and_cmd >> 4) & 0x0f == 0x02));

named!(pub parse_v2_header<HeaderV2>,
  do_parse!(
    signature: tag!(&PROTOCOL_SIGNATURE_V2) >>
    ver_and_cmd: read_and_verify_ver_and_command >>
    family: be_u8 >>
    len: be_u16 >>
    addr: apply!(parse_addr_v2, family) >>
    (
      HeaderV2 {
        command: Command::Local,
        family,
        addr
      }
    )
  )
);

named_args!(address_family(family: u8)<u8>, value!((family >> 4) & 0x0f));

named!(unspec<ProxyAddr>, value!(ProxyAddr::AfUnspec));

named_args!(parse_addr_v2(family: u8)<ProxyAddr>,
  // family: 4 bits for address family and 4 bits for transport protocol
  switch!(apply!(address_family, family),
    0x00 => call!(unspec) |
    0x01 => call!(parse_ipv4_on_v2) |
    0x02 => call!(parse_ipv6_on_v2)
  )
);

named!(take_4_bytes, take!(4));

named!(parse_ipv4_on_v2<ProxyAddr>,
  do_parse!(
    src_ip: take_4_bytes >>
    dest_ip: take_4_bytes >>
    src_port: be_u16 >>
    dest_port: be_u16 >>
    (
      ProxyAddr::Ipv4Addr {
        src_addr: SocketAddrV4::new(Ipv4Addr::new(src_ip[0], src_ip[1], src_ip[2], src_ip[3]), src_port),
        dst_addr: SocketAddrV4::new(Ipv4Addr::new(dest_ip[0], dest_ip[1], dest_ip[2], dest_ip[3]), dest_port)
      }
    )
  )
);

named!(take_16_bytes, take!(16));

named!(parse_ipv6_on_v2<ProxyAddr>,
  do_parse!(
    src_ip: take_16_bytes >>
    dest_ip: take_16_bytes >>
    src_port: be_u16 >>
    dest_port: be_u16 >>
    (
      ProxyAddr::Ipv6Addr {
        src_addr: SocketAddrV6::new(Ipv6Addr::from(clone_into_array::<[u8; 16], u8>(&src_ip[..])), src_port, 0 ,0),
        dst_addr: SocketAddrV6::new(Ipv6Addr::from(clone_into_array::<[u8; 16], u8>(&dest_ip[..])), dest_port, 0 ,0),
      }
    )
  )
);

// Transform a slice to an array
fn clone_into_array<A, T>(slice: &[T]) -> A where A: Sized + Default + AsMut<[T]>, T: Clone {
  let mut a = Default::default();
  <A as AsMut<[T]>>::as_mut(&mut a).clone_from_slice(slice);
  a
}

#[cfg(test)]
mod test {

  use super::*;
  use nom::ErrorKind;
  use nom::IResult;
  use nom::IResult::*;
  use std::net::{IpAddr, SocketAddr};
  use nom::Needed::Size;

  #[test]
  fn test_parse_proxy_protocol_v2_ipv4_addr_header() {
    let input = &[
      0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A, // MAGIC header
      0x20,                                                                   // Version 2 and command LOCAL
      0x11,                                                                   // family AF_UNIX with IPv4
      0x00, 0x0C,                                                             // address sizes = 12
      0x7D, 0x19, 0x0A, 0x01,                                                 // source address
      0x0A, 0x04, 0x05, 0x08,                                                 // destination address
      0x1F, 0x90,                                                             // source port
      0x10, 0x68,                                                             // destination port
    ];

    let src_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(125, 25, 10, 1)), 8080);
    let dst_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(10, 4, 5, 8)), 4200);
    let expected = HeaderV2::new(Command::Local, src_addr, dst_addr);

    assert_eq!(Done(&[][..], expected), parse_v2_header(input));
  }

  #[test]
  fn it_should_parse_proxy_protocol_v2_ipv6_addr_header() {
    let input = &[
      0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A,                         // MAGIC header
      0x20,                                                                                // Version 2 and command LOCAL
      0x21,                                                                                // family AF_UNIX with IPv6
      0x00, 0x24,                                                                                // address sizes = 36
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // source address
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, // destination address
      0x1F, 0x90,                                                                                // source port
      0x10, 0x68,                                                                                // destination port
    ];

    let src_addr = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 8080);
    let dst_addr = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 2)), 4200);
    let expected = HeaderV2::new(Command::Local, src_addr, dst_addr);

    assert_eq!(Done(&[][..], expected), parse_v2_header(input));
  }

  #[test]
  fn it_should_parse_proxy_protocol_v2_afunspec_header() {
    let input = &[
      0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A, // MAGIC header
      0x20,                                                                   // Version 2 and command LOCAL
      0x00,                                                                   // family AF_UNSPEC and transport protocol unknow
      0x00, 0x00,                                                             // address sizes = 0
    ];

    let expected = HeaderV2 {
                    command: Command::Local,
                    family: 0,
                    addr: ProxyAddr::AfUnspec,
                  };

    assert_eq!(Done(&[][..], expected), parse_v2_header(input));
  }

  #[test]
  fn it_should_not_parse_proxy_protocol_v2_with_unknown_version() {
    let unknow_version = 0x30;

    let input = &[
      0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A, // MAGIC header
      unknow_version,                                                         // Version 2 and command LOCAL
    ];

    assert_eq!(Error(error_code!(ErrorKind::Verify)), parse_v2_header(input));
  }

  #[test]
  fn it_should_not_parse_proxy_protocol_with_unknown_family() {
    let unknow_family = 0x30;

    let input = &[
      0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A, // MAGIC header
      0x20,                                                                   // Version 2 and command LOCAL
      unknow_family,                                                          // family
      0x00, 0x00,                                                             // address sizes = 0
    ];

    assert_eq!(Error(error_code!(ErrorKind::Switch)), parse_v2_header(input));
  }

  #[test]
  fn it_should_not_parse_request_without_magic_header() {

    let input = &[
      0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, // INCORRECT MAGIC header
    ];

    assert_eq!(Error(error_code!(ErrorKind::Tag)), parse_v2_header(input));
  }

  #[test]
  fn it_should_not_parse_proxy_protocol_v2_ipv4_addr_header_with_missing_data() {
    let input = &[
      0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A, // MAGIC header
      0x20,                                                                   // Version 2 and command LOCAL
      0x11,                                                                   // family AF_UNIX with IPv4
    ];

    assert_eq!(Incomplete(Size(16)), parse_v2_header(input));
  }
}<commit_msg>Check only if its an error in the proxy protocol parser and not anymore the error code<commit_after>use nom::{be_u8, be_u16};

use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
use std::convert::AsMut;
use std::convert::From;

use network::protocol::proxy_protocol::header::*;

const PROTOCOL_SIGNATURE_V2: [u8; 12] = [0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A];

named!(read_and_verify_ver_and_command<u8>, verify!(be_u8, |ver_and_cmd: u8| (ver_and_cmd >> 4) & 0x0f == 0x02));

named!(pub parse_v2_header<HeaderV2>,
  do_parse!(
    signature: tag!(&PROTOCOL_SIGNATURE_V2) >>
    ver_and_cmd: read_and_verify_ver_and_command >>
    family: be_u8 >>
    len: be_u16 >>
    addr: apply!(parse_addr_v2, family) >>
    (
      HeaderV2 {
        command: Command::Local,
        family,
        addr
      }
    )
  )
);

named_args!(address_family(family: u8)<u8>, value!((family >> 4) & 0x0f));

named!(unspec<ProxyAddr>, value!(ProxyAddr::AfUnspec));

named_args!(parse_addr_v2(family: u8)<ProxyAddr>,
  // family: 4 bits for address family and 4 bits for transport protocol
  switch!(apply!(address_family, family),
    0x00 => call!(unspec) |
    0x01 => call!(parse_ipv4_on_v2) |
    0x02 => call!(parse_ipv6_on_v2)
  )
);

named!(take_4_bytes, take!(4));

named!(parse_ipv4_on_v2<ProxyAddr>,
  do_parse!(
    src_ip: take_4_bytes >>
    dest_ip: take_4_bytes >>
    src_port: be_u16 >>
    dest_port: be_u16 >>
    (
      ProxyAddr::Ipv4Addr {
        src_addr: SocketAddrV4::new(Ipv4Addr::new(src_ip[0], src_ip[1], src_ip[2], src_ip[3]), src_port),
        dst_addr: SocketAddrV4::new(Ipv4Addr::new(dest_ip[0], dest_ip[1], dest_ip[2], dest_ip[3]), dest_port)
      }
    )
  )
);

named!(take_16_bytes, take!(16));

named!(parse_ipv6_on_v2<ProxyAddr>,
  do_parse!(
    src_ip: take_16_bytes >>
    dest_ip: take_16_bytes >>
    src_port: be_u16 >>
    dest_port: be_u16 >>
    (
      ProxyAddr::Ipv6Addr {
        src_addr: SocketAddrV6::new(Ipv6Addr::from(clone_into_array::<[u8; 16], u8>(&src_ip[..])), src_port, 0 ,0),
        dst_addr: SocketAddrV6::new(Ipv6Addr::from(clone_into_array::<[u8; 16], u8>(&dest_ip[..])), dest_port, 0 ,0),
      }
    )
  )
);

// Transform a slice to an array
fn clone_into_array<A, T>(slice: &[T]) -> A where A: Sized + Default + AsMut<[T]>, T: Clone {
  let mut a = Default::default();
  <A as AsMut<[T]>>::as_mut(&mut a).clone_from_slice(slice);
  a
}

#[cfg(test)]
mod test {

  use super::*;
  use nom::ErrorKind;
  use nom::IResult;
  use nom::IResult::*;
  use std::net::{IpAddr, SocketAddr};
  use nom::Needed::Size;

  #[test]
  fn test_parse_proxy_protocol_v2_ipv4_addr_header() {
    let input = &[
      0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A, // MAGIC header
      0x20,                                                                   // Version 2 and command LOCAL
      0x11,                                                                   // family AF_UNIX with IPv4
      0x00, 0x0C,                                                             // address sizes = 12
      0x7D, 0x19, 0x0A, 0x01,                                                 // source address
      0x0A, 0x04, 0x05, 0x08,                                                 // destination address
      0x1F, 0x90,                                                             // source port
      0x10, 0x68,                                                             // destination port
    ];

    let src_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(125, 25, 10, 1)), 8080);
    let dst_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(10, 4, 5, 8)), 4200);
    let expected = HeaderV2::new(Command::Local, src_addr, dst_addr);

    assert_eq!(Done(&[][..], expected), parse_v2_header(input));
  }

  #[test]
  fn it_should_parse_proxy_protocol_v2_ipv6_addr_header() {
    let input = &[
      0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A,                         // MAGIC header
      0x20,                                                                                // Version 2 and command LOCAL
      0x21,                                                                                // family AF_UNIX with IPv6
      0x00, 0x24,                                                                                // address sizes = 36
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // source address
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, // destination address
      0x1F, 0x90,                                                                                // source port
      0x10, 0x68,                                                                                // destination port
    ];

    let src_addr = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 8080);
    let dst_addr = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 2)), 4200);
    let expected = HeaderV2::new(Command::Local, src_addr, dst_addr);

    assert_eq!(Done(&[][..], expected), parse_v2_header(input));
  }

  #[test]
  fn it_should_parse_proxy_protocol_v2_afunspec_header() {
    let input = &[
      0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A, // MAGIC header
      0x20,                                                                   // Version 2 and command LOCAL
      0x00,                                                                   // family AF_UNSPEC and transport protocol unknow
      0x00, 0x00,                                                             // address sizes = 0
    ];

    let expected = HeaderV2 {
                    command: Command::Local,
                    family: 0,
                    addr: ProxyAddr::AfUnspec,
                  };

    assert_eq!(Done(&[][..], expected), parse_v2_header(input));
  }

  #[test]
  fn it_should_not_parse_proxy_protocol_v2_with_unknown_version() {
    let unknow_version = 0x30;

    let input = &[
      0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A, // MAGIC header
      unknow_version,                                                         // Version 2 and command LOCAL
    ];

    assert!(parse_v2_header(input).is_err());
  }

  #[test]
  fn it_should_not_parse_proxy_protocol_with_unknown_family() {
    let unknow_family = 0x30;

    let input = &[
      0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A, // MAGIC header
      0x20,                                                                   // Version 2 and command LOCAL
      unknow_family,                                                          // family
      0x00, 0x00,                                                             // address sizes = 0
    ];

    assert!(parse_v2_header(input).is_err());
  }

  #[test]
  fn it_should_not_parse_request_without_magic_header() {

    let input = &[
      0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, // INCORRECT MAGIC header
    ];

    assert!(parse_v2_header(input).is_err());
  }

  #[test]
  fn it_should_not_parse_proxy_protocol_v2_ipv4_addr_header_with_missing_data() {
    let input = &[
      0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A, // MAGIC header
      0x20,                                                                   // Version 2 and command LOCAL
      0x11,                                                                   // family AF_UNIX with IPv4
    ];

    assert_eq!(Incomplete(Size(16)), parse_v2_header(input));
  }
}<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::path::PathBuf;

use libimagstore::store::Result as StoreResult;
use libimagstore::storeid::IntoStoreId;
use libimagstore::storeid::StoreId;

/// A tag for time-tracking. This is not a normal `libimagentrytag` tag, because we want the user
/// give the possibility to use the tagging functionality without interfering with this functionality.
pub struct TimeTrackingTag(String);

impl TimeTrackingTag {
    pub fn as_str(&self) -> &str {
        &self.0
    }
}

impl Into<String> for TimeTrackingTag {
    fn into(self) -> String {
        self.0
    }
}

impl From<String> for TimeTrackingTag {
    fn from(s: String) -> TimeTrackingTag {
        TimeTrackingTag(s)
    }
}

impl<'a> From<&'a String> for TimeTrackingTag {
    fn from(s: &'a String) -> TimeTrackingTag {
        TimeTrackingTag(s.clone())
    }
}

impl IntoStoreId for TimeTrackingTag {
    fn into_storeid(self) -> StoreResult<StoreId> {
        StoreId::new_baseless(PathBuf::from(self.0))
    }
}

<commit_msg>Derive all kinds of traits for TimeTrackingTag<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::path::PathBuf;

use libimagstore::store::Result as StoreResult;
use libimagstore::storeid::IntoStoreId;
use libimagstore::storeid::StoreId;

/// A tag for time-tracking. This is not a normal `libimagentrytag` tag, because we want the user
/// give the possibility to use the tagging functionality without interfering with this functionality.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TimeTrackingTag(String);

impl TimeTrackingTag {
    pub fn as_str(&self) -> &str {
        &self.0
    }
}

impl Into<String> for TimeTrackingTag {
    fn into(self) -> String {
        self.0
    }
}

impl From<String> for TimeTrackingTag {
    fn from(s: String) -> TimeTrackingTag {
        TimeTrackingTag(s)
    }
}

impl<'a> From<&'a String> for TimeTrackingTag {
    fn from(s: &'a String) -> TimeTrackingTag {
        TimeTrackingTag(s.clone())
    }
}

impl IntoStoreId for TimeTrackingTag {
    fn into_storeid(self) -> StoreResult<StoreId> {
        StoreId::new_baseless(PathBuf::from(self.0))
    }
}

<|endoftext|>


<commit_before>//! Serializes and deserializes Ardite Schema Definitions from different data
//! formats such as JSON and YAML.

use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;
use std::path::PathBuf;
use regex::Regex;
use serde_json;
use serde_yaml;
use error::{Error, ErrorCode};
use schema::{Definition, Type, Schema};
use value::Value;

mod types;

use schema::serde::types::*;

/// Gets an Ardite Schema Definition from a file. Aims to support mainly the
/// JSON and YAML formats.
pub fn from_file(path: PathBuf) -> Result<Definition, Error> {
  let extension = path.extension().map_or("", |s| s.to_str().unwrap());
  let mut file = try!(File::open(&path));
  match extension {
    "json" => {
      let reader = BufReader::new(file);
      let definition: SerdeDefinition = try!(serde_json::from_reader(reader));
      Ok(try!(serde_definition_into_definition(definition)))
    },
    "yml" => {
      let mut string = String::new();
      try!(file.read_to_string(&mut string));
      let definition: SerdeDefinition = try!(serde_yaml::from_str(&string));
      Ok(try!(serde_definition_into_definition(definition)))
    },
    _ => Err(Error::new(
      ErrorCode::NotAcceptable,
      format!("File extension '{}' cannot be deserialized in '{}'.", extension, path.display()),
      Some("Use a recognizable file extension like '.json' or '.yml'.".to_owned())
    ))
  }
}

/// Transforms the intermediary type into the useful type.
fn serde_definition_into_definition(serde_definition: SerdeDefinition) -> Result<Definition, Error> {
  let mut definition = Definition::new();

  for (key, schema) in serde_definition.types.into_iter() {
    let mut type_ = Type::new(key);
    type_.set_boxed_schema(try!(serde_schema_into_schema(schema)));
    definition.add_type(type_);
  }

  Ok(definition)
}

/// Transforms the intermediary type into the useful type.
fn serde_schema_into_schema(serde_schema: SerdeSchema) -> Result<Box<Schema + 'static>, Error> {
  match serde_schema.type_ {
    Some(type_) => match type_.as_str() {
      "null" => Ok(Box::new(Schema::null())),
      "boolean" => Ok(Box::new(Schema::boolean())),
      type_ @ "number" | type_ @ "integer" => {
        let mut schema = Schema::number();
        if type_ == "integer" { schema.set_multiple_of(1.0); }
        else if let Some(multiple_of) = serde_schema.multiple_of { schema.set_multiple_of(multiple_of); }
        if let Some(minimum) = serde_schema.minimum { schema.set_minimum(minimum); }
        if let Some(maximum) = serde_schema.maximum { schema.set_maximum(maximum); }
        if serde_schema.exclusive_minimum.unwrap_or(false) { schema.enable_exclusive_minimum(); }
        if serde_schema.exclusive_maximum.unwrap_or(false) { schema.enable_exclusive_maximum(); }
        Ok(Box::new(schema))
      },
      "string" => {
        let mut schema = Schema::string();
        if let Some(min_length) = serde_schema.min_length { schema.set_min_length(min_length); }
        if let Some(max_length) = serde_schema.max_length { schema.set_min_length(max_length); }
        if let Some(pattern) = serde_schema.pattern.and_then(|p| Regex::new(&p).ok()) { schema.set_pattern(pattern); }
        Ok(Box::new(schema))
      },
      "array" => {
        let mut schema = Schema::array();
        if let Some(items) = serde_schema.items { schema.set_boxed_items(try!(serde_schema_into_schema(*items))); }
        Ok(Box::new(schema))
      },
      "object" => {
        let mut schema = Schema::object();
        schema.set_required(serde_schema.required.unwrap_or_else(|| vec![]));
        if serde_schema.additional_properties.unwrap_or(false) { schema.enable_additional_properties(); }
        for (key, value) in serde_schema.properties.unwrap_or_default() {
          schema.add_boxed_property(key, try!(serde_schema_into_schema(value)));
        }
        Ok(Box::new(schema))
      },
      _ => Err(Error::validation(
        format!("Invalid type '{}'.", type_),
        format!("Use a permitted type like 'string' and not '{}'.", type_)
      ))
    },
    None => {
      if let Some(enum_) = serde_schema.enum_ {
        Ok(Box::new(Schema::enum_(enum_.into_iter().map(Value::String).collect())))
      } else {
        Err(Error::validation("No schema type specified.", "Set a `type` property or an `enum` property."))
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::from_file;
  use std::path::PathBuf;
  use schema::definition::create_basic;

  #[test]
  fn test_basic_json() {
    assert_eq!(from_file(PathBuf::from("tests/fixtures/definitions/basic.json")).unwrap(), create_basic());
  }

  #[test]
  fn test_basic_yaml() {
    assert_eq!(from_file(PathBuf::from("tests/fixtures/definitions/basic.yml")).unwrap(), create_basic());
  }
}
<commit_msg>fix(schema): fix max_length bug<commit_after>//! Serializes and deserializes Ardite Schema Definitions from different data
//! formats such as JSON and YAML.

use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;
use std::path::PathBuf;
use regex::Regex;
use serde_json;
use serde_yaml;
use error::{Error, ErrorCode};
use schema::{Definition, Type, Schema};
use value::Value;

mod types;

use schema::serde::types::*;

/// Gets an Ardite Schema Definition from a file. Aims to support mainly the
/// JSON and YAML formats.
pub fn from_file(path: PathBuf) -> Result<Definition, Error> {
  let extension = path.extension().map_or("", |s| s.to_str().unwrap());
  let mut file = try!(File::open(&path));
  match extension {
    "json" => {
      let reader = BufReader::new(file);
      let definition: SerdeDefinition = try!(serde_json::from_reader(reader));
      Ok(try!(serde_definition_into_definition(definition)))
    },
    "yml" => {
      let mut string = String::new();
      try!(file.read_to_string(&mut string));
      let definition: SerdeDefinition = try!(serde_yaml::from_str(&string));
      Ok(try!(serde_definition_into_definition(definition)))
    },
    _ => Err(Error::new(
      ErrorCode::NotAcceptable,
      format!("File extension '{}' cannot be deserialized in '{}'.", extension, path.display()),
      Some("Use a recognizable file extension like '.json' or '.yml'.".to_owned())
    ))
  }
}

/// Transforms the intermediary type into the useful type.
fn serde_definition_into_definition(serde_definition: SerdeDefinition) -> Result<Definition, Error> {
  let mut definition = Definition::new();

  for (key, schema) in serde_definition.types.into_iter() {
    let mut type_ = Type::new(key);
    type_.set_boxed_schema(try!(serde_schema_into_schema(schema)));
    definition.add_type(type_);
  }

  Ok(definition)
}

/// Transforms the intermediary type into the useful type.
fn serde_schema_into_schema(serde_schema: SerdeSchema) -> Result<Box<Schema + 'static>, Error> {
  match serde_schema.type_ {
    Some(type_) => match type_.as_str() {
      "null" => Ok(Box::new(Schema::null())),
      "boolean" => Ok(Box::new(Schema::boolean())),
      type_ @ "number" | type_ @ "integer" => {
        let mut schema = Schema::number();
        if type_ == "integer" { schema.set_multiple_of(1.0); }
        else if let Some(multiple_of) = serde_schema.multiple_of { schema.set_multiple_of(multiple_of); }
        if let Some(minimum) = serde_schema.minimum { schema.set_minimum(minimum); }
        if let Some(maximum) = serde_schema.maximum { schema.set_maximum(maximum); }
        if serde_schema.exclusive_minimum.unwrap_or(false) { schema.enable_exclusive_minimum(); }
        if serde_schema.exclusive_maximum.unwrap_or(false) { schema.enable_exclusive_maximum(); }
        Ok(Box::new(schema))
      },
      "string" => {
        let mut schema = Schema::string();
        if let Some(min_length) = serde_schema.min_length { schema.set_min_length(min_length); }
        if let Some(max_length) = serde_schema.max_length { schema.set_max_length(max_length); }
        if let Some(pattern) = serde_schema.pattern.and_then(|p| Regex::new(&p).ok()) { schema.set_pattern(pattern); }
        Ok(Box::new(schema))
      },
      "array" => {
        let mut schema = Schema::array();
        if let Some(items) = serde_schema.items { schema.set_boxed_items(try!(serde_schema_into_schema(*items))); }
        Ok(Box::new(schema))
      },
      "object" => {
        let mut schema = Schema::object();
        schema.set_required(serde_schema.required.unwrap_or_default());
        if serde_schema.additional_properties.unwrap_or(false) { schema.enable_additional_properties(); }
        for (key, value) in serde_schema.properties.unwrap_or_default() {
          schema.add_boxed_property(key, try!(serde_schema_into_schema(value)));
        }
        Ok(Box::new(schema))
      },
      _ => Err(Error::validation(
        format!("Invalid type '{}'.", type_),
        format!("Use a permitted type like 'string' and not '{}'.", type_)
      ))
    },
    None => {
      if let Some(enum_) = serde_schema.enum_ {
        Ok(Box::new(Schema::enum_(enum_.into_iter().map(Value::String).collect())))
      } else {
        Err(Error::validation("No schema type specified.", "Set a `type` property or an `enum` property."))
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::from_file;
  use std::path::PathBuf;
  use schema::definition::create_basic;

  #[test]
  fn test_basic_json() {
    assert_eq!(from_file(PathBuf::from("tests/fixtures/definitions/basic.json")).unwrap(), create_basic());
  }

  #[test]
  fn test_basic_yaml() {
    assert_eq!(from_file(PathBuf::from("tests/fixtures/definitions/basic.yml")).unwrap(), create_basic());
  }
}
<|endoftext|>


<commit_before>use alloc::string::String;
use alloc::vec::Vec;
use core::fmt::Write;
use core::str;

use crate::context;
use crate::syscall;
use crate::syscall::error::Result;

pub fn resource() -> Result<Vec<u8>> {
    let mut string = String::new();

    {
        let mut rows = Vec::new();
        {
            let contexts = context::contexts();
            for (id, context_lock) in contexts.iter() {
                let context = context_lock.read();
                rows.push((*id, context.name.lock().clone(), context.status_reason));
            }
        }

        for row in rows.iter() {
            let id: usize = row.0.into();
            let name = str::from_utf8(&row.1).unwrap_or(".");

            let _ = writeln!(string, "{}: {}", id, name);

            if ! row.2.is_empty() {
                let _ = writeln!(string, "  {}", row.2);
            }
        }
    }

    Ok(string.into_bytes())
}
<commit_msg>Remove unused import<commit_after>use alloc::string::String;
use alloc::vec::Vec;
use core::fmt::Write;
use core::str;

use crate::context;
use crate::syscall::error::Result;

pub fn resource() -> Result<Vec<u8>> {
    let mut string = String::new();

    {
        let mut rows = Vec::new();
        {
            let contexts = context::contexts();
            for (id, context_lock) in contexts.iter() {
                let context = context_lock.read();
                rows.push((*id, context.name.lock().clone(), context.status_reason));
            }
        }

        for row in rows.iter() {
            let id: usize = row.0.into();
            let name = str::from_utf8(&row.1).unwrap_or(".");

            let _ = writeln!(string, "{}: {}", id, name);

            if ! row.2.is_empty() {
                let _ = writeln!(string, "  {}", row.2);
            }
        }
    }

    Ok(string.into_bytes())
}
<|endoftext|>


<commit_before>use super::mpsc_queue::{Queue};
use alloc::arc::Arc;
use super::mpsc_queue::PopResult::*;

pub enum TryRecvError {
    Empty,
    Disconnected,
}

pub struct Receiver<T> {
    pub queue: Arc<Queue<T>>,
}

impl<T> Receiver<T> {
    fn try_recv(&self, t: T) -> Result<T, TryRecvError> {
        match self.queue.pop() {
            Data(t) => Ok(t),
            _ => Err(TryRecvError::Empty),
        }
    }

    fn recv(&self, t: T) -> Result<T, ()> {
        loop {
            match self.queue.pop() {
                Data(t) => return Ok(t),
                _ => continue,
            }
        }

    }
}

unsafe impl<T: Send> Send for Receiver<T> {}
<commit_msg>Remove unused parameter<commit_after>use super::mpsc_queue::{Queue};
use alloc::arc::Arc;
use super::mpsc_queue::PopResult::*;

pub enum TryRecvError {
    Empty,
    Disconnected,
}

pub struct Receiver<T> {
    pub queue: Arc<Queue<T>>,
}

impl<T> Receiver<T> {
    fn try_recv(&self) -> Result<T, TryRecvError> {
        match self.queue.pop() {
            Data(t) => Ok(t),
            _ => Err(TryRecvError::Empty),
        }
    }

    fn recv(&self) -> Result<T, ()> {
        loop {
            match self.queue.pop() {
                Data(t) => return Ok(t),
                _ => continue,
            }
        }

    }
}

unsafe impl<T: Send> Send for Receiver<T> {}
<|endoftext|>


<commit_before>extern crate orbfont;
extern crate ransid;

use self::orbfont::Font;

use std::mem;

use orbclient::{Color, Event, EventOption, Window};
use orbclient::event;

pub struct Console {
    pub window: Window,
    pub inner: ransid::Console,
    pub font: Font,
    pub font_bold: Font,
    pub command: String,
}

impl Console {
    pub fn new(width: u32, height: u32) -> Console {
        let mut window = Window::new_flags(-1, -1, width, height, "Terminal", true).unwrap();
        window.sync();
        Console {
            window: window,
            inner: ransid::Console::new(width as usize/8, height as usize/16),
            font: Font::find(Some("Mono"), None, None).unwrap(),
            font_bold: Font::find(Some("Mono"), None, Some("Bold")).unwrap(),
            command: String::new(),
        }
    }

    pub fn event(&mut self, event: Event) -> Option<String> {
        match event.to_option() {
            EventOption::Key(key_event) => {
                if key_event.pressed {
                    if self.inner.raw_mode {
                        match key_event.scancode {
                            event::K_BKSP => self.command.push_str("\x7F"),
                            event::K_UP => self.command.push_str("\x1B[A"),
                            event::K_DOWN => self.command.push_str("\x1B[B"),
                            event::K_RIGHT => self.command.push_str("\x1B[C"),
                            event::K_LEFT => self.command.push_str("\x1B[D"),
                            _ => match key_event.character {
                                '\0' => {},
                                c => {
                                    self.command.push(c);
                                }
                            },
                        }

                        if ! self.command.is_empty() {
                            let mut command = String::new();
                            mem::swap(&mut self.command, &mut command);
                            return Some(command);
                        }
                    } else {
                        match key_event.scancode {
                            event::K_BKSP => if ! self.command.is_empty() {
                                self.inner.redraw = true;

                                self.write(&[8]);
                                self.command.pop();
                            },
                            _ => match key_event.character {
                                '\0' => (),
                                c => {
                                    self.inner.redraw = true;

                                    self.write(&[c as u8]);
                                    self.command.push(c);

                                    if c == '\n' {
                                        let mut command = String::new();
                                        mem::swap(&mut self.command, &mut command);
                                        return Some(command);
                                    }
                                }
                            },
                        }
                    }
                }
            },
            _ => (),
        }

        None
    }

    pub fn write(&mut self, bytes: &[u8]) {
        self.inner.write(bytes);
        if self.inner.redraw {
            self.inner.redraw = false;

            self.window.set(Color {
                data: self.inner.background.data
            });
            for y in 0..self.inner.h {
                for x in 0..self.inner.w {
                    let block = self.inner.display[y * self.inner.w + x];
                    self.window.rect(x as i32 * 8, y as i32 * 16, 8, 16, Color {
                        data: block.bg.data
                    });
                    if block.c != ' ' {
                        if block.bold {
                            self.font_bold.render(&block.c.to_string(), 16.0).draw(&mut self.window, x as i32 * 8, y as i32 * 16, Color {
                                data: block.fg.data
                            });
                        } else {
                            self.font.render(&block.c.to_string(), 16.0).draw(&mut self.window, x as i32 * 8, y as i32 * 16, Color {
                                data: block.fg.data
                            });
                        }
                    }
                    if block.underlined {
                        self.window.rect(x as i32 * 8, y as i32 * 16 + 14, 8, 1, Color {
                            data: block.fg.data
                        });
                    }
                }
            }
            if self.inner.cursor {
                self.window.rect(self.inner.x as i32 * 8, self.inner.y as i32 * 16, 8, 16, Color {
                    data: self.inner.foreground.data
                });
            }
            self.window.sync();
        }
    }
}
<commit_msg>Focus event turns cursor into empty rectangle<commit_after>extern crate orbfont;
extern crate ransid;

use self::orbfont::Font;

use std::mem;

use orbclient::{Color, Event, EventOption, Window};
use orbclient::event;

pub struct Console {
    pub window: Window,
    pub inner: ransid::Console,
    pub font: Font,
    pub font_bold: Font,
    pub focused: bool,
    pub command: String,
}

impl Console {
    pub fn new(width: u32, height: u32) -> Console {
        let mut window = Window::new_flags(-1, -1, width, height, "Terminal", true).unwrap();
        window.sync();
        Console {
            window: window,
            inner: ransid::Console::new(width as usize/8, height as usize/16),
            font: Font::find(Some("Mono"), None, None).unwrap(),
            font_bold: Font::find(Some("Mono"), None, Some("Bold")).unwrap(),
            focused: true,
            command: String::new(),
        }
    }

    pub fn event(&mut self, event: Event) -> Option<String> {
        match event.to_option() {
            EventOption::Key(key_event) => {
                if key_event.pressed {
                    if self.inner.raw_mode {
                        match key_event.scancode {
                            event::K_BKSP => self.command.push_str("\x7F"),
                            event::K_UP => self.command.push_str("\x1B[A"),
                            event::K_DOWN => self.command.push_str("\x1B[B"),
                            event::K_RIGHT => self.command.push_str("\x1B[C"),
                            event::K_LEFT => self.command.push_str("\x1B[D"),
                            _ => match key_event.character {
                                '\0' => {},
                                c => {
                                    self.command.push(c);
                                }
                            },
                        }

                        if ! self.command.is_empty() {
                            let mut command = String::new();
                            mem::swap(&mut self.command, &mut command);
                            return Some(command);
                        }
                    } else {
                        match key_event.scancode {
                            event::K_BKSP => if ! self.command.is_empty() {
                                self.inner.redraw = true;

                                self.write(&[8]);
                                self.command.pop();
                            },
                            _ => match key_event.character {
                                '\0' => (),
                                c => {
                                    self.inner.redraw = true;

                                    self.write(&[c as u8]);
                                    self.command.push(c);

                                    if c == '\n' {
                                        let mut command = String::new();
                                        mem::swap(&mut self.command, &mut command);
                                        return Some(command);
                                    }
                                }
                            },
                        }
                    }
                }
            },
            EventOption::Focus(focus_event) => if self.focused != focus_event.focused {
                self.focused = focus_event.focused;
                self.inner.redraw = true;
                self.write(&[]);
            },
            _ => (),
        }

        None
    }

    pub fn write(&mut self, bytes: &[u8]) {
        self.inner.write(bytes);
        if self.inner.redraw {
            self.inner.redraw = false;

            self.window.set(Color {
                data: self.inner.background.data
            });
            for y in 0..self.inner.h {
                for x in 0..self.inner.w {
                    let block = self.inner.display[y * self.inner.w + x];
                    self.window.rect(x as i32 * 8, y as i32 * 16, 8, 16, Color {
                        data: block.bg.data
                    });
                    if block.c != ' ' {
                        if block.bold {
                            self.font_bold.render(&block.c.to_string(), 16.0).draw(&mut self.window, x as i32 * 8, y as i32 * 16, Color {
                                data: block.fg.data
                            });
                        } else {
                            self.font.render(&block.c.to_string(), 16.0).draw(&mut self.window, x as i32 * 8, y as i32 * 16, Color {
                                data: block.fg.data
                            });
                        }
                    }
                    if block.underlined {
                        self.window.rect(x as i32 * 8, y as i32 * 16 + 14, 8, 1, Color {
                            data: block.fg.data
                        });
                    }
                }
            }
            if self.inner.cursor {
                self.window.rect(self.inner.x as i32 * 8, self.inner.y as i32 * 16, 8, 16, Color {
                    data: self.inner.foreground.data
                });
                if ! self.focused {
                    self.window.rect(self.inner.x as i32 * 8 + 1, self.inner.y as i32 * 16 + 1, 6, 14, Color {
                        data: self.inner.background.data
                    });
                }
            }
            self.window.sync();
        }
    }
}
<|endoftext|>