<commit_before>use std::collections::{BTreeMap, BTreeSet};
use std::io;
use std::error::FromError;

use rustc_serialize::json;
use rustc_serialize::json::{Json, ToJson};

#[derive(Clone, Debug, PartialEq)]
pub enum ChatJsonError {
    MalformedJson(json::ParserError),
    IoError(io::Error),
    InvalidObject,
    InvalidField,
    UnknownField,
    UnknownColor,
    InvalidClickEvent,
    InvalidHoverEvent
}

impl FromError<io::Error> for ChatJsonError {
    fn from_error(err: io::Error) -> ChatJsonError {
        ChatJsonError::IoError(err)
    }
}

impl FromError<json::ParserError> for ChatJsonError {
    fn from_error(err: json::ParserError) -> ChatJsonError {
        if let json::ParserError::IoError(e) = err {
            ChatJsonError::IoError(e)
        } else {
            ChatJsonError::MalformedJson(err)
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct ChatJson {
    pub msg: Message,
    pub extra: Option<Vec<Json>>,
    pub color: Option<Color>,
    pub formats: BTreeSet<Format>,
    pub click_event: Option<ClickEvent>,
    pub hover_event: Option<HoverEvent>,
    pub insertion: Option<String>
}

impl ChatJson {
    pub fn msg(msg: String) -> ChatJson {
        ChatJson {
            msg: Message::PlainText(msg), extra: None, color: None, formats: BTreeSet::new(),
            click_event: None, hover_event: None, insertion: None
        }
    }

    pub fn from_json<T: Iterator<Item=char>>(src: T) -> Result<ChatJson, ChatJsonError> {
        let json = try!(json::Builder::new(src).build());
        if let Json::Object(map) = json {
            let mut result = ChatJson::msg("".to_string());
            for (key, value) in map {
                println!("{:?}: {:?}", key, value);
                match key.as_slice() {
                    "text" => {
                        if let Json::String(string) = value {
                            result.msg = Message::PlainText(string);
                        } else {
                            return Err(ChatJsonError::InvalidField);
                        }
                    },
                    "insertion" => {
                        if let Json::String(string) = value {
                            result.insertion = Some(string);
                        } else {
                            return Err(ChatJsonError::InvalidField);
                        }
                    },
                    "color" => {
                        if let Json::String(string) = value {
                            result.color = match Color::from_string(&string) {
                                None => return Err(ChatJsonError::UnknownColor),
                                c => c
                            };
                        } else {
                            return Err(ChatJsonError::InvalidField);
                        }
                    },
                    // Handle all of the different format strings.
                    "bold"|"italic"|"underlined"|"strikethrough"|"obfuscated"|"reset"|"random" => {
                        if let Json::Boolean(b) = value {
                            if b == true {
                                result.formats.insert(Format::from_string(&key).unwrap());
                            }
                        } else {
                            return Err(ChatJsonError::InvalidField);
                        }
                    },
                    // Handle the JSON format of click events.
                    "clickEvent" => {
                        if let Json::Object(event) = value {
                            // Get the `value` first.
                            let val: String = match event.get("value") {
                                Some(&Json::String(ref string)) => string.clone(),
                                _ => return Err(ChatJsonError::InvalidClickEvent)
                            };
                            // Handle the different click events.
                            if let Some(&Json::String(ref string)) = event.get("action") {
                                result.click_event = match string.as_slice() {
                                    "open_url" => Some(ClickEvent::OpenUrl(val)),
                                    "open_file" => Some(ClickEvent::OpenFile(val)),
                                    "run_command" => Some(ClickEvent::RunCommand(val)),
                                    "suggest_command" => Some(ClickEvent::SuggestCommand(val)),
                                    _ => return Err(ChatJsonError::InvalidClickEvent)
                                };
                            } else {
                                return Err(ChatJsonError::InvalidClickEvent);
                            }
                        }
                    },
                    // Handle the JSON format of hover events.
                    "hoverEvent" => {
                        if let Json::Object(event) = value {
                            // Get the `value` first.
                            let val: String = match event.get("value") {
                                Some(&Json::String(ref string)) => string.clone(),
                                _ => return Err(ChatJsonError::InvalidHoverEvent)
                            };
                            // Handle the different click events.
                            if let Some(&Json::String(ref string)) = event.get("action") {
                                result.hover_event = match string.as_slice() {
                                    "show_text" => Some(HoverEvent::Text(val)),
                                    "show_achievement" => Some(HoverEvent::Achievement(val)),
                                    "show_item" => Some(HoverEvent::Item(val)),
                                    _ => return Err(ChatJsonError::InvalidHoverEvent)
                                };
                            } else {
                                return Err(ChatJsonError::InvalidHoverEvent);
                            }
                        }
                    },
                    "extra" => {
                        if let Json::Array(extra) = value {
                            result.extra = Some(extra);
                        } else {
                            return Err(ChatJsonError::InvalidField);
                        }
                    },
                    // TODO: Error on unknown key when the implementation is complete.
                    _ => (),
                };
            }
            Ok(result)
        } else {
            Err(ChatJsonError::InvalidObject)
        }
    }
}

impl ToJson for ChatJson {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();

        match self.msg {
            Message::PlainText(ref text) => {
                d.insert("text".to_string(), text.to_json());
            },
            _ => unimplemented!()
        };

        if let Some(ref extra) = self.extra {
            d.insert("extra".to_string(), extra.to_json());
        }
        if let Some(ref color) = self.color {
            d.insert("color".to_string(), color.to_string().to_json());
        }
        if let Some(ref event) = self.click_event {
            d.insert("clickEvent".to_string(), event.to_json());
        }
        if let Some(ref event) = self.hover_event {
            d.insert("hoverEvent".to_string(), event.to_json());
        }
        if let Some(ref ins) = self.insertion {
            d.insert("insertion".to_string(), ins.to_json());
        }

        Json::Object(d)
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Message {
    PlainText(String),
    Score(String, String),
    Translatable,
    Selector
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ClickEvent {
    OpenUrl(String),
    OpenFile(String),
    RunCommand(String),
    SuggestCommand(String)
}

impl ToJson for ClickEvent {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        match self {
            &ClickEvent::OpenUrl(ref url) => {
                d.insert("action".to_string(), "open_url".to_json());
                d.insert("value".to_string(), url.to_json());
            },
            &ClickEvent::OpenFile(ref file) => {
                d.insert("action".to_string(), "open_file".to_json());
                d.insert("value".to_string(), file.to_json());
            },
            &ClickEvent::RunCommand(ref cmd) => {
                d.insert("action".to_string(), "run_command".to_json());
                d.insert("value".to_string(), cmd.to_json());
            },
            &ClickEvent::SuggestCommand(ref cmd) => {
                d.insert("action".to_string(), "suggest_command".to_json());
                d.insert("value".to_string(), cmd.to_json());
            }
        }
        Json::Object(d)
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum HoverEvent {
    Text(String),
    Achievement(String),
    Item(String)
}

impl ToJson for HoverEvent {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        match self {
            &HoverEvent::Text(ref text) => {
                d.insert("action".to_string(), "show_text".to_json());
                d.insert("value".to_string(), text.to_json());
            },
            &HoverEvent::Achievement(ref ach) => {
                d.insert("action".to_string(), "show_achievement".to_json());
                d.insert("value".to_string(), ach.to_json());
            },
            &HoverEvent::Item(ref item) => {
                d.insert("action".to_string(), "show_item".to_json());
                // The string is actually a JSON object, just in the form of a
                // string.
                d.insert("value".to_string(), item.to_json());
            }
        }
        Json::Object(d)
    }
}

#[derive(Copy, Debug, Clone, Eq, PartialEq)]
pub enum Color {
    Black       = 0x0,
    DarkBlue    = 0x1,
    DarkGreen   = 0x2,
    DarkCyan    = 0x3,
    DarkRed     = 0x4,
    Purple      = 0x5,
    Gold        = 0x6,
    Gray        = 0x7,
    DarkGray    = 0x8,
    Blue        = 0x9,
    BrightGreen = 0xa,
    Cyan        = 0xb,
    Red         = 0xc,
    Pink        = 0xd,
    Yellow      = 0xe,
    White       = 0xf
}

impl Color {
    pub fn to_string(&self) -> String {
        match self {
            &Color::Black => "black".to_string(),
            &Color::DarkBlue => "dark_blue".to_string(),
            &Color::DarkGreen => "dark_green".to_string(),
            &Color::DarkCyan => "dark_aqua".to_string(),
            &Color::DarkRed => "dark_red".to_string(),
            &Color::Purple => "dark_purple".to_string(),
            &Color::Gold => "gold".to_string(),
            &Color::Gray => "gray".to_string(),
            &Color::DarkGray => "dark_gray".to_string(),
            &Color::Blue => "blue".to_string(),
            &Color::BrightGreen => "green".to_string(),
            &Color::Cyan => "aqua".to_string(),
            &Color::Red => "red".to_string(),
            &Color::Pink => "light_purple".to_string(),
            &Color::Yellow => "yellow".to_string(),
            &Color::White => "white".to_string()
        }
    }

    pub fn from_string(string: &String) -> Option<Color> {
        match string.as_slice() {
            "black"        => Some(Color::Black),
            "dark_blue"    => Some(Color::DarkBlue),
            "dark_green"   => Some(Color::DarkGreen),
            "dark_aqua"    => Some(Color::DarkCyan),
            "dark_red"     => Some(Color::DarkRed),
            "dark_purple"  => Some(Color::Purple),
            "gold"         => Some(Color::Gold),
            "gray"         => Some(Color::Gray),
            "dark_gray"    => Some(Color::DarkGray),
            "blue"         => Some(Color::Blue),
            "green"        => Some(Color::BrightGreen),
            "aqua"         => Some(Color::Cyan),
            "red"          => Some(Color::Red),
            "light_purple" => Some(Color::Pink),
            "yellow"       => Some(Color::Yellow),
            "white"        => Some(Color::White),
            _              => None
        }
    }
}

#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
pub enum Format {
    Bold, Underlined, Strikethrough, Italic, Obfuscated, Random, Reset
}

impl Format {
    pub fn from_string(string: &String) -> Option<Format> {
        match string.as_slice() {
            "bold"          => Some(Format::Bold),
            "italic"        => Some(Format::Italic),
            "underlined"    => Some(Format::Underlined),
            "strikethrough" => Some(Format::Strikethrough),
            "obfuscated"    => Some(Format::Obfuscated),
            "random"        => Some(Format::Random),
            "reset"         => Some(Format::Reset),
            _               => None
        }
    }
}

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

    #[test]
    fn chat_plain() {
        let msg = ChatJson::msg("Hello, world!".to_string());
        let blob = r#"{
            "text": "Hello, world!"
        }"#;
        let parsed = ChatJson::from_json(blob.chars()).unwrap();
        assert_eq!(&msg, &parsed);
    }

    #[test]
    fn chat_invalid_field() {
        let blob = r#"{
            "text": true
        }"#;
        let parsed = ChatJson::from_json(blob.chars());
        assert_eq!(&parsed, &Err(ChatJsonError::InvalidField));
    }

    #[test]
    fn chat_extra() {
        let blob = r#"{
            "text": "Hello world",
            "extra": [
                "Testing",
                {"translate":"demo.day.2"}
            ],
            "bold":true,
            "italic":false,
            "underlined": false,
            "strikethrough": true,
            "obfuscated": false,
            "color":"red",
            "clickEvent":{
                "action":"run_command",
                "value": "/time set day"
            },
            "hoverEvent": {
                "action":"show_text",
                "value": "Hello"
            },
            "insertion": "Hello world"
        }"#;

        let parsed = ChatJson::from_json(blob.chars());
        println!("{:?}", parsed);
    }
}
<commit_msg>chat: Now serializes formatting.<commit_after>use std::collections::{BTreeMap, BTreeSet};
use std::io;
use std::error::FromError;

use rustc_serialize::json;
use rustc_serialize::json::{Json, ToJson};

#[derive(Clone, Debug, PartialEq)]
pub enum ChatJsonError {
    MalformedJson(json::ParserError),
    IoError(io::Error),
    InvalidObject,
    InvalidField,
    UnknownField,
    UnknownColor,
    InvalidClickEvent,
    InvalidHoverEvent
}

impl FromError<io::Error> for ChatJsonError {
    fn from_error(err: io::Error) -> ChatJsonError {
        ChatJsonError::IoError(err)
    }
}

impl FromError<json::ParserError> for ChatJsonError {
    fn from_error(err: json::ParserError) -> ChatJsonError {
        if let json::ParserError::IoError(e) = err {
            ChatJsonError::IoError(e)
        } else {
            ChatJsonError::MalformedJson(err)
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct ChatJson {
    pub msg: Message,
    pub extra: Option<Vec<Json>>,
    pub color: Option<Color>,
    pub formats: BTreeSet<Format>,
    pub click_event: Option<ClickEvent>,
    pub hover_event: Option<HoverEvent>,
    pub insertion: Option<String>
}

impl ChatJson {
    pub fn msg(msg: String) -> ChatJson {
        ChatJson {
            msg: Message::PlainText(msg), extra: None, color: None, formats: BTreeSet::new(),
            click_event: None, hover_event: None, insertion: None
        }
    }

    pub fn from_json<T: Iterator<Item=char>>(src: T) -> Result<ChatJson, ChatJsonError> {
        let json = try!(json::Builder::new(src).build());
        if let Json::Object(map) = json {
            let mut result = ChatJson::msg("".to_string());
            for (key, value) in map {
                println!("{:?}: {:?}", key, value);
                match key.as_slice() {
                    "text" => {
                        if let Json::String(string) = value {
                            result.msg = Message::PlainText(string);
                        } else {
                            return Err(ChatJsonError::InvalidField);
                        }
                    },
                    "insertion" => {
                        if let Json::String(string) = value {
                            result.insertion = Some(string);
                        } else {
                            return Err(ChatJsonError::InvalidField);
                        }
                    },
                    "color" => {
                        if let Json::String(string) = value {
                            result.color = match Color::from_string(&string) {
                                None => return Err(ChatJsonError::UnknownColor),
                                c => c
                            };
                        } else {
                            return Err(ChatJsonError::InvalidField);
                        }
                    },
                    // Handle all of the different format strings.
                    "bold"|"italic"|"underlined"|"strikethrough"|"obfuscated"|"reset"|"random" => {
                        if let Json::Boolean(b) = value {
                            if b == true {
                                result.formats.insert(Format::from_string(&key).unwrap());
                            }
                        } else {
                            return Err(ChatJsonError::InvalidField);
                        }
                    },
                    // Handle the JSON format of click events.
                    "clickEvent" => {
                        if let Json::Object(event) = value {
                            // Get the `value` first.
                            let val: String = match event.get("value") {
                                Some(&Json::String(ref string)) => string.clone(),
                                _ => return Err(ChatJsonError::InvalidClickEvent)
                            };
                            // Handle the different click events.
                            if let Some(&Json::String(ref string)) = event.get("action") {
                                result.click_event = match string.as_slice() {
                                    "open_url" => Some(ClickEvent::OpenUrl(val)),
                                    "open_file" => Some(ClickEvent::OpenFile(val)),
                                    "run_command" => Some(ClickEvent::RunCommand(val)),
                                    "suggest_command" => Some(ClickEvent::SuggestCommand(val)),
                                    _ => return Err(ChatJsonError::InvalidClickEvent)
                                };
                            } else {
                                return Err(ChatJsonError::InvalidClickEvent);
                            }
                        }
                    },
                    // Handle the JSON format of hover events.
                    "hoverEvent" => {
                        if let Json::Object(event) = value {
                            // Get the `value` first.
                            let val: String = match event.get("value") {
                                Some(&Json::String(ref string)) => string.clone(),
                                _ => return Err(ChatJsonError::InvalidHoverEvent)
                            };
                            // Handle the different click events.
                            if let Some(&Json::String(ref string)) = event.get("action") {
                                result.hover_event = match string.as_slice() {
                                    "show_text" => Some(HoverEvent::Text(val)),
                                    "show_achievement" => Some(HoverEvent::Achievement(val)),
                                    "show_item" => Some(HoverEvent::Item(val)),
                                    _ => return Err(ChatJsonError::InvalidHoverEvent)
                                };
                            } else {
                                return Err(ChatJsonError::InvalidHoverEvent);
                            }
                        }
                    },
                    "extra" => {
                        if let Json::Array(extra) = value {
                            result.extra = Some(extra);
                        } else {
                            return Err(ChatJsonError::InvalidField);
                        }
                    },
                    // TODO: Error on unknown key when the implementation is complete.
                    _ => (),
                };
            }
            Ok(result)
        } else {
            Err(ChatJsonError::InvalidObject)
        }
    }
}

impl ToJson for ChatJson {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();

        match self.msg {
            Message::PlainText(ref text) => {
                d.insert("text".to_string(), text.to_json());
            },
            _ => unimplemented!()
        };

        for format in self.formats.iter() {
            d.insert(format.to_string(), Json::Boolean(true));
        }

        if let Some(ref extra) = self.extra {
            d.insert("extra".to_string(), extra.to_json());
        }
        if let Some(ref color) = self.color {
            d.insert("color".to_string(), color.to_string().to_json());
        }
        if let Some(ref event) = self.click_event {
            d.insert("clickEvent".to_string(), event.to_json());
        }
        if let Some(ref event) = self.hover_event {
            d.insert("hoverEvent".to_string(), event.to_json());
        }
        if let Some(ref ins) = self.insertion {
            d.insert("insertion".to_string(), ins.to_json());
        }

        Json::Object(d)
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Message {
    PlainText(String),
    Score(String, String),
    Translatable,
    Selector
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ClickEvent {
    OpenUrl(String),
    OpenFile(String),
    RunCommand(String),
    SuggestCommand(String)
}

impl ToJson for ClickEvent {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        match self {
            &ClickEvent::OpenUrl(ref url) => {
                d.insert("action".to_string(), "open_url".to_json());
                d.insert("value".to_string(), url.to_json());
            },
            &ClickEvent::OpenFile(ref file) => {
                d.insert("action".to_string(), "open_file".to_json());
                d.insert("value".to_string(), file.to_json());
            },
            &ClickEvent::RunCommand(ref cmd) => {
                d.insert("action".to_string(), "run_command".to_json());
                d.insert("value".to_string(), cmd.to_json());
            },
            &ClickEvent::SuggestCommand(ref cmd) => {
                d.insert("action".to_string(), "suggest_command".to_json());
                d.insert("value".to_string(), cmd.to_json());
            }
        }
        Json::Object(d)
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum HoverEvent {
    Text(String),
    Achievement(String),
    Item(String)
}

impl ToJson for HoverEvent {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        match self {
            &HoverEvent::Text(ref text) => {
                d.insert("action".to_string(), "show_text".to_json());
                d.insert("value".to_string(), text.to_json());
            },
            &HoverEvent::Achievement(ref ach) => {
                d.insert("action".to_string(), "show_achievement".to_json());
                d.insert("value".to_string(), ach.to_json());
            },
            &HoverEvent::Item(ref item) => {
                d.insert("action".to_string(), "show_item".to_json());
                // The string is actually a JSON object, just in the form of a
                // string.
                d.insert("value".to_string(), item.to_json());
            }
        }
        Json::Object(d)
    }
}

#[derive(Copy, Debug, Clone, Eq, PartialEq)]
pub enum Color {
    Black       = 0x0,
    DarkBlue    = 0x1,
    DarkGreen   = 0x2,
    DarkCyan    = 0x3,
    DarkRed     = 0x4,
    Purple      = 0x5,
    Gold        = 0x6,
    Gray        = 0x7,
    DarkGray    = 0x8,
    Blue        = 0x9,
    BrightGreen = 0xa,
    Cyan        = 0xb,
    Red         = 0xc,
    Pink        = 0xd,
    Yellow      = 0xe,
    White       = 0xf
}

impl Color {
    pub fn to_string(&self) -> String {
        match self {
            &Color::Black => "black".to_string(),
            &Color::DarkBlue => "dark_blue".to_string(),
            &Color::DarkGreen => "dark_green".to_string(),
            &Color::DarkCyan => "dark_aqua".to_string(),
            &Color::DarkRed => "dark_red".to_string(),
            &Color::Purple => "dark_purple".to_string(),
            &Color::Gold => "gold".to_string(),
            &Color::Gray => "gray".to_string(),
            &Color::DarkGray => "dark_gray".to_string(),
            &Color::Blue => "blue".to_string(),
            &Color::BrightGreen => "green".to_string(),
            &Color::Cyan => "aqua".to_string(),
            &Color::Red => "red".to_string(),
            &Color::Pink => "light_purple".to_string(),
            &Color::Yellow => "yellow".to_string(),
            &Color::White => "white".to_string()
        }
    }

    pub fn from_string(string: &String) -> Option<Color> {
        match string.as_slice() {
            "black"        => Some(Color::Black),
            "dark_blue"    => Some(Color::DarkBlue),
            "dark_green"   => Some(Color::DarkGreen),
            "dark_aqua"    => Some(Color::DarkCyan),
            "dark_red"     => Some(Color::DarkRed),
            "dark_purple"  => Some(Color::Purple),
            "gold"         => Some(Color::Gold),
            "gray"         => Some(Color::Gray),
            "dark_gray"    => Some(Color::DarkGray),
            "blue"         => Some(Color::Blue),
            "green"        => Some(Color::BrightGreen),
            "aqua"         => Some(Color::Cyan),
            "red"          => Some(Color::Red),
            "light_purple" => Some(Color::Pink),
            "yellow"       => Some(Color::Yellow),
            "white"        => Some(Color::White),
            _              => None
        }
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
pub enum Format {
    Bold, Underlined, Strikethrough, Italic, Obfuscated, Random, Reset
}

impl Format {
    pub fn to_string(&self) -> String {
        match self {
            &Format::Bold          => "bold".to_string(),
            &Format::Italic        => "italic".to_string(),
            &Format::Underlined    => "underlined".to_string(),
            &Format::Strikethrough => "strikethrough".to_string(),
            &Format::Obfuscated    => "obfuscated".to_string(),
            &Format::Random        => "random".to_string(),
            &Format::Reset         => "reset".to_string()
        }
    }

    pub fn from_string(string: &String) -> Option<Format> {
        match string.as_slice() {
            "bold"          => Some(Format::Bold),
            "italic"        => Some(Format::Italic),
            "underlined"    => Some(Format::Underlined),
            "strikethrough" => Some(Format::Strikethrough),
            "obfuscated"    => Some(Format::Obfuscated),
            "random"        => Some(Format::Random),
            "reset"         => Some(Format::Reset),
            _               => None
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use rustc_serialize::json::{Builder, ToJson};

    #[test]
    fn chat_plain() {
        let msg = ChatJson::msg("Hello, world!".to_string());
        let blob = r#"{
            "text": "Hello, world!"
        }"#;
        let parsed = ChatJson::from_json(blob.chars()).unwrap();
        assert_eq!(&msg, &parsed);
    }

    #[test]
    fn chat_invalid_field() {
        let blob = r#"{
            "text": true
        }"#;
        let parsed = ChatJson::from_json(blob.chars());
        assert_eq!(&parsed, &Err(ChatJsonError::InvalidField));
    }

    #[test]
    fn chat_with_events() {
        let mut msg = ChatJson::msg("Hello, world!".to_string());
        msg.formats.insert(Format::Bold);
        msg.formats.insert(Format::Strikethrough);
        msg.color = Some(Color::Red);
        msg.insertion = Some("Hello, world!".to_string());
        msg.click_event = Some(ClickEvent::RunCommand("/time set day".to_string()));
        msg.hover_event = Some(HoverEvent::Text("Goodbye!".to_string()));

        let blob = r#"{
            "text": "Hello, world!",
            "bold": true,
            "strikethrough": true,
            "color":"red",
            "clickEvent":{
                "action":"run_command",
                "value": "/time set day"
            },
            "hoverEvent": {
                "action":"show_text",
                "value": "Goodbye!"
            },
            "insertion": "Hello, world!"
        }"#;

        let blob_json = Builder::new(blob.chars()).build().unwrap();
        assert_eq!(&blob_json, &msg.to_json());
        assert_eq!(&msg, &ChatJson::from_json(blob.chars()));
    }

    #[test]
    fn chat_extra() {
        let blob = r#"{
            "text": "Hello world",
            "extra": [
                "Testing",
                {"translate":"demo.day.2"}
            ],
            "bold":true,
            "italic":false,
            "underlined": false,
            "strikethrough": true,
            "obfuscated": false,
            "color":"red",
            "clickEvent":{
                "action":"run_command",
                "value": "/time set day"
            },
            "hoverEvent": {
                "action":"show_text",
                "value": "Hello"
            },
            "insertion": "Hello world"
        }"#;

        let parsed = ChatJson::from_json(blob.chars());
        println!("{:?}", parsed);
    }
}
<|endoftext|>


<commit_before>use crate::options::SkimOptions;
///! Handle the color theme
use tuikit::attr::{Attr, Color, Effect};

#[rustfmt::skip]
pub const DEFAULT_THEME: ColorTheme = ColorTheme {
    fg:               Color::Default,
    bg:               Color::Default,
    matched:          Color::AnsiValue(108),
    matched_bg:       Color::AnsiValue(0),
    current:          Color::AnsiValue(254),
    current_bg:       Color::AnsiValue(236),
    current_match:    Color::AnsiValue(151),
    current_match_bg: Color::AnsiValue(236),
    spinner:          Color::AnsiValue(148),
    info:             Color::AnsiValue(144),
    prompt:           Color::AnsiValue(110),
    cursor:           Color::AnsiValue(161),
    selected:         Color::AnsiValue(168),
    header:           Color::AnsiValue(109),
    border:           Color::AnsiValue(59),
};

#[rustfmt::skip]
#[derive(Copy, Clone, Debug)]
pub struct ColorTheme {
    fg:               Color, // text fg
    bg:               Color, // text bg
    matched:          Color,
    matched_bg:       Color,
    current:          Color,
    current_bg:       Color,
    current_match:    Color,
    current_match_bg: Color,
    spinner:          Color,
    info:             Color,
    prompt:           Color,
    cursor:           Color,
    selected:         Color,
    header:           Color,
    border:           Color,
}

#[rustfmt::skip]
#[allow(dead_code)]
impl ColorTheme {
    pub fn init_from_options(options: &SkimOptions) -> ColorTheme {
        // register
        if let Some(color) = options.color {
            ColorTheme::from_options(color)
        } else {
            ColorTheme::dark256()
        }
    }

    fn default16() -> Self {
        ColorTheme {
            fg:               Color::Default,
            bg:               Color::Default,
            matched:          Color::GREEN,
            matched_bg:       Color::BLACK,
            current:          Color::YELLOW,
            current_bg:       Color::BLACK,
            current_match:    Color::GREEN,
            current_match_bg: Color::BLACK,
            spinner:          Color::GREEN,
            info:             Color::WHITE,
            prompt:           Color::BLUE,
            cursor:           Color::RED,
            selected:         Color::MAGENTA,
            header:           Color::CYAN,
            border:           Color::LIGHT_BLACK,
        }
    }

    fn dark256() -> Self {
        ColorTheme {
            fg:               Color::Default,
            bg:               Color::Default,
            matched:          Color::AnsiValue(108),
            matched_bg:       Color::AnsiValue(0),
            current:          Color::AnsiValue(254),
            current_bg:       Color::AnsiValue(236),
            current_match:    Color::AnsiValue(151),
            current_match_bg: Color::AnsiValue(236),
            spinner:          Color::AnsiValue(148),
            info:             Color::AnsiValue(144),
            prompt:           Color::AnsiValue(110),
            cursor:           Color::AnsiValue(161),
            selected:         Color::AnsiValue(168),
            header:           Color::AnsiValue(109),
            border:           Color::AnsiValue(59),
        }
    }

    fn molokai256() -> Self {
        ColorTheme {
            fg:               Color::Default,
            bg:               Color::Default,
            matched:          Color::AnsiValue(234),
            matched_bg:       Color::AnsiValue(186),
            current:          Color::AnsiValue(254),
            current_bg:       Color::AnsiValue(236),
            current_match:    Color::AnsiValue(234),
            current_match_bg: Color::AnsiValue(186),
            spinner:          Color::AnsiValue(148),
            info:             Color::AnsiValue(144),
            prompt:           Color::AnsiValue(110),
            cursor:           Color::AnsiValue(161),
            selected:         Color::AnsiValue(168),
            header:           Color::AnsiValue(109),
            border:           Color::AnsiValue(59),
        }
    }

    fn light256() -> Self {
        ColorTheme {
            fg:               Color::Default,
            bg:               Color::Default,
            matched:          Color::AnsiValue(0),
            matched_bg:       Color::AnsiValue(220),
            current:          Color::AnsiValue(237),
            current_bg:       Color::AnsiValue(251),
            current_match:    Color::AnsiValue(66),
            current_match_bg: Color::AnsiValue(251),
            spinner:          Color::AnsiValue(65),
            info:             Color::AnsiValue(101),
            prompt:           Color::AnsiValue(25),
            cursor:           Color::AnsiValue(161),
            selected:         Color::AnsiValue(168),
            header:           Color::AnsiValue(31),
            border:           Color::AnsiValue(145),
        }
    }

    fn from_options(color: &str) -> Self {
        let mut theme = ColorTheme::dark256();
        for pair in color.split(',') {
            let color: Vec<&str> = pair.split(':').collect();
            if color.len() < 2 {
                theme = match color[0] {
                    "molokai"  => ColorTheme::molokai256(),
                    "light"    => ColorTheme::light256(),
                    "16"       => ColorTheme::default16(),
                    "dark" | "default" | _ => ColorTheme::dark256(),
                };
                continue;
            }

            let new_color = if color[1].len() == 7 {
                // 256 color
                let r = u8::from_str_radix(&color[1][1..3], 16).unwrap_or(255);
                let g = u8::from_str_radix(&color[1][3..5], 16).unwrap_or(255);
                let b = u8::from_str_radix(&color[1][5..7], 16).unwrap_or(255);
                Color::Rgb(r, g, b)
            } else {
                Color::AnsiValue(color[1].parse::<u8>().unwrap_or(255))
            };

            match color[0] {
                "fg"               => theme.fg               = new_color,
                "bg"               => theme.bg               = new_color,
                "matched"          => theme.matched          = new_color,
                "matched_bg"       => theme.matched_bg       = new_color,
                "current"          => theme.current          = new_color,
                "current_bg"       => theme.current_bg       = new_color,
                "current_match"    => theme.current_match    = new_color,
                "current_match_bg" => theme.current_match_bg = new_color,
                "spinner"          => theme.spinner          = new_color,
                "info"             => theme.info             = new_color,
                "prompt"           => theme.prompt           = new_color,
                "cursor"           => theme.cursor           = new_color,
                "selected"         => theme.selected         = new_color,
                "header"           => theme.header           = new_color,
                "border"           => theme.border           = new_color,
                _ => {}
            }
        }
        theme
    }

    pub fn normal(&self) -> Attr {
        Attr {
            fg: self.fg,
            bg: self.bg,
            effect: Effect::empty(),
        }
    }

    pub fn matched(&self) -> Attr {
        Attr {
            fg: self.matched,
            bg: self.matched_bg,
            effect: Effect::empty(),
        }
    }

    pub fn current(&self) -> Attr {
        Attr {
            fg: self.current,
            bg: self.current_bg,
            effect: Effect::empty(),
        }
    }

    pub fn current_match(&self) -> Attr {
        Attr {
            fg: self.current_match,
            bg: self.current_match_bg,
            effect: Effect::empty(),
        }
    }

    pub fn spinner(&self) -> Attr {
        Attr {
            fg: self.spinner,
            bg: self.bg,
            effect: Effect::BOLD,
        }
    }

    pub fn info(&self) -> Attr {
        Attr {
            fg: self.info,
            bg: self.bg,
            effect: Effect::empty(),
        }
    }

    pub fn prompt(&self) -> Attr {
        Attr {
            fg: self.prompt,
            bg: self.bg,
            effect: Effect::empty(),
        }
    }

    pub fn cursor(&self) -> Attr {
        Attr {
            fg: self.cursor,
            bg: self.current_bg,
            effect: Effect::empty(),
        }
    }

    pub fn selected(&self) -> Attr {
        Attr {
            fg: self.selected,
            bg: self.current_bg,
            effect: Effect::empty(),
        }
    }

    pub fn header(&self) -> Attr {
        Attr {
            fg: self.header,
            bg: self.bg,
            effect: Effect::empty(),
        }
    }

    pub fn border(&self) -> Attr {
        Attr {
            fg: self.border,
            bg: self.bg,
            effect: Effect::empty(),
        }
    }
}
<commit_msg>fix #164: implement color theme bw<commit_after>use crate::options::SkimOptions;
///! Handle the color theme
use tuikit::attr::{Attr, Color, Effect};

#[rustfmt::skip]
pub const DEFAULT_THEME: ColorTheme = ColorTheme {
    fg:               Color::Default,
    bg:               Color::Default,
    matched:          Color::AnsiValue(108),
    matched_bg:       Color::AnsiValue(0),
    current:          Color::AnsiValue(254),
    current_bg:       Color::AnsiValue(236),
    current_match:    Color::AnsiValue(151),
    current_match_bg: Color::AnsiValue(236),
    spinner:          Color::AnsiValue(148),
    info:             Color::AnsiValue(144),
    prompt:           Color::AnsiValue(110),
    cursor:           Color::AnsiValue(161),
    selected:         Color::AnsiValue(168),
    header:           Color::AnsiValue(109),
    border:           Color::AnsiValue(59),
};

#[rustfmt::skip]
#[derive(Copy, Clone, Debug)]
pub struct ColorTheme {
    fg:               Color, // text fg
    bg:               Color, // text bg
    matched:          Color,
    matched_bg:       Color,
    current:          Color,
    current_bg:       Color,
    current_match:    Color,
    current_match_bg: Color,
    spinner:          Color,
    info:             Color,
    prompt:           Color,
    cursor:           Color,
    selected:         Color,
    header:           Color,
    border:           Color,
}

#[rustfmt::skip]
#[allow(dead_code)]
impl ColorTheme {
    pub fn init_from_options(options: &SkimOptions) -> ColorTheme {
        // register
        if let Some(color) = options.color {
            ColorTheme::from_options(color)
        } else {
            ColorTheme::dark256()
        }
    }

    fn bw() -> Self {
        ColorTheme {
            fg:               Color::Default,
            bg:               Color::Default,
            matched:          Color::Default,
            matched_bg:       Color::Default,
            current:          Color::Default,
            current_bg:       Color::Default,
            current_match:    Color::Default,
            current_match_bg: Color::Default,
            spinner:          Color::Default,
            info:             Color::Default,
            prompt:           Color::Default,
            cursor:           Color::Default,
            selected:         Color::Default,
            header:           Color::Default,
            border:           Color::Default,
        }
    }

    fn default16() -> Self {
        ColorTheme {
            fg:               Color::Default,
            bg:               Color::Default,
            matched:          Color::GREEN,
            matched_bg:       Color::BLACK,
            current:          Color::YELLOW,
            current_bg:       Color::BLACK,
            current_match:    Color::GREEN,
            current_match_bg: Color::BLACK,
            spinner:          Color::GREEN,
            info:             Color::WHITE,
            prompt:           Color::BLUE,
            cursor:           Color::RED,
            selected:         Color::MAGENTA,
            header:           Color::CYAN,
            border:           Color::LIGHT_BLACK,
        }
    }

    fn dark256() -> Self {
        ColorTheme {
            fg:               Color::Default,
            bg:               Color::Default,
            matched:          Color::AnsiValue(108),
            matched_bg:       Color::AnsiValue(0),
            current:          Color::AnsiValue(254),
            current_bg:       Color::AnsiValue(236),
            current_match:    Color::AnsiValue(151),
            current_match_bg: Color::AnsiValue(236),
            spinner:          Color::AnsiValue(148),
            info:             Color::AnsiValue(144),
            prompt:           Color::AnsiValue(110),
            cursor:           Color::AnsiValue(161),
            selected:         Color::AnsiValue(168),
            header:           Color::AnsiValue(109),
            border:           Color::AnsiValue(59),
        }
    }

    fn molokai256() -> Self {
        ColorTheme {
            fg:               Color::Default,
            bg:               Color::Default,
            matched:          Color::AnsiValue(234),
            matched_bg:       Color::AnsiValue(186),
            current:          Color::AnsiValue(254),
            current_bg:       Color::AnsiValue(236),
            current_match:    Color::AnsiValue(234),
            current_match_bg: Color::AnsiValue(186),
            spinner:          Color::AnsiValue(148),
            info:             Color::AnsiValue(144),
            prompt:           Color::AnsiValue(110),
            cursor:           Color::AnsiValue(161),
            selected:         Color::AnsiValue(168),
            header:           Color::AnsiValue(109),
            border:           Color::AnsiValue(59),
        }
    }

    fn light256() -> Self {
        ColorTheme {
            fg:               Color::Default,
            bg:               Color::Default,
            matched:          Color::AnsiValue(0),
            matched_bg:       Color::AnsiValue(220),
            current:          Color::AnsiValue(237),
            current_bg:       Color::AnsiValue(251),
            current_match:    Color::AnsiValue(66),
            current_match_bg: Color::AnsiValue(251),
            spinner:          Color::AnsiValue(65),
            info:             Color::AnsiValue(101),
            prompt:           Color::AnsiValue(25),
            cursor:           Color::AnsiValue(161),
            selected:         Color::AnsiValue(168),
            header:           Color::AnsiValue(31),
            border:           Color::AnsiValue(145),
        }
    }

    fn from_options(color: &str) -> Self {
        let mut theme = ColorTheme::dark256();
        for pair in color.split(',') {
            let color: Vec<&str> = pair.split(':').collect();
            if color.len() < 2 {
                theme = match color[0] {
                    "molokai"  => ColorTheme::molokai256(),
                    "light"    => ColorTheme::light256(),
                    "16"       => ColorTheme::default16(),
                    "bw"       => ColorTheme::bw(),
                    "dark" | "default" | _ => ColorTheme::dark256(),
                };
                continue;
            }

            let new_color = if color[1].len() == 7 {
                // 256 color
                let r = u8::from_str_radix(&color[1][1..3], 16).unwrap_or(255);
                let g = u8::from_str_radix(&color[1][3..5], 16).unwrap_or(255);
                let b = u8::from_str_radix(&color[1][5..7], 16).unwrap_or(255);
                Color::Rgb(r, g, b)
            } else {
                Color::AnsiValue(color[1].parse::<u8>().unwrap_or(255))
            };

            match color[0] {
                "fg"               => theme.fg               = new_color,
                "bg"               => theme.bg               = new_color,
                "matched"          => theme.matched          = new_color,
                "matched_bg"       => theme.matched_bg       = new_color,
                "current"          => theme.current          = new_color,
                "current_bg"       => theme.current_bg       = new_color,
                "current_match"    => theme.current_match    = new_color,
                "current_match_bg" => theme.current_match_bg = new_color,
                "spinner"          => theme.spinner          = new_color,
                "info"             => theme.info             = new_color,
                "prompt"           => theme.prompt           = new_color,
                "cursor"           => theme.cursor           = new_color,
                "selected"         => theme.selected         = new_color,
                "header"           => theme.header           = new_color,
                "border"           => theme.border           = new_color,
                _ => {}
            }
        }
        theme
    }

    pub fn normal(&self) -> Attr {
        Attr {
            fg: self.fg,
            bg: self.bg,
            effect: Effect::empty(),
        }
    }

    pub fn matched(&self) -> Attr {
        Attr {
            fg: self.matched,
            bg: self.matched_bg,
            effect: Effect::empty(),
        }
    }

    pub fn current(&self) -> Attr {
        Attr {
            fg: self.current,
            bg: self.current_bg,
            effect: Effect::empty(),
        }
    }

    pub fn current_match(&self) -> Attr {
        Attr {
            fg: self.current_match,
            bg: self.current_match_bg,
            effect: Effect::empty(),
        }
    }

    pub fn spinner(&self) -> Attr {
        Attr {
            fg: self.spinner,
            bg: self.bg,
            effect: Effect::BOLD,
        }
    }

    pub fn info(&self) -> Attr {
        Attr {
            fg: self.info,
            bg: self.bg,
            effect: Effect::empty(),
        }
    }

    pub fn prompt(&self) -> Attr {
        Attr {
            fg: self.prompt,
            bg: self.bg,
            effect: Effect::empty(),
        }
    }

    pub fn cursor(&self) -> Attr {
        Attr {
            fg: self.cursor,
            bg: self.current_bg,
            effect: Effect::empty(),
        }
    }

    pub fn selected(&self) -> Attr {
        Attr {
            fg: self.selected,
            bg: self.current_bg,
            effect: Effect::empty(),
        }
    }

    pub fn header(&self) -> Attr {
        Attr {
            fg: self.header,
            bg: self.bg,
            effect: Effect::empty(),
        }
    }

    pub fn border(&self) -> Attr {
        Attr {
            fg: self.border,
            bg: self.bg,
            effect: Effect::empty(),
        }
    }
}
<|endoftext|>


<commit_before>pub trait XYPair {
    fn as_tuple(&self) -> (int, int);
}

#[deriving(Show, Copy)]
pub struct Point {
    pub x: int,
    pub y: int
}

impl Point {

    pub fn new(x: int, y: int) -> Point {
        Point { x: x, y: y }
    }

    pub fn zero() -> Point {
        Point { x: 0, y: 0 }
    }

    pub fn move_dir(&self, dir: Direction) -> Point {
        *self + dir.as_tuple()
    }

}

impl Add<Point, Point> for Point {
    fn add(self, other: Point) -> Point {
        let (ox, oy) = other.as_tuple();
        Point { x: self.x + ox, y: self.y + oy }
    }
}

impl Add<(int, int), Point> for Point {
    fn add(self, other: (int, int)) -> Point {
        let (ox, oy) = other;
        Point { x: self.x + ox, y: self.y + oy }
    }
}

impl XYPair for Point {
    fn as_tuple(&self) -> (int, int) {
        (self.x, self.y)
    }
}

pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}

impl XYPair for Direction {
    fn as_tuple(&self) -> (int, int) {
        match *self {
            Direction::Up      => (  0, -1),
            Direction::Down    => (  0,  1),
            Direction::Left    => ( -1,  0),
            Direction::Right   => (  1,  0),
        }
    }
}
<commit_msg>Make XYPair generic (XYPair<T>)<commit_after>pub trait XYPair<T> {
    fn as_tuple(&self) -> (T, T);
}

#[deriving(Show, Copy)]
pub struct Point {
    pub x: int,
    pub y: int
}

impl Point {

    pub fn new(x: int, y: int) -> Point {
        Point { x: x, y: y }
    }

    pub fn zero() -> Point {
        Point { x: 0, y: 0 }
    }

    pub fn move_dir(&self, dir: Direction) -> Point {
        *self + dir.as_tuple()
    }

}

impl Add<Point, Point> for Point {
    fn add(self, other: Point) -> Point {
        let (ox, oy) = other.as_tuple();
        Point { x: self.x + ox, y: self.y + oy }
    }
}

impl Add<(int, int), Point> for Point {
    fn add(self, other: (int, int)) -> Point {
        let (ox, oy) = other;
        Point { x: self.x + ox, y: self.y + oy }
    }
}

impl XYPair<int> for Point {
    fn as_tuple(&self) -> (int, int) {
        (self.x, self.y)
    }
}

pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}

impl XYPair<int> for Direction {
    fn as_tuple(&self) -> (int, int) {
        match *self {
            Direction::Up      => (  0, -1),
            Direction::Down    => (  0,  1),
            Direction::Left    => ( -1,  0),
            Direction::Right   => (  1,  0),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

extern crate num;

use self::num::complex::{Complex, Complex32, Complex64};
use std::cmp;
use pointer::CPtr;
use scalar::Scalar;
use vector;
use vector::BlasVector;

pub trait Copy {
    fn copy(x: &BlasVector<Self>, y: &mut BlasVector<Self>);
}

macro_rules! copy_impl(
    ($t: ty, $copy_fn: ident) => (
        impl Copy for $t {
            fn copy(x: &BlasVector<$t>, y: &mut BlasVector<$t>) {
                unsafe {
                    vector::ll::$copy_fn(x.len(),
                        x.as_ptr().as_c_ptr(),  x.inc(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

copy_impl!(f32,       cblas_scopy)
copy_impl!(f64,       cblas_dcopy)
copy_impl!(Complex32, cblas_ccopy)
copy_impl!(Complex64, cblas_zcopy)

pub trait Axpy {
    fn axpy(alpha: Self, x: &BlasVector<Self>, y: &mut BlasVector<Self>);
}

macro_rules! axpy_impl(
    ($t: ty, $update_fn: ident) => (
        impl Axpy for $t {
            fn axpy(alpha: $t, x: &BlasVector<$t>, y: &mut BlasVector<$t>) {
                unsafe {
                    let n = cmp::min(x.len(), y.len());

                    vector::ll::$update_fn(n,
                        (&alpha).as_const(),
                        x.as_ptr().as_c_ptr(), x.inc(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

axpy_impl!(f32,       cblas_saxpy)
axpy_impl!(f64,       cblas_daxpy)
axpy_impl!(Complex32, cblas_caxpy)
axpy_impl!(Complex64, cblas_zaxpy)

#[cfg(test)]
mod axpy_tests {
    extern crate num;
    extern crate test;

    use self::num::complex::Complex;
    use vector::ops::Axpy;

    #[test]
    fn real() {
        let x = vec![1f32,-2f32,3f32,4f32];
        let y = vec![3f32,7f32,-2f32,2f32];
        let mut z = y.clone();

        Axpy::axpy(1f32, &y, &mut z);
        Axpy::axpy(1f32, &x, &mut z);
        assert_eq!(z, vec![7f32,12f32,-1f32,8f32]);
    }

    #[test]
    fn complex() {
        let x = vec![Complex::new(1f32, 1f32), Complex::new(1f32, 3f32)];
        let y = vec![Complex::new(3f32, -2f32), Complex::new(2f32, 3f32)];
        let mut z = x.clone();

        Axpy::axpy(Complex::new(-1f32, 1f32), &y, &mut z);
        assert_eq!(z, vec![Complex::new(0f32, 6f32), Complex::new(-4f32, 2f32)]);
    }

}

pub trait Scal {
    fn scal(alpha: Self, x: &mut BlasVector<Self>);
}

macro_rules! scal_impl(
    ($t: ty, $scal_fn: ident) => (
        impl Scal for $t {
            #[inline]
            fn scal(alpha: $t, x: &mut BlasVector<$t>) {
                unsafe {
                    vector::ll::$scal_fn(x.len(),
                        alpha,
                        x.as_mut_ptr().as_c_ptr(), x.inc());
                }
            }
        }
    );

    ($t: ty, $scal_fn: ident, $real_scal_fn: ident) => (
        impl Scal for $t {
            #[inline]
            fn scal(alpha: $t, x: &mut BlasVector<$t>) {
                if alpha.im == 0.0 {
                    unsafe {
                        vector::ll::$real_scal_fn(x.len(),
                            alpha.re,
                            x.as_mut_ptr().as_c_ptr(), x.inc());
                    }
                } else {
                    unsafe {
                        vector::ll::$scal_fn(x.len(),
                            (&alpha).as_const(),
                            x.as_mut_ptr().as_c_ptr(), x.inc());
                    }
                }
            }
        }
    );
)

scal_impl!(f32, cblas_sscal)
scal_impl!(f64, cblas_dscal)
scal_impl!(Complex32, cblas_cscal, cblas_csscal)
scal_impl!(Complex64, cblas_zscal, cblas_zdscal)

#[cfg(test)]
mod scal_tests {
    extern crate num;
    extern crate test;

    use self::num::complex::Complex;
    use vector::ops::Scal;

    #[test]
    fn real() {
        let mut x = vec![1f32,-2f32,3f32,4f32];

        Scal::scal(-2f32, &mut x);
        assert_eq!(x, vec![-2f32, 4f32, -6f32, -8f32]);
    }

    #[test]
    fn complex() {
        let mut x = vec![Complex::new(1f32, 1f32), Complex::new(1f32, 3f32)];

        Scal::scal(Complex::new(1f32, 1f32), &mut x);
        assert_eq!(x, vec![Complex::new(0f32, 2f32), Complex::new(-2f32, 4f32)]);
    }

    #[test]
    fn complex_real() {
        let mut x = vec![Complex::new(1f32, 1f32), Complex::new(1f32, 3f32)];

        Scal::scal(Complex::new(2f32, 0f32), &mut x);
        assert_eq!(x, vec![Complex::new(2f32, 2f32), Complex::new(2f32, 6f32)]);
    }

}

pub trait Swap {
    fn swap(x: &mut BlasVector<Self>, y: &mut BlasVector<Self>);
}

macro_rules! swap_impl(
    ($t: ty, $swap_fn: ident) => (
        impl Swap for $t {
            fn swap(x: &mut BlasVector<$t>, y: &mut BlasVector<$t>) {
                unsafe {
                    let n = cmp::min(x.len(), y.len());

                    vector::ll::$swap_fn(n,
                        x.as_mut_ptr().as_c_ptr(), x.inc(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

swap_impl!(f32,       cblas_sswap)
swap_impl!(f64,       cblas_dswap)
swap_impl!(Complex32, cblas_cswap)
swap_impl!(Complex64, cblas_zswap)

#[cfg(test)]
mod swap_tests {
    extern crate num;
    extern crate test;

    use self::num::complex::Complex;
    use vector::ops::Swap;

    #[test]
    fn real() {
        let mut x = vec![1f32,-2f32,3f32,4f32];
        let mut y = vec![2f32,-3f32,4f32,1f32];
        let xr = y.clone();
        let yr = x.clone();

        Swap::swap(&mut x, &mut y);
        assert_eq!(x, xr);
        assert_eq!(y, yr);
    }

    #[test]
    fn complex() {
        let mut x = vec![Complex::new(2f32, -3f32)];
        let mut y = vec![Complex::new(-1f32, 4f32)];
        let xr = y.clone();
        let yr = x.clone();

        Swap::swap(&mut x, &mut y);
        assert_eq!(x, xr);
        assert_eq!(y, yr);
    }

}
<commit_msg>Add Dot trait<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

extern crate num;

use self::num::complex::{Complex, Complex32, Complex64};
use std::cmp;
use default::Default;
use pointer::CPtr;
use scalar::Scalar;
use vector;
use vector::BlasVector;

pub trait Copy {
    fn copy(x: &BlasVector<Self>, y: &mut BlasVector<Self>);
}

macro_rules! copy_impl(
    ($t: ty, $copy_fn: ident) => (
        impl Copy for $t {
            fn copy(x: &BlasVector<$t>, y: &mut BlasVector<$t>) {
                unsafe {
                    vector::ll::$copy_fn(x.len(),
                        x.as_ptr().as_c_ptr(),  x.inc(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

copy_impl!(f32,       cblas_scopy)
copy_impl!(f64,       cblas_dcopy)
copy_impl!(Complex32, cblas_ccopy)
copy_impl!(Complex64, cblas_zcopy)

pub trait Axpy {
    fn axpy(alpha: Self, x: &BlasVector<Self>, y: &mut BlasVector<Self>);
}

macro_rules! axpy_impl(
    ($t: ty, $update_fn: ident) => (
        impl Axpy for $t {
            fn axpy(alpha: $t, x: &BlasVector<$t>, y: &mut BlasVector<$t>) {
                unsafe {
                    let n = cmp::min(x.len(), y.len());

                    vector::ll::$update_fn(n,
                        (&alpha).as_const(),
                        x.as_ptr().as_c_ptr(), x.inc(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

axpy_impl!(f32,       cblas_saxpy)
axpy_impl!(f64,       cblas_daxpy)
axpy_impl!(Complex32, cblas_caxpy)
axpy_impl!(Complex64, cblas_zaxpy)

#[cfg(test)]
mod axpy_tests {
    extern crate num;
    extern crate test;

    use self::num::complex::Complex;
    use vector::ops::Axpy;

    #[test]
    fn real() {
        let x = vec![1f32,-2f32,3f32,4f32];
        let y = vec![3f32,7f32,-2f32,2f32];
        let mut z = y.clone();

        Axpy::axpy(1f32, &y, &mut z);
        Axpy::axpy(1f32, &x, &mut z);
        assert_eq!(z, vec![7f32,12f32,-1f32,8f32]);
    }

    #[test]
    fn complex() {
        let x = vec![Complex::new(1f32, 1f32), Complex::new(1f32, 3f32)];
        let y = vec![Complex::new(3f32, -2f32), Complex::new(2f32, 3f32)];
        let mut z = x.clone();

        Axpy::axpy(Complex::new(-1f32, 1f32), &y, &mut z);
        assert_eq!(z, vec![Complex::new(0f32, 6f32), Complex::new(-4f32, 2f32)]);
    }

}

pub trait Scal {
    fn scal(alpha: Self, x: &mut BlasVector<Self>);
}

macro_rules! scal_impl(
    ($t: ty, $scal_fn: ident) => (
        impl Scal for $t {
            #[inline]
            fn scal(alpha: $t, x: &mut BlasVector<$t>) {
                unsafe {
                    vector::ll::$scal_fn(x.len(),
                        alpha,
                        x.as_mut_ptr().as_c_ptr(), x.inc());
                }
            }
        }
    );

    ($t: ty, $scal_fn: ident, $real_scal_fn: ident) => (
        impl Scal for $t {
            #[inline]
            fn scal(alpha: $t, x: &mut BlasVector<$t>) {
                if alpha.im == 0.0 {
                    unsafe {
                        vector::ll::$real_scal_fn(x.len(),
                            alpha.re,
                            x.as_mut_ptr().as_c_ptr(), x.inc());
                    }
                } else {
                    unsafe {
                        vector::ll::$scal_fn(x.len(),
                            (&alpha).as_const(),
                            x.as_mut_ptr().as_c_ptr(), x.inc());
                    }
                }
            }
        }
    );
)

scal_impl!(f32, cblas_sscal)
scal_impl!(f64, cblas_dscal)
scal_impl!(Complex32, cblas_cscal, cblas_csscal)
scal_impl!(Complex64, cblas_zscal, cblas_zdscal)

#[cfg(test)]
mod scal_tests {
    extern crate num;
    extern crate test;

    use self::num::complex::Complex;
    use vector::ops::Scal;

    #[test]
    fn real() {
        let mut x = vec![1f32,-2f32,3f32,4f32];

        Scal::scal(-2f32, &mut x);
        assert_eq!(x, vec![-2f32, 4f32, -6f32, -8f32]);
    }

    #[test]
    fn complex() {
        let mut x = vec![Complex::new(1f32, 1f32), Complex::new(1f32, 3f32)];

        Scal::scal(Complex::new(1f32, 1f32), &mut x);
        assert_eq!(x, vec![Complex::new(0f32, 2f32), Complex::new(-2f32, 4f32)]);
    }

    #[test]
    fn complex_real() {
        let mut x = vec![Complex::new(1f32, 1f32), Complex::new(1f32, 3f32)];

        Scal::scal(Complex::new(2f32, 0f32), &mut x);
        assert_eq!(x, vec![Complex::new(2f32, 2f32), Complex::new(2f32, 6f32)]);
    }

}

pub trait Swap {
    fn swap(x: &mut BlasVector<Self>, y: &mut BlasVector<Self>);
}

macro_rules! swap_impl(
    ($t: ty, $swap_fn: ident) => (
        impl Swap for $t {
            fn swap(x: &mut BlasVector<$t>, y: &mut BlasVector<$t>) {
                unsafe {
                    let n = cmp::min(x.len(), y.len());

                    vector::ll::$swap_fn(n,
                        x.as_mut_ptr().as_c_ptr(), x.inc(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

swap_impl!(f32,       cblas_sswap)
swap_impl!(f64,       cblas_dswap)
swap_impl!(Complex32, cblas_cswap)
swap_impl!(Complex64, cblas_zswap)

#[cfg(test)]
mod swap_tests {
    extern crate num;
    extern crate test;

    use self::num::complex::Complex;
    use vector::ops::Swap;

    #[test]
    fn real() {
        let mut x = vec![1f32,-2f32,3f32,4f32];
        let mut y = vec![2f32,-3f32,4f32,1f32];
        let xr = y.clone();
        let yr = x.clone();

        Swap::swap(&mut x, &mut y);
        assert_eq!(x, xr);
        assert_eq!(y, yr);
    }

    #[test]
    fn complex() {
        let mut x = vec![Complex::new(2f32, -3f32)];
        let mut y = vec![Complex::new(-1f32, 4f32)];
        let xr = y.clone();
        let yr = x.clone();

        Swap::swap(&mut x, &mut y);
        assert_eq!(x, xr);
        assert_eq!(y, yr);
    }

}

pub trait Dot {
    fn dot(x: &BlasVector<Self>, y: &BlasVector<Self>) -> Self;
}

macro_rules! real_dot_impl(
    ($t: ty, $dot_fn: ident) => (
        impl Dot for $t {
            fn dot(x: &BlasVector<$t>, y: &BlasVector<$t>) -> $t {
                unsafe {
                    let n = cmp::min(x.len(), y.len());

                    vector::ll::$dot_fn(n,
                        x.as_ptr().as_c_ptr(), x.inc(),
                        y.as_ptr().as_c_ptr(), y.inc()) as $t
                }
            }
        }
    );
)

macro_rules! complex_dot_impl(
    ($t: ty, $dot_fn: ident) => (
        impl Dot for $t {
            fn dot(x: &BlasVector<$t>, y: &BlasVector<$t>) -> $t {
                let result: $t = Default::zero();

                unsafe {
                    let n = cmp::min(x.len(), y.len());

                    vector::ll::$dot_fn(n,
                        x.as_ptr().as_c_ptr(), x.inc(),
                        y.as_ptr().as_c_ptr(), y.inc(),
                        (&result).as_mut());
                }

                result
            }
        }
    );
)

real_dot_impl!(f32, cblas_sdot)
real_dot_impl!(f64, cblas_ddot)
complex_dot_impl!(Complex32, cblas_cdotu_sub)
complex_dot_impl!(Complex64, cblas_zdotu_sub)

#[cfg(test)]
mod dot_tests {
    extern crate num;
    extern crate test;

    use self::num::complex::Complex;
    use vector::ops::Dot;

    #[test]
    fn real() {
        let x = vec![1f32,-2f32,3f32,4f32];
        let y = vec![1f32,1f32,1f32,1f32];

        let xr: f32 = Dot::dot(&x, &y);
        assert_eq!(xr, 6f32);
    }

    #[test]
    fn complex() {
        let x = vec![Complex::new(1f32, 1f32), Complex::new(1f32, 3f32)];
        let y = vec![Complex::new(1f32, 1f32), Complex::new(1f32, 1f32)];

        let xr: Complex<f32> = Dot::dot(&x, &y);
        assert_eq!(xr, Complex::new(-2f32, 6f32));
    }

}
<|endoftext|>


<commit_before>use verex::Verex;

const A_VEREX_STRING: &'static str = r"(?:a)";

#[test]
fn test_constructors() {
    let verex1: Verex = Verex::new();
    assert_eq!(verex1.source(), r"(?:)");

    let verex2: Verex = Verex::from_string(r"a".to_string());
    assert_eq!(verex2.source(), A_VEREX_STRING);

    let verex3: Verex = Verex::from_str(r"a");
    assert_eq!(verex3.source(), A_VEREX_STRING);
}

#[test]
fn test_add() {
    let mut verex: Verex = Verex::new();
    verex.add(r"a");
    verex.update_source_with_modifiers();
    assert_eq!(verex.source(), A_VEREX_STRING);
}

#[test]
fn test_compile_regex() {
    let mut verex: Verex = Verex::new();
    verex.find(r"a");

    let regex1 = verex.compile().unwrap();
    assert!(regex1.is_match(r"a"));

    let regex2 = verex.regex().unwrap();
    assert!(regex2.is_match(r"a"));
}

#[test]
fn test_i_modifier() {
    let mut verex = Verex::from_str(r"a");
    verex.with_any_case(true);
    assert_eq!(verex.source(), r"(?i:a)");

    let regex = verex.compile().unwrap();
    assert!(regex.is_match(r"a"));
    assert!(regex.is_match(r"A"));
    assert!(!regex.is_match(r"b"));
}

#[test]
fn test_m_modifier() {
    let verex = Verex::new()
                   .start_of_line()
                   .find(r"a")
                   .end_of_line()
                   .search_one_line(false)
                   .clone();
    assert_eq!(verex.source(), r"(?m:^(?:a)$)");

    let regex = verex.compile().unwrap();
    assert!(regex.is_match(r"a"));
    assert!(!regex.is_match(r"aa"));
    assert!(regex.is_match("a\n"));
    assert_eq!(regex.find_iter("a\na").count(), 2);
}

#[test]
fn test_source_and_raw_and_value() {
    let verex: Verex = Verex::from_str(r"a");
    assert_eq!(verex.source(), A_VEREX_STRING);
    assert_eq!(verex.raw(), A_VEREX_STRING);
    assert_eq!(verex.value(), A_VEREX_STRING);
}

#[test]
fn test_any_and_any_of() {
    let mut verex1: Verex = Verex::new();
    verex1.any(r"ab");

    let regex1 = verex1.compile().unwrap();
    assert!(regex1.is_match(r"a"));
    assert!(regex1.is_match(r"b"));
    assert!(!regex1.is_match(r"c"));

    let mut verex2: Verex = Verex::new();
    verex2.any_of(r"ab");

    let regex2 = verex2.compile().unwrap();
    assert!(regex2.is_match(r"a"));
    assert!(regex2.is_match(r"b"));
    assert!(!regex2.is_match(r"c"));
}

#[test]
fn test_anything() {
    let mut verex: Verex = Verex::new();
    verex.anything();
    assert_eq!(verex.source(), r"(?:(.*))");

    let regex = verex.compile().unwrap();
    assert!(regex.is_match(r""));
    assert!(regex.is_match(r"foobar"));
}

#[test]
fn test_anything_but() {
    let mut verex: Verex = Verex::new();
    verex.start_of_line()
         .anything_but("foo")
         .end_of_line();
    assert_eq!(verex.source(), r"(?:^(?:[^foo]*)$)");

    let regex = verex.compile().unwrap();
    assert!(regex.is_match(r""));
    assert!(regex.is_match(r"bar"));
    assert!(!regex.is_match(r"foo"));
    assert!(!regex.is_match(r"foofoo"));
    assert!(!regex.is_match(r"barfoo"));
}

#[test]
fn test_digit() {
    let verex = Verex::new().digit().clone();
    assert_eq!(verex.source(), r"(?:\d)");

    let regex = verex.compile().unwrap();
    assert!(regex.is_match(r"0"));
    assert!(regex.is_match(r"1"));
    assert!(regex.is_match(r"3"));
    assert!(regex.is_match(r"9"));
    assert!(!regex.is_match(r"a"));
    assert!(!regex.is_match(r" "));
    assert!(!regex.is_match(r"?"));
}

#[test]
fn test_find_and_then() {
    let mut verex: Verex = Verex::new();
    verex.find("foo");
    assert_eq!(verex.source(), r"(?:(?:foo))");

    let regex = verex.compile().unwrap();
    assert!(!regex.is_match(r"bar"));
    assert!(regex.is_match(r"foo"));
    assert!(regex.is_match(r"foofoo"));
    assert!(regex.is_match(r"barfoo"));

    // same as find
    let mut verex2: Verex = Verex::new();
    verex2.then("foo");
    assert_eq!(verex2.source(), r"(?:(?:foo))");

    let regex2 = verex2.compile().unwrap();
    assert!(!regex2.is_match(r"bar"));
    assert!(regex2.is_match(r"foo"));
    assert!(regex2.is_match(r"foofoo"));
    assert!(regex2.is_match(r"barfoo"));
}

#[test]
fn test_find_chained() {
    let mut verex: Verex = Verex::new();
    verex.find("foo")
         .then("bar");
    assert_eq!(verex.source(), r"(?:(?:foo)(?:bar))");

    let regex = verex.compile().unwrap();
    assert!(!regex.is_match(r"bar"));
    assert!(!regex.is_match(r"foo"));
    assert!(!regex.is_match(r"barfoo"));
    assert!(regex.is_match(r"foobar"));
}

#[test]
fn test_maybe() {
    let mut verex: Verex = Verex::new();
    verex.start_of_line()
         .maybe(r"a")
         .end_of_line();
    assert_eq!(verex.source(), r"(?:^(?:a)?$)");

    let regex = verex.compile().unwrap();
    assert!(regex.is_match(r""));
    assert!(regex.is_match(r"a"));
    assert!(!regex.is_match(r"foo"));
}

#[test]
fn test_or_and_or_find() {
    let mut verex1 = Verex::new();
    verex1.find(r"a")
          .or()
          .find(r"b");
    assert_eq!(verex1.source(), r"(?:(?:a)|(?:b))");

    let regex1 = verex1.compile().unwrap();
    assert!(regex1.is_match(r"a"));
    assert!(regex1.is_match(r"b"));
    assert!(!regex1.is_match(r"z"));

    let mut verex2 = Verex::new();
    verex2.find(r"a")
          .or_find(r"b");
    assert_eq!(verex2.source(), r"(?:(?:a)|(?:b))");

    let regex2 = verex2.compile().unwrap();
    assert!(regex2.is_match(r"a"));
    assert!(regex2.is_match(r"b"));
    assert!(!regex2.is_match(r"z"));
}

#[test]
fn test_range() {
    let mut verex = Verex::new();
    verex.range(vec![('a', 'z')]);
    assert_eq!(verex.source(), r"(?:[a-z])");

    let regex = verex.compile().unwrap();
    assert!(regex.is_match(r"a"));
    assert!(regex.is_match(r"b"));
    assert!(regex.is_match(r"h"));
    assert!(regex.is_match(r"u"));
    assert!(regex.is_match(r"z"));
    assert!(!regex.is_match(r"A"));
    assert!(!regex.is_match(r"Z"));
}

#[test]
fn test_replace() {
    let verex = Verex::from_str(r"r");
    let replaced = verex.replace(r"foobar", r"z").unwrap();
    assert_eq!(replaced, r"foobaz");
}

#[test]
fn test_something() {
    let mut verex: Verex = Verex::new();
    verex.something();
    assert_eq!(verex.source(), r"(?:(.+))");

    let regex = verex.compile().unwrap();
    assert!(!regex.is_match(r""));
    assert!(regex.is_match(r"foobar"));
}

#[test]
fn test_someting_but() {
    let mut verex: Verex = Verex::new();
    verex.start_of_line()
         .something_but("foo")
         .end_of_line();
    assert_eq!(verex.source(), r"(?:^(?:[^foo]+)$)");

    let regex = verex.compile().unwrap();
    assert!(!regex.is_match(r""));
    assert!(regex.is_match(r"bar"));
    assert!(!regex.is_match(r"foo"));
    assert!(!regex.is_match(r"foofoo"));
    assert!(!regex.is_match(r"barfoo"));
}

#[test]
fn test_word() {
    let mut verex = Verex::new();
    verex.word();
    assert_eq!(verex.source(), r"(?:(?:\w+))");

    let regex = verex.compile().unwrap();
    assert!(regex.is_match(r"word"));
    assert!(regex.is_match(r"w0rd"));
    assert!(!regex.is_match(r"./"));
}

// test the standalone functions
<commit_msg>add test for line_break<commit_after>use verex::Verex;

const A_VEREX_STRING: &'static str = r"(?:a)";

#[test]
fn test_constructors() {
    let verex1: Verex = Verex::new();
    assert_eq!(verex1.source(), r"(?:)");

    let verex2: Verex = Verex::from_string(r"a".to_string());
    assert_eq!(verex2.source(), A_VEREX_STRING);

    let verex3: Verex = Verex::from_str(r"a");
    assert_eq!(verex3.source(), A_VEREX_STRING);
}

#[test]
fn test_add() {
    let mut verex: Verex = Verex::new();
    verex.add(r"a");
    verex.update_source_with_modifiers();
    assert_eq!(verex.source(), A_VEREX_STRING);
}

#[test]
fn test_compile_regex() {
    let mut verex: Verex = Verex::new();
    verex.find(r"a");

    let regex1 = verex.compile().unwrap();
    assert!(regex1.is_match(r"a"));

    let regex2 = verex.regex().unwrap();
    assert!(regex2.is_match(r"a"));
}

#[test]
fn test_i_modifier() {
    let mut verex = Verex::from_str(r"a");
    verex.with_any_case(true);
    assert_eq!(verex.source(), r"(?i:a)");

    let regex = verex.compile().unwrap();
    assert!(regex.is_match(r"a"));
    assert!(regex.is_match(r"A"));
    assert!(!regex.is_match(r"b"));
}

#[test]
fn test_m_modifier() {
    let verex = Verex::new()
                   .start_of_line()
                   .find(r"a")
                   .end_of_line()
                   .search_one_line(false)
                   .clone();
    assert_eq!(verex.source(), r"(?m:^(?:a)$)");

    let regex = verex.compile().unwrap();
    assert!(regex.is_match(r"a"));
    assert!(!regex.is_match(r"aa"));
    assert!(regex.is_match("a\n"));
    assert_eq!(regex.find_iter("a\na").count(), 2);
}

#[test]
fn test_source_and_raw_and_value() {
    let verex: Verex = Verex::from_str(r"a");
    assert_eq!(verex.source(), A_VEREX_STRING);
    assert_eq!(verex.raw(), A_VEREX_STRING);
    assert_eq!(verex.value(), A_VEREX_STRING);
}

#[test]
fn test_any_and_any_of() {
    let mut verex1: Verex = Verex::new();
    verex1.any(r"ab");

    let regex1 = verex1.compile().unwrap();
    assert!(regex1.is_match(r"a"));
    assert!(regex1.is_match(r"b"));
    assert!(!regex1.is_match(r"c"));

    let mut verex2: Verex = Verex::new();
    verex2.any_of(r"ab");

    let regex2 = verex2.compile().unwrap();
    assert!(regex2.is_match(r"a"));
    assert!(regex2.is_match(r"b"));
    assert!(!regex2.is_match(r"c"));
}

#[test]
fn test_anything() {
    let mut verex: Verex = Verex::new();
    verex.anything();
    assert_eq!(verex.source(), r"(?:(.*))");

    let regex = verex.compile().unwrap();
    assert!(regex.is_match(r""));
    assert!(regex.is_match(r"foobar"));
}

#[test]
fn test_anything_but() {
    let mut verex: Verex = Verex::new();
    verex.start_of_line()
         .anything_but("foo")
         .end_of_line();
    assert_eq!(verex.source(), r"(?:^(?:[^foo]*)$)");

    let regex = verex.compile().unwrap();
    assert!(regex.is_match(r""));
    assert!(regex.is_match(r"bar"));
    assert!(!regex.is_match(r"foo"));
    assert!(!regex.is_match(r"foofoo"));
    assert!(!regex.is_match(r"barfoo"));
}

#[test]
fn test_br_and_linebreak() {
    // br
    let or_regex_string = r"(?:(?:\n|(?:\r\n)))";
    let verex1 = Verex::new().br().clone();
    assert_eq!(verex1.source(), or_regex_string);

    let regex1 = verex1.compile().unwrap();
    assert!(regex1.is_match("\n"));
    assert!(regex1.is_match("\r\n"));

    // line_break
    let verex2 = Verex::new().line_break().clone();
    assert_eq!(verex2.source(), or_regex_string);

    let regex2 = verex2.compile().unwrap();
    assert!(regex2.is_match("\n"));
    assert!(regex2.is_match("\r\n"));
}

#[test]
fn test_digit() {
    let verex = Verex::new().digit().clone();
    assert_eq!(verex.source(), r"(?:\d)");

    let regex = verex.compile().unwrap();
    assert!(regex.is_match(r"0"));
    assert!(regex.is_match(r"1"));
    assert!(regex.is_match(r"3"));
    assert!(regex.is_match(r"9"));
    assert!(!regex.is_match(r"a"));
    assert!(!regex.is_match(r" "));
    assert!(!regex.is_match(r"?"));
}

#[test]
fn test_find_and_then() {
    let mut verex: Verex = Verex::new();
    verex.find("foo");
    assert_eq!(verex.source(), r"(?:(?:foo))");

    let regex = verex.compile().unwrap();
    assert!(!regex.is_match(r"bar"));
    assert!(regex.is_match(r"foo"));
    assert!(regex.is_match(r"foofoo"));
    assert!(regex.is_match(r"barfoo"));

    // same as find
    let mut verex2: Verex = Verex::new();
    verex2.then("foo");
    assert_eq!(verex2.source(), r"(?:(?:foo))");

    let regex2 = verex2.compile().unwrap();
    assert!(!regex2.is_match(r"bar"));
    assert!(regex2.is_match(r"foo"));
    assert!(regex2.is_match(r"foofoo"));
    assert!(regex2.is_match(r"barfoo"));
}

#[test]
fn test_find_chained() {
    let mut verex: Verex = Verex::new();
    verex.find("foo")
         .then("bar");
    assert_eq!(verex.source(), r"(?:(?:foo)(?:bar))");

    let regex = verex.compile().unwrap();
    assert!(!regex.is_match(r"bar"));
    assert!(!regex.is_match(r"foo"));
    assert!(!regex.is_match(r"barfoo"));
    assert!(regex.is_match(r"foobar"));
}

#[test]
fn test_maybe() {
    let mut verex: Verex = Verex::new();
    verex.start_of_line()
         .maybe(r"a")
         .end_of_line();
    assert_eq!(verex.source(), r"(?:^(?:a)?$)");

    let regex = verex.compile().unwrap();
    assert!(regex.is_match(r""));
    assert!(regex.is_match(r"a"));
    assert!(!regex.is_match(r"foo"));
}

#[test]
fn test_or_and_or_find() {
    let mut verex1 = Verex::new();
    verex1.find(r"a")
          .or()
          .find(r"b");
    assert_eq!(verex1.source(), r"(?:(?:a)|(?:b))");

    let regex1 = verex1.compile().unwrap();
    assert!(regex1.is_match(r"a"));
    assert!(regex1.is_match(r"b"));
    assert!(!regex1.is_match(r"z"));

    let mut verex2 = Verex::new();
    verex2.find(r"a")
          .or_find(r"b");
    assert_eq!(verex2.source(), r"(?:(?:a)|(?:b))");

    let regex2 = verex2.compile().unwrap();
    assert!(regex2.is_match(r"a"));
    assert!(regex2.is_match(r"b"));
    assert!(!regex2.is_match(r"z"));
}

#[test]
fn test_range() {
    let mut verex = Verex::new();
    verex.range(vec![('a', 'z')]);
    assert_eq!(verex.source(), r"(?:[a-z])");

    let regex = verex.compile().unwrap();
    assert!(regex.is_match(r"a"));
    assert!(regex.is_match(r"b"));
    assert!(regex.is_match(r"h"));
    assert!(regex.is_match(r"u"));
    assert!(regex.is_match(r"z"));
    assert!(!regex.is_match(r"A"));
    assert!(!regex.is_match(r"Z"));
}

#[test]
fn test_replace() {
    let verex = Verex::from_str(r"r");
    let replaced = verex.replace(r"foobar", r"z").unwrap();
    assert_eq!(replaced, r"foobaz");
}

#[test]
fn test_something() {
    let mut verex: Verex = Verex::new();
    verex.something();
    assert_eq!(verex.source(), r"(?:(.+))");

    let regex = verex.compile().unwrap();
    assert!(!regex.is_match(r""));
    assert!(regex.is_match(r"foobar"));
}

#[test]
fn test_someting_but() {
    let mut verex: Verex = Verex::new();
    verex.start_of_line()
         .something_but("foo")
         .end_of_line();
    assert_eq!(verex.source(), r"(?:^(?:[^foo]+)$)");

    let regex = verex.compile().unwrap();
    assert!(!regex.is_match(r""));
    assert!(regex.is_match(r"bar"));
    assert!(!regex.is_match(r"foo"));
    assert!(!regex.is_match(r"foofoo"));
    assert!(!regex.is_match(r"barfoo"));
}

#[test]
fn test_word() {
    let mut verex = Verex::new();
    verex.word();
    assert_eq!(verex.source(), r"(?:(?:\w+))");

    let regex = verex.compile().unwrap();
    assert!(regex.is_match(r"word"));
    assert!(regex.is_match(r"w0rd"));
    assert!(!regex.is_match(r"./"));
}

// test the standalone functions
<|endoftext|>


<commit_before>// Copyright 2016 Philipp Oppermann. See the README.md
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core::ptr::Unique;
use core::fmt;
use spin::Mutex;
use volatile::Volatile;

const BUFFER_HEIGHT: usize = 25;
const BUFFER_WIDTH: usize = 80;

pub static WRITER: Mutex<Writer> = Mutex::new(Writer {
    column_position: 0,
    color_code: ColorCode::new(Color::LightGreen, Color::Black),
    buffer: unsafe { Unique::new(0xb8000 as *mut _) },
});

macro_rules! println {
    ($fmt:expr) => (print!(concat!($fmt, "\n")));
    ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
}

macro_rules! print {
    ($($arg:tt)*) => ({
            $crate::vga_buffer::print(format_args!($($arg)*));
    });
}

pub fn print(args: fmt::Arguments) {
    use core::fmt::Write;
    WRITER.lock().write_fmt(args).unwrap();
}

pub fn clear_screen() {
    for _ in 0..BUFFER_HEIGHT {
        println!("");
    }
}

pub unsafe fn print_error(fmt: fmt::Arguments) {
    use core::fmt::Write;

    let mut writer = Writer {
        column_position: 0,
        color_code: ColorCode::new(Color::Red, Color::Black),
        buffer: Unique::new(0xb8000 as *mut _),
    };
    writer.new_line();
    writer.write_fmt(fmt);
}

#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
pub enum Color {
    Black = 0,
    Blue = 1,
    Green = 2,
    Cyan = 3,
    Red = 4,
    Magenta = 5,
    Brown = 6,
    LightGray = 7,
    DarkGray = 8,
    LightBlue = 9,
    LightGreen = 10,
    LightCyan = 11,
    LightRed = 12,
    Pink = 13,
    Yellow = 14,
    White = 15,
}

pub struct Writer {
    column_position: usize,
    color_code: ColorCode,
    buffer: Unique<Buffer>,
}

impl Writer {
    pub fn write_byte(&mut self, byte: u8) {
        match byte {
            b'\n' => self.new_line(),
            byte => {
                if self.column_position >= BUFFER_WIDTH {
                    self.new_line();
                }
                let row = BUFFER_HEIGHT - 1;
                let col = self.column_position;

                let color_code = self.color_code;

                self.buffer().chars[row][col].write(ScreenChar {
                    ascii_character: byte,
                    color_code: color_code,
                });
                self.column_position += 1;
            }
        }
    }

    fn buffer(&mut self) -> &mut Buffer {
        unsafe { self.buffer.get_mut() }
    }

    fn new_line(&mut self) {
        for row in 1..BUFFER_HEIGHT {
            for col in 0..BUFFER_WIDTH {
                let buffer = self.buffer();
                let character = buffer.chars[row][col].read();
                buffer.chars[row - 1][col].write(character);
            }
        }
        self.clear_row(BUFFER_HEIGHT - 1);
        self.column_position = 0;
    }

    fn clear_row(&mut self, row: usize) {
        let blank = ScreenChar {
            ascii_character: b' ',
            color_code: self.color_code,
        };
        for col in 0..BUFFER_WIDTH {
            self.buffer().chars[row][col].write(blank);
        }
    }
}

impl fmt::Write for Writer {
    fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
        for byte in s.bytes() {
            self.write_byte(byte)
        }
        Ok(())
    }
}

#[derive(Debug, Clone, Copy)]
struct ColorCode(u8);

impl ColorCode {
    const fn new(foreground: Color, background: Color) -> ColorCode {
        ColorCode((background as u8) << 4 | (foreground as u8))
    }
}

#[derive(Debug, Clone, Copy)]
#[repr(C)]
struct ScreenChar {
    ascii_character: u8,
    color_code: ColorCode,
}

struct Buffer {
    chars: [[Volatile<ScreenChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
}
<commit_msg>Make print_error safe by using the global writer<commit_after>// Copyright 2016 Philipp Oppermann. See the README.md
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core::ptr::Unique;
use core::fmt;
use spin::Mutex;
use volatile::Volatile;

const BUFFER_HEIGHT: usize = 25;
const BUFFER_WIDTH: usize = 80;

pub static WRITER: Mutex<Writer> = Mutex::new(Writer {
    column_position: 0,
    color_code: ColorCode::new(Color::LightGreen, Color::Black),
    buffer: unsafe { Unique::new(0xb8000 as *mut _) },
});

macro_rules! println {
    ($fmt:expr) => (print!(concat!($fmt, "\n")));
    ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
}

macro_rules! print {
    ($($arg:tt)*) => ({
            $crate::vga_buffer::print(format_args!($($arg)*));
    });
}

pub fn print(args: fmt::Arguments) {
    use core::fmt::Write;
    WRITER.lock().write_fmt(args).unwrap();
}

pub fn clear_screen() {
    for _ in 0..BUFFER_HEIGHT {
        println!("");
    }
}

pub fn print_error(fmt: fmt::Arguments) {
    use core::fmt::Write;
    use core::mem;

    let mut writer = WRITER.lock();
    let red = ColorCode::new(Color::Red, Color::Black);
    let default_color = mem::replace(&mut writer.color_code, red);
    writer.write_fmt(fmt).unwrap();
    writer.color_code = default_color;
}

#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
pub enum Color {
    Black = 0,
    Blue = 1,
    Green = 2,
    Cyan = 3,
    Red = 4,
    Magenta = 5,
    Brown = 6,
    LightGray = 7,
    DarkGray = 8,
    LightBlue = 9,
    LightGreen = 10,
    LightCyan = 11,
    LightRed = 12,
    Pink = 13,
    Yellow = 14,
    White = 15,
}

pub struct Writer {
    column_position: usize,
    color_code: ColorCode,
    buffer: Unique<Buffer>,
}

impl Writer {
    pub fn write_byte(&mut self, byte: u8) {
        match byte {
            b'\n' => self.new_line(),
            byte => {
                if self.column_position >= BUFFER_WIDTH {
                    self.new_line();
                }
                let row = BUFFER_HEIGHT - 1;
                let col = self.column_position;

                let color_code = self.color_code;

                self.buffer().chars[row][col].write(ScreenChar {
                    ascii_character: byte,
                    color_code: color_code,
                });
                self.column_position += 1;
            }
        }
    }

    fn buffer(&mut self) -> &mut Buffer {
        unsafe { self.buffer.get_mut() }
    }

    fn new_line(&mut self) {
        for row in 1..BUFFER_HEIGHT {
            for col in 0..BUFFER_WIDTH {
                let buffer = self.buffer();
                let character = buffer.chars[row][col].read();
                buffer.chars[row - 1][col].write(character);
            }
        }
        self.clear_row(BUFFER_HEIGHT - 1);
        self.column_position = 0;
    }

    fn clear_row(&mut self, row: usize) {
        let blank = ScreenChar {
            ascii_character: b' ',
            color_code: self.color_code,
        };
        for col in 0..BUFFER_WIDTH {
            self.buffer().chars[row][col].write(blank);
        }
    }
}

impl fmt::Write for Writer {
    fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
        for byte in s.bytes() {
            self.write_byte(byte)
        }
        Ok(())
    }
}

#[derive(Debug, Clone, Copy)]
struct ColorCode(u8);

impl ColorCode {
    const fn new(foreground: Color, background: Color) -> ColorCode {
        ColorCode((background as u8) << 4 | (foreground as u8))
    }
}

#[derive(Debug, Clone, Copy)]
#[repr(C)]
struct ScreenChar {
    ascii_character: u8,
    color_code: ColorCode,
}

struct Buffer {
    chars: [[Volatile<ScreenChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
}
<|endoftext|>


<commit_before>//! Types that do not fit in any module.

#[derive(PartialEq, Eq, Copy, Clone, Show)]
pub struct NumNodes(pub u64);

#[derive(PartialEq, Eq, Copy, Clone, Show)]
pub struct NumVariations(pub u32);

#[derive(PartialEq, Eq, Copy, Clone, Show)]
pub struct PerMill(pub u32);

#[derive(PartialEq, Eq, Copy, Clone, Show)]
pub struct NumCpu(pub u32);

#[derive(PartialEq, Eq, Copy, Clone, Show)]
pub struct NumPlies(pub u32);

#[derive(PartialEq, Eq, Copy, Clone, Show)]
pub struct NumMoves(pub u32);
<commit_msg>Derive PartialOrd and Ord for types<commit_after>//! Types that do not fit in any module.

#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Show)]
pub struct NumNodes(pub u64);

#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Show)]
pub struct NumVariations(pub u32);

#[derive(PartialEq, Eq, Copy, Clone, Show)]
pub struct PerMill(pub u32);

#[derive(PartialEq, Eq, Copy, Clone, Show)]
pub struct NumCpu(pub u32);

#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Show)]
pub struct NumPlies(pub u32);

#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Show)]
pub struct NumMoves(pub u32);
<|endoftext|>