<commit_before>//! Command part of IPC

use std::io::prelude::*;
use std::collections::BTreeMap;

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

use super::channel::{self, ReceiveError};

use registry;
use registry::AccessFlags;

macro_rules! expect_key {
    ($in_json:expr; $name:expr, $typ:ident) => {
        match $in_json.remove($name) {
            Some(key) => match key {
                Json::$typ(var) => var,
                _ => return Err(channel::error_expecting_key($name,
                          stringify!($typ)))
            },
            None => return Err(channel::error_expecting_key($name,
            stringify!($typ)))
        }
    }
}

/// Run a thread reading and replying to queries
pub fn thread<S: Read + Write>(mut stream: S) {
    loop {
        match channel::read_packet(&mut stream) {
            Ok(packet) => {
                trace!("Read packet: {}", encode(&packet)
                    .unwrap_or("<packet that was read already??>".to_string()));
                let reply = reply(packet).unwrap_or_else(|e| e);
                trace!("Writing reply: {}", encode(&reply)
                       .unwrap_or("<a reply which is not writable>".to_string()));
                channel::write_packet(&mut stream, &reply)
                    .expect("response: Unable to reply!");
            },
            Err(read_err) => match read_err {
                ReceiveError::IO(ioerr) => {
                    warn!("Unable to read reply! Closing connection.");
                    debug!("Got IOError: {:?}", ioerr);
                    return;
                },
                ReceiveError::InvalidJson(parse_err) => match parse_err {
                    ParserError::SyntaxError(code, start, end) => {
                        let mut responses = BTreeMap::new();
                        responses.insert("code".to_string(),
                                         Json::String(format!("{:?}", code)));
                        responses.insert("start".to_string(),
                                         Json::U64(start as u64));
                        responses.insert("end".to_string(),
                                         Json::U64(end as u64));
                        channel::write_packet(&mut stream,
                                              &channel::error_json_with(
                                                  "invalid json".to_string(),
                                                  responses))
                            .expect("invalid syntax: Unaable to reply!");
                    }
                    _ => unreachable!()
                }
            }
        }
    }
}

/// Generates the response needed to a given command
/// If the request is invalid it returns an Err.
/// If the request is valid but fails it returns an Ok.
fn reply(json: Json) -> Result<Json, Json> {
    let mut object: BTreeMap<String, Json>;
    if let Json::Object(obj) = json {
        object = obj;
    }
    else {
        return Err(channel::error_json(
            "invalid format - object required".to_string()))
    }

    let request_type = expect_key!(object; "type", String);

    // Converts the string to a str in the most Rustic way possible
    match &*request_type {
        // Registry
        "get" => {
            use std::ops::Deref;
            use registry::RegistryError::*;

            let key = expect_key!(object; "key", String);

            match registry::get_data(&key) {
                Ok(data) => {
                    let (flags, arc) = data.resolve();
                    let mut json = BTreeMap::new();
                    json.insert("flags".to_string(), flags.to_json());
                    // I'd return a Cow<Json> because write_packet needs an
                    // &Json, but I dunno how to move the fields over in a
                    // borrow.
                    json.insert("value".to_string(), arc.deref().clone());
                    return Ok(channel::success_json_with(json));
                },
                Err(err) => match err {
                    KeyNotFound =>
                        return Err(channel::error_json("key not found".to_string())),
                    InvalidOperation|WrongKeyType =>
                        return Err(channel::error_json("invalid operation".to_string())),
                    DecoderError(err) => {
                        error!("Got a decoder error from the registry! {:?}", err);
                        return Err(channel::error_json("key not found".to_string()))
                    }
                }
            }
        },
        "set" => {
            use registry::RegistryError::*;

            let key = expect_key!(&mut object; "key", String);
            let value: Json;
            match object.remove("value") {
                Some(val) => value = val,
                None => return Err(channel::error_expecting_key("value", "any"))
            }

            // TODO FIXME properly implement flags
            let mut applied_flags = AccessFlags::all();
            if let Some(json_flags) = object.get("flags") {
                // Parse custom flags
                let flag_list = try!(json_flags.as_array()
                                     .ok_or(channel::error_expecting_key(
                                         "flags", "string array")));
                let mut flags = AccessFlags::empty();
                for flag in flag_list {
                    let flag_str = try!(flag.as_string()
                                        .ok_or(channel::error_expecting_key(
                                            "flags", "string array")));
                    match flag_str {
                        "read"|"r" => flags.insert(AccessFlags::READ()),
                        "write"|"w" => flags.insert(AccessFlags::WRITE()),
                        _ => return Err(channel::error_json(
                            "Flags can either be 'read' or 'write'".to_string()))
                    }
                }
                applied_flags = flags;
            }
            try!(registry::set_json(key, applied_flags, value)
                 .map_err(|e| match e {
                     InvalidOperation =>
                         channel::error_json("invalid operation 'set'".to_string()),
                     WrongKeyType =>
                         channel::error_json("invalid operation; use 'run'".to_string()),
                     _ => unimplemented!() // TODO clean up registry err enum(s)
                 }));
            Ok(channel::success_json())
        },
        "exists" => {
            let key = expect_key!(&mut object; "key", String);

            let reg_key = registry::contains_key(&key);

            // TODO registry::key_info(key)
            Ok(channel::value_json(Json::Boolean(reg_key)))
        },

        // Commands
        "run" => {
            use registry::RegistryError::*;
            let key = expect_key!(&mut object; "key", String);

            let command = try!(registry::get_command(&key).map_err(|e| match e {
                KeyNotFound => channel::error_json("field not found".to_string()),
                WrongKeyType =>
                    channel::error_json("invalid operation; use 'get/'set'".to_string()),
                // may not be relevant
                InvalidOperation =>
                    channel::error_json("invalid operation; use 'set'".to_string()),
                _ => unimplemented!()
            }));

            command();

            Ok(channel::success_json())
        },

        // Meta/API commands
        "version" => {
            Ok(channel::value_json(Json::U64(super::VERSION)))
        },
        "commands" => {
            Ok(channel::value_json(Json::Array(vec![
                Json::String("get".to_string()),
                Json::String("set".to_string()),
                Json::String("exists".to_string()),
                Json::String("run".to_string()),
                Json::String("version".to_string()),
                Json::String("commands".to_string()) ])))
        },
        _ => Err(channel::error_json("invalid request; see 'commands'".to_string()))
    }
}
<commit_msg>Add ping command<commit_after>//! Command part of IPC

use std::io::prelude::*;
use std::collections::BTreeMap;

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

use super::channel::{self, ReceiveError};

use registry;
use registry::AccessFlags;

macro_rules! expect_key {
    ($in_json:expr; $name:expr, $typ:ident) => {
        match $in_json.remove($name) {
            Some(key) => match key {
                Json::$typ(var) => var,
                _ => return Err(channel::error_expecting_key($name,
                          stringify!($typ)))
            },
            None => return Err(channel::error_expecting_key($name,
            stringify!($typ)))
        }
    }
}

/// Run a thread reading and replying to queries
pub fn thread<S: Read + Write>(mut stream: S) {
    loop {
        match channel::read_packet(&mut stream) {
            Ok(packet) => {
                trace!("Read packet: {}", encode(&packet)
                    .unwrap_or("<packet that was read already??>".to_string()));
                let reply = reply(packet).unwrap_or_else(|e| e);
                trace!("Writing reply: {}", encode(&reply)
                       .unwrap_or("<a reply which is not writable>".to_string()));
                channel::write_packet(&mut stream, &reply)
                    .expect("response: Unable to reply!");
            },
            Err(read_err) => match read_err {
                ReceiveError::IO(ioerr) => {
                    warn!("Unable to read reply! Closing connection.");
                    debug!("Got IOError: {:?}", ioerr);
                    return;
                },
                ReceiveError::InvalidJson(parse_err) => match parse_err {
                    ParserError::SyntaxError(code, start, end) => {
                        let mut responses = BTreeMap::new();
                        responses.insert("code".to_string(),
                                         Json::String(format!("{:?}", code)));
                        responses.insert("start".to_string(),
                                         Json::U64(start as u64));
                        responses.insert("end".to_string(),
                                         Json::U64(end as u64));
                        channel::write_packet(&mut stream,
                                              &channel::error_json_with(
                                                  "invalid json".to_string(),
                                                  responses))
                            .expect("invalid syntax: Unaable to reply!");
                    }
                    _ => unreachable!()
                }
            }
        }
    }
}

/// Generates the response needed to a given command
/// If the request is invalid it returns an Err.
/// If the request is valid but fails it returns an Ok.
pub fn reply(json: Json) -> Result<Json, Json> {
    let mut object: BTreeMap<String, Json>;
    if let Json::Object(obj) = json {
        object = obj;
    }
    else {
        return Err(channel::error_json(
            "invalid format - object required".to_string()))
    }

    let request_type = expect_key!(object; "type", String);

    // Converts the string to a str in the most Rustic way possible
    match &*request_type {
        // Registry
        "get" => {
            use std::ops::Deref;
            use registry::RegistryError::*;

            let key = expect_key!(object; "key", String);

            match registry::get_data(&key) {
                Ok(data) => {
                    let (flags, arc) = data.resolve();
                    let mut json = BTreeMap::new();
                    json.insert("flags".to_string(), flags.to_json());
                    // I'd return a Cow<Json> because write_packet needs an
                    // &Json, but I dunno how to move the fields over in a
                    // borrow.
                    json.insert("value".to_string(), arc.deref().clone());
                    return Ok(channel::success_json_with(json));
                },
                Err(err) => match err {
                    KeyNotFound =>
                        return Err(channel::error_json("key not found".to_string())),
                    InvalidOperation|WrongKeyType =>
                        return Err(channel::error_json("invalid operation".to_string())),
                    DecoderError(err) => {
                        error!("Got a decoder error from the registry! {:?}", err);
                        return Err(channel::error_json("key not found".to_string()))
                    }
                }
            }
        },
        "set" => {
            use registry::RegistryError::*;

            let key = expect_key!(&mut object; "key", String);
            let value: Json;
            match object.remove("value") {
                Some(val) => value = val,
                None => return Err(channel::error_expecting_key("value", "any"))
            }

            // TODO FIXME properly implement flags
            let mut applied_flags = AccessFlags::all();
            if let Some(json_flags) = object.get("flags") {
                // Parse custom flags
                let flag_list = try!(json_flags.as_array()
                                     .ok_or(channel::error_expecting_key(
                                         "flags", "string array")));
                let mut flags = AccessFlags::empty();
                for flag in flag_list {
                    let flag_str = try!(flag.as_string()
                                        .ok_or(channel::error_expecting_key(
                                            "flags", "string array")));
                    match flag_str {
                        "read"|"r" => flags.insert(AccessFlags::READ()),
                        "write"|"w" => flags.insert(AccessFlags::WRITE()),
                        _ => return Err(channel::error_json(
                            "Flags can either be 'read' or 'write'".to_string()))
                    }
                }
                applied_flags = flags;
            }
            try!(registry::set_json(key, applied_flags, value)
                 .map_err(|e| match e {
                     InvalidOperation =>
                         channel::error_json("invalid operation 'set'".to_string()),
                     WrongKeyType =>
                         channel::error_json("invalid operation; use 'run'".to_string()),
                     _ => unimplemented!() // TODO clean up registry err enum(s)
                 }));
            Ok(channel::success_json())
        },
        "exists" => {
            let key = expect_key!(&mut object; "key", String);

            let reg_key = registry::contains_key(&key);

            // TODO registry::key_info(key)
            Ok(channel::value_json(Json::Boolean(reg_key)))
        },

        // Commands
        "run" => {
            use registry::RegistryError::*;
            let key = expect_key!(&mut object; "key", String);

            let command = try!(registry::get_command(&key).map_err(|e| match e {
                KeyNotFound => channel::error_json("field not found".to_string()),
                WrongKeyType =>
                    channel::error_json("invalid operation; use 'get/'set'".to_string()),
                // may not be relevant
                InvalidOperation =>
                    channel::error_json("invalid operation; use 'set'".to_string()),
                _ => unimplemented!()
            }));

            command();

            Ok(channel::success_json())
        },

        // Meta/API commands
        "version" => {
            Ok(channel::value_json(Json::U64(super::VERSION)))
        },

        "commands" => {
            Ok(channel::value_json(Json::Array(vec![
                Json::String("get".to_string()),
                Json::String("set".to_string()),
                Json::String("exists".to_string()),
                Json::String("run".to_string()),
                Json::String("version".to_string()),
                Json::String("commands".to_string()),
                Json::String("ping".to_string())  ])))
        },

        "ping" => {
            Ok(channel::success_json())
        },

        _ => Err(channel::error_json("invalid request; see 'commands'".to_string()))
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

use jsapi::{JSContext, JSObject, JSPropertyDescriptor, JSBool};

pub type JSJitPropertyOp = *const u8;

pub struct JSJitInfo {
    pub op: JSJitPropertyOp,
    pub protoID: u32,
    pub depth: u32,
    pub isInfallible: bool,
    pub isConstant: bool
}

extern {
pub fn JS_ObjectToOuterObject(cx: *mut JSContext,
                              obj: *mut JSObject) -> *mut JSObject;
pub fn JS_WrapPropertyDescriptor(cx: *mut JSContext,
                                 desc: *mut JSPropertyDescriptor) -> JSBool;
}

//pub type JSJitInfo = JSJitInfo_struct;

pub mod bindgen {
    use jsapi::{JSContext, JSObject, JSClass, JSRuntime};
    use libc::{uintptr_t, uint8_t, uint32_t};

    extern {
        pub fn JS_NewObjectWithUniqueType(cx: *mut JSContext, clasp: *const JSClass,
                                          proto: *const JSObject, parent: *const JSObject) -> *mut JSObject;
        pub fn JS_GetAddressableObject(rt: *mut JSRuntime, candidateObj: uintptr_t) -> *mut JSObject;
        pub fn JS_NewUint8ClampedArray(cx: *mut JSContext, nelements: uint32_t) -> *mut JSObject;
        pub fn JS_GetUint8ClampedArrayData(obj: *mut JSObject, cx: *mut JSContext) -> *mut uint8_t;
    }
}
<commit_msg>enable all typed array function<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

use jsapi::{JSContext, JSObject, JSPropertyDescriptor, JSBool};

pub type JSJitPropertyOp = *const u8;

pub struct JSJitInfo {
    pub op: JSJitPropertyOp,
    pub protoID: u32,
    pub depth: u32,
    pub isInfallible: bool,
    pub isConstant: bool
}

extern {
pub fn JS_ObjectToOuterObject(cx: *mut JSContext,
                              obj: *mut JSObject) -> *mut JSObject;
pub fn JS_WrapPropertyDescriptor(cx: *mut JSContext,
                                 desc: *mut JSPropertyDescriptor) -> JSBool;
}

//pub type JSJitInfo = JSJitInfo_struct;

pub mod bindgen {
    use jsapi::{JSContext, JSObject, JSClass, JSRuntime};
    use libc::{uintptr_t, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, c_float, c_double};

    extern {
        pub fn JS_NewObjectWithUniqueType(cx: *mut JSContext, clasp: *const JSClass,
                                          proto: *const JSObject, parent: *const JSObject) -> *mut JSObject;
        pub fn JS_GetAddressableObject(rt: *mut JSRuntime, candidateObj: uintptr_t) -> *mut JSObject;

        pub fn JS_NewInt8Array(cx: *mut JSContext, nelements: uint32_t) -> *mut JSObject;
        pub fn JS_GetInt8ArrayData(obj: *mut JSObject, cx: *mut JSContext) -> *mut int8_t;

        pub fn JS_NewUint8Array(cx: *mut JSContext, nelements: uint32_t) -> *mut JSObject;
        pub fn JS_GetUint8ArrayData(obj: *mut JSObject, cx: *mut JSContext) -> *mut uint8_t;

        pub fn JS_NewUint8ClampedArray(cx: *mut JSContext, nelements: uint32_t) -> *mut JSObject;
        pub fn JS_GetUint8ClampedArrayData(obj: *mut JSObject, cx: *mut JSContext) -> *mut uint8_t;

        pub fn JS_NewInt16Array(cx: *mut JSContext, nelements: uint32_t) -> *mut JSObject;
        pub fn JS_GetInt16ArrayData(obj: *mut JSObject, cx: *mut JSContext) -> *mut int16_t;

        pub fn JS_NewUint16Array(cx: *mut JSContext, nelements: uint32_t) -> *mut JSObject;
        pub fn JS_GetUint16ArrayData(obj: *mut JSObject, cx: *mut JSContext) -> *mut uint16_t;

        pub fn JS_NewInt32Array(cx: *mut JSContext, nelements: uint32_t) -> *mut JSObject;
        pub fn JS_GetInt32ArrayData(obj: *mut JSObject, cx: *mut JSContext) -> *mut int32_t;

        pub fn JS_NewUint32Array(cx: *mut JSContext, nelements: uint32_t) -> *mut JSObject;
        pub fn JS_GetUint32ArrayData(obj: *mut JSObject, cx: *mut JSContext) -> *mut uint32_t;

        pub fn JS_NewFloat32Array(cx: *mut JSContext, nelements: uint32_t) -> *mut JSObject;
        pub fn JS_GetFloat32ArrayData(obj: *mut JSObject, cx: *mut JSContext) -> *mut c_float;

        pub fn JS_NewFloat64Array(cx: *mut JSContext, nelements: uint32_t) -> *mut JSObject;
        pub fn JS_GetFloat64ArrayData(obj: *mut JSObject, cx: *mut JSContext) -> *mut c_double;
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::ffi::{OsStr, OsString};
use std::ops::Deref;

use nmk::container;

fn slice_contains_term<T: Deref<Target = OsStr>>(slice: &[&str], term: Option<T>) -> bool {
    term.as_deref()
        .and_then(OsStr::to_str)
        .map_or(false, |s| slice.contains(&s))
}

fn is_256_color_term(term: Option<OsString>) -> bool {
    const TERM_LIST: &[&str] = &[
        "cygwin",
        "gnome-256color",
        "putty",
        "screen-256color",
        "xterm-256color",
    ];
    slice_contains_term(TERM_LIST, term)
}

fn is_256_color_colorterm(term: Option<OsString>) -> bool {
    const COLORTERM_LIST: &[&str] = &["gnome-terminal", "rxvt-xpm", "xfce4-terminal"];
    slice_contains_term(COLORTERM_LIST, term)
}

pub fn support_256_color() -> bool {
    is_256_color_term(env::var_os("TERM"))
        || is_256_color_colorterm(env::var_os("COLORTERM"))
        || container::is_containerized()
}

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

    fn input(i: &str) -> Option<OsString> {
        Some(OsString::from(i))
    }

    #[test]
    fn test_is_256_term() {
        assert!(is_256_color_term(input("cygwin")));
        assert!(is_256_color_term(input("gnome-256color")));
        assert!(is_256_color_term(input("putty")));
        assert!(is_256_color_term(input("screen-256color")));
        assert!(is_256_color_term(input("xterm-256color")));
        assert!(!is_256_color_term(input("linux")));
        assert!(!is_256_color_term(input("")));
        assert!(!is_256_color_term(None));
    }

    #[test]
    fn test_is_256_colorterm() {
        assert!(is_256_color_colorterm(input("gnome-terminal")));
        assert!(is_256_color_colorterm(input("rxvt-xpm")));
        assert!(is_256_color_colorterm(input("xfce4-terminal")));
        assert!(!is_256_color_colorterm(input("unknown")));
        assert!(!is_256_color_colorterm(input("")));
        assert!(!is_256_color_colorterm(None));
    }
}
<commit_msg>Keep it simple<commit_after>use std::env;

use nmk::container;

fn is_256_color_term<T: AsRef<str>>(term: T) -> bool {
    let term = term.as_ref();
    const TERM_LIST: &[&str] = &[
        "cygwin",
        "gnome-256color",
        "putty",
        "screen-256color",
        "xterm-256color",
    ];
    TERM_LIST.contains(&term)
}

fn is_256_color_colorterm<T: AsRef<str>>(term: T) -> bool {
    let term = term.as_ref();
    const COLORTERM_LIST: &[&str] = &["gnome-terminal", "rxvt-xpm", "xfce4-terminal"];
    COLORTERM_LIST.contains(&term)
}

pub fn support_256_color() -> bool {
    env::var("TERM").iter().any(is_256_color_term)
        || env::var("COLORTERM").iter().any(is_256_color_colorterm)
        || container::is_containerized()
}

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

    #[test]
    fn test_is_256_term() {
        assert!(is_256_color_term("cygwin"));
        assert!(is_256_color_term("gnome-256color"));
        assert!(is_256_color_term("putty"));
        assert!(is_256_color_term("screen-256color"));
        assert!(is_256_color_term("xterm-256color"));
        assert!(!is_256_color_term("linux"));
        assert!(!is_256_color_term(""));
    }

    #[test]
    fn test_is_256_colorterm() {
        assert!(is_256_color_colorterm("gnome-terminal"));
        assert!(is_256_color_colorterm("rxvt-xpm"));
        assert!(is_256_color_colorterm("xfce4-terminal"));
        assert!(!is_256_color_colorterm("unknown"));
        assert!(!is_256_color_colorterm(""));
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::sync::Arc;
use style::gecko_bindings::bindings::Gecko_LoadStyleSheet;
use style::gecko_bindings::structs::{Loader, ServoStyleSheet};
use style::gecko_bindings::sugar::ownership::HasArcFFI;
use style::media_queries::MediaList;
use style::shared_lock::Locked;
use style::stylesheets::{ImportRule, StylesheetLoader as StyleStylesheetLoader};
use style_traits::ToCss;

pub struct StylesheetLoader(*mut Loader, *mut ServoStyleSheet);

impl StylesheetLoader {
    pub fn new(loader: *mut Loader, parent: *mut ServoStyleSheet) -> Self {
        StylesheetLoader(loader, parent)
    }
}

impl StyleStylesheetLoader for StylesheetLoader {
    fn request_stylesheet(
        &self,
        media: MediaList,
        make_import: &mut FnMut(MediaList) -> ImportRule,
        make_arc: &mut FnMut(ImportRule) -> Arc<Locked<ImportRule>>,
    ) -> Arc<Locked<ImportRule>> {
        // TODO(emilio): We probably want to share media representation with
        // Gecko in Stylo.
        //
        // This also allows us to get rid of a bunch of extra work to evaluate
        // and ensure parity, and shouldn't be much Gecko work given we always
        // evaluate them on the main thread.
        //
        // Meanwhile, this works.
        let media_string = media.to_css_string();

        let import = make_import(media);

        // After we get this raw pointer ImportRule will be moved into a lock and Arc
        // and so the Arc<Url> pointer inside will also move,
        // but the Url it points to or the allocating backing the String inside that Url won’t,
        // so this raw pointer will still be valid.
        let (spec_bytes, spec_len): (*const u8, usize) = import.url.as_slice_components();

        let base_url_data = import.url.extra_data.get();
        let arc = make_arc(import);
        unsafe {
            Gecko_LoadStyleSheet(self.0,
                                 self.1,
                                 HasArcFFI::arc_as_borrowed(&arc),
                                 base_url_data,
                                 spec_bytes,
                                 spec_len as u32,
                                 media_string.as_bytes().as_ptr(),
                                 media_string.len() as u32);
        }
        arc
    }
}
<commit_msg>Pass borrowed child stylesheet to Gecko for loading rather than the import rule.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::sync::Arc;
use style::gecko_bindings::bindings::Gecko_LoadStyleSheet;
use style::gecko_bindings::structs::{Loader, ServoStyleSheet};
use style::gecko_bindings::sugar::ownership::HasArcFFI;
use style::media_queries::MediaList;
use style::shared_lock::Locked;
use style::stylesheets::{ImportRule, Stylesheet, StylesheetLoader as StyleStylesheetLoader};
use style_traits::ToCss;

pub struct StylesheetLoader(*mut Loader, *mut ServoStyleSheet);

impl StylesheetLoader {
    pub fn new(loader: *mut Loader, parent: *mut ServoStyleSheet) -> Self {
        StylesheetLoader(loader, parent)
    }
}

impl StyleStylesheetLoader for StylesheetLoader {
    fn request_stylesheet(
        &self,
        media: MediaList,
        make_import: &mut FnMut(MediaList) -> ImportRule,
        make_arc: &mut FnMut(ImportRule) -> Arc<Locked<ImportRule>>,
    ) -> Arc<Locked<ImportRule>> {
        // TODO(emilio): We probably want to share media representation with
        // Gecko in Stylo.
        //
        // This also allows us to get rid of a bunch of extra work to evaluate
        // and ensure parity, and shouldn't be much Gecko work given we always
        // evaluate them on the main thread.
        //
        // Meanwhile, this works.
        let media_string = media.to_css_string();

        let import = make_import(media);

        // After we get this raw pointer ImportRule will be moved into a lock and Arc
        // and so the Arc<Url> pointer inside will also move,
        // but the Url it points to or the allocating backing the String inside that Url won’t,
        // so this raw pointer will still be valid.
        let (spec_bytes, spec_len): (*const u8, usize) = import.url.as_slice_components();

        let base_url_data = import.url.extra_data.get();
        unsafe {
            Gecko_LoadStyleSheet(self.0,
                                 self.1,
                                 Stylesheet::arc_as_borrowed(&import.stylesheet),
                                 base_url_data,
                                 spec_bytes,
                                 spec_len as u32,
                                 media_string.as_bytes().as_ptr(),
                                 media_string.len() as u32);
        }
        make_arc(import)
    }
}
<|endoftext|>


<commit_before>//! Types for the [`m.sticker`] event.
//!
//! [`m.sticker`]: https://spec.matrix.org/v1.2/client-server-api/#msticker

use ruma_macros::EventContent;
use serde::{Deserialize, Serialize};

#[cfg(feature = "unstable-msc3552")]
use super::{
    file::FileContent,
    image::{ImageContent, ThumbnailContent},
    message::MessageContent,
};
use crate::{events::room::ImageInfo, MxcUri};

/// The content of an `m.sticker` event.
///
/// A sticker message.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.sticker", kind = MessageLike)]
pub struct StickerEventContent {
    /// A textual representation or associated description of the sticker image.
    ///
    /// This could be the alt text of the original image, or a message to accompany and further
    /// describe the sticker.
    pub body: String,

    /// Metadata about the image referred to in `url` including a thumbnail representation.
    pub info: ImageInfo,

    /// The URL to the sticker image.
    pub url: Box<MxcUri>,

    /// Extensible-event text representation of the message.
    ///
    /// If present, this should be preferred over the `body` field.
    #[cfg(feature = "unstable-msc3552")]
    #[serde(flatten, skip_serializing_if = "Option::is_none")]
    pub message: Option<MessageContent>,

    /// Extensible-event file content of the message.
    ///
    /// If present, this should be preferred over the `url`, `file` and `info` fields.
    #[cfg(feature = "unstable-msc3552")]
    #[serde(
        rename = "org.matrix.msc1767.file",
        alias = "m.file",
        skip_serializing_if = "Option::is_none"
    )]
    pub file: Option<FileContent>,

    /// Extensible-event image info of the message.
    ///
    /// If present, this should be preferred over the `info` field.
    #[cfg(feature = "unstable-msc3552")]
    #[serde(
        rename = "org.matrix.msc1767.image",
        alias = "m.image",
        skip_serializing_if = "Option::is_none"
    )]
    pub image: Option<Box<ImageContent>>,

    /// Extensible-event thumbnails of the message.
    ///
    /// If present, this should be preferred over the `info` field.
    #[cfg(feature = "unstable-msc3552")]
    #[serde(
        rename = "org.matrix.msc1767.thumbnail",
        alias = "m.thumbnail",
        skip_serializing_if = "Option::is_none"
    )]
    pub thumbnail: Option<Vec<ThumbnailContent>>,

    /// Extensible-event captions of the message.
    #[cfg(feature = "unstable-msc3552")]
    #[serde(
        rename = "org.matrix.msc1767.caption",
        alias = "m.caption",
        with = "super::message::content_serde::as_vec",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    pub caption: Option<MessageContent>,
}

impl StickerEventContent {
    /// Creates a new `StickerEventContent` with the given body, image info and URL.
    pub fn new(body: String, info: ImageInfo, url: Box<MxcUri>) -> Self {
        Self {
            #[cfg(feature = "unstable-msc3552")]
            message: Some(MessageContent::plain(body.clone())),
            #[cfg(feature = "unstable-msc3552")]
            file: Some(FileContent::plain(url.clone(), Some(Box::new((&info).into())))),
            #[cfg(feature = "unstable-msc3552")]
            image: Some(Box::new((&info).into())),
            #[cfg(feature = "unstable-msc3552")]
            thumbnail: ThumbnailContent::from_room_message_content(
                info.thumbnail_source.as_ref(),
                info.thumbnail_info.as_deref(),
            )
            .map(|thumbnail| vec![thumbnail]),
            #[cfg(feature = "unstable-msc3552")]
            caption: None,
            body,
            info,
            url,
        }
    }
}
<commit_msg>fixup! events: Document transitional extensible events<commit_after>//! Types for the [`m.sticker`] event.
//!
//! [`m.sticker`]: https://spec.matrix.org/v1.2/client-server-api/#msticker

use ruma_macros::EventContent;
use serde::{Deserialize, Serialize};

#[cfg(feature = "unstable-msc3552")]
use super::{
    file::FileContent,
    image::{ImageContent, ThumbnailContent},
    message::MessageContent,
};
use crate::{events::room::ImageInfo, MxcUri};

/// The content of an `m.sticker` event.
///
/// A sticker message.
///
/// With the `unstable-msc3552` feature, this type also contains the transitional extensible events
/// format. See the documentation of the [`message`] module for more information.
///
/// [`message`]: super::message
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.sticker", kind = MessageLike)]
pub struct StickerEventContent {
    /// A textual representation or associated description of the sticker image.
    ///
    /// This could be the alt text of the original image, or a message to accompany and further
    /// describe the sticker.
    pub body: String,

    /// Metadata about the image referred to in `url` including a thumbnail representation.
    pub info: ImageInfo,

    /// The URL to the sticker image.
    pub url: Box<MxcUri>,

    /// Extensible-event text representation of the message.
    ///
    /// If present, this should be preferred over the `body` field.
    #[cfg(feature = "unstable-msc3552")]
    #[serde(flatten, skip_serializing_if = "Option::is_none")]
    pub message: Option<MessageContent>,

    /// Extensible-event file content of the message.
    ///
    /// If present, this should be preferred over the `url`, `file` and `info` fields.
    #[cfg(feature = "unstable-msc3552")]
    #[serde(
        rename = "org.matrix.msc1767.file",
        alias = "m.file",
        skip_serializing_if = "Option::is_none"
    )]
    pub file: Option<FileContent>,

    /// Extensible-event image info of the message.
    ///
    /// If present, this should be preferred over the `info` field.
    #[cfg(feature = "unstable-msc3552")]
    #[serde(
        rename = "org.matrix.msc1767.image",
        alias = "m.image",
        skip_serializing_if = "Option::is_none"
    )]
    pub image: Option<Box<ImageContent>>,

    /// Extensible-event thumbnails of the message.
    ///
    /// If present, this should be preferred over the `info` field.
    #[cfg(feature = "unstable-msc3552")]
    #[serde(
        rename = "org.matrix.msc1767.thumbnail",
        alias = "m.thumbnail",
        skip_serializing_if = "Option::is_none"
    )]
    pub thumbnail: Option<Vec<ThumbnailContent>>,

    /// Extensible-event captions of the message.
    #[cfg(feature = "unstable-msc3552")]
    #[serde(
        rename = "org.matrix.msc1767.caption",
        alias = "m.caption",
        with = "super::message::content_serde::as_vec",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    pub caption: Option<MessageContent>,
}

impl StickerEventContent {
    /// Creates a new `StickerEventContent` with the given body, image info and URL.
    pub fn new(body: String, info: ImageInfo, url: Box<MxcUri>) -> Self {
        Self {
            #[cfg(feature = "unstable-msc3552")]
            message: Some(MessageContent::plain(body.clone())),
            #[cfg(feature = "unstable-msc3552")]
            file: Some(FileContent::plain(url.clone(), Some(Box::new((&info).into())))),
            #[cfg(feature = "unstable-msc3552")]
            image: Some(Box::new((&info).into())),
            #[cfg(feature = "unstable-msc3552")]
            thumbnail: ThumbnailContent::from_room_message_content(
                info.thumbnail_source.as_ref(),
                info.thumbnail_info.as_deref(),
            )
            .map(|thumbnail| vec![thumbnail]),
            #[cfg(feature = "unstable-msc3552")]
            caption: None,
            body,
            info,
            url,
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::generate_traffic;
use forge::system_metrics::{MetricsThreshold, SystemMetricsThreshold};
use forge::{NetworkContext, NetworkTest, Result, Test};
use std::time::{SystemTime, UNIX_EPOCH};
use tokio::runtime::Runtime;

pub struct PerformanceBenchmarkWithFN;

impl Test for PerformanceBenchmarkWithFN {
    fn name(&self) -> &'static str {
        "performance benchmark with full nodes"
    }
}

impl NetworkTest for PerformanceBenchmarkWithFN {
    fn run<'t>(&self, ctx: &mut NetworkContext<'t>) -> Result<()> {
        let duration = ctx.global_job.duration;

        let start_timestamp = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .expect("Time went backwards")
            .as_secs();

        let all_fullnodes = ctx
            .swarm()
            .full_nodes()
            .map(|v| v.peer_id())
            .collect::<Vec<_>>();

        // Generate some traffic
        let txn_stat = generate_traffic(ctx, &all_fullnodes, duration, 1)?;
        ctx.report
            .report_txn_stats(self.name().to_string(), &txn_stat, duration);
        // ensure we meet the success criteria
        ctx.check_for_success(&txn_stat, &duration)?;

        let end_timestamp = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .expect("Time went backwards")
            .as_secs();

        let runtime = Runtime::new().unwrap();
        runtime.block_on(ctx.swarm().ensure_no_validator_restart())?;
        runtime.block_on(ctx.swarm().ensure_no_fullnode_restart())?;

        // Threshold of more than 12 CPU cores for 30% of the time
        let cpu_threshold = MetricsThreshold::new(12, 30);
        // Threshold of more than 3 GB of memory for 30% of the time
        let memory_threshold = MetricsThreshold::new(3 * 1024 * 1024 * 1024, 30);
        runtime.block_on(ctx.swarm().ensure_healthy_system_metrics(
            start_timestamp as i64,
            end_timestamp as i64,
            SystemMetricsThreshold::new(cpu_threshold, memory_threshold),
        ))?;
        Ok(())
    }
}
<commit_msg>[Forge] Disable System metrics check as querying prometheus is not stable (#3567)<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::generate_traffic;
use forge::{NetworkContext, NetworkTest, Result, Test};
use tokio::runtime::Runtime;

pub struct PerformanceBenchmarkWithFN;

impl Test for PerformanceBenchmarkWithFN {
    fn name(&self) -> &'static str {
        "performance benchmark with full nodes"
    }
}

impl NetworkTest for PerformanceBenchmarkWithFN {
    fn run<'t>(&self, ctx: &mut NetworkContext<'t>) -> Result<()> {
        let duration = ctx.global_job.duration;

        let all_fullnodes = ctx
            .swarm()
            .full_nodes()
            .map(|v| v.peer_id())
            .collect::<Vec<_>>();

        // Generate some traffic
        let txn_stat = generate_traffic(ctx, &all_fullnodes, duration, 1)?;
        ctx.report
            .report_txn_stats(self.name().to_string(), &txn_stat, duration);
        // ensure we meet the success criteria
        ctx.check_for_success(&txn_stat, &duration)?;

        let runtime = Runtime::new().unwrap();
        runtime.block_on(ctx.swarm().ensure_no_validator_restart())?;
        runtime.block_on(ctx.swarm().ensure_no_fullnode_restart())?;

        // Threshold of more than 12 CPU cores for 30% of the time
        //let cpu_threshold = MetricsThreshold::new(12, 30);
        // Threshold of more than 3 GB of memory for 30% of the time
        // let memory_threshold = MetricsThreshold::new(3 * 1024 * 1024 * 1024, 30);
        // runtime.block_on(ctx.swarm().ensure_healthy_system_metrics(
        //     start_timestamp as i64,
        //     end_timestamp as i64,
        //     SystemMetricsThreshold::new(cpu_threshold, memory_threshold),
        // ))?;
        Ok(())
    }
}
<|endoftext|>


<commit_before>//! A handshake request packet

use super::super::super::deque_buffer::DequeBuffer;
use super::super::super::game_connection::GameConnection; //It's super super super effective!
use super::super::PacketHeader;

/// A packet sent from the client to initiate a handshake
pub struct HandshakePacket {

    pub header: PacketHeader,

    pub protocol_version: u32,

    pub server_address: String,

    pub server_port: u16,

    pub next_state: u32

}

impl HandshakePacket {

    /// Decodes this HandshakePacket
    pub fn decode(header: PacketHeader, connection: &mut GameConnection, buffer: &mut DequeBuffer) -> HandshakePacket {

        let header = header;

        let protocol_result = buffer.read_unsigned_varint_32();

        if protocol_result.is_err() {
            error!("Error reading protocol version");
            connection.disconnect();
        }

        let hostname: String = buffer.read_utf8_string();

        let port: u16 = buffer.read_unsigned_short();

        let next_state_result = buffer.read_unsigned_varint_32();

        if next_state_result.is_err() {
            error!("Invalid next state: {:?}", next_state_result);
            connection.disconnect();
        }

        debug!("Protocol version {}, hostname: {}, port: {}, next_state: {}", protocol_result.unwrap(), hostname, port, next_state_result.unwrap());

        HandshakePacket { header: header, protocol_version: protocol_result.unwrap(), server_address: hostname, server_port: port, next_state: next_state_result.unwrap() }

    }

    pub fn handle(&self, connection: &mut GameConnection) {
        info!("Handling handshake!");
    }

}<commit_msg>Use the handshake packet to set the next state<commit_after>//! A handshake request packet

use super::super::super::deque_buffer::DequeBuffer;
use super::super::super::game_connection::{ConnectionState, GameConnection}; //It's super super super effective!
use super::super::PacketHeader;

/// A packet sent from the client to initiate a handshake
pub struct HandshakePacket {

    pub header: PacketHeader,

    pub protocol_version: u32,

    pub server_address: String,

    pub server_port: u16,

    pub next_state: u32

}

impl HandshakePacket {

    /// Decodes this HandshakePacket
    pub fn decode(header: PacketHeader, connection: &mut GameConnection, buffer: &mut DequeBuffer) -> HandshakePacket {

        let header = header;

        let protocol_result = buffer.read_unsigned_varint_32();

        if protocol_result.is_err() {
            error!("Error reading protocol version");
            connection.disconnect();
        }

        let hostname: String = buffer.read_utf8_string();

        let port: u16 = buffer.read_unsigned_short();

        let next_state_result = buffer.read_unsigned_varint_32();

        if next_state_result.is_err() {
            error!("Invalid next state: {:?}", next_state_result);
            connection.disconnect();
        }

        debug!("Protocol version {}, hostname: {}, port: {}, next_state: {}", protocol_result.unwrap(), hostname, port, next_state_result.unwrap());

        HandshakePacket { header: header, protocol_version: protocol_result.unwrap(), server_address: hostname, server_port: port, next_state: next_state_result.unwrap() }

    }

    /// Handles this HandshakePacket
    pub fn handle(&self, connection: &mut GameConnection) {
        info!("Got a handshake packet!");

        match self.next_state {

            1 => {
                connection.state = ConnectionState::STATUS;
            },
            2 => {
                connection.state = ConnectionState::LOGIN;
            }
            _ => {
                error!("Invalid handshake next state of {}, disconnecting", self.next_state);
                connection.disconnect();
            }

        }
    }

}<|endoftext|>


<commit_before>use std::io;
use std::io::prelude::*;

pub fn main() {
    let stdin = io::stdin();
    let mut floor = 0;
    let mut part2 = None;
    let mut n = 1;
    for line in stdin.lock().lines() {
        for c in line.unwrap().chars() {
            match c {
                '(' => floor += 1,
                ')' => floor -= 1,
                _ => panic!(),
            }
            if floor == -1 && part2 == None {
                part2 = Some(n);
            }
            n += 1;
        }
    }
    println!("part 1: {}", floor);
    println!("part 2: {}", part2.unwrap());
}
<commit_msg>rewrite day1 to be a testable function<commit_after>use std::io;
use std::io::prelude::*;

fn day1<R>(input: R) -> (i32, u32)
    where R: BufRead
{
    let mut part2 = None;
    let mut floor = 0;
    let mut n = 1;
    for line in input.lines() {
        for c in line.unwrap().chars() {
            match c {
                '(' => floor += 1,
                ')' => floor -= 1,
                _ => panic!(),
            }
            if floor == -1 && part2 == None {
                part2 = Some(n);
            }
            n += 1;
        }
    }
    (floor, part2.unwrap())
}

pub fn main() {
    let stdin = io::stdin();
    let (part1, part2) = day1(stdin.lock());
    println!("part 1: {}", part1);
    println!("part 2: {}", part2);
}
<|endoftext|>


<commit_before>//! Space API definitions and serialization.
//!
//! This crate contains all data-related definitions that are present in the Space API
//! (http://spaceapi.net/). It also handles serializing that data to JSON by implementing the
//! [`ToJson`](http://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/trait.ToJson.html)
//! trait for all structs.
//!
//! # Examples
//!
//! You can create a new ``Status`` instance by using the ``new`` constructor method:
//!
//!     let status = Status::new(
//!         "coredump".to_string(),
//!         "https://www.coredump.ch/logo.png".to_string(),
//!         "https://www.coredump.ch/".to_string(),
//!         Location {
//!             address: Optional::Value("Spinnereistrasse 2, 8640 Rapperswil, Switzerland".to_string()),
//!             lat: 47.22936,
//!             lon: 8.82949,
//!         },
//!         Contact {
//!             irc: Optional::Value("irc://freenode.net/#coredump".to_string()),
//!             twitter: Optional::Value("@coredump_ch".to_string()),
//!             foursquare: Optional::Value("525c20e5498e875d8231b1e5".to_string()),
//!             email: Optional::Value("danilo@coredump.ch".to_string()),
//!         },
//!         vec![
//!             "email".to_string(),
//!             "twitter".to_string(),
//!         ],
//!     );
//!
//! To serialize this to `Json`, use the ``ToJson`` trait implementation:
//!
//!     let jsonstatus = status.to_json();
//!
//! You can then create a string from the JSON object:
//!
//!     let stringstatus = jsonstatus.to_string();

extern crate rustc_serialize;

use std::collections::BTreeMap;

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

/// An ``Optional`` can contain ``Optional::Value<T>`` or ``Optional::Absent``.
/// It is similar to an ``Option``, but ``Optional::Absent`` means it will be
/// omitted when serialized, while ``None`` will be serialized to ``null``.
#[derive(Debug, Copy, Clone)]
pub enum Optional<T> {
    Value(T),
    Absent,
}

impl<T> Optional<T> {

    /// Applies a function to the contained value or returns a default.  see
    /// [`std::option::Option<T>::map_or`](http://doc.rust-lang.org/std/option/enum.Option.html#method.map_or)
    pub fn map_or<U, F: FnOnce(T) -> U>(self, def: U, f: F) -> U {
        match self {
            Optional::Value(v) => f(v),
            Optional::Absent => def,
        }
    }

    pub fn as_mut<'r>(&'r mut self) -> Optional<&'r mut T> {
        match *self {
            Optional::Value(ref mut x) => Optional::Value(x),
            Optional::Absent => Optional::Absent
        }
    }

    pub fn as_ref<'r>(&'r self) -> Optional<&'r T> {
        match *self {
            Optional::Value(ref x) => Optional::Value(x),
            Optional::Absent => Optional::Absent
        }
    }
}

pub struct Location {
    pub address: Optional<String>,
    pub lat: f64,
    pub lon: f64,
}

pub struct Spacefed {
    pub spacenet: bool,
    pub spacesaml: bool,
    pub spacephone: bool,
}

pub struct Icon {
    pub open: String,
    pub close: String,
}

pub struct State {
    pub open: Option<bool>,
    pub lastchange: Optional<u64>,
    pub trigger_person: Optional<String>,
    pub message: Optional<String>,
    pub icon: Optional<Icon>,
}

pub struct Event {
    pub name: String,
    pub _type: String,
    pub timestamp: u64,
    pub extra: Optional<String>,
}

pub struct Contact {
    pub irc: Optional<String>,
    pub twitter: Optional<String>,
    pub foursquare: Optional<String>,
    pub email: Optional<String>,
}

pub struct Feed {
    pub _type: Optional<String>,
    pub url: String,
}

pub struct Feeds {
    pub blog: Optional<Feed>,
    pub wiki: Optional<Feed>,
    pub calendar: Optional<Feed>,
    pub flickr: Optional<Feed>,
}

pub struct Sensors {
    pub people_now_present: Optional<Vec<PeopleNowPresentSensor>>,
    pub temperature: Optional<Vec<TemperatureSensor>>,
}

pub struct PeopleNowPresentSensor {
    pub value: u32,
    pub location: Optional<String>,
    pub name: Optional<String>,
    pub names: Optional<Vec<String>>,
    pub description: Optional<String>,
}

pub struct TemperatureSensor {
    pub value: f32,
    pub unit: String,
    pub location: String,
    pub name: Optional<String>,
    pub description: Optional<String>,
}

pub struct Cache {
    pub schedule: String,
}

pub struct RadioShow {
    pub name: String,
    pub url: String,
    pub _type: String,
    pub start: String,
    pub end: String,
}

/// The main Space API status object.
pub struct Status {

    // Hackerspace properties
    pub api: String,
    pub space: String,
    pub logo: String,
    pub url: String,
    pub location: Location,
    pub contact: Contact,

    // Hackerspace features / projects
    pub spacefed: Optional<Spacefed>,
    pub projects: Optional<Vec<String>>,
    pub cam: Optional<Vec<String>>,
    pub feeds: Optional<Feeds>,
    pub events: Optional<Vec<Event>>,
    pub radio_show: Optional<Vec<RadioShow>>,

    // SpaceAPI internal usage
    pub cache: Optional<Cache>,
    pub issue_report_channels: Vec<String>,

    // Mutable data
    pub state: State,
    pub sensors: Optional<Sensors>,

}

impl Status {

    /// Create a new Status object with only the minimum amount of fields.
    pub fn new(space: String, logo: String, url: String, location: Location, contact: Contact, issue_report_channels: Vec<String>) -> Status {
        Status {
            api: "0.13".to_string(),
            space: space,
            logo: logo,
            url: url,
            location: location,
            contact: contact,

            spacefed: Optional::Absent,
            projects: Optional::Absent,
            cam: Optional::Absent,
            feeds: Optional::Absent,
            events: Optional::Absent,
            radio_show: Optional::Absent,

            cache: Optional::Absent,
            issue_report_channels: issue_report_channels,

            state: State {
                open: None,
                lastchange: Optional::Absent,
                trigger_person: Optional::Absent,
                message: Optional::Absent,
                icon: Optional::Absent,
            },
            sensors: Optional::Absent,
        }
    }

}

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

        d.insert("api".to_string(), self.api.to_json());
        d.insert("space".to_string(), self.space.to_json());
        d.insert("logo".to_string(), self.logo.to_json());
        d.insert("url".to_string(), self.url.to_json());
        d.insert("location".to_string(), self.location.to_json());
        d.insert("contact".to_string(), self.contact.to_json());

        self.spacefed.as_ref().map_or((), |v| { d.insert("spacefed".to_string(), v.to_json()); } );
        self.projects.as_ref().map_or((), |v| { d.insert("projects".to_string(), v.to_json()); });
        self.cam.as_ref().map_or((), |v| { d.insert("cam".to_string(), v.to_json()); });
        self.feeds.as_ref().map_or((), |v| { d.insert("feeds".to_string(), v.to_json()); });
        self.events.as_ref().map_or((), |v| { d.insert("events".to_string(), v.to_json()); });
        self.radio_show.as_ref().map_or((), |v| { d.insert("radio_show".to_string(), v.to_json()); });

        self.cache.as_ref().map_or((), |v| { d.insert("cache".to_string(), v.to_json()); });
        d.insert("issue_report_channels".to_string(), self.issue_report_channels.to_json());

        d.insert("state".to_string(), self.state.to_json());
        self.sensors.as_ref().map_or((), |v| { d.insert("sensors".to_string(), v.to_json()); });

        Json::Object(d)
    }
}

impl ToJson for Location {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("lat".to_string(), self.lat.to_json());
        d.insert("lon".to_string(), self.lon.to_json());
        match self.address {
            Optional::Value(ref address) => {
                d.insert("address".to_string(), address.to_json());
            },
            Optional::Absent => (),
        };
        Json::Object(d)
    }
}

impl ToJson for Spacefed {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("spacenet".to_string(), self.spacenet.to_json());
        d.insert("spacesaml".to_string(), self.spacesaml.to_json());
        d.insert("spacephone".to_string(), self.spacephone.to_json());
        Json::Object(d)
    }
}

impl ToJson for Icon {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("open".to_string(), self.open.to_json());
        d.insert("close".to_string(), self.close.to_json());
        Json::Object(d)
    }
}

impl ToJson for State {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("open".to_string(), self.open.to_json());
        self.lastchange.as_ref().map_or((), |v| { d.insert("lastchange".to_string(), v.to_json()); });
        self.trigger_person.as_ref().map_or((), |v| { d.insert("trigger_person".to_string(), v.to_json()); });
        self.message.as_ref().map_or((), |v| { d.insert("message".to_string(), v.to_json()); });
        self.icon.as_ref().map_or((), |v| { d.insert("icon".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Event {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("name".to_string(), self.name.to_json());
        d.insert("type".to_string(), self._type.to_json());
        d.insert("timestamp".to_string(), self.timestamp.to_json());
        self.extra.as_ref().map_or((), |v| { d.insert("extra".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Contact {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        self.irc.as_ref().map_or((), |v| { d.insert("irc".to_string(), v.to_json()); });
        self.twitter.as_ref().map_or((), |v| { d.insert("twitter".to_string(), v.to_json()); });
        self.foursquare.as_ref().map_or((), |v| { d.insert("foursquare".to_string(), v.to_json()); });
        self.email.as_ref().map_or((), |v| { d.insert("email".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Feed {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("url".to_string(), self.url.to_json());
        self._type.as_ref().map_or((), |v| { d.insert("type".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Feeds {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        self.blog.as_ref().map_or((), |v| { d.insert("blog".to_string(), v.to_json()); });
        self.wiki.as_ref().map_or((), |v| { d.insert("wiki".to_string(), v.to_json()); });
        self.calendar.as_ref().map_or((), |v| { d.insert("calendar".to_string(), v.to_json()); });
        self.flickr.as_ref().map_or((), |v| { d.insert("flickr".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Sensors {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        self.people_now_present.as_ref().map_or((), |v| { d.insert("people_now_present".to_string(), v.to_json()); });
        self.temperature.as_ref().map_or((), |v| { d.insert("temperature".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for PeopleNowPresentSensor {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("value".to_string(), self.value.to_json());
        self.location.as_ref().map_or((), |v| { d.insert("location".to_string(), v.to_json()); });
        self.name.as_ref().map_or((), |v| { d.insert("name".to_string(), v.to_json()); });
        self.names.as_ref().map_or((), |v| { d.insert("names".to_string(), v.to_json()); });
        self.description.as_ref().map_or((), |v| { d.insert("description".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for TemperatureSensor {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("value".to_string(), self.value.to_json());
        d.insert("unit".to_string(), self.unit.to_json());
        d.insert("location".to_string(), self.location.to_json());
        self.name.as_ref().map_or((), |v| { d.insert("name".to_string(), v.to_json()); });
        self.description.as_ref().map_or((), |v| { d.insert("description".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Cache {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("schedule".to_string(), self.schedule.to_json());
        Json::Object(d)
    }
}

impl ToJson for RadioShow {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("name".to_string(), self.name.to_json());
        d.insert("url".to_string(), self.url.to_json());
        d.insert("type".to_string(), self._type.to_json());
        d.insert("start".to_string(), self.start.to_json()); d.insert("end".to_string(), self.end.to_json());
        Json::Object(d)
    }
}
<commit_msg>Fixed doctests<commit_after>//! Space API definitions and serialization.
//!
//! This crate contains all data-related definitions that are present in the Space API
//! (http://spaceapi.net/). It also handles serializing that data to JSON by implementing the
//! [`ToJson`](http://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/trait.ToJson.html)
//! trait for all structs.
//!
//! # Examples
//!
//! You can create a new ``Status`` instance by using the ``new()`` constructor method. To serialize
//! this to [``Json``](http://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/enum.Json.html), use
//! the [`ToJson`](http://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/trait.ToJson.html)
//! trait implementation. You can then create a string from the resulting object.
//!
//!     # extern crate rustc_serialize;
//!     # extern crate spaceapi;
//!     # use spaceapi::{Status, Location, Contact, Optional};
//!     use rustc_serialize::json::ToJson;
//!
//!     # fn main() {
//!     let status = Status::new(
//!         "coredump".to_string(),
//!         "https://www.coredump.ch/logo.png".to_string(),
//!         "https://www.coredump.ch/".to_string(),
//!         Location {
//!             address: Optional::Value("Spinnereistrasse 2, 8640 Rapperswil, Switzerland".to_string()),
//!             lat: 47.22936,
//!             lon: 8.82949,
//!         },
//!         Contact {
//!             irc: Optional::Value("irc://freenode.net/#coredump".to_string()),
//!             twitter: Optional::Value("@coredump_ch".to_string()),
//!             foursquare: Optional::Value("525c20e5498e875d8231b1e5".to_string()),
//!             email: Optional::Value("danilo@coredump.ch".to_string()),
//!         },
//!         vec![
//!             "email".to_string(),
//!             "twitter".to_string(),
//!         ],
//!     );
//!
//!     let jsonstatus = status.to_json();
//!     let stringstatus = jsonstatus.to_string();
//!     # }

extern crate rustc_serialize;

use std::collections::BTreeMap;

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

/// An ``Optional`` can contain ``Optional::Value<T>`` or ``Optional::Absent``.
/// It is similar to an ``Option``, but ``Optional::Absent`` means it will be
/// omitted when serialized, while ``None`` will be serialized to ``null``.
#[derive(Debug, Copy, Clone)]
pub enum Optional<T> {
    Value(T),
    Absent,
}

impl<T> Optional<T> {

    /// Applies a function to the contained value or returns a default.  see
    /// [`std::option::Option<T>::map_or`](http://doc.rust-lang.org/std/option/enum.Option.html#method.map_or)
    pub fn map_or<U, F: FnOnce(T) -> U>(self, def: U, f: F) -> U {
        match self {
            Optional::Value(v) => f(v),
            Optional::Absent => def,
        }
    }

    pub fn as_mut<'r>(&'r mut self) -> Optional<&'r mut T> {
        match *self {
            Optional::Value(ref mut x) => Optional::Value(x),
            Optional::Absent => Optional::Absent
        }
    }

    pub fn as_ref<'r>(&'r self) -> Optional<&'r T> {
        match *self {
            Optional::Value(ref x) => Optional::Value(x),
            Optional::Absent => Optional::Absent
        }
    }
}

pub struct Location {
    pub address: Optional<String>,
    pub lat: f64,
    pub lon: f64,
}

pub struct Spacefed {
    pub spacenet: bool,
    pub spacesaml: bool,
    pub spacephone: bool,
}

pub struct Icon {
    pub open: String,
    pub close: String,
}

pub struct State {
    pub open: Option<bool>,
    pub lastchange: Optional<u64>,
    pub trigger_person: Optional<String>,
    pub message: Optional<String>,
    pub icon: Optional<Icon>,
}

pub struct Event {
    pub name: String,
    pub _type: String,
    pub timestamp: u64,
    pub extra: Optional<String>,
}

pub struct Contact {
    pub irc: Optional<String>,
    pub twitter: Optional<String>,
    pub foursquare: Optional<String>,
    pub email: Optional<String>,
}

pub struct Feed {
    pub _type: Optional<String>,
    pub url: String,
}

pub struct Feeds {
    pub blog: Optional<Feed>,
    pub wiki: Optional<Feed>,
    pub calendar: Optional<Feed>,
    pub flickr: Optional<Feed>,
}

pub struct Sensors {
    pub people_now_present: Optional<Vec<PeopleNowPresentSensor>>,
    pub temperature: Optional<Vec<TemperatureSensor>>,
}

pub struct PeopleNowPresentSensor {
    pub value: u32,
    pub location: Optional<String>,
    pub name: Optional<String>,
    pub names: Optional<Vec<String>>,
    pub description: Optional<String>,
}

pub struct TemperatureSensor {
    pub value: f32,
    pub unit: String,
    pub location: String,
    pub name: Optional<String>,
    pub description: Optional<String>,
}

pub struct Cache {
    pub schedule: String,
}

pub struct RadioShow {
    pub name: String,
    pub url: String,
    pub _type: String,
    pub start: String,
    pub end: String,
}

/// The main Space API status object.
pub struct Status {

    // Hackerspace properties
    pub api: String,
    pub space: String,
    pub logo: String,
    pub url: String,
    pub location: Location,
    pub contact: Contact,

    // Hackerspace features / projects
    pub spacefed: Optional<Spacefed>,
    pub projects: Optional<Vec<String>>,
    pub cam: Optional<Vec<String>>,
    pub feeds: Optional<Feeds>,
    pub events: Optional<Vec<Event>>,
    pub radio_show: Optional<Vec<RadioShow>>,

    // SpaceAPI internal usage
    pub cache: Optional<Cache>,
    pub issue_report_channels: Vec<String>,

    // Mutable data
    pub state: State,
    pub sensors: Optional<Sensors>,

}

impl Status {

    /// Create a new Status object with only the minimum amount of fields.
    pub fn new(space: String, logo: String, url: String, location: Location, contact: Contact, issue_report_channels: Vec<String>) -> Status {
        Status {
            api: "0.13".to_string(),
            space: space,
            logo: logo,
            url: url,
            location: location,
            contact: contact,

            spacefed: Optional::Absent,
            projects: Optional::Absent,
            cam: Optional::Absent,
            feeds: Optional::Absent,
            events: Optional::Absent,
            radio_show: Optional::Absent,

            cache: Optional::Absent,
            issue_report_channels: issue_report_channels,

            state: State {
                open: None,
                lastchange: Optional::Absent,
                trigger_person: Optional::Absent,
                message: Optional::Absent,
                icon: Optional::Absent,
            },
            sensors: Optional::Absent,
        }
    }

}

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

        d.insert("api".to_string(), self.api.to_json());
        d.insert("space".to_string(), self.space.to_json());
        d.insert("logo".to_string(), self.logo.to_json());
        d.insert("url".to_string(), self.url.to_json());
        d.insert("location".to_string(), self.location.to_json());
        d.insert("contact".to_string(), self.contact.to_json());

        self.spacefed.as_ref().map_or((), |v| { d.insert("spacefed".to_string(), v.to_json()); } );
        self.projects.as_ref().map_or((), |v| { d.insert("projects".to_string(), v.to_json()); });
        self.cam.as_ref().map_or((), |v| { d.insert("cam".to_string(), v.to_json()); });
        self.feeds.as_ref().map_or((), |v| { d.insert("feeds".to_string(), v.to_json()); });
        self.events.as_ref().map_or((), |v| { d.insert("events".to_string(), v.to_json()); });
        self.radio_show.as_ref().map_or((), |v| { d.insert("radio_show".to_string(), v.to_json()); });

        self.cache.as_ref().map_or((), |v| { d.insert("cache".to_string(), v.to_json()); });
        d.insert("issue_report_channels".to_string(), self.issue_report_channels.to_json());

        d.insert("state".to_string(), self.state.to_json());
        self.sensors.as_ref().map_or((), |v| { d.insert("sensors".to_string(), v.to_json()); });

        Json::Object(d)
    }
}

impl ToJson for Location {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("lat".to_string(), self.lat.to_json());
        d.insert("lon".to_string(), self.lon.to_json());
        match self.address {
            Optional::Value(ref address) => {
                d.insert("address".to_string(), address.to_json());
            },
            Optional::Absent => (),
        };
        Json::Object(d)
    }
}

impl ToJson for Spacefed {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("spacenet".to_string(), self.spacenet.to_json());
        d.insert("spacesaml".to_string(), self.spacesaml.to_json());
        d.insert("spacephone".to_string(), self.spacephone.to_json());
        Json::Object(d)
    }
}

impl ToJson for Icon {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("open".to_string(), self.open.to_json());
        d.insert("close".to_string(), self.close.to_json());
        Json::Object(d)
    }
}

impl ToJson for State {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("open".to_string(), self.open.to_json());
        self.lastchange.as_ref().map_or((), |v| { d.insert("lastchange".to_string(), v.to_json()); });
        self.trigger_person.as_ref().map_or((), |v| { d.insert("trigger_person".to_string(), v.to_json()); });
        self.message.as_ref().map_or((), |v| { d.insert("message".to_string(), v.to_json()); });
        self.icon.as_ref().map_or((), |v| { d.insert("icon".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Event {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("name".to_string(), self.name.to_json());
        d.insert("type".to_string(), self._type.to_json());
        d.insert("timestamp".to_string(), self.timestamp.to_json());
        self.extra.as_ref().map_or((), |v| { d.insert("extra".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Contact {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        self.irc.as_ref().map_or((), |v| { d.insert("irc".to_string(), v.to_json()); });
        self.twitter.as_ref().map_or((), |v| { d.insert("twitter".to_string(), v.to_json()); });
        self.foursquare.as_ref().map_or((), |v| { d.insert("foursquare".to_string(), v.to_json()); });
        self.email.as_ref().map_or((), |v| { d.insert("email".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Feed {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("url".to_string(), self.url.to_json());
        self._type.as_ref().map_or((), |v| { d.insert("type".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Feeds {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        self.blog.as_ref().map_or((), |v| { d.insert("blog".to_string(), v.to_json()); });
        self.wiki.as_ref().map_or((), |v| { d.insert("wiki".to_string(), v.to_json()); });
        self.calendar.as_ref().map_or((), |v| { d.insert("calendar".to_string(), v.to_json()); });
        self.flickr.as_ref().map_or((), |v| { d.insert("flickr".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Sensors {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        self.people_now_present.as_ref().map_or((), |v| { d.insert("people_now_present".to_string(), v.to_json()); });
        self.temperature.as_ref().map_or((), |v| { d.insert("temperature".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for PeopleNowPresentSensor {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("value".to_string(), self.value.to_json());
        self.location.as_ref().map_or((), |v| { d.insert("location".to_string(), v.to_json()); });
        self.name.as_ref().map_or((), |v| { d.insert("name".to_string(), v.to_json()); });
        self.names.as_ref().map_or((), |v| { d.insert("names".to_string(), v.to_json()); });
        self.description.as_ref().map_or((), |v| { d.insert("description".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for TemperatureSensor {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("value".to_string(), self.value.to_json());
        d.insert("unit".to_string(), self.unit.to_json());
        d.insert("location".to_string(), self.location.to_json());
        self.name.as_ref().map_or((), |v| { d.insert("name".to_string(), v.to_json()); });
        self.description.as_ref().map_or((), |v| { d.insert("description".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Cache {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("schedule".to_string(), self.schedule.to_json());
        Json::Object(d)
    }
}

impl ToJson for RadioShow {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("name".to_string(), self.name.to_json());
        d.insert("url".to_string(), self.url.to_json());
        d.insert("type".to_string(), self._type.to_json());
        d.insert("start".to_string(), self.start.to_json()); d.insert("end".to_string(), self.end.to_json());
        Json::Object(d)
    }
}
<|endoftext|>