<commit_before>mod actions;
mod core;
pub mod commands;

pub use self::actions::movement::MovementError;

pub use self::core::action::{Action, ActionErr};
pub use self::core::container::{Container, ContainerType, Handle, Layout};
pub use self::core::tree::{Direction, TreeError};
use self::core::InnerTree;

use petgraph::graph::NodeIndex;
use rustc_serialize::json::{Json, ToJson};

use std::sync::{Mutex, MutexGuard, TryLockError};

/// A wrapper around tree, to hide its methods
pub struct Tree(TreeGuard);
/// Mutex guard around the tree
pub type TreeGuard = MutexGuard<'static, LayoutTree>;
/// Error for trying to lock the tree
pub type TreeErr = TryLockError<TreeGuard>;
/// Result for locking the tree
pub type TreeResult = Result<MutexGuard<'static, LayoutTree>, TreeErr>;

#[derive(Debug)]
pub struct LayoutTree {
    tree: InnerTree,
    active_container: Option<NodeIndex>
}

lazy_static! {
    static ref TREE: Mutex<LayoutTree> = {
        Mutex::new(LayoutTree {
            tree: InnerTree::new(),
            active_container: None
        })
    };
    static ref PREV_ACTION: Mutex<Option<Action>> = Mutex::new(None);
}

impl ToJson for LayoutTree {
    fn to_json(&self) -> Json {
        use std::collections::BTreeMap;
        fn node_to_json(node_ix: NodeIndex, tree: &LayoutTree) -> Json {
            match &tree.tree[node_ix] {
                &Container::Workspace { ref name, .. } => {
                    let mut inner_map = BTreeMap::new();
                    let children = tree.tree.children_of(node_ix).iter()
                        .map(|node| node_to_json(*node, tree)).collect();
                    inner_map.insert(format!("Workspace {}", name), Json::Array(children));
                    return Json::Object(inner_map);
                }
                &Container::Container { ref layout, id, .. } => {
                    let mut inner_map = BTreeMap::new();
                    let children = tree.tree.children_of(node_ix).iter()
                        .map(|node| node_to_json(*node, tree)).collect();
                    inner_map.insert(format!("Container w/ layout {:?} and id {:?}", layout, id),
                                     Json::Array(children));
                    return Json::Object(inner_map);
                }
                &Container::View { ref handle, id, .. } => {
                    return Json::String(format!("View: title: \"{:?}\", class: \"{:?}\", id: {}",
                                                handle.get_title(), handle.get_class(), id));
                },
                ref container => {
                    let mut inner_map = BTreeMap::new();
                    let children = tree.tree.children_of(node_ix).iter()
                        .map(|node| node_to_json(*node, tree)).collect();
                    inner_map.insert(format!("{:?}", container.get_type()),
                                     Json::Array(children));
                    return Json::Object(inner_map)
                }
            }
        }
        return node_to_json(self.tree.root_ix(), self);
    }
}

/// Attempts to lock the tree. If the Result is Err, then the lock could
/// not be returned at this time, already locked.
pub fn try_lock_tree() -> Result<Tree, TreeErr> {
    let tree = try!(TREE.try_lock());
    Ok(Tree(tree))
}

/// Attempts to lock the action mutex. If the Result is Err, then the lock could
/// not be returned at this time, already locked.
pub fn try_lock_action() -> Result<MutexGuard<'static, Option<Action>>,
                                 TryLockError<MutexGuard<'static,
                                                         Option<Action>>>> {
    PREV_ACTION.try_lock()
}
<commit_msg>Exposed FocusError outside of layout/<commit_after>mod actions;
mod core;
pub mod commands;

pub use self::actions::movement::MovementError;
pub use self::actions::focus::FocusError;

pub use self::core::action::{Action, ActionErr};
pub use self::core::container::{Container, ContainerType, Handle, Layout};
pub use self::core::tree::{Direction, TreeError};
use self::core::InnerTree;

use petgraph::graph::NodeIndex;
use rustc_serialize::json::{Json, ToJson};

use std::sync::{Mutex, MutexGuard, TryLockError};

/// A wrapper around tree, to hide its methods
pub struct Tree(TreeGuard);
/// Mutex guard around the tree
pub type TreeGuard = MutexGuard<'static, LayoutTree>;
/// Error for trying to lock the tree
pub type TreeErr = TryLockError<TreeGuard>;
/// Result for locking the tree
pub type TreeResult = Result<MutexGuard<'static, LayoutTree>, TreeErr>;

#[derive(Debug)]
pub struct LayoutTree {
    tree: InnerTree,
    active_container: Option<NodeIndex>
}

lazy_static! {
    static ref TREE: Mutex<LayoutTree> = {
        Mutex::new(LayoutTree {
            tree: InnerTree::new(),
            active_container: None
        })
    };
    static ref PREV_ACTION: Mutex<Option<Action>> = Mutex::new(None);
}

impl ToJson for LayoutTree {
    fn to_json(&self) -> Json {
        use std::collections::BTreeMap;
        fn node_to_json(node_ix: NodeIndex, tree: &LayoutTree) -> Json {
            match &tree.tree[node_ix] {
                &Container::Workspace { ref name, .. } => {
                    let mut inner_map = BTreeMap::new();
                    let children = tree.tree.children_of(node_ix).iter()
                        .map(|node| node_to_json(*node, tree)).collect();
                    inner_map.insert(format!("Workspace {}", name), Json::Array(children));
                    return Json::Object(inner_map);
                }
                &Container::Container { ref layout, id, .. } => {
                    let mut inner_map = BTreeMap::new();
                    let children = tree.tree.children_of(node_ix).iter()
                        .map(|node| node_to_json(*node, tree)).collect();
                    inner_map.insert(format!("Container w/ layout {:?} and id {:?}", layout, id),
                                     Json::Array(children));
                    return Json::Object(inner_map);
                }
                &Container::View { ref handle, id, .. } => {
                    return Json::String(format!("View: title: \"{:?}\", class: \"{:?}\", id: {}",
                                                handle.get_title(), handle.get_class(), id));
                },
                ref container => {
                    let mut inner_map = BTreeMap::new();
                    let children = tree.tree.children_of(node_ix).iter()
                        .map(|node| node_to_json(*node, tree)).collect();
                    inner_map.insert(format!("{:?}", container.get_type()),
                                     Json::Array(children));
                    return Json::Object(inner_map)
                }
            }
        }
        return node_to_json(self.tree.root_ix(), self);
    }
}

/// Attempts to lock the tree. If the Result is Err, then the lock could
/// not be returned at this time, already locked.
pub fn try_lock_tree() -> Result<Tree, TreeErr> {
    let tree = try!(TREE.try_lock());
    Ok(Tree(tree))
}

/// Attempts to lock the action mutex. If the Result is Err, then the lock could
/// not be returned at this time, already locked.
pub fn try_lock_action() -> Result<MutexGuard<'static, Option<Action>>,
                                 TryLockError<MutexGuard<'static,
                                                         Option<Action>>>> {
    PREV_ACTION.try_lock()
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 T. Okubo
// This file is part of vlc-rs.
// Licensed under the MIT license, see the LICENSE file.

use ffi;

pub struct MediaList {
    pub ptr: *mut ffi::libvlc_media_list_t,
}

impl Drop for MediaList {
    fn drop(&mut self) {
        unsafe{ ffi::libvlc_media_list_release(self.ptr) };
    }
}
<commit_msg>Add methods to MediaList<commit_after>// Copyright (c) 2015 T. Okubo
// This file is part of vlc-rs.
// Licensed under the MIT license, see the LICENSE file.

use ffi;
use ::{Instance, Media, EventManager};

pub struct MediaList {
    pub ptr: *mut ffi::libvlc_media_list_t,
}

impl MediaList {
    /// Create an empty media list.
    pub fn new(instance: &Instance) -> Option<MediaList> {
        unsafe{
            let p = ffi::libvlc_media_list_new(instance.ptr);
            if p.is_null() { None }else{ Some(MediaList{ptr: p}) }
        }
    }

    /// Associate media instance with this media list instance.
    /// If another media instance was present it will be released. The libvlc_media_list_lock should NOT be held upon entering this function.
    pub fn set_media(&self, md: &Media) {
        unsafe{ ffi::libvlc_media_list_set_media(self.ptr, md.ptr); }
    }

    /// Get media instance from this media list instance.
    /// The MediaList::lock should NOT be held upon entering this function.
    pub fn media(&self) -> Option<Media> {
        unsafe{
            let p = ffi::libvlc_media_list_media(self.ptr);
            if p.is_null() { None }else{ Some(Media{ptr: p}) }
        }
    }

    /// Add media instance to media list.
    /// The MediaList::lock should be held upon entering this function.
    pub fn add_media(&self, md: &Media) -> Result<(), ()> {
        unsafe{
            if ffi::libvlc_media_list_add_media(self.ptr, md.ptr) == 0 { Ok(()) }else{ Err(()) }
        }
    }

    /// Insert media instance in media list on a position.
    /// The MediaList::lock should be held upon entering this function.
    pub fn insert_media(&self, md: &Media, pos: i32) -> Result<(), ()> {
        unsafe{
            if ffi::libvlc_media_list_insert_media(self.ptr, md.ptr, pos) == 0 { Ok(()) }else{ Err(()) }
        }
    }

    /// Remove media instance from media list on a position.
    /// The MediaList::lock should be held upon entering this function.
    pub fn remove_index(&self, pos: i32) -> Result<(), ()> {
        unsafe{
            if ffi::libvlc_media_list_remove_index(self.ptr, pos) == 0 { Ok(()) }else{ Err(()) }
        }
    }

    /// Get count on media list items.
    /// The MediaList::lock should be held upon entering this function.
    pub fn count(&self) -> i32 {
        unsafe{ ffi::libvlc_media_list_count(self.ptr) }
    }

    /// List media instance in media list at a position.
    /// The MediaList::lock should be held upon entering this function.
    pub fn item_at_index(&self, pos: i32) -> Option<Media> {
        unsafe{
            let p = ffi::libvlc_media_list_item_at_index(self.ptr, pos);
            if p.is_null() { None }else{ Some(Media{ptr: p}) }
        }
    }

    /// Find index position of List media instance in media list.
    pub fn index_of_item(&self, md: &Media) -> Option<i32> {
        unsafe{
            let i = ffi::libvlc_media_list_index_of_item(self.ptr, md.ptr);
            if i == -1 { None }else{ Some(i) }
        }
    }

    /// This indicates if this media list is read-only from a user point of view.
    pub fn is_readonly(&self) -> bool {
        unsafe{ if ffi::libvlc_media_list_is_readonly(self.ptr) == 0 { false }else{ true } }
    }

    /// Get lock on media list items
    pub fn lock(&self) {
        unsafe{ ffi::libvlc_media_list_lock(self.ptr); }
    }

    /// Release lock on media list items
    /// The libvlc_media_list_lock should be held upon entering this function.
    pub fn unlock(&self) {
        unsafe{ ffi::libvlc_media_list_unlock(self.ptr); }
    }

    /// Get EventManager from this media list instance.
    pub fn event_manager<'a>(&'a self) -> EventManager<'a> {
        unsafe{
            let p = ffi::libvlc_media_list_event_manager(self.ptr);
            assert!(!p.is_null());
            EventManager{ptr: p, _phantomdata: ::std::marker::PhantomData}
        }
    }
}

impl Drop for MediaList {
    fn drop(&mut self) {
        unsafe{ ffi::libvlc_media_list_release(self.ptr) };
    }
}
<|endoftext|>


<commit_before>#![feature(globs)]
extern crate iron;
extern crate handlebars;
extern crate "rustc-serialize" as serialize;

use std::str::FromStr;
use std::io::{File};
use std::collections::BTreeMap;

use iron::prelude::*;
use iron::{AfterMiddleware, ChainBuilder, typemap};
use iron::status;
use iron::headers;

use handlebars::Handlebars;
use serialize::json::{ToJson, Json};

struct HandlebarsRenderer {
	  registry: Handlebars
}

impl typemap::Assoc<(&'static str, Json)> for HandlebarsRenderer {}

impl HandlebarsRenderer {
	  fn new(dir: &'static str, suffix: &'static str) -> HandlebarsRenderer {
		    let mut r = Handlebars::new();

		    let t = r.register_template_string("index", File::open(&Path::new("./examples/index.hbs")).unwrap().read_to_string().unwrap());

        if t.is_err() {
            panic!("Failed to create template.");
        }

		    HandlebarsRenderer {
			      registry: r
		    }
	  }
}

impl AfterMiddleware for HandlebarsRenderer {
	  fn after(&self, _: &mut Request, resp: &mut Response) -> IronResult<()> {
        let page = match resp.extensions.get::<HandlebarsRenderer, (&str, Json)>() {
            Some(h) => {
                let (name, ref value) = *h;
		            let page = self.registry.render(name, value).unwrap();
                Some(page)
            },
            None => {
                None
            }
        };

        if page.is_some() {
            resp.headers.set(headers::ContentType(FromStr::from_str("text/html;charset=utf-8").unwrap()));
            resp.set_mut(status::Ok).set_mut(page.unwrap());
        }

        Ok(())
    }
}

fn hello_world(_: &mut Request) -> IronResult<Response> {
	  let mut resp = Response::new();

	  let mut data = BTreeMap::new();
	  data.insert("title".to_string(), "Handlebars on Iron".to_json());

	  resp.extensions.insert::<HandlebarsRenderer, (&str, Json)>(("index", data.to_json()));

    Ok(resp)
}

/*
fn main() {
	  let mut chain = ChainBuilder::new(hello_world);
    chain.link_after(HandlebarsRenderer::new());
    Iron::new(chain).listen("localhost:3000").unwrap();
}
*/
<commit_msg>(feat) (wip) Template struct and its modifier to Response<commit_after>#![feature(globs)]
extern crate iron;
extern crate handlebars;
extern crate "rustc-serialize" as serialize;

use std::str::FromStr;
use std::io::{File};
use std::collections::BTreeMap;

use iron::prelude::*;
use iron::{AfterMiddleware, ChainBuilder, typemap, Response};
use iron::status;
use iron::headers;

use handlebars::Handlebars;
use serialize::json::{ToJson, Json};
use modifier::Modifier;

struct HandlebarsRenderer {
	  registry: Handlebars
}

struct Template<'a> {
    name: &'a str,
    value: Json
}

impl<'a> Template<'a> {
    pub fn new(name: &'a str, value: Json) -> Template<'a>{
        Template<'a> {
            name: name,
            value: value
        }
    }
}

impl<'a> Modifier<Response> for Template<'a> {
    fn modify(self, resp: &mut Response) {
        resp.extensions.insert::<HandlebarsRenderer, Template<'a>>(self);
    }
}

impl typemap::Assoc<Template<'a>> for HandlebarsRenderer {}

impl HandlebarsRenderer {
	  fn new(dir: &'static str, suffix: &'static str) -> HandlebarsRenderer {
		    let mut r = Handlebars::new();

		    let t = r.register_template_string("index", File::open(&Path::new("./examples/index.hbs")).unwrap().read_to_string().unwrap());

        if t.is_err() {
            panic!("Failed to create template.");
        }

		    HandlebarsRenderer {
			      registry: r
		    }
	  }
}

impl AfterMiddleware for HandlebarsRenderer {
	  fn after(&self, _: &mut Request, resp: &mut Response) -> IronResult<()> {
        let page = match resp.extensions.get::<HandlebarsRenderer, Template<'a>>() {
            Some(h) => {
                let name = h.name;
                let value = &h.value;
		            let page = self.registry.render(name, value).unwrap();
                Some(page)
            },
            None => {
                None
            }
        };

        if page.is_some() {
            resp.headers.set(headers::ContentType(FromStr::from_str("text/html;charset=utf-8").unwrap()));
            resp.set_mut(status::Ok).set_mut(page.unwrap());
        }

        Ok(())
    }
}

fn hello_world(_: &mut Request) -> IronResult<Response> {
	  let mut resp = Response::new();

	  let mut data = BTreeMap::new();
	  data.insert("title".to_string(), "Handlebars on Iron".to_json());

    resp.set(Template::new("index", data.to_json()));
    Ok(resp)
}

/*
fn main() {
	  let mut chain = ChainBuilder::new(hello_world);
    chain.link_after(HandlebarsRenderer::new());
    Iron::new(chain).listen("localhost:3000").unwrap();
}
*/
<|endoftext|>


<commit_before>//! Miscellaneous helper traits, enums, and structs for models.

use super::prelude::*;
use internal::RwLockExt;

#[cfg(all(feature = "model", feature = "utils"))]
use std::error::Error as StdError;
#[cfg(all(feature = "model", feature = "utils"))]
use std::result::Result as StdResult;
#[cfg(all(feature = "model", feature = "utils"))]
use std::str::FromStr;
#[cfg(all(feature = "model", feature = "utils"))]
use std::fmt;
#[cfg(all(feature = "model", any(feature = "cache", feature = "utils")))]
use utils;

/// Allows something - such as a channel or role - to be mentioned in a message.
pub trait Mentionable {
    /// Creates a mentionable string, that will be able to notify and/or create
    /// a link to the item.
    fn mention(&self) -> String;
}

impl Mentionable for ChannelId {
    fn mention(&self) -> String { format!("<#{}>", self.0) }
}

impl Mentionable for Channel {
    fn mention(&self) -> String {
        match *self {
            Channel::Guild(ref x) => format!("<#{}>", x.with(|x| x.id.0)),
            Channel::Private(ref x) => format!("<#{}>", x.with(|x| x.id.0)),
            Channel::Group(ref x) => format!("<#{}>", x.with(|x| x.channel_id.0)),
            Channel::Category(ref x) => format!("<#{}>", x.with(|x| x.id.0)),
        }
    }
}

impl Mentionable for ChannelCategory {
    fn mention(&self) -> String {
        format!("#{}", self.name)
    }
}

impl Mentionable for CurrentUser {
    fn mention(&self) -> String {
        format!("<@{}>", self.id.0)
    }
}

impl Mentionable for Emoji {
    fn mention(&self) -> String { format!("<:{}:{}>", self.name, self.id.0) }
}

impl Mentionable for Member {
    fn mention(&self) -> String { format!("<@{}>", self.user.with(|u| u.id.0)) }
}

impl Mentionable for RoleId {
    fn mention(&self) -> String { format!("<@&{}>", self.0) }
}

impl Mentionable for Role {
    fn mention(&self) -> String { format!("<@&{}>", self.id.0) }
}

impl Mentionable for UserId {
    fn mention(&self) -> String { format!("<@{}>", self.0) }
}

impl Mentionable for User {
    fn mention(&self) -> String { format!("<@{}>", self.id.0) }
}

impl Mentionable for GuildChannel {
    fn mention(&self) -> String { format!("<#{}>", self.id.0) }
}

#[cfg(all(feature = "model", feature = "utils"))]
#[derive(Debug)]
pub enum UserParseError {
    InvalidUsername,
    Rest(Box<Error>),
}

#[cfg(all(feature = "model", feature = "utils"))]
impl fmt::Display for UserParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.description()) }
}

#[cfg(all(feature = "model", feature = "utils"))]
impl StdError for UserParseError {
    fn description(&self) -> &str {
        use self::UserParseError::*;

        match *self {
            InvalidUsername => "invalid username",
            Rest(_) => "could not fetch",
        }
    }
}

#[cfg(all(feature = "model", feature = "utils"))]
impl FromStr for User {
    type Err = UserParseError;

    fn from_str(s: &str) -> StdResult<Self, Self::Err> {
        match utils::parse_username(s) {
            Some(x) => UserId(x as u64)
                .get()
                .map_err(|e| UserParseError::Rest(Box::new(e))),
            _ => Err(UserParseError::InvalidUsername),
        }
    }
}

macro_rules! impl_from_str {
    (id: $($id:tt, $err:ident;)*) => {
        $(
            #[cfg(all(feature = "model", feature = "utils"))]
            #[derive(Debug)]
            pub enum $err {
                InvalidFormat,
            }

            #[cfg(all(feature = "model", feature = "utils"))]
            impl fmt::Display for $err {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.description()) }
            }

            #[cfg(all(feature = "model", feature = "utils"))]
            impl StdError for $err {
                fn description(&self) -> &str {
                    use self::$err::*;

                    match *self {
                        InvalidFormat => "invalid id format",
                    }
                }
            }

            #[cfg(all(feature = "model", feature = "utils"))]
            impl FromStr for $id {
                type Err = $err;

                fn from_str(s: &str) -> StdResult<Self, Self::Err> {
                    Ok(match utils::parse_username(s) {
                        Some(id) => $id(id),
                        None => s.parse::<u64>().map($id).map_err(|_| $err::InvalidFormat)?,
                    })
                }
            }
        )*
    };

    (struct: $($struct:ty, $id:tt, $err:ident, $invalid_variant:tt, $parse_fn:ident, $desc:expr;)*) => {
        $(
            #[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
            #[derive(Debug)]
            pub enum $err {
                NotPresentInCache,
                $invalid_variant,
            }

            #[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
            impl fmt::Display for $err {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.description()) }
            }

            #[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
            impl StdError for $err {
                fn description(&self) -> &str {
                    use self::$err::*;

                    match *self {
                        NotPresentInCache => "not present in cache",
                        $invalid_variant => $desc,
                    }
                }
            }

            #[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
            impl FromStr for $struct {
                type Err = $err;

                fn from_str(s: &str) -> StdResult<Self, Self::Err> {
                    match utils::$parse_fn(s) {
                        Some(x) => match $id(x).find() {
                            Some(user) => Ok(user),
                            _ => Err($err::NotPresentInCache),
                        },
                        _ => Err($err::$invalid_variant),
                    }
                }
            }
        )*
    };
}

impl_from_str! { id:
    UserId, UserIdParseError;
    RoleId, RoleIdParseError;
    ChannelId, ChannelIdParseError;
}

impl_from_str! { struct:
    Channel, ChannelId, ChannelParseError, InvalidChannel, parse_channel, "invalid channel";
    Role, RoleId, RoleParseError, InvalidRole, parse_role, "invalid role";
}

/// A version of an emoji used only when solely the Id and name are known.
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct EmojiIdentifier {
    /// The Id of the emoji.
    pub id: EmojiId,
    /// The name of the emoji. It must be at least 2 characters long and can
    /// only contain alphanumeric characters and underscores.
    pub name: String,
}

#[cfg(all(feature = "model", feature = "utils"))]
impl EmojiIdentifier {
    /// Generates a URL to the emoji's image.
    #[inline]
    pub fn url(&self) -> String { format!(cdn!("/emojis/{}.png"), self.id) }
}

#[cfg(all(feature = "model", feature = "utils"))]
impl FromStr for EmojiIdentifier {
    type Err = ();

    fn from_str(s: &str) -> StdResult<Self, ()> { utils::parse_emoji(s).ok_or_else(|| ()) }
}

/// A component that was affected during a service incident.
///
/// This is pulled from the Discord status page.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct AffectedComponent {
    pub name: String,
}

/// An incident retrieved from the Discord status page.
///
/// This is not necessarily a representation of an ongoing incident.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Incident {
    pub created_at: String,
    pub id: String,
    pub impact: String,
    pub incident_updates: Vec<IncidentUpdate>,
    pub monitoring_at: Option<String>,
    pub name: String,
    pub page_id: String,
    pub resolved_at: Option<String>,
    pub short_link: String,
    pub status: String,
    pub updated_at: String,
}

/// An update to an incident from the Discord status page.
///
/// This will typically state what new information has been discovered about an
/// incident.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct IncidentUpdate {
    pub affected_components: Vec<AffectedComponent>,
    pub body: String,
    pub created_at: String,
    pub display_at: String,
    pub id: String,
    pub incident_id: String,
    pub status: IncidentStatus,
    pub updated_at: String,
}

/// The type of status update during a service incident.
#[derive(Copy, Clone, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum IncidentStatus {
    Identified,
    Investigating,
    Monitoring,
    Postmortem,
    Resolved,
}

/// A Discord status maintenance message. This can be either for active
/// maintenances or for scheduled maintenances.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Maintenance {
    pub description: String,
    pub id: String,
    pub name: String,
    pub start: String,
    pub stop: String,
}
<commit_msg>Implement Mentionable for PrivateChannel<commit_after>//! Miscellaneous helper traits, enums, and structs for models.

use super::prelude::*;
use internal::RwLockExt;

#[cfg(all(feature = "model", feature = "utils"))]
use std::error::Error as StdError;
#[cfg(all(feature = "model", feature = "utils"))]
use std::result::Result as StdResult;
#[cfg(all(feature = "model", feature = "utils"))]
use std::str::FromStr;
#[cfg(all(feature = "model", feature = "utils"))]
use std::fmt;
#[cfg(all(feature = "model", any(feature = "cache", feature = "utils")))]
use utils;

/// Allows something - such as a channel or role - to be mentioned in a message.
pub trait Mentionable {
    /// Creates a mentionable string, that will be able to notify and/or create
    /// a link to the item.
    fn mention(&self) -> String;
}

impl Mentionable for ChannelId {
    fn mention(&self) -> String { format!("<#{}>", self.0) }
}

impl Mentionable for Channel {
    fn mention(&self) -> String {
        match *self {
            Channel::Guild(ref x) => format!("<#{}>", x.with(|x| x.id.0)),
            Channel::Private(ref x) => format!("<#{}>", x.with(|x| x.id.0)),
            Channel::Group(ref x) => format!("<#{}>", x.with(|x| x.channel_id.0)),
            Channel::Category(ref x) => format!("<#{}>", x.with(|x| x.id.0)),
        }
    }
}

impl Mentionable for ChannelCategory {
    fn mention(&self) -> String {
        format!("#{}", self.name)
    }
}

impl Mentionable for CurrentUser {
    fn mention(&self) -> String {
        format!("<@{}>", self.id.0)
    }
}

impl Mentionable for Emoji {
    fn mention(&self) -> String { format!("<:{}:{}>", self.name, self.id.0) }
}

impl Mentionable for Member {
    fn mention(&self) -> String { format!("<@{}>", self.user.with(|u| u.id.0)) }
}

impl Mentionable for PrivateChannel {
    fn mention(&self) -> String {
        format!("<#{}>", self.id.0)
    }
}

impl Mentionable for RoleId {
    fn mention(&self) -> String { format!("<@&{}>", self.0) }
}

impl Mentionable for Role {
    fn mention(&self) -> String { format!("<@&{}>", self.id.0) }
}

impl Mentionable for UserId {
    fn mention(&self) -> String { format!("<@{}>", self.0) }
}

impl Mentionable for User {
    fn mention(&self) -> String { format!("<@{}>", self.id.0) }
}

impl Mentionable for GuildChannel {
    fn mention(&self) -> String { format!("<#{}>", self.id.0) }
}

#[cfg(all(feature = "model", feature = "utils"))]
#[derive(Debug)]
pub enum UserParseError {
    InvalidUsername,
    Rest(Box<Error>),
}

#[cfg(all(feature = "model", feature = "utils"))]
impl fmt::Display for UserParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.description()) }
}

#[cfg(all(feature = "model", feature = "utils"))]
impl StdError for UserParseError {
    fn description(&self) -> &str {
        use self::UserParseError::*;

        match *self {
            InvalidUsername => "invalid username",
            Rest(_) => "could not fetch",
        }
    }
}

#[cfg(all(feature = "model", feature = "utils"))]
impl FromStr for User {
    type Err = UserParseError;

    fn from_str(s: &str) -> StdResult<Self, Self::Err> {
        match utils::parse_username(s) {
            Some(x) => UserId(x as u64)
                .get()
                .map_err(|e| UserParseError::Rest(Box::new(e))),
            _ => Err(UserParseError::InvalidUsername),
        }
    }
}

macro_rules! impl_from_str {
    (id: $($id:tt, $err:ident;)*) => {
        $(
            #[cfg(all(feature = "model", feature = "utils"))]
            #[derive(Debug)]
            pub enum $err {
                InvalidFormat,
            }

            #[cfg(all(feature = "model", feature = "utils"))]
            impl fmt::Display for $err {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.description()) }
            }

            #[cfg(all(feature = "model", feature = "utils"))]
            impl StdError for $err {
                fn description(&self) -> &str {
                    use self::$err::*;

                    match *self {
                        InvalidFormat => "invalid id format",
                    }
                }
            }

            #[cfg(all(feature = "model", feature = "utils"))]
            impl FromStr for $id {
                type Err = $err;

                fn from_str(s: &str) -> StdResult<Self, Self::Err> {
                    Ok(match utils::parse_username(s) {
                        Some(id) => $id(id),
                        None => s.parse::<u64>().map($id).map_err(|_| $err::InvalidFormat)?,
                    })
                }
            }
        )*
    };

    (struct: $($struct:ty, $id:tt, $err:ident, $invalid_variant:tt, $parse_fn:ident, $desc:expr;)*) => {
        $(
            #[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
            #[derive(Debug)]
            pub enum $err {
                NotPresentInCache,
                $invalid_variant,
            }

            #[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
            impl fmt::Display for $err {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.description()) }
            }

            #[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
            impl StdError for $err {
                fn description(&self) -> &str {
                    use self::$err::*;

                    match *self {
                        NotPresentInCache => "not present in cache",
                        $invalid_variant => $desc,
                    }
                }
            }

            #[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
            impl FromStr for $struct {
                type Err = $err;

                fn from_str(s: &str) -> StdResult<Self, Self::Err> {
                    match utils::$parse_fn(s) {
                        Some(x) => match $id(x).find() {
                            Some(user) => Ok(user),
                            _ => Err($err::NotPresentInCache),
                        },
                        _ => Err($err::$invalid_variant),
                    }
                }
            }
        )*
    };
}

impl_from_str! { id:
    UserId, UserIdParseError;
    RoleId, RoleIdParseError;
    ChannelId, ChannelIdParseError;
}

impl_from_str! { struct:
    Channel, ChannelId, ChannelParseError, InvalidChannel, parse_channel, "invalid channel";
    Role, RoleId, RoleParseError, InvalidRole, parse_role, "invalid role";
}

/// A version of an emoji used only when solely the Id and name are known.
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct EmojiIdentifier {
    /// The Id of the emoji.
    pub id: EmojiId,
    /// The name of the emoji. It must be at least 2 characters long and can
    /// only contain alphanumeric characters and underscores.
    pub name: String,
}

#[cfg(all(feature = "model", feature = "utils"))]
impl EmojiIdentifier {
    /// Generates a URL to the emoji's image.
    #[inline]
    pub fn url(&self) -> String { format!(cdn!("/emojis/{}.png"), self.id) }
}

#[cfg(all(feature = "model", feature = "utils"))]
impl FromStr for EmojiIdentifier {
    type Err = ();

    fn from_str(s: &str) -> StdResult<Self, ()> { utils::parse_emoji(s).ok_or_else(|| ()) }
}

/// A component that was affected during a service incident.
///
/// This is pulled from the Discord status page.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct AffectedComponent {
    pub name: String,
}

/// An incident retrieved from the Discord status page.
///
/// This is not necessarily a representation of an ongoing incident.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Incident {
    pub created_at: String,
    pub id: String,
    pub impact: String,
    pub incident_updates: Vec<IncidentUpdate>,
    pub monitoring_at: Option<String>,
    pub name: String,
    pub page_id: String,
    pub resolved_at: Option<String>,
    pub short_link: String,
    pub status: String,
    pub updated_at: String,
}

/// An update to an incident from the Discord status page.
///
/// This will typically state what new information has been discovered about an
/// incident.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct IncidentUpdate {
    pub affected_components: Vec<AffectedComponent>,
    pub body: String,
    pub created_at: String,
    pub display_at: String,
    pub id: String,
    pub incident_id: String,
    pub status: IncidentStatus,
    pub updated_at: String,
}

/// The type of status update during a service incident.
#[derive(Copy, Clone, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum IncidentStatus {
    Identified,
    Investigating,
    Monitoring,
    Postmortem,
    Resolved,
}

/// A Discord status maintenance message. This can be either for active
/// maintenances or for scheduled maintenances.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Maintenance {
    pub description: String,
    pub id: String,
    pub name: String,
    pub start: String,
    pub stop: String,
}
<|endoftext|>


<commit_before>/*!
factorizes a matrix of times and observed values
into ...

use it by repeatedly calling `update` with data
and inspecting `hidden` and `weights`.
*/

use num::{Zero};
use nalgebra::{DMat};

pub struct OnlineNMF<FloatT> {
    /// maps hidden variables (one per row) to observed variables (one per column).
    /// changes on every `update`.
    /// stays constant in size.
    pub hidden: DMat<FloatT>,
    /// maps times (one per row) to hidden variables (one per column).
    /// changes on every `update`.
    /// inspect this.
    /// will grow in size.
    pub weights: DMat<FloatT>,
}

impl<FloatT: Zero + Clone + Copy> OnlineNMF<FloatT> {
    /// returns an online nonnegative matrix factorization
    /// that is supposed to find `nhidden` hidden variables
    /// when repeatedly being `update`d with columns of `nobserved` variables
    pub fn new(nobserved: usize, nhidden: usize) -> OnlineNMF<FloatT> {
        OnlineNMF {
            hidden: DMat::new_zeros(nhidden, nobserved),
            weights: DMat::new_zeros(0, nhidden)
        }
    }

    /// returns the number of observed variables
    #[inline]
    pub fn nobserved(&self) -> usize {
        self.hidden.ncols()
    }

    /// returns the number of hidden variables
    #[inline]
    pub fn nhidden(&self) -> usize {
        self.hidden.nrows()
    }

    pub fn update(&mut self, new_observed_columns: &DMat<FloatT>) {
        assert_eq!(self.nobserved(), new_observed_columns.nrows());

        // do nothing for now
    }
}
<commit_msg>online nmf: add nsamples()<commit_after>/*!
factorizes a matrix of times and observed values
into ...

use it by repeatedly calling `update` with data
and inspecting `hidden` and `weights`.
*/

use num::{Zero};
use nalgebra::{DMat};

pub struct OnlineNMF<FloatT> {
    /// maps hidden variables (one per row) to observed variables (one per column).
    /// changes on every `update`.
    /// stays constant in size.
    pub hidden: DMat<FloatT>,
    /// maps times (one per row) to hidden variables (one per column).
    /// changes on every `update`.
    /// inspect this.
    /// will grow in size.
    pub weights: DMat<FloatT>,
}

impl<FloatT: Zero + Clone + Copy> OnlineNMF<FloatT> {
    /// returns an online nonnegative matrix factorization
    /// that is supposed to find `nhidden` hidden variables
    /// when repeatedly being `update`d with columns of `nobserved` variables
    pub fn new(nobserved: usize, nhidden: usize) -> OnlineNMF<FloatT> {
        OnlineNMF {
            hidden: DMat::new_zeros(nhidden, nobserved),
            weights: DMat::new_zeros(0, nhidden)
        }
    }

    /// returns the number of observed variables
    #[inline]
    pub fn nobserved(&self) -> usize {
        self.hidden.ncols()
    }

    /// returns the number of hidden variables
    #[inline]
    pub fn nhidden(&self) -> usize {
        self.hidden.nrows()
    }

    /// returns the number of data points
    #[inline]
    pub fn nsamples(&self) -> usize {
        self.weights.nrows()
    }

    pub fn update(&mut self, new_observed_columns: &DMat<FloatT>) {
        assert_eq!(self.nobserved(), new_observed_columns.nrows());

        // do nothing for now
    }
}
<|endoftext|>


<commit_before>//! Functions to read and write debug registers.
//!
//! * The dr{0,1,2,3} registers are used to set break points.
//! * The dr6 register contains debug conditions that were sampled at the time
//!   the last debug exception.
//! * The dr7 register enables or disables breakpoints and sets breakpoint
//!   conditions.
//!
//! See Intel Vol. 3a Chapter 17, "Debug, Branch, Profile, TSC ... Features"

use bit_field::BitField;
use bitflags::bitflags;

/// An array list of all available breakpoint registers.
pub const BREAKPOINT_REGS: [Breakpoint; 4] = [
    Breakpoint::Dr0,
    Breakpoint::Dr1,
    Breakpoint::Dr2,
    Breakpoint::Dr3,
];

/// Write dr{0-3} register based on provided `reg` enum.
pub unsafe fn dr_write(reg: Breakpoint, val: usize) {
    match reg {
        Breakpoint::Dr0 => dr0_write(val),
        Breakpoint::Dr1 => dr1_write(val),
        Breakpoint::Dr2 => dr2_write(val),
        Breakpoint::Dr3 => dr3_write(val),
    }
}

/// Read dr{0-3} register based on provided `reg` enum.
pub unsafe fn dr(reg: Breakpoint) -> usize {
    match reg {
        Breakpoint::Dr0 => dr0(),
        Breakpoint::Dr1 => dr1(),
        Breakpoint::Dr2 => dr2(),
        Breakpoint::Dr3 => dr3(),
    }
}

/// Read dr0.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr0() -> usize {
    let ret: usize;
    asm!("mov dr0, {}", out(reg) ret, options(att_syntax));
    ret
}

/// Write dr0.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr0_write(val: usize) {
    asm!("mov {}, dr0", in(reg) val, options(att_syntax));
}

/// Read dr1.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr1() -> usize {
    let ret: usize;
    asm!("mov dr1, {}", out(reg) ret, options(att_syntax));
    ret
}

/// Write dr1.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr1_write(val: usize) {
    asm!("mov {}, dr1", in(reg) val, options(att_syntax));
}

/// Read dr2.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr2() -> usize {
    let ret: usize;
    asm!("mov dr2, {}", out(reg) ret, options(att_syntax));
    ret
}

/// Write dr2.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr2_write(val: usize) {
    asm!("mov {}, dr2", in(reg) val, options(att_syntax));
}

/// Read dr3.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr3() -> usize {
    let ret: usize;
    asm!("mov dr3, {}", out(reg) ret, options(att_syntax));
    ret
}

/// Write dr3.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr3_write(val: usize) {
    asm!("mov {}, dr3", in(reg) val, options(att_syntax));
}

bitflags! {
    /// Debug register 6 (dr6) flags.
    pub struct Dr6: usize {
        /// B0 breakpoint condition detected
        ///
        /// # Notes
        ///
        /// The flag is set if the condition described for the breakpoint by
        /// the LENn, and R/Wn flags in debug control register DR7 is true. They
        /// may or may not be set if the breakpoint is not enabled by the Ln or
        /// the Gn flags in register DR7. Therefore on a #DB, a debug handler
        /// should check only those B0-B3 bits which correspond to an enabled
        /// breakpoint.
        const B0 = 0b0001;

        /// B1 breakpoint condition detected
        ///
        /// # Notes
        ///
        /// The flag is set if the condition described for the breakpoint by
        /// the LENn, and R/Wn flags in debug control register DR7 is true. They
        /// may or may not be set if the breakpoint is not enabled by the Ln or
        /// the Gn flags in register DR7. Therefore on a #DB, a debug handler
        /// should check only those B0-B3 bits which correspond to an enabled
        /// breakpoint.
        const B1 = 0b0010;

        /// B2 breakpoint condition detected
        ///
        /// # Notes
        ///
        /// The flag is set if the condition described for the breakpoint by
        /// the LENn, and R/Wn flags in debug control register DR7 is true. They
        /// may or may not be set if the breakpoint is not enabled by the Ln or
        /// the Gn flags in register DR7. Therefore on a #DB, a debug handler
        /// should check only those B0-B3 bits which correspond to an enabled
        /// breakpoint.
        const B2 = 0b0100;

        /// B3 breakpoint condition detected
        ///
        /// # Notes
        ///
        /// The flag is set if the condition described for the breakpoint by
        /// the LENn, and R/Wn flags in debug control register DR7 is true. They
        /// may or may not be set if the breakpoint is not enabled by the Ln or
        /// the Gn flags in register DR7. Therefore on a #DB, a debug handler
        /// should check only those B0-B3 bits which correspond to an enabled
        /// breakpoint.
        const B3 = 0b1000;

        /// BD debug register access detected
        ///
        /// Indicates that the next instruction in the instruction stream
        /// accesses one of the debug registers.
        ///
        /// This flag is enabled when the GD (general detect) flag in debug
        /// control register DR7 is set.
        const BD = 1 << 13;

        /// BS single step
        ///
        /// Indicates (when set) that the debug exception was triggered by the
        /// single- step execution mode (enabled with the TF flag in the EFLAGS
        /// register).
        const BS = 1 << 14;

        /// BT task switch
        ///
        /// Indicates (when set) that the debug exception resulted from a task
        /// switch where the T flag (debug trap flag) in the TSS of the target
        /// task was set.
        const BT = 1 << 15;

        /// Enables (when set) advanced debugging of RTM transactional regions.
        const RTM = 1 << 16;
    }
}

/// Read dr6.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr6() -> Dr6 {
    let ret: usize;
    asm!("mov dr6, {}", out(reg) ret, options(att_syntax));
    Dr6::from_bits_truncate(ret)
}

/// Write dr6.
///
/// # Notes
///
/// Certain debug exceptions may clear bits 0-3. The remaining contents of the
/// DR6 register are never cleared by the processor. To avoid confusion in
/// identifying debug exceptions, debug handlers should clear the register
/// (except bit 16, which they should set) before returning to the interrupted
/// task).
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr6_write(val: Dr6) {
    asm!("mov {}, dr6", in(reg) val.bits, options(att_syntax));
}

/// Specifies available hardware breakpoints.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Breakpoint {
    Dr0 = 0,
    Dr1 = 1,
    Dr2 = 2,
    Dr3 = 3,
}

/// Specifies the  breakpoint condition for a corresponding breakpoint.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum BreakCondition {
    /// 00 — Break on instruction execution only.
    Instructions = 0b00,
    /// 01 — Break on data writes only.
    DataWrites = 0b01,
    /// 10 — Break on I/O reads or writes.
    ///
    /// # Notes
    /// For this type to be available, the DE (debug extensions) flag in control
    /// register CR4 must be set.
    IoReadsWrites = 0b10,
    /// 11 — Break on data reads or writes but not instruction fetches.
    DataReadsWrites = 0b11,
}

/// Specify the size of the memory location at the address specified in the
/// corresponding breakpoint address register (DR0 through DR3).
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum BreakSize {
    /// 00 — 1-byte length.
    Bytes1 = 0b00,
    /// 01 — 2-byte length.
    Bytes2 = 0b01,
    /// 10 — 8 byte length (or undefined, on older processors).
    Bytes8 = 0b10,
    /// 11 — 4-byte length.
    Bytes4 = 0b11,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Dr7(pub usize);

impl Default for Dr7 {
    fn default() -> Self {
        Self(1 << 10)
    }
}

impl Dr7 {
    fn set_bp(&mut self, bp: Breakpoint, global: bool, val: bool) {
        let bp = bp as usize;
        assert!(bp < 4);
        let idx = if global { bp + 1 } else { bp };
        self.0.set_bit(idx, val);
    }

    fn set_bc(&mut self, bp: Breakpoint, bc: BreakCondition) {
        let idx = 16 + (bp as usize * 4);
        assert!(idx == 16 || idx == 20 || idx == 24 || idx == 28);
        self.0.set_bits(idx..=idx + 1, bc as usize);
    }

    fn set_bs(&mut self, bp: Breakpoint, bs: BreakSize) {
        let idx = 18 + (bp as usize * 4);
        assert!(idx == 18 || idx == 22 || idx == 26 || idx == 30);
        self.0.set_bits(idx..=idx + 1, bs as usize);
    }

    /// Enables the breakpoint condition for the associated breakpoint.
    ///
    /// - `bp`: The breakpoint to enable.
    /// - `global`: If true, the breakpoint is global (e.g., never reset on task
    ///   switches). If false, the CPU resets the flag (disables bp) on task
    ///   switch.
    pub fn enable_bp(&mut self, bp: Breakpoint, bc: BreakCondition, bs: BreakSize, global: bool) {
        assert!(
            !(bc == BreakCondition::Instructions && bs != BreakSize::Bytes1),
            "If bc is 00 (instruction execution), then the bs field should be 00"
        );
        self.set_bp(bp, global, true);
        self.set_bc(bp, bc);
        self.set_bs(bp, bs);
    }

    /// Disables the breakpoint condition for the associated breakpoint.
    ///
    /// - `bp`: The breakpoint to disable.
    /// - `global`: If true, the breakpoint is global (e.g., never reset on task
    ///   switches). If false, the CPU resets the flag (disables bp) on task
    ///   switch.
    pub fn disable_bp(&mut self, bp: Breakpoint, global: bool) {
        self.set_bp(bp, global, false);
    }

    /// Local exact breakpoint enable.
    ///
    /// This flag causes the processor to detect the exact instruction that
    /// caused a data breakpoint condition. This feature is not supported in the
    /// P6 family processors, later IA-32 processors, and Intel 64 processors.
    ///
    /// For backward and forward compatibility with other Intel processors,
    /// Intel recommends that the LE flag be set to 1 if exact breakpoints are
    /// required.
    pub fn enable_exact_local_bp(&mut self) {
        self.0.set_bit(8, true);
    }

    /// Global exact breakpoint enable.
    ///
    /// This flag causes the processor to detect the exact instruction that
    /// caused a data breakpoint condition. This feature is not supported in the
    /// P6 family processors, later IA-32 processors, and Intel 64 processors.
    ///
    /// For backward and forward compatibility with other Intel processors,
    /// Intel recommends that the GE flag be set to 1 if exact breakpoints are
    /// required.
    pub fn enable_exact_global_bp(&mut self) {
        self.0.set_bit(9, true);
    }

    /// Enables advanced debugging of RTM transactional regions.
    ///
    /// # Note
    /// This advanced debugging is enabled only if IA32_DEBUGCTL.RTM is also
    /// set.
    pub fn enable_rtm(&mut self) {
        self.0.set_bit(11, true);
    }

    /// Enables debug-register protection, which causes a debug exception to be
    /// generated prior to any MOV instruction that accesses a debug register.
    pub fn enable_general_detect(&mut self) {
        self.0.set_bit(13, true);
    }
}

/// Read dr7.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr7() -> Dr7 {
    let ret: usize;
    asm!("mov dr7, {}", out(reg) ret, options(att_syntax));
    Dr7(ret)
}

/// Write dr7.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr7_write(val: Dr7) {
    asm!("mov {}, dr7", in(reg) val.0, options(att_syntax));
}
<commit_msg>Fix register names.<commit_after>//! Functions to read and write debug registers.
//!
//! * The dr{0,1,2,3} registers are used to set break points.
//! * The dr6 register contains debug conditions that were sampled at the time
//!   the last debug exception.
//! * The dr7 register enables or disables breakpoints and sets breakpoint
//!   conditions.
//!
//! See Intel Vol. 3a Chapter 17, "Debug, Branch, Profile, TSC ... Features"

use bit_field::BitField;
use bitflags::bitflags;

/// An array list of all available breakpoint registers.
pub const BREAKPOINT_REGS: [Breakpoint; 4] = [
    Breakpoint::Dr0,
    Breakpoint::Dr1,
    Breakpoint::Dr2,
    Breakpoint::Dr3,
];

/// Write dr{0-3} register based on provided `reg` enum.
pub unsafe fn dr_write(reg: Breakpoint, val: usize) {
    match reg {
        Breakpoint::Dr0 => dr0_write(val),
        Breakpoint::Dr1 => dr1_write(val),
        Breakpoint::Dr2 => dr2_write(val),
        Breakpoint::Dr3 => dr3_write(val),
    }
}

/// Read dr{0-3} register based on provided `reg` enum.
pub unsafe fn dr(reg: Breakpoint) -> usize {
    match reg {
        Breakpoint::Dr0 => dr0(),
        Breakpoint::Dr1 => dr1(),
        Breakpoint::Dr2 => dr2(),
        Breakpoint::Dr3 => dr3(),
    }
}

/// Read dr0.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr0() -> usize {
    let ret: usize;
    asm!("mov %dr0, {}", out(reg) ret, options(att_syntax));
    ret
}

/// Write dr0.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr0_write(val: usize) {
    asm!("mov {}, %dr0", in(reg) val, options(att_syntax));
}

/// Read dr1.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr1() -> usize {
    let ret: usize;
    asm!("mov %dr1, {}", out(reg) ret, options(att_syntax));
    ret
}

/// Write dr1.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr1_write(val: usize) {
    asm!("mov {}, %dr1", in(reg) val, options(att_syntax));
}

/// Read dr2.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr2() -> usize {
    let ret: usize;
    asm!("mov %dr2, {}", out(reg) ret, options(att_syntax));
    ret
}

/// Write dr2.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr2_write(val: usize) {
    asm!("mov {}, %dr2", in(reg) val, options(att_syntax));
}

/// Read dr3.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr3() -> usize {
    let ret: usize;
    asm!("mov %dr3, {}", out(reg) ret, options(att_syntax));
    ret
}

/// Write dr3.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr3_write(val: usize) {
    asm!("mov {}, %dr3", in(reg) val, options(att_syntax));
}

bitflags! {
    /// Debug register 6 (dr6) flags.
    pub struct Dr6: usize {
        /// B0 breakpoint condition detected
        ///
        /// # Notes
        ///
        /// The flag is set if the condition described for the breakpoint by
        /// the LENn, and R/Wn flags in debug control register DR7 is true. They
        /// may or may not be set if the breakpoint is not enabled by the Ln or
        /// the Gn flags in register DR7. Therefore on a #DB, a debug handler
        /// should check only those B0-B3 bits which correspond to an enabled
        /// breakpoint.
        const B0 = 0b0001;

        /// B1 breakpoint condition detected
        ///
        /// # Notes
        ///
        /// The flag is set if the condition described for the breakpoint by
        /// the LENn, and R/Wn flags in debug control register DR7 is true. They
        /// may or may not be set if the breakpoint is not enabled by the Ln or
        /// the Gn flags in register DR7. Therefore on a #DB, a debug handler
        /// should check only those B0-B3 bits which correspond to an enabled
        /// breakpoint.
        const B1 = 0b0010;

        /// B2 breakpoint condition detected
        ///
        /// # Notes
        ///
        /// The flag is set if the condition described for the breakpoint by
        /// the LENn, and R/Wn flags in debug control register DR7 is true. They
        /// may or may not be set if the breakpoint is not enabled by the Ln or
        /// the Gn flags in register DR7. Therefore on a #DB, a debug handler
        /// should check only those B0-B3 bits which correspond to an enabled
        /// breakpoint.
        const B2 = 0b0100;

        /// B3 breakpoint condition detected
        ///
        /// # Notes
        ///
        /// The flag is set if the condition described for the breakpoint by
        /// the LENn, and R/Wn flags in debug control register DR7 is true. They
        /// may or may not be set if the breakpoint is not enabled by the Ln or
        /// the Gn flags in register DR7. Therefore on a #DB, a debug handler
        /// should check only those B0-B3 bits which correspond to an enabled
        /// breakpoint.
        const B3 = 0b1000;

        /// BD debug register access detected
        ///
        /// Indicates that the next instruction in the instruction stream
        /// accesses one of the debug registers.
        ///
        /// This flag is enabled when the GD (general detect) flag in debug
        /// control register DR7 is set.
        const BD = 1 << 13;

        /// BS single step
        ///
        /// Indicates (when set) that the debug exception was triggered by the
        /// single- step execution mode (enabled with the TF flag in the EFLAGS
        /// register).
        const BS = 1 << 14;

        /// BT task switch
        ///
        /// Indicates (when set) that the debug exception resulted from a task
        /// switch where the T flag (debug trap flag) in the TSS of the target
        /// task was set.
        const BT = 1 << 15;

        /// Enables (when set) advanced debugging of RTM transactional regions.
        const RTM = 1 << 16;
    }
}

/// Read dr6.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr6() -> Dr6 {
    let ret: usize;
    asm!("mov %dr6, {}", out(reg) ret, options(att_syntax));
    Dr6::from_bits_truncate(ret)
}

/// Write dr6.
///
/// # Notes
///
/// Certain debug exceptions may clear bits 0-3. The remaining contents of the
/// DR6 register are never cleared by the processor. To avoid confusion in
/// identifying debug exceptions, debug handlers should clear the register
/// (except bit 16, which they should set) before returning to the interrupted
/// task).
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr6_write(val: Dr6) {
    asm!("mov {}, %dr6", in(reg) val.bits, options(att_syntax));
}

/// Specifies available hardware breakpoints.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Breakpoint {
    Dr0 = 0,
    Dr1 = 1,
    Dr2 = 2,
    Dr3 = 3,
}

/// Specifies the  breakpoint condition for a corresponding breakpoint.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum BreakCondition {
    /// 00 — Break on instruction execution only.
    Instructions = 0b00,
    /// 01 — Break on data writes only.
    DataWrites = 0b01,
    /// 10 — Break on I/O reads or writes.
    ///
    /// # Notes
    /// For this type to be available, the DE (debug extensions) flag in control
    /// register CR4 must be set.
    IoReadsWrites = 0b10,
    /// 11 — Break on data reads or writes but not instruction fetches.
    DataReadsWrites = 0b11,
}

/// Specify the size of the memory location at the address specified in the
/// corresponding breakpoint address register (DR0 through DR3).
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum BreakSize {
    /// 00 — 1-byte length.
    Bytes1 = 0b00,
    /// 01 — 2-byte length.
    Bytes2 = 0b01,
    /// 10 — 8 byte length (or undefined, on older processors).
    Bytes8 = 0b10,
    /// 11 — 4-byte length.
    Bytes4 = 0b11,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Dr7(pub usize);

impl Default for Dr7 {
    fn default() -> Self {
        Self(1 << 10)
    }
}

impl Dr7 {
    fn set_bp(&mut self, bp: Breakpoint, global: bool, val: bool) {
        let bp = bp as usize;
        assert!(bp < 4);
        let idx = if global { bp + 1 } else { bp };
        self.0.set_bit(idx, val);
    }

    fn set_bc(&mut self, bp: Breakpoint, bc: BreakCondition) {
        let idx = 16 + (bp as usize * 4);
        assert!(idx == 16 || idx == 20 || idx == 24 || idx == 28);
        self.0.set_bits(idx..=idx + 1, bc as usize);
    }

    fn set_bs(&mut self, bp: Breakpoint, bs: BreakSize) {
        let idx = 18 + (bp as usize * 4);
        assert!(idx == 18 || idx == 22 || idx == 26 || idx == 30);
        self.0.set_bits(idx..=idx + 1, bs as usize);
    }

    /// Enables the breakpoint condition for the associated breakpoint.
    ///
    /// - `bp`: The breakpoint to enable.
    /// - `global`: If true, the breakpoint is global (e.g., never reset on task
    ///   switches). If false, the CPU resets the flag (disables bp) on task
    ///   switch.
    pub fn enable_bp(&mut self, bp: Breakpoint, bc: BreakCondition, bs: BreakSize, global: bool) {
        assert!(
            !(bc == BreakCondition::Instructions && bs != BreakSize::Bytes1),
            "If bc is 00 (instruction execution), then the bs field should be 00"
        );
        self.set_bp(bp, global, true);
        self.set_bc(bp, bc);
        self.set_bs(bp, bs);
    }

    /// Disables the breakpoint condition for the associated breakpoint.
    ///
    /// - `bp`: The breakpoint to disable.
    /// - `global`: If true, the breakpoint is global (e.g., never reset on task
    ///   switches). If false, the CPU resets the flag (disables bp) on task
    ///   switch.
    pub fn disable_bp(&mut self, bp: Breakpoint, global: bool) {
        self.set_bp(bp, global, false);
    }

    /// Local exact breakpoint enable.
    ///
    /// This flag causes the processor to detect the exact instruction that
    /// caused a data breakpoint condition. This feature is not supported in the
    /// P6 family processors, later IA-32 processors, and Intel 64 processors.
    ///
    /// For backward and forward compatibility with other Intel processors,
    /// Intel recommends that the LE flag be set to 1 if exact breakpoints are
    /// required.
    pub fn enable_exact_local_bp(&mut self) {
        self.0.set_bit(8, true);
    }

    /// Global exact breakpoint enable.
    ///
    /// This flag causes the processor to detect the exact instruction that
    /// caused a data breakpoint condition. This feature is not supported in the
    /// P6 family processors, later IA-32 processors, and Intel 64 processors.
    ///
    /// For backward and forward compatibility with other Intel processors,
    /// Intel recommends that the GE flag be set to 1 if exact breakpoints are
    /// required.
    pub fn enable_exact_global_bp(&mut self) {
        self.0.set_bit(9, true);
    }

    /// Enables advanced debugging of RTM transactional regions.
    ///
    /// # Note
    /// This advanced debugging is enabled only if IA32_DEBUGCTL.RTM is also
    /// set.
    pub fn enable_rtm(&mut self) {
        self.0.set_bit(11, true);
    }

    /// Enables debug-register protection, which causes a debug exception to be
    /// generated prior to any MOV instruction that accesses a debug register.
    pub fn enable_general_detect(&mut self) {
        self.0.set_bit(13, true);
    }
}

/// Read dr7.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr7() -> Dr7 {
    let ret: usize;
    asm!("mov %dr7, {}", out(reg) ret, options(att_syntax));
    Dr7(ret)
}

/// Write dr7.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn dr7_write(val: Dr7) {
    asm!("mov {}, %dr7", in(reg) val.0, options(att_syntax));
}
<|endoftext|>


<commit_before>pub fn get_mtp() -> usize {
    MTP
}
/// Common MTP size for ethernet
pub const MTP: usize = 1536;<commit_msg>Remove unused method<commit_after>/// Common MTP size for ethernet
pub const MTP: usize = 1536;<|endoftext|>


<commit_before>pub mod decoder;
pub mod encoder;

pub use self::decoder::BinaryDecoder;
pub use self::encoder::BinaryEncoder;

#[cfg(test)]
mod test {
    macro_rules! test_codec {
        ($mod_name:ident, $val:expr, $bytes:expr) => {
            mod $mod_name {
                use super::*;

                #[test]
                fn decode() {
                    let result = deserialize($bytes);
                    assert_eq!(Ok($val), result);
                }

                #[test]
                fn encode() {
                    let result = serialize(&$val);
                    assert_eq!(Ok($bytes.to_vec()), result);
                }
            }
        };

        ($mod_name:ident<$tyname:ident>, $val:expr, $bytes:expr) => {
            mod $mod_name {
                use super::*;

                #[test]
                fn decode() {
                    let result = deserialize::<$tyname>($bytes);
                    assert_eq!(Ok($val), result);
                }

                #[test]
                fn encode() {
                    let result = serialize::<$tyname>(&$val);
                    assert_eq!(Ok($bytes.to_vec()), result);
                }
            }
        }
    }

    pub use super::decoder::{deserialize, de_inner, de_bytes, de_name_list};
    pub use super::encoder::{serialize, ser_inner, ser_bytes, ser_name_list};
    pub use serde::bytes::ByteBuf;
    pub use serde::{Deserialize, Deserializer, Serialize, Serializer};

    #[derive(Debug, PartialEq, Deserialize, Serialize)]
    pub struct TestStruct {
        pkt_len: u32,
        pad_len: u8
    }

    #[derive(Debug, PartialEq, Deserialize, Serialize)]
    pub struct OuterStruct {
        #[serde(deserialize_with = "de_bytes", serialize_with = "ser_bytes")]
        data: Vec<u8>,
        #[serde(deserialize_with = "de_inner", serialize_with = "ser_inner")]
        inner: TestStruct
    }

    #[derive(Debug, PartialEq, Deserialize, Serialize)]
    pub enum TestEnum {
        #[serde(rename = "newtype")]
        NewtypeVariant(u32),
        #[serde(rename = "tuple")]
        TupleVariant(String, String),
        #[serde(rename = "struct")]
        StructVariant { a: u32, b: String }
    }

    #[derive(Debug, PartialEq, Deserialize, Serialize)]
    pub struct EnumWrapper {
        #[serde(deserialize_with = "de_inner", serialize_with = "ser_inner")]
        e: TestEnum,
        flag: bool
    }

    #[derive(Debug, PartialEq)]
    pub enum NameEnum {
        TestName,
        AnotherName,
        Unknown(String)
    }

    impl AsRef<str> for NameEnum {
        fn as_ref(&self) -> &str {
            match *self {
                NameEnum::TestName => "test-name",
                NameEnum::AnotherName => "another-name",
                NameEnum::Unknown(ref s) => s.as_ref()
            }
        }
    }

    impl <'r> From<&'r str> for NameEnum {
        fn from(s: &str) -> NameEnum {
            match s {
                "test-name" => NameEnum::TestName,
                "another-name" => NameEnum::AnotherName,
                _ => NameEnum::Unknown(s.to_string())
            }
        }
    }

    impl Deserialize for NameEnum {
        fn deserialize<D: Deserializer>(d: &mut D) -> Result<NameEnum, D::Error> {
            pub use serde::de::Visitor;

            struct IntoVisitor;

            impl Visitor for IntoVisitor {
                type Value = NameEnum;

                fn visit_str<E>(&mut self, v: &str) -> Result<NameEnum, E>
                {
                    Ok(v.into())
                }
            }

            d.deserialize_str(IntoVisitor)
        }
    }

    #[derive(Debug, PartialEq, Deserialize, Serialize)]
    pub struct NameListWrapper {
        #[serde(deserialize_with = "de_name_list", serialize_with = "ser_name_list")]
        e: Vec<NameEnum>,
        #[serde(deserialize_with = "de_bytes", serialize_with = "ser_bytes")]
        f: Vec<u8>
    }

    impl Serialize for NameEnum {
        fn serialize<S: Serializer>(&self, s: &mut S) -> Result<(), S::Error> {
            s.serialize_str(self.as_ref())
        }
    }

    test_codec!(prim_false, false, &[0]);
    test_codec!(prim_true, true, &[1]);
    test_codec!(prim_u8, 30u8, &[30]);
    test_codec!(prim_u32, 0x010203u32, &[0, 1, 2, 3]);

    test_codec!(
        bytebuf<ByteBuf>,
        b"test".to_vec().into(),
        &[0, 0, 0, 4, b't', b'e', b's', b't']
    );

    test_codec!(
        prim_string,
        "test".to_string(),
        &[0, 0, 0, 4, b't', b'e', b's', b't']
    );

    test_codec!(
        plain_struct,
        TestStruct { pkt_len: 0x010203, pad_len: 30 },
        &[0, 1, 2, 3, 30]
    );

    test_codec!(
        inner_struct,
        OuterStruct {
            data: b"test".to_vec(),
            inner: TestStruct { pkt_len: 0x010203, pad_len: 30 }
        },
        &[0, 0, 0, 4, b't', b'e', b's', b't', 0, 0, 0, 5, 0, 1, 2, 3, 30]
    );

    test_codec!(
        enum_newtype,
        TestEnum::NewtypeVariant(0x0102),
        &[0, 0, 0, 7, b'n', b'e', b'w', b't', b'y', b'p', b'e', 0, 0, 1, 2]
    );

    test_codec!(
        enum_tuple,
        TestEnum::TupleVariant("a".to_string(), "bc".to_string()),
        &[0, 0, 0, 5, b't', b'u', b'p', b'l', b'e',
            0, 0, 0, 1, b'a',
            0, 0, 0, 2, b'b', b'c'
        ]
    );

    test_codec!(
        enum_struct,
        TestEnum::StructVariant { a: 0x0102, b: "x".to_string() },
        &[0, 0, 0, 6, b's', b't', b'r', b'u', b'c', b't',
            0, 0, 1, 2,
            0, 0, 0, 1, b'x',
        ]
    );

    test_codec!(
        wrapped_enum,
        EnumWrapper {
            e: TestEnum::StructVariant { a: 0x0102, b: "x".to_string() },
            flag: true
        },
        &[
            0, 0, 0, 19,
            0, 0, 0, 6, b's', b't', b'r', b'u', b'c', b't',
            0, 0, 1, 2,
            0, 0, 0, 1, b'x',
            1
        ]
    );

    test_codec!(
        empty_name_list,
        NameListWrapper {
            e: vec![],
            f: b"test-name".to_vec()
        },
        b"\x00\x00\x00\x00\x00\x00\x00\x09test-name"
    );

    test_codec!(
        name_list,
        NameListWrapper {
            e: vec![NameEnum::TestName, NameEnum::Unknown("unknown".to_string()), NameEnum::AnotherName],
            f: b"test-name".to_vec()
        },
        b"\x00\x00\x00\x1Etest-name,unknown,another-name\x00\x00\x00\x09test-name"
    );
}
<commit_msg>Test serde directive in struct enum<commit_after>pub mod decoder;
pub mod encoder;
pub mod types;

pub use self::decoder::{BinaryDecoder, deserialize};
pub use self::encoder::{BinaryEncoder, serialize};

#[cfg(test)]
mod test {
    macro_rules! test_codec {
        ($mod_name:ident, $val:expr, $bytes:expr) => {
            mod $mod_name {
                use super::*;

                #[test]
                fn decode() {
                    let result = deserialize($bytes);
                    assert_eq!(Ok($val), result);
                }

                #[test]
                fn encode() {
                    let result = serialize(&$val);
                    assert_eq!(Ok($bytes.to_vec()), result);
                }
            }
        };

        ($mod_name:ident<$tyname:ident>, $val:expr, $bytes:expr) => {
            mod $mod_name {
                use super::*;

                #[test]
                fn decode() {
                    let result = deserialize::<$tyname>($bytes);
                    assert_eq!(Ok($val), result);
                }

                #[test]
                fn encode() {
                    let result = serialize::<$tyname>(&$val);
                    assert_eq!(Ok($bytes.to_vec()), result);
                }
            }
        }
    }

    pub use super::decoder::{deserialize, de_inner, de_bytes, de_name_list};
    pub use super::encoder::{serialize, ser_inner, ser_bytes, ser_name_list};
    pub use serde::bytes::ByteBuf;
    pub use serde::{Deserialize, Deserializer, Serialize, Serializer};

    #[derive(Debug, PartialEq, Deserialize, Serialize)]
    pub struct TestStruct {
        pkt_len: u32,
        pad_len: u8
    }

    #[derive(Debug, PartialEq, Deserialize, Serialize)]
    pub struct OuterStruct {
        #[serde(deserialize_with = "de_bytes", serialize_with = "ser_bytes")]
        data: Vec<u8>,
        #[serde(deserialize_with = "de_inner", serialize_with = "ser_inner")]
        inner: TestStruct
    }

    #[derive(Debug, PartialEq, Deserialize, Serialize)]
    pub enum TestEnum {
        #[serde(rename = "newtype")]
        NewtypeVariant(u32),
        #[serde(rename = "tuple")]
        TupleVariant(String, String),
        #[serde(rename = "struct")]
        StructVariant { a: u32, b: String },
        #[serde(rename = "bytes-struct")]
        BytesStruct {
            #[serde(deserialize_with = "de_bytes", serialize_with = "ser_bytes")]
            a: Vec<u8>,
            b: bool
        }
    }

    #[derive(Debug, PartialEq, Deserialize, Serialize)]
    pub struct EnumWrapper {
        #[serde(deserialize_with = "de_inner", serialize_with = "ser_inner")]
        e: TestEnum,
        flag: bool
    }

    #[derive(Debug, PartialEq)]
    pub enum NameEnum {
        TestName,
        AnotherName,
        Unknown(String)
    }

    impl AsRef<str> for NameEnum {
        fn as_ref(&self) -> &str {
            match *self {
                NameEnum::TestName => "test-name",
                NameEnum::AnotherName => "another-name",
                NameEnum::Unknown(ref s) => s.as_ref()
            }
        }
    }

    impl <'r> From<&'r str> for NameEnum {
        fn from(s: &str) -> NameEnum {
            match s {
                "test-name" => NameEnum::TestName,
                "another-name" => NameEnum::AnotherName,
                _ => NameEnum::Unknown(s.to_string())
            }
        }
    }

    impl Deserialize for NameEnum {
        fn deserialize<D: Deserializer>(d: &mut D) -> Result<NameEnum, D::Error> {
            pub use serde::de::Visitor;

            struct IntoVisitor;

            impl Visitor for IntoVisitor {
                type Value = NameEnum;

                fn visit_str<E>(&mut self, v: &str) -> Result<NameEnum, E>
                {
                    Ok(v.into())
                }
            }

            d.deserialize_str(IntoVisitor)
        }
    }

    #[derive(Debug, PartialEq, Deserialize, Serialize)]
    pub struct NameListWrapper {
        #[serde(deserialize_with = "de_name_list", serialize_with = "ser_name_list")]
        e: Vec<NameEnum>,
        #[serde(deserialize_with = "de_bytes", serialize_with = "ser_bytes")]
        f: Vec<u8>
    }

    impl Serialize for NameEnum {
        fn serialize<S: Serializer>(&self, s: &mut S) -> Result<(), S::Error> {
            s.serialize_str(self.as_ref())
        }
    }

    test_codec!(prim_false, false, &[0]);
    test_codec!(prim_true, true, &[1]);
    test_codec!(prim_u8, 30u8, &[30]);
    test_codec!(prim_u32, 0x010203u32, &[0, 1, 2, 3]);

    test_codec!(
        bytebuf<ByteBuf>,
        b"test".to_vec().into(),
        &[0, 0, 0, 4, b't', b'e', b's', b't']
    );

    test_codec!(
        prim_string,
        "test".to_string(),
        &[0, 0, 0, 4, b't', b'e', b's', b't']
    );

    test_codec!(
        plain_struct,
        TestStruct { pkt_len: 0x010203, pad_len: 30 },
        &[0, 1, 2, 3, 30]
    );

    test_codec!(
        inner_struct,
        OuterStruct {
            data: b"test".to_vec(),
            inner: TestStruct { pkt_len: 0x010203, pad_len: 30 }
        },
        &[0, 0, 0, 4, b't', b'e', b's', b't', 0, 0, 0, 5, 0, 1, 2, 3, 30]
    );

    test_codec!(
        enum_newtype,
        TestEnum::NewtypeVariant(0x0102),
        &[0, 0, 0, 7, b'n', b'e', b'w', b't', b'y', b'p', b'e', 0, 0, 1, 2]
    );

    test_codec!(
        enum_tuple,
        TestEnum::TupleVariant("a".to_string(), "bc".to_string()),
        &[0, 0, 0, 5, b't', b'u', b'p', b'l', b'e',
            0, 0, 0, 1, b'a',
            0, 0, 0, 2, b'b', b'c'
        ]
    );

    test_codec!(
        enum_struct,
        TestEnum::StructVariant { a: 0x0102, b: "x".to_string() },
        &[0, 0, 0, 6, b's', b't', b'r', b'u', b'c', b't',
            0, 0, 1, 2,
            0, 0, 0, 1, b'x',
        ]
    );

    test_codec!(
        enum_bytes_in_struct,
        TestEnum::BytesStruct { a: b"test".to_vec(), b: true },
        b"\x00\x00\x00\x0cbytes-struct\x00\x00\x00\x04test\x01"
    );

    test_codec!(
        wrapped_enum,
        EnumWrapper {
            e: TestEnum::StructVariant { a: 0x0102, b: "x".to_string() },
            flag: true
        },
        &[
            0, 0, 0, 19,
            0, 0, 0, 6, b's', b't', b'r', b'u', b'c', b't',
            0, 0, 1, 2,
            0, 0, 0, 1, b'x',
            1
        ]
    );

    test_codec!(
        empty_name_list,
        NameListWrapper {
            e: vec![],
            f: b"test-name".to_vec()
        },
        b"\x00\x00\x00\x00\x00\x00\x00\x09test-name"
    );

    test_codec!(
        name_list,
        NameListWrapper {
            e: vec![NameEnum::TestName, NameEnum::Unknown("unknown".to_string()), NameEnum::AnotherName],
            f: b"test-name".to_vec()
        },
        b"\x00\x00\x00\x1Etest-name,unknown,another-name\x00\x00\x00\x09test-name"
    );
}
<|endoftext|>


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

use ast;
use syntax_pos::{self, Pos, Span};
use ext::base::*;
use ext::base;
use ext::build::AstBuilder;
use parse::{token, DirectoryOwnership};
use parse;
use print::pprust;
use ptr::P;
use symbol::Symbol;
use tokenstream;
use util::small_vector::SmallVector;

use std::fs::File;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::rc::Rc;

// These macros all relate to the file system; they either return
// the column/row/filename of the expression, or they include
// a given file into the current one.

/// line!(): expands to the current line number
pub fn expand_line(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
                   -> Box<base::MacResult+'static> {
    base::check_zero_tts(cx, sp, tts, "line!");

    let topmost = cx.expansion_cause().unwrap_or(sp);
    let loc = cx.codemap().lookup_char_pos(topmost.lo);

    base::MacEager::expr(cx.expr_u32(topmost, loc.line as u32))
}

/* column!(): expands to the current column number */
pub fn expand_column(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
                  -> Box<base::MacResult+'static> {
    base::check_zero_tts(cx, sp, tts, "column!");

    let topmost = cx.expansion_cause().unwrap_or(sp);
    let loc = cx.codemap().lookup_char_pos(topmost.lo);

    base::MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32))
}

/// file!(): expands to the current filename */
/// The filemap (`loc.file`) contains a bunch more information we could spit
/// out if we wanted.
pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
                   -> Box<base::MacResult+'static> {
    base::check_zero_tts(cx, sp, tts, "file!");

    let topmost = cx.expansion_cause().unwrap_or(sp);
    let loc = cx.codemap().lookup_char_pos(topmost.lo);
    base::MacEager::expr(cx.expr_str(topmost, Symbol::intern(&loc.file.name)))
}

pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
                        -> Box<base::MacResult+'static> {
    let s = pprust::tts_to_string(tts);
    base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&s)))
}

pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
                  -> Box<base::MacResult+'static> {
    base::check_zero_tts(cx, sp, tts, "module_path!");
    let mod_path = &cx.current_expansion.module.mod_path;
    let string = mod_path.iter().map(|x| x.to_string()).collect::<Vec<String>>().join("::");

    base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&string)))
}

/// include! : parse the given file as an expr
/// This is generally a bad idea because it's going to behave
/// unhygienically.
pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
                           -> Box<base::MacResult+'cx> {
    let file = match get_single_str_from_tts(cx, sp, tts, "include!") {
        Some(f) => f,
        None => return DummyResult::expr(sp),
    };
    // The file will be added to the code map by the parser
    let path = res_rel_file(cx, sp, Path::new(&file));
    let directory_ownership = DirectoryOwnership::Owned;
    let p = parse::new_sub_parser_from_file(cx.parse_sess(), &path, directory_ownership, None, sp);

    struct ExpandResult<'a> {
        p: parse::parser::Parser<'a>,
    }
    impl<'a> base::MacResult for ExpandResult<'a> {
        fn make_expr(mut self: Box<ExpandResult<'a>>) -> Option<P<ast::Expr>> {
            Some(panictry!(self.p.parse_expr()))
        }
        fn make_items(mut self: Box<ExpandResult<'a>>)
                      -> Option<SmallVector<P<ast::Item>>> {
            let mut ret = SmallVector::new();
            while self.p.token != token::Eof {
                match panictry!(self.p.parse_item()) {
                    Some(item) => ret.push(item),
                    None => panic!(self.p.diagnostic().span_fatal(self.p.span,
                                                           &format!("expected item, found `{}`",
                                                                    self.p.this_token_to_string())))
                }
            }
            Some(ret)
        }
    }

    Box::new(ExpandResult { p: p })
}

// include_str! : read the given file, insert it as a literal string expr
pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
                          -> Box<base::MacResult+'static> {
    let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") {
        Some(f) => f,
        None => return DummyResult::expr(sp)
    };
    let file = res_rel_file(cx, sp, Path::new(&file));
    let mut bytes = Vec::new();
    match File::open(&file).and_then(|mut f| f.read_to_end(&mut bytes)) {
        Ok(..) => {}
        Err(e) => {
            cx.span_err(sp,
                        &format!("couldn't read {}: {}",
                                file.display(),
                                e));
            return DummyResult::expr(sp);
        }
    };
    match String::from_utf8(bytes) {
        Ok(src) => {
            // Add this input file to the code map to make it available as
            // dependency information
            let filename = format!("{}", file.display());
            cx.codemap().new_filemap_and_lines(&filename, &src);

            base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&src)))
        }
        Err(_) => {
            cx.span_err(sp,
                        &format!("{} wasn't a utf-8 file",
                                file.display()));
            DummyResult::expr(sp)
        }
    }
}

pub fn expand_include_bytes(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
                            -> Box<base::MacResult+'static> {
    let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") {
        Some(f) => f,
        None => return DummyResult::expr(sp)
    };
    let file = res_rel_file(cx, sp, Path::new(&file));
    let mut bytes = Vec::new();
    match File::open(&file).and_then(|mut f| f.read_to_end(&mut bytes)) {
        Err(e) => {
            cx.span_err(sp,
                        &format!("couldn't read {}: {}", file.display(), e));
            DummyResult::expr(sp)
        }
        Ok(..) => {
            // Add this input file to the code map to make it available as
            // dependency information, but don't enter it's contents
            let filename = format!("{}", file.display());
            cx.codemap().new_filemap_and_lines(&filename, "");

            base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Rc::new(bytes))))
        }
    }
}

// resolve a file-system path to an absolute file-system path (if it
// isn't already)
fn res_rel_file(cx: &mut ExtCtxt, sp: syntax_pos::Span, arg: &Path) -> PathBuf {
    // NB: relative paths are resolved relative to the compilation unit
    if !arg.is_absolute() {
        let callsite = sp.source_callsite();
        let mut cu = PathBuf::from(&cx.codemap().span_to_filename(callsite));
        cu.pop();
        cu.push(arg);
        cu
    } else {
        arg.to_path_buf()
    }
}
<commit_msg>Some tidying up around include!<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use ast;
use syntax_pos::{self, Pos, Span};
use ext::base::*;
use ext::base;
use ext::build::AstBuilder;
use parse::{token, DirectoryOwnership};
use parse;
use print::pprust;
use ptr::P;
use symbol::Symbol;
use tokenstream;
use util::small_vector::SmallVector;

use std::fs::File;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::rc::Rc;

// These macros all relate to the file system; they either return
// the column/row/filename of the expression, or they include
// a given file into the current one.

/// line!(): expands to the current line number
pub fn expand_line(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
                   -> Box<base::MacResult+'static> {
    base::check_zero_tts(cx, sp, tts, "line!");

    let topmost = cx.expansion_cause().unwrap_or(sp);
    let loc = cx.codemap().lookup_char_pos(topmost.lo);

    base::MacEager::expr(cx.expr_u32(topmost, loc.line as u32))
}

/* column!(): expands to the current column number */
pub fn expand_column(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
                  -> Box<base::MacResult+'static> {
    base::check_zero_tts(cx, sp, tts, "column!");

    let topmost = cx.expansion_cause().unwrap_or(sp);
    let loc = cx.codemap().lookup_char_pos(topmost.lo);

    base::MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32))
}

/// file!(): expands to the current filename */
/// The filemap (`loc.file`) contains a bunch more information we could spit
/// out if we wanted.
pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
                   -> Box<base::MacResult+'static> {
    base::check_zero_tts(cx, sp, tts, "file!");

    let topmost = cx.expansion_cause().unwrap_or(sp);
    let loc = cx.codemap().lookup_char_pos(topmost.lo);
    base::MacEager::expr(cx.expr_str(topmost, Symbol::intern(&loc.file.name)))
}

pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
                        -> Box<base::MacResult+'static> {
    let s = pprust::tts_to_string(tts);
    base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&s)))
}

pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
                  -> Box<base::MacResult+'static> {
    base::check_zero_tts(cx, sp, tts, "module_path!");
    let mod_path = &cx.current_expansion.module.mod_path;
    let string = mod_path.iter().map(|x| x.to_string()).collect::<Vec<String>>().join("::");

    base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&string)))
}

/// include! : parse the given file as an expr
/// This is generally a bad idea because it's going to behave
/// unhygienically.
pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
                           -> Box<base::MacResult+'cx> {
    let file = match get_single_str_from_tts(cx, sp, tts, "include!") {
        Some(f) => f,
        None => return DummyResult::expr(sp),
    };
    // The file will be added to the code map by the parser
    let path = res_rel_file(cx, sp, Path::new(&file));
    let directory_ownership = DirectoryOwnership::Owned;
    let p = parse::new_sub_parser_from_file(cx.parse_sess(), &path, directory_ownership, None, sp);

    struct ExpandResult<'a> {
        p: parse::parser::Parser<'a>,
    }
    impl<'a> base::MacResult for ExpandResult<'a> {
        fn make_expr(mut self: Box<ExpandResult<'a>>) -> Option<P<ast::Expr>> {
            Some(panictry!(self.p.parse_expr()))
        }
        fn make_items(mut self: Box<ExpandResult<'a>>)
                      -> Option<SmallVector<P<ast::Item>>> {
            let mut ret = SmallVector::new();
            while self.p.token != token::Eof {
                match panictry!(self.p.parse_item()) {
                    Some(item) => ret.push(item),
                    None => panic!(self.p.diagnostic().span_fatal(self.p.span,
                                                           &format!("expected item, found `{}`",
                                                                    self.p.this_token_to_string())))
                }
            }
            Some(ret)
        }
    }

    Box::new(ExpandResult { p: p })
}

// include_str! : read the given file, insert it as a literal string expr
pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
                          -> Box<base::MacResult+'static> {
    let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") {
        Some(f) => f,
        None => return DummyResult::expr(sp)
    };
    let file = res_rel_file(cx, sp, Path::new(&file));
    let mut bytes = Vec::new();
    match File::open(&file).and_then(|mut f| f.read_to_end(&mut bytes)) {
        Ok(..) => {}
        Err(e) => {
            cx.span_err(sp,
                        &format!("couldn't read {}: {}",
                                file.display(),
                                e));
            return DummyResult::expr(sp);
        }
    };
    match String::from_utf8(bytes) {
        Ok(src) => {
            // Add this input file to the code map to make it available as
            // dependency information
            let filename = format!("{}", file.display());
            cx.codemap().new_filemap_and_lines(&filename, &src);

            base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&src)))
        }
        Err(_) => {
            cx.span_err(sp,
                        &format!("{} wasn't a utf-8 file",
                                file.display()));
            DummyResult::expr(sp)
        }
    }
}

pub fn expand_include_bytes(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
                            -> Box<base::MacResult+'static> {
    let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") {
        Some(f) => f,
        None => return DummyResult::expr(sp)
    };
    let file = res_rel_file(cx, sp, Path::new(&file));
    let mut bytes = Vec::new();
    match File::open(&file).and_then(|mut f| f.read_to_end(&mut bytes)) {
        Err(e) => {
            cx.span_err(sp,
                        &format!("couldn't read {}: {}", file.display(), e));
            DummyResult::expr(sp)
        }
        Ok(..) => {
            // Add this input file to the code map to make it available as
            // dependency information, but don't enter it's contents
            let filename = format!("{}", file.display());
            cx.codemap().new_filemap_and_lines(&filename, "");

            base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Rc::new(bytes))))
        }
    }
}

// resolve a file-system path to an absolute file-system path (if it
// isn't already)
fn res_rel_file(cx: &mut ExtCtxt, sp: syntax_pos::Span, arg: &Path) -> PathBuf {
    // Relative paths are resolved relative to the file in which they are found
    // after macro expansion (that is, they are unhygienic).
    if !arg.is_absolute() {
        let callsite = sp.source_callsite();
        let mut path = PathBuf::from(&cx.codemap().span_to_filename(callsite));
        path.pop();
        path.push(arg);
        path
    } else {
        arg.to_path_buf()
    }
}
<|endoftext|>


<commit_before>/*!
 * Helpers for headers
 */

pub mod tags;

/**
 * Utility helpers for header data
 */
pub mod data {
    use std::ops::Deref;
    use storage::file::header::data::FileHeaderData as FHD;

    /**
     * Get an URL from a header, whereas the header has to have the following format:
     *
     *   { ..., "URL": "<URL>", ... }
     *
     * Does no spec verification.
     */
    pub fn get_url_from_header(header: &FHD) -> Option<String> {
        match header {
            &FHD::Map{keys: ref ks} => {
                let mut keys : Vec<FHD> = ks.clone();
                keys.iter().find(|k| {
                    match k.deref() {
                        &FHD::Key{name: ref n, value: ref v} => n == "URL",
                        _ => false
                    }
                }).and_then(|urlkey| {
                    match urlkey.deref().clone() {
                        FHD::Key{name: _, value: ref v} => {
                            match v.deref().clone() {
                                FHD::Text(s) => Some(s),
                                _ => {
                                    warn!("Malformed Header Data: Expected Text, found non-Text");
                                    None
                                },
                            }
                        }
                        _ => {
                            warn!("Malformed Header Data: Expected Text, found non-Text");
                            None
                        },
                    }
                })
            },
            _ => {
                warn!("Malformed Header Data: Expected Map, found non-Map");
                None
            }
        }
    }

    /**
     * Get an NAME from a header, whereas the header has to have the following format:
     *
     *   { ..., "NAME": "<NAME>", ... }
     *
     * Does no spec verification.
     */
    pub fn get_name_from_header(header: &FHD) -> Option<String> {
        match header {
            &FHD::Map{keys: ref ks} => {
                let mut keys : Vec<FHD> = ks.clone();
                keys.iter().find(|k| {
                    match k.deref() {
                        &FHD::Key{name: ref n, value: ref v} => n == "NAME",
                        _ => false
                    }
                }).and_then(|urlkey| {
                    match urlkey.deref().clone() {
                        FHD::Key{name: _, value: ref v} => {
                            match v.deref().clone() {
                                FHD::Text(s) => Some(s),
                                _ => {
                                    warn!("Malformed Header Data: Expected Text, found non-Text");
                                    None
                                },
                            }
                        }
                        _ => {
                            warn!("Malformed Header Data: Expected Text, found non-Text");
                            None
                        },
                    }
                })
            },
            _ => {
                warn!("Malformed Header Data: Expected Map, found non-Map");
                None
            }
        }
    }

}

<commit_msg>Refactor: Header helper code can use generic function<commit_after>/*!
 * Helpers for headers
 */

pub mod tags;

/**
 * Utility helpers for header data
 */
pub mod data {
    use std::ops::Deref;
    use storage::file::header::data::FileHeaderData as FHD;

    /**
     * Get an URL from a header, whereas the header has to have the following format:
     *
     *   { ..., "URL": "<URL>", ... }
     *
     * Does no spec verification.
     */
    pub fn get_url_from_header(header: &FHD) -> Option<String> {
        get_named_text_from_header("URL", header)
    }

    /**
     * Get an NAME from a header, whereas the header has to have the following format:
     *
     *   { ..., "NAME": "<NAME>", ... }
     *
     * Does no spec verification.
     */
    pub fn get_name_from_header(header: &FHD) -> Option<String> {
        get_named_text_from_header("NAME", header)
    }

    /**
     * Get a named field from the header, which has to be of this format
     *
     *   { ..., "<name of field>": "<content as string>", ... }
     *
     * Does no spec verification.
     */
    pub fn get_named_text_from_header(name: &'static str, header: &FHD) -> Option<String> {
        match header {
            &FHD::Map{keys: ref ks} => {
                let mut keys : Vec<FHD> = ks.clone();
                keys.iter().find(|k| {
                    match k.deref() {
                        &FHD::Key{name: ref n, value: ref v} => n == name,
                        _ => false
                    }
                }).and_then(|urlkey| {
                    match urlkey.deref().clone() {
                        FHD::Key{name: _, value: ref v} => {
                            match v.deref().clone() {
                                FHD::Text(s) => Some(s),
                                _ => {
                                    warn!("Malformed Header Data: Expected Text, found non-Text");
                                    None
                                },
                            }
                        }
                        _ => {
                            warn!("Malformed Header Data: Expected Text, found non-Text");
                            None
                        },
                    }
                })
            },
            _ => {
                warn!("Malformed Header Data: Expected Map, found non-Map");
                None
            }
        }
    }

}

<|endoftext|>


<commit_before>extern crate blake2_rfc;

use self::blake2_rfc::blake2b::blake2b;

pub fn canonical_hash(input: &[u8]) -> Vec<u8> {
    let result = blake2b(64, &[], input);
    result.as_bytes()[0..32].to_vec()
}
<commit_msg>Add proof-of-possession hash fn<commit_after>extern crate blake2_rfc;

use self::blake2_rfc::blake2b::blake2b;

pub fn canonical_hash(input: &[u8]) -> Vec<u8> {
    let result = blake2b(64, &[], input);
    result.as_bytes()[0..32].to_vec()
}

pub fn proof_of_possession_hash(input: &[u8]) -> Vec<u8> {
    let result = blake2b(64, &[], input);
    let mut hash = result.as_bytes()[32..64].to_vec();
    // TODO: this padding is not part of the spec, it is required otherwise Milagro will panic.
    // We should either drop the padding or ensure the padding is in the spec.
    hash.append(&mut vec![0; 18]);
    hash
}
<|endoftext|>


<commit_before>// exec-env:RUST_POISON_ON_FREE=1

fn main() {
    let mut x = @{f: ~3};
    match x {
      @{f: b_x} => {
        assert *b_x == 3;
        assert ptr::addr_of(&(*x.f)) == ptr::addr_of(&(*b_x));

        x = @{f: ~4};

        debug!("ptr::addr_of(*b_x) = %x", ptr::addr_of(&(*b_x)) as uint);
        assert *b_x == 3;
        assert ptr::addr_of(&(*x.f)) != ptr::addr_of(&(*b_x));
      }
    }
}
<commit_msg>test: Fix borrowck-preserve-box-in-discr; more fallout from pattern bindings. rs=bustage<commit_after>// exec-env:RUST_POISON_ON_FREE=1

fn main() {
    let mut x = @{f: ~3};
    match x {
      @{f: ref b_x} => {
        assert **b_x == 3;
        assert ptr::addr_of(&(*x.f)) == ptr::addr_of(&(**b_x));

        x = @{f: ~4};

        debug!("ptr::addr_of(*b_x) = %x", ptr::addr_of(&(**b_x)) as uint);
        assert **b_x == 3;
        assert ptr::addr_of(&(*x.f)) != ptr::addr_of(&(**b_x));
      }
    }
}
<|endoftext|>


<commit_before>// aux-build:cci_class_6.rs
use cci_class_6;
import cci_class_6::kitties::*;

fn main() {
  let nyan : cat<char> = cat::<char>(52u, 99, ~['p']);
  let kitty = cat(1000u, 2, ~["tabby"]);
  assert(nyan.how_hungry == 99);
  assert(kitty.how_hungry == 2);
  nyan.speak(~[1u,2u,3u]);
  assert(nyan.meow_count() == 55u);
  kitty.speak(~["meow", "mew", "purr", "chirp"]);
  assert(kitty.meow_count() == 1004u);
}
<commit_msg>Xfail-fast a recent test that doesn't work on check-fast.<commit_after>// xfail-fast
// aux-build:cci_class_6.rs
use cci_class_6;
import cci_class_6::kitties::*;

fn main() {
  let nyan : cat<char> = cat::<char>(52u, 99, ~['p']);
  let kitty = cat(1000u, 2, ~["tabby"]);
  assert(nyan.how_hungry == 99);
  assert(kitty.how_hungry == 2);
  nyan.speak(~[1u,2u,3u]);
  assert(nyan.meow_count() == 55u);
  kitty.speak(~["meow", "mew", "purr", "chirp"]);
  assert(kitty.meow_count() == 1004u);
}
<|endoftext|>