<commit_before>//! Pulls type information out of the AST and attaches it to the document

use doc::ItemUtils;
use syntax::ast;
use syntax::print::pprust;
use syntax::ast_map;
use std::map::HashMap;
use extract::to_str;

export mk_pass;

fn mk_pass() -> Pass {
    {
        name: ~"tystr",
        f: run
    }
}

fn run(
    srv: astsrv::Srv,
    doc: doc::Doc
) -> doc::Doc {
    let fold = fold::Fold({
        fold_fn: fold_fn,
        fold_const: fold_const,
        fold_enum: fold_enum,
        fold_trait: fold_trait,
        fold_impl: fold_impl,
        fold_type: fold_type,
        fold_struct: fold_struct,
        .. *fold::default_any_fold(srv)
    });
    fold.fold_doc(fold, doc)
}

fn fold_fn(
    fold: fold::Fold<astsrv::Srv>,
    doc: doc::FnDoc
) -> doc::FnDoc {

    let srv = fold.ctxt;

    {
        sig: get_fn_sig(srv, doc.id()),
        .. doc
    }
}

fn get_fn_sig(srv: astsrv::Srv, fn_id: doc::AstId) -> Option<~str> {
    do astsrv::exec(srv) |ctxt| {
        match ctxt.ast_map.get(fn_id) {
          ast_map::node_item(@{
            ident: ident,
            node: ast::item_fn(decl, _, tys, _), _
          }, _) |
          ast_map::node_foreign_item(@{
            ident: ident,
            node: ast::foreign_item_fn(decl, _, tys), _
          }, _, _) => {
            Some(pprust::fun_to_str(decl, ident, tys, extract::interner()))
          }
          _ => fail ~"get_fn_sig: fn_id not bound to a fn item"
        }
    }
}

#[test]
fn should_add_fn_sig() {
    let doc = test::mk_doc(~"fn a<T>() -> int { }");
    assert doc.cratemod().fns()[0].sig == Some(~"fn a<T>() -> int");
}

#[test]
fn should_add_foreign_fn_sig() {
    let doc = test::mk_doc(~"extern mod a { fn a<T>() -> int; }");
    assert doc.cratemod().nmods()[0].fns[0].sig == Some(~"fn a<T>() -> int");
}

fn fold_const(
    fold: fold::Fold<astsrv::Srv>,
    doc: doc::ConstDoc
) -> doc::ConstDoc {
    let srv = fold.ctxt;

    {
        sig: Some(do astsrv::exec(srv) |ctxt| {
            match ctxt.ast_map.get(doc.id()) {
              ast_map::node_item(@{
                node: ast::item_const(ty, _), _
              }, _) => {
                pprust::ty_to_str(ty, extract::interner())
              }
              _ => fail ~"fold_const: id not bound to a const item"
            }
        }),
        .. doc
    }
}

#[test]
fn should_add_const_types() {
    let doc = test::mk_doc(~"const a: bool = true;");
    assert doc.cratemod().consts()[0].sig == Some(~"bool");
}

fn fold_enum(
    fold: fold::Fold<astsrv::Srv>,
    doc: doc::EnumDoc
) -> doc::EnumDoc {
    let doc_id = doc.id();
    let srv = fold.ctxt;

    {
        variants: do par::map(doc.variants) |variant| {
            let sig = do astsrv::exec(srv) |ctxt| {
                match ctxt.ast_map.get(doc_id) {
                  ast_map::node_item(@{
                    node: ast::item_enum(enum_definition, _), _
                  }, _) => {
                    let ast_variant = option::get(
                        do vec::find(enum_definition.variants) |v| {
                            to_str(v.node.name) == variant.name
                        });

                    pprust::variant_to_str(ast_variant, extract::interner())
                  }
                  _ => fail ~"enum variant not bound to an enum item"
                }
            };

            {
                sig: Some(sig),
                .. variant
            }
        },
        .. doc
    }
}

#[test]
fn should_add_variant_sigs() {
    let doc = test::mk_doc(~"enum a { b(int) }");
    assert doc.cratemod().enums()[0].variants[0].sig == Some(~"b(int)");
}

fn fold_trait(
    fold: fold::Fold<astsrv::Srv>,
    doc: doc::TraitDoc
) -> doc::TraitDoc {
    {
        methods: merge_methods(fold.ctxt, doc.id(), doc.methods),
        .. doc
    }
}

fn merge_methods(
    srv: astsrv::Srv,
    item_id: doc::AstId,
    docs: ~[doc::MethodDoc]
) -> ~[doc::MethodDoc] {
    do par::map(docs) |doc| {
        {
            sig: get_method_sig(srv, item_id, doc.name),
            .. doc
        }
    }
}

fn get_method_sig(
    srv: astsrv::Srv,
    item_id: doc::AstId,
    method_name: ~str
) -> Option<~str> {
    do astsrv::exec(srv) |ctxt| {
        match ctxt.ast_map.get(item_id) {
          ast_map::node_item(@{
            node: ast::item_trait(_, _, methods), _
          }, _) => {
            match vec::find(methods, |method| {
                match method {
                  ast::required(ty_m) => to_str(ty_m.ident) == method_name,
                  ast::provided(m) => to_str(m.ident) == method_name,
                }
            }) {
                Some(method) => {
                  match method {
                    ast::required(ty_m) => {
                      Some(pprust::fun_to_str(
                          ty_m.decl,
                          ty_m.ident,
                          ty_m.tps,
                          extract::interner()
                      ))
                    }
                    ast::provided(m) => {
                      Some(pprust::fun_to_str(
                          m.decl,
                          m.ident,
                          m.tps,
                          extract::interner()
                      ))
                    }
                  }
                }
                _ => fail ~"method not found"
            }
          }
          ast_map::node_item(@{
            node: ast::item_impl(_, _, _, methods), _
          }, _) => {
            match vec::find(methods, |method| {
                to_str(method.ident) == method_name
            }) {
                Some(method) => {
                    Some(pprust::fun_to_str(
                        method.decl,
                        method.ident,
                        method.tps,
                        extract::interner()
                    ))
                }
                None => fail ~"method not found"
            }
          }
          _ => fail ~"get_method_sig: item ID not bound to trait or impl"
        }
    }
}

#[test]
fn should_add_trait_method_sigs() {
    let doc = test::mk_doc(~"trait i { fn a<T>() -> int; }");
    assert doc.cratemod().traits()[0].methods[0].sig
        == Some(~"fn a<T>() -> int");
}

fn fold_impl(
    fold: fold::Fold<astsrv::Srv>,
    doc: doc::ImplDoc
) -> doc::ImplDoc {

    let srv = fold.ctxt;

    let (trait_types, self_ty) = do astsrv::exec(srv) |ctxt| {
        match ctxt.ast_map.get(doc.id()) {
          ast_map::node_item(@{
            node: ast::item_impl(_, opt_trait_type, self_ty, _), _
          }, _) => {
            let trait_types = opt_trait_type.map_default(~[], |p| {
                ~[pprust::path_to_str(p.path, extract::interner())]
            });
            (trait_types, Some(pprust::ty_to_str(self_ty,
                                                 extract::interner())))
          }
          _ => fail ~"expected impl"
        }
    };

    {
        trait_types: trait_types,
        self_ty: self_ty,
        methods: merge_methods(fold.ctxt, doc.id(), doc.methods),
        .. doc
    }
}

#[test]
fn should_add_impl_trait_types() {
    let doc = test::mk_doc(~"impl int: j { fn a<T>() { } }");
    assert doc.cratemod().impls()[0].trait_types[0] == ~"j";
}

#[test]
fn should_not_add_impl_trait_types_if_none() {
    let doc = test::mk_doc(~"impl int { fn a() { } }");
    assert vec::len(doc.cratemod().impls()[0].trait_types) == 0;
}

#[test]
fn should_add_impl_self_ty() {
    let doc = test::mk_doc(~"impl int { fn a() { } }");
    assert doc.cratemod().impls()[0].self_ty == Some(~"int");
}

#[test]
fn should_add_impl_method_sigs() {
    let doc = test::mk_doc(~"impl int { fn a<T>() -> int { fail } }");
    assert doc.cratemod().impls()[0].methods[0].sig
        == Some(~"fn a<T>() -> int");
}

fn fold_type(
    fold: fold::Fold<astsrv::Srv>,
    doc: doc::TyDoc
) -> doc::TyDoc {

    let srv = fold.ctxt;

    {
        sig: do astsrv::exec(srv) |ctxt| {
            match ctxt.ast_map.get(doc.id()) {
              ast_map::node_item(@{
                ident: ident,
                node: ast::item_ty(ty, params), _
              }, _) => {
                Some(fmt!(
                    "type %s%s = %s",
                    to_str(ident),
                    pprust::typarams_to_str(params, extract::interner()),
                    pprust::ty_to_str(ty, extract::interner())
                ))
              }
              _ => fail ~"expected type"
            }
        },
        .. doc
    }
}

#[test]
fn should_add_type_signatures() {
    let doc = test::mk_doc(~"type t<T> = int;");
    assert doc.cratemod().types()[0].sig == Some(~"type t<T> = int");
}

fn fold_struct(
    fold: fold::Fold<astsrv::Srv>,
    doc: doc::StructDoc
) -> doc::StructDoc {
    let srv = fold.ctxt;

    {
        sig: do astsrv::exec(srv) |ctxt| {
            match ctxt.ast_map.get(doc.id()) {
                ast_map::node_item(item, _) => {
                    let item = strip_struct_drop_block(item);
                    Some(pprust::item_to_str(item,
                                             extract::interner()))
                }
                _ => fail ~"not an item"
            }
        },
        .. doc
    }
}

/// Removes the drop block from structs so that they aren't displayed
/// as part of the type
fn strip_struct_drop_block(item: @ast::item) -> @ast::item {
    let node = match item.node {
        ast::item_class(def, tys) => {
            let def = @{
                dtor: None,
                .. *def
            };
            ast::item_class(def, tys)
        }
        _ => fail ~"not a struct"
    };

    @{
        node: node,
        .. *item
    }
}

#[test]
fn should_add_struct_defs() {
    let doc = test::mk_doc(~"struct S { field: () }");
    assert doc.cratemod().structs()[0].sig.get().contains("struct S {");
}

#[test]
fn should_not_serialize_struct_drop_blocks() {
    // All we care about are the fields
    let doc = test::mk_doc(~"struct S { field: (), drop { } }");
    assert !doc.cratemod().structs()[0].sig.get().contains("drop");
}

#[cfg(test)]
mod test {
    fn mk_doc(source: ~str) -> doc::Doc {
        do astsrv::from_str(source) |srv| {
            let doc = extract::from_srv(srv, ~"");
            run(srv, doc)
        }
    }
}
<commit_msg>rustdoc: Also don't print struct attributes<commit_after>//! Pulls type information out of the AST and attaches it to the document

use doc::ItemUtils;
use syntax::ast;
use syntax::print::pprust;
use syntax::ast_map;
use std::map::HashMap;
use extract::to_str;

export mk_pass;

fn mk_pass() -> Pass {
    {
        name: ~"tystr",
        f: run
    }
}

fn run(
    srv: astsrv::Srv,
    doc: doc::Doc
) -> doc::Doc {
    let fold = fold::Fold({
        fold_fn: fold_fn,
        fold_const: fold_const,
        fold_enum: fold_enum,
        fold_trait: fold_trait,
        fold_impl: fold_impl,
        fold_type: fold_type,
        fold_struct: fold_struct,
        .. *fold::default_any_fold(srv)
    });
    fold.fold_doc(fold, doc)
}

fn fold_fn(
    fold: fold::Fold<astsrv::Srv>,
    doc: doc::FnDoc
) -> doc::FnDoc {

    let srv = fold.ctxt;

    {
        sig: get_fn_sig(srv, doc.id()),
        .. doc
    }
}

fn get_fn_sig(srv: astsrv::Srv, fn_id: doc::AstId) -> Option<~str> {
    do astsrv::exec(srv) |ctxt| {
        match ctxt.ast_map.get(fn_id) {
          ast_map::node_item(@{
            ident: ident,
            node: ast::item_fn(decl, _, tys, _), _
          }, _) |
          ast_map::node_foreign_item(@{
            ident: ident,
            node: ast::foreign_item_fn(decl, _, tys), _
          }, _, _) => {
            Some(pprust::fun_to_str(decl, ident, tys, extract::interner()))
          }
          _ => fail ~"get_fn_sig: fn_id not bound to a fn item"
        }
    }
}

#[test]
fn should_add_fn_sig() {
    let doc = test::mk_doc(~"fn a<T>() -> int { }");
    assert doc.cratemod().fns()[0].sig == Some(~"fn a<T>() -> int");
}

#[test]
fn should_add_foreign_fn_sig() {
    let doc = test::mk_doc(~"extern mod a { fn a<T>() -> int; }");
    assert doc.cratemod().nmods()[0].fns[0].sig == Some(~"fn a<T>() -> int");
}

fn fold_const(
    fold: fold::Fold<astsrv::Srv>,
    doc: doc::ConstDoc
) -> doc::ConstDoc {
    let srv = fold.ctxt;

    {
        sig: Some(do astsrv::exec(srv) |ctxt| {
            match ctxt.ast_map.get(doc.id()) {
              ast_map::node_item(@{
                node: ast::item_const(ty, _), _
              }, _) => {
                pprust::ty_to_str(ty, extract::interner())
              }
              _ => fail ~"fold_const: id not bound to a const item"
            }
        }),
        .. doc
    }
}

#[test]
fn should_add_const_types() {
    let doc = test::mk_doc(~"const a: bool = true;");
    assert doc.cratemod().consts()[0].sig == Some(~"bool");
}

fn fold_enum(
    fold: fold::Fold<astsrv::Srv>,
    doc: doc::EnumDoc
) -> doc::EnumDoc {
    let doc_id = doc.id();
    let srv = fold.ctxt;

    {
        variants: do par::map(doc.variants) |variant| {
            let sig = do astsrv::exec(srv) |ctxt| {
                match ctxt.ast_map.get(doc_id) {
                  ast_map::node_item(@{
                    node: ast::item_enum(enum_definition, _), _
                  }, _) => {
                    let ast_variant = option::get(
                        do vec::find(enum_definition.variants) |v| {
                            to_str(v.node.name) == variant.name
                        });

                    pprust::variant_to_str(ast_variant, extract::interner())
                  }
                  _ => fail ~"enum variant not bound to an enum item"
                }
            };

            {
                sig: Some(sig),
                .. variant
            }
        },
        .. doc
    }
}

#[test]
fn should_add_variant_sigs() {
    let doc = test::mk_doc(~"enum a { b(int) }");
    assert doc.cratemod().enums()[0].variants[0].sig == Some(~"b(int)");
}

fn fold_trait(
    fold: fold::Fold<astsrv::Srv>,
    doc: doc::TraitDoc
) -> doc::TraitDoc {
    {
        methods: merge_methods(fold.ctxt, doc.id(), doc.methods),
        .. doc
    }
}

fn merge_methods(
    srv: astsrv::Srv,
    item_id: doc::AstId,
    docs: ~[doc::MethodDoc]
) -> ~[doc::MethodDoc] {
    do par::map(docs) |doc| {
        {
            sig: get_method_sig(srv, item_id, doc.name),
            .. doc
        }
    }
}

fn get_method_sig(
    srv: astsrv::Srv,
    item_id: doc::AstId,
    method_name: ~str
) -> Option<~str> {
    do astsrv::exec(srv) |ctxt| {
        match ctxt.ast_map.get(item_id) {
          ast_map::node_item(@{
            node: ast::item_trait(_, _, methods), _
          }, _) => {
            match vec::find(methods, |method| {
                match method {
                  ast::required(ty_m) => to_str(ty_m.ident) == method_name,
                  ast::provided(m) => to_str(m.ident) == method_name,
                }
            }) {
                Some(method) => {
                  match method {
                    ast::required(ty_m) => {
                      Some(pprust::fun_to_str(
                          ty_m.decl,
                          ty_m.ident,
                          ty_m.tps,
                          extract::interner()
                      ))
                    }
                    ast::provided(m) => {
                      Some(pprust::fun_to_str(
                          m.decl,
                          m.ident,
                          m.tps,
                          extract::interner()
                      ))
                    }
                  }
                }
                _ => fail ~"method not found"
            }
          }
          ast_map::node_item(@{
            node: ast::item_impl(_, _, _, methods), _
          }, _) => {
            match vec::find(methods, |method| {
                to_str(method.ident) == method_name
            }) {
                Some(method) => {
                    Some(pprust::fun_to_str(
                        method.decl,
                        method.ident,
                        method.tps,
                        extract::interner()
                    ))
                }
                None => fail ~"method not found"
            }
          }
          _ => fail ~"get_method_sig: item ID not bound to trait or impl"
        }
    }
}

#[test]
fn should_add_trait_method_sigs() {
    let doc = test::mk_doc(~"trait i { fn a<T>() -> int; }");
    assert doc.cratemod().traits()[0].methods[0].sig
        == Some(~"fn a<T>() -> int");
}

fn fold_impl(
    fold: fold::Fold<astsrv::Srv>,
    doc: doc::ImplDoc
) -> doc::ImplDoc {

    let srv = fold.ctxt;

    let (trait_types, self_ty) = do astsrv::exec(srv) |ctxt| {
        match ctxt.ast_map.get(doc.id()) {
          ast_map::node_item(@{
            node: ast::item_impl(_, opt_trait_type, self_ty, _), _
          }, _) => {
            let trait_types = opt_trait_type.map_default(~[], |p| {
                ~[pprust::path_to_str(p.path, extract::interner())]
            });
            (trait_types, Some(pprust::ty_to_str(self_ty,
                                                 extract::interner())))
          }
          _ => fail ~"expected impl"
        }
    };

    {
        trait_types: trait_types,
        self_ty: self_ty,
        methods: merge_methods(fold.ctxt, doc.id(), doc.methods),
        .. doc
    }
}

#[test]
fn should_add_impl_trait_types() {
    let doc = test::mk_doc(~"impl int: j { fn a<T>() { } }");
    assert doc.cratemod().impls()[0].trait_types[0] == ~"j";
}

#[test]
fn should_not_add_impl_trait_types_if_none() {
    let doc = test::mk_doc(~"impl int { fn a() { } }");
    assert vec::len(doc.cratemod().impls()[0].trait_types) == 0;
}

#[test]
fn should_add_impl_self_ty() {
    let doc = test::mk_doc(~"impl int { fn a() { } }");
    assert doc.cratemod().impls()[0].self_ty == Some(~"int");
}

#[test]
fn should_add_impl_method_sigs() {
    let doc = test::mk_doc(~"impl int { fn a<T>() -> int { fail } }");
    assert doc.cratemod().impls()[0].methods[0].sig
        == Some(~"fn a<T>() -> int");
}

fn fold_type(
    fold: fold::Fold<astsrv::Srv>,
    doc: doc::TyDoc
) -> doc::TyDoc {

    let srv = fold.ctxt;

    {
        sig: do astsrv::exec(srv) |ctxt| {
            match ctxt.ast_map.get(doc.id()) {
              ast_map::node_item(@{
                ident: ident,
                node: ast::item_ty(ty, params), _
              }, _) => {
                Some(fmt!(
                    "type %s%s = %s",
                    to_str(ident),
                    pprust::typarams_to_str(params, extract::interner()),
                    pprust::ty_to_str(ty, extract::interner())
                ))
              }
              _ => fail ~"expected type"
            }
        },
        .. doc
    }
}

#[test]
fn should_add_type_signatures() {
    let doc = test::mk_doc(~"type t<T> = int;");
    assert doc.cratemod().types()[0].sig == Some(~"type t<T> = int");
}

fn fold_struct(
    fold: fold::Fold<astsrv::Srv>,
    doc: doc::StructDoc
) -> doc::StructDoc {
    let srv = fold.ctxt;

    {
        sig: do astsrv::exec(srv) |ctxt| {
            match ctxt.ast_map.get(doc.id()) {
                ast_map::node_item(item, _) => {
                    let item = strip_struct_extra_stuff(item);
                    Some(pprust::item_to_str(item,
                                             extract::interner()))
                }
                _ => fail ~"not an item"
            }
        },
        .. doc
    }
}

/// Removes various things from the struct item definition that
/// shouldn't be displayed in the struct signature. Probably there
/// should be a simple pprust::struct_to_str function that does
/// what I actually want
fn strip_struct_extra_stuff(item: @ast::item) -> @ast::item {
    let node = match item.node {
        ast::item_class(def, tys) => {
            let def = @{
                dtor: None, // Remove the drop { } block
                .. *def
            };
            ast::item_class(def, tys)
        }
        _ => fail ~"not a struct"
    };

    @{
        attrs: ~[], // Remove the attributes
        node: node,
        .. *item
    }
}

#[test]
fn should_add_struct_defs() {
    let doc = test::mk_doc(~"struct S { field: () }");
    assert doc.cratemod().structs()[0].sig.get().contains("struct S {");
}

#[test]
fn should_not_serialize_struct_drop_blocks() {
    // All we care about are the fields
    let doc = test::mk_doc(~"struct S { field: (), drop { } }");
    assert !doc.cratemod().structs()[0].sig.get().contains("drop");
}

#[test]
fn should_not_serialize_struct_attrs() {
    // All we care about are the fields
    let doc = test::mk_doc(~"#[wut] struct S { field: () }");
    assert !doc.cratemod().structs()[0].sig.get().contains("wut");
}

#[cfg(test)]
mod test {
    fn mk_doc(source: ~str) -> doc::Doc {
        do astsrv::from_str(source) |srv| {
            let doc = extract::from_srv(srv, ~"");
            run(srv, doc)
        }
    }
}
<|endoftext|>


<commit_before>//!
//! Values manipulated by services
//!
use std::cmp::{PartialOrd, Ordering};
use std::time::Duration;
use std::str::FromStr;
use std::sync::Arc;

use serde_json;
use chrono;
use serde::ser::{Serialize, Serializer};
use serde::de::{Deserialize, Deserializer, Error};

///
/// The type of values manipulated by endpoints.
///
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
pub enum Type {
    ///
    /// # Trivial values
    ///

    /// An empty value. Used for instance to inform that a countdown
    /// has reached 0 or that a device is ready.
    Unit,

    /// A boolean. Used for instance for on-off switches, presence
    /// detectors, etc.
    Bool,

    ///
    /// # Time
    ///

    /// A duration. Used for instance in countdowns.
    Duration,

    /// A precise timestamp. Used for instance to determine when an
    /// event has taken place.
    TimeStamp,

    Temperature,
    String,
    ///
    /// ...
    ///
    Color,
    Json,
    Binary,
    ExtNumeric,
}

/// A temperature. Internal representation may be either Fahrenheit or
/// Celcius. The FoxBox adapters are expected to perform conversions
/// to the format requested by their devices.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Temperature {
    /// Fahrenheit
    F(f64),
    /// Celcius
    C(f64),
}

impl Temperature {
    /// Get a temperature in Fahrenheit.
    pub fn as_f(&self) -> f64 {
        unimplemented!();
    }

    /// Get a temperature in Celcius.
    pub fn as_c(&self) -> f64 {
        unimplemented!();
    }
}

impl PartialOrd for Temperature {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.as_c().partial_cmp(&other.as_c())
    }
}

/// A color. Internal representation may vary. The FoxBox adapters are
/// expected to perform conversions to the format requested by their
/// device.
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
pub enum Color {
    RGBA(f64, f64, f64, f64, f64)
}

/// Representation of an object in JSON. It is often (albeit not
/// always) possible to choose a more precise data structure for
/// representing values send/accepted by a service. If possible,
/// adapters should rather pick such more precise data structure.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Json(pub serde_json::value::Value);

impl PartialOrd for Json {
    /// Two Json objects are never comparable to each other.
    fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
        None
    }
}

/// A data structure holding a numeric value of a type that has not
/// been standardized yet.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ExtNumeric {
    pub value: f64,

    /// The vendor. Used for namespacing purposes, to avoid
    /// confusing two incompatible extensions with similar
    /// names. For instance, "foxlink@mozilla.com".
    pub vendor: String,

    /// Identification of the adapter introducing this value.
    /// Designed to aid with tracing and debugging.
    pub adapter: String,

    /// A string describing the nature of the value, designed to
    /// aid with type-checking.
    ///
    /// Examples: `"GroundHumidity"`.
    pub kind: String,
}

impl PartialOrd for ExtNumeric {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        if self.vendor != other.vendor {
            return None;
        } else if self.kind != other.kind {
            return None;
        } else {
            self.value.partial_cmp(&other.value)
        }
    }
}

/// Representation of an actual value that can be sent to/received
/// from a service.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Value {
    Unit,
    Bool(bool),
    Duration(ValDuration),
    TimeStamp(TimeStamp),
    Temperature(Temperature),
    Color(Color),
    String(Arc<String>),

    // FIXME: Add more as we identify needs

    /// A numeric value representing a unit that has not been
    /// standardized yet into the API.
    ExtNumeric(ExtNumeric),

    /// A Json value. We put it behind an `Arc` to make sure that
    /// cloning remains unexpensive.
    Json(Arc<Json>),

    /// Binary data.
    Binary {
        /// The actual data. We put it behind an `Arc` to make sure
        /// that cloning remains unexpensive.
        data: Arc<Vec<u8>>,
        mimetype: String
    }
}

impl Value {
    pub fn get_type(&self) -> Type {
        match *self {
            Value::Unit => Type::Unit,
            Value::Bool(_) => Type::Bool,
            Value::String(_) => Type::String,
            Value::Duration(_) => Type::Duration,
            Value::TimeStamp(_) => Type::TimeStamp,
            Value::Temperature(_) => Type::Temperature,
            Value::Color(_) => Type::Color,
            Value::Json(_) => Type::Json,
            Value::Binary{..} => Type::Binary,
            Value::ExtNumeric(_) => Type::ExtNumeric,
        }
    }
}

impl PartialOrd for Value {
    /// Two values of the same type can be compared using the usual
    /// comparison for values of this type. Two values of distinct
    /// types cannot be compared.
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        use self::Value::*;
        use std::cmp::Ordering::*;
        match (self, other) {
            (&Unit, &Unit) => Some(Equal),
            (&Unit, _) => None,

            (&Bool(a), &Bool(b)) => a.partial_cmp(&b),
            (&Bool(_), _) => None,

            (&Duration(ref a), &Duration(ref b)) => a.partial_cmp(b),
            (&Duration(_), _) => None,

            (&TimeStamp(ref a), &TimeStamp(ref b)) => a.partial_cmp(b),
            (&TimeStamp(_), _) => None,

            (&Temperature(ref a), &Temperature(ref b)) => a.partial_cmp(b),
            (&Temperature(_), _) => None,

            (&Color(ref a), &Color(ref b)) => a.partial_cmp(b),
            (&Color(_), _) => None,

            (&ExtNumeric(ref a), &ExtNumeric(ref b)) => a.partial_cmp(b),
            (&ExtNumeric(_), _) => None,

            (&String(ref a), &String(ref b)) => a.partial_cmp(b),
            (&String(_), _) => None,

            (&Json(ref a), &Json(ref b)) => a.partial_cmp(b),
            (&Json(_), _) => None,

            (&Binary{mimetype: ref a_mimetype, data: ref a_data},
             &Binary{mimetype: ref b_mimetype, data: ref b_data}) if a_mimetype == b_mimetype => a_data.partial_cmp(b_data),
            (&Binary{..}, _) => None,
        }
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct ValDuration(Duration);
impl ValDuration {
    pub fn new(duration: Duration) -> Self {
        ValDuration(duration)
    }
}
impl Serialize for ValDuration {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        let as_ms : u64 = self.0.as_secs() * 1000
            + (self.0.subsec_nanos() as u64) / 1_000_000;
        as_ms.serialize(serializer)
    }
}
impl Deserialize for ValDuration {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer {
        let as_ms : u64 = try!(u64::deserialize(deserializer));
        let as_sec = as_ms / 1000;
        let as_ns = (as_ms / 1_000_000) as u32;
        Ok(ValDuration(Duration::new(as_sec, as_ns)))
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct TimeStamp(chrono::DateTime<chrono::Local>);
impl TimeStamp {
    pub fn from_s(s: i64) -> Self {
        use chrono::*;
        let naive = chrono::naive::datetime::NaiveDateTime::from_timestamp(s, 0);
        let offset = chrono::offset::fixed::FixedOffset::east(0);
        let date = DateTime::<Local>::from_utc(naive, offset);
        TimeStamp(date)
    }
}
impl Serialize for TimeStamp {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        let str = self.0.to_rfc3339();
        str.serialize(serializer)
    }
}
impl Deserialize for TimeStamp {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer {
        let str = try!(String::deserialize(deserializer));
        match chrono::DateTime::<chrono::Local>::from_str(&str) {
            Ok(dt) => Ok(TimeStamp(dt)),
            Err(_) => Err(D::Error::syntax("Invalid date"))
        }
    }
}
<commit_msg>[fxbox/taxonomy] ValDuration now uses float<commit_after>//!
//! Values manipulated by services
//!
use std::cmp::{PartialOrd, Ordering};
use std::time::Duration;
use std::str::FromStr;
use std::sync::Arc;

use serde_json;
use chrono;
use serde::ser::{Serialize, Serializer};
use serde::de::{Deserialize, Deserializer, Error};

///
/// The type of values manipulated by endpoints.
///
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
pub enum Type {
    ///
    /// # Trivial values
    ///

    /// An empty value. Used for instance to inform that a countdown
    /// has reached 0 or that a device is ready.
    Unit,

    /// A boolean. Used for instance for on-off switches, presence
    /// detectors, etc.
    Bool,

    ///
    /// # Time
    ///

    /// A duration. Used for instance in countdowns.
    Duration,

    /// A precise timestamp. Used for instance to determine when an
    /// event has taken place.
    TimeStamp,

    Temperature,
    String,
    ///
    /// ...
    ///
    Color,
    Json,
    Binary,
    ExtNumeric,
}

/// A temperature. Internal representation may be either Fahrenheit or
/// Celcius. The FoxBox adapters are expected to perform conversions
/// to the format requested by their devices.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Temperature {
    /// Fahrenheit
    F(f64),
    /// Celcius
    C(f64),
}

impl Temperature {
    /// Get a temperature in Fahrenheit.
    pub fn as_f(&self) -> f64 {
        unimplemented!();
    }

    /// Get a temperature in Celcius.
    pub fn as_c(&self) -> f64 {
        unimplemented!();
    }
}

impl PartialOrd for Temperature {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.as_c().partial_cmp(&other.as_c())
    }
}

/// A color. Internal representation may vary. The FoxBox adapters are
/// expected to perform conversions to the format requested by their
/// device.
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
pub enum Color {
    RGBA(f64, f64, f64, f64, f64)
}

/// Representation of an object in JSON. It is often (albeit not
/// always) possible to choose a more precise data structure for
/// representing values send/accepted by a service. If possible,
/// adapters should rather pick such more precise data structure.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Json(pub serde_json::value::Value);

impl PartialOrd for Json {
    /// Two Json objects are never comparable to each other.
    fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
        None
    }
}

/// A data structure holding a numeric value of a type that has not
/// been standardized yet.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ExtNumeric {
    pub value: f64,

    /// The vendor. Used for namespacing purposes, to avoid
    /// confusing two incompatible extensions with similar
    /// names. For instance, "foxlink@mozilla.com".
    pub vendor: String,

    /// Identification of the adapter introducing this value.
    /// Designed to aid with tracing and debugging.
    pub adapter: String,

    /// A string describing the nature of the value, designed to
    /// aid with type-checking.
    ///
    /// Examples: `"GroundHumidity"`.
    pub kind: String,
}

impl PartialOrd for ExtNumeric {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        if self.vendor != other.vendor {
            return None;
        } else if self.kind != other.kind {
            return None;
        } else {
            self.value.partial_cmp(&other.value)
        }
    }
}

/// Representation of an actual value that can be sent to/received
/// from a service.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Value {
    Unit,
    Bool(bool),
    Duration(ValDuration),
    TimeStamp(TimeStamp),
    Temperature(Temperature),
    Color(Color),
    String(Arc<String>),

    // FIXME: Add more as we identify needs

    /// A numeric value representing a unit that has not been
    /// standardized yet into the API.
    ExtNumeric(ExtNumeric),

    /// A Json value. We put it behind an `Arc` to make sure that
    /// cloning remains unexpensive.
    Json(Arc<Json>),

    /// Binary data.
    Binary {
        /// The actual data. We put it behind an `Arc` to make sure
        /// that cloning remains unexpensive.
        data: Arc<Vec<u8>>,
        mimetype: String
    }
}

impl Value {
    pub fn get_type(&self) -> Type {
        match *self {
            Value::Unit => Type::Unit,
            Value::Bool(_) => Type::Bool,
            Value::String(_) => Type::String,
            Value::Duration(_) => Type::Duration,
            Value::TimeStamp(_) => Type::TimeStamp,
            Value::Temperature(_) => Type::Temperature,
            Value::Color(_) => Type::Color,
            Value::Json(_) => Type::Json,
            Value::Binary{..} => Type::Binary,
            Value::ExtNumeric(_) => Type::ExtNumeric,
        }
    }
}

impl PartialOrd for Value {
    /// Two values of the same type can be compared using the usual
    /// comparison for values of this type. Two values of distinct
    /// types cannot be compared.
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        use self::Value::*;
        use std::cmp::Ordering::*;
        match (self, other) {
            (&Unit, &Unit) => Some(Equal),
            (&Unit, _) => None,

            (&Bool(a), &Bool(b)) => a.partial_cmp(&b),
            (&Bool(_), _) => None,

            (&Duration(ref a), &Duration(ref b)) => a.partial_cmp(b),
            (&Duration(_), _) => None,

            (&TimeStamp(ref a), &TimeStamp(ref b)) => a.partial_cmp(b),
            (&TimeStamp(_), _) => None,

            (&Temperature(ref a), &Temperature(ref b)) => a.partial_cmp(b),
            (&Temperature(_), _) => None,

            (&Color(ref a), &Color(ref b)) => a.partial_cmp(b),
            (&Color(_), _) => None,

            (&ExtNumeric(ref a), &ExtNumeric(ref b)) => a.partial_cmp(b),
            (&ExtNumeric(_), _) => None,

            (&String(ref a), &String(ref b)) => a.partial_cmp(b),
            (&String(_), _) => None,

            (&Json(ref a), &Json(ref b)) => a.partial_cmp(b),
            (&Json(_), _) => None,

            (&Binary{mimetype: ref a_mimetype, data: ref a_data},
             &Binary{mimetype: ref b_mimetype, data: ref b_data}) if a_mimetype == b_mimetype => a_data.partial_cmp(b_data),
            (&Binary{..}, _) => None,
        }
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct ValDuration(Duration);
impl ValDuration {
    pub fn new(duration: Duration) -> Self {
        ValDuration(duration)
    }
}
impl Serialize for ValDuration {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        let as_ms : u64 = self.0.as_secs() * 1000
            + (self.0.subsec_nanos() as u64) / 1_000_000;
        as_ms.serialize(serializer)
    }
}
impl Deserialize for ValDuration {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer {
        let as_sec : f64 = try!(f64::deserialize(deserializer));
        Ok(ValDuration(Duration::new(as_sec as u64, as_sec.fract() as u32)))
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct TimeStamp(chrono::DateTime<chrono::Local>);
impl TimeStamp {
    pub fn from_s(s: i64) -> Self {
        use chrono::*;
        let naive = chrono::naive::datetime::NaiveDateTime::from_timestamp(s, 0);
        let offset = chrono::offset::fixed::FixedOffset::east(0);
        let date = DateTime::<Local>::from_utc(naive, offset);
        TimeStamp(date)
    }
}
impl Serialize for TimeStamp {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        let str = self.0.to_rfc3339();
        str.serialize(serializer)
    }
}
impl Deserialize for TimeStamp {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer {
        let str = try!(String::deserialize(deserializer));
        match chrono::DateTime::<chrono::Local>::from_str(&str) {
            Ok(dt) => Ok(TimeStamp(dt)),
            Err(_) => Err(D::Error::syntax("Invalid date"))
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 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.

//! A priority queue implemented with a binary heap

#![allow(missing_doc)]

use std::clone::Clone;
use std::mem::{move_val_init, init, replace, swap};
use std::slice;

/// A priority queue implemented with a binary heap
#[deriving(Clone)]
pub struct PriorityQueue<T> {
    data: Vec<T>,
}

impl<T:Ord> Container for PriorityQueue<T> {
    /// Returns the length of the queue
    fn len(&self) -> uint { self.data.len() }
}

impl<T:Ord> Mutable for PriorityQueue<T> {
    /// Drop all items from the queue
    fn clear(&mut self) { self.data.truncate(0) }
}

impl<T:Ord> PriorityQueue<T> {
    /// An iterator visiting all values in underlying vector, in
    /// arbitrary order.
    pub fn iter<'a>(&'a self) -> Items<'a, T> {
        Items { iter: self.data.iter() }
    }

    /// Returns the greatest item in the queue - fails if empty
    pub fn top<'a>(&'a self) -> &'a T { self.data.get(0) }

    /// Returns the greatest item in the queue - None if empty
    pub fn maybe_top<'a>(&'a self) -> Option<&'a T> {
        if self.is_empty() { None } else { Some(self.top()) }
    }

    /// Returns the number of elements the queue can hold without reallocating
    pub fn capacity(&self) -> uint { self.data.capacity() }

    /// Reserve capacity for exactly n elements in the PriorityQueue.
    /// Do nothing if the capacity is already sufficient.
    pub fn reserve_exact(&mut self, n: uint) { self.data.reserve_exact(n) }

    /// Reserve capacity for at least n elements in the PriorityQueue.
    /// Do nothing if the capacity is already sufficient.
    pub fn reserve(&mut self, n: uint) {
        self.data.reserve(n)
    }

    /// Pop the greatest item from the queue - fails if empty
    pub fn pop(&mut self) -> T {
        let mut item = self.data.pop().unwrap();
        if !self.is_empty() {
            swap(&mut item, self.data.get_mut(0));
            self.siftdown(0);
        }
        item
    }

    /// Pop the greatest item from the queue - None if empty
    pub fn maybe_pop(&mut self) -> Option<T> {
        if self.is_empty() { None } else { Some(self.pop()) }
    }

    /// Push an item onto the queue
    pub fn push(&mut self, item: T) {
        self.data.push(item);
        let new_len = self.len() - 1;
        self.siftup(0, new_len);
    }

    /// Optimized version of a push followed by a pop
    pub fn push_pop(&mut self, mut item: T) -> T {
        if !self.is_empty() && *self.top() > item {
            swap(&mut item, self.data.get_mut(0));
            self.siftdown(0);
        }
        item
    }

    /// Optimized version of a pop followed by a push - fails if empty
    pub fn replace(&mut self, mut item: T) -> T {
        swap(&mut item, self.data.get_mut(0));
        self.siftdown(0);
        item
    }

    /// Consume the PriorityQueue and return the underlying vector
    pub fn to_vec(self) -> Vec<T> { let PriorityQueue{data: v} = self; v }

    /// Consume the PriorityQueue and return a vector in sorted
    /// (ascending) order
    pub fn to_sorted_vec(self) -> Vec<T> {
        let mut q = self;
        let mut end = q.len();
        while end > 1 {
            end -= 1;
            q.data.as_mut_slice().swap(0, end);
            q.siftdown_range(0, end)
        }
        q.to_vec()
    }

    /// Create an empty PriorityQueue
    pub fn new() -> PriorityQueue<T> { PriorityQueue{data: vec!(),} }

    /// Create an empty PriorityQueue with capacity `capacity`
    pub fn with_capacity(capacity: uint) -> PriorityQueue<T> {
        PriorityQueue { data: Vec::with_capacity(capacity) }
    }

    /// Create a PriorityQueue from a vector (heapify)
    pub fn from_vec(xs: Vec<T>) -> PriorityQueue<T> {
        let mut q = PriorityQueue{data: xs,};
        let mut n = q.len() / 2;
        while n > 0 {
            n -= 1;
            q.siftdown(n)
        }
        q
    }

    // The implementations of siftup and siftdown use unsafe blocks in
    // order to move an element out of the vector (leaving behind a
    // zeroed element), shift along the others and move it back into the
    // vector over the junk element.  This reduces the constant factor
    // compared to using swaps, which involves twice as many moves.
    fn siftup(&mut self, start: uint, mut pos: uint) {
        unsafe {
            let new = replace(self.data.get_mut(pos), init());

            while pos > start {
                let parent = (pos - 1) >> 1;
                if new > *self.data.get(parent) {
                    let x = replace(self.data.get_mut(parent), init());
                    move_val_init(self.data.get_mut(pos), x);
                    pos = parent;
                    continue
                }
                break
            }
            move_val_init(self.data.get_mut(pos), new);
        }
    }

    fn siftdown_range(&mut self, mut pos: uint, end: uint) {
        unsafe {
            let start = pos;
            let new = replace(self.data.get_mut(pos), init());

            let mut child = 2 * pos + 1;
            while child < end {
                let right = child + 1;
                if right < end && !(*self.data.get(child) > *self.data.get(right)) {
                    child = right;
                }
                let x = replace(self.data.get_mut(child), init());
                move_val_init(self.data.get_mut(pos), x);
                pos = child;
                child = 2 * pos + 1;
            }

            move_val_init(self.data.get_mut(pos), new);
            self.siftup(start, pos);
        }
    }

    fn siftdown(&mut self, pos: uint) {
        let len = self.len();
        self.siftdown_range(pos, len);
    }
}

/// PriorityQueue iterator
pub struct Items <'a, T> {
    iter: slice::Items<'a, T>,
}

impl<'a, T> Iterator<&'a T> for Items<'a, T> {
    #[inline]
    fn next(&mut self) -> Option<(&'a T)> { self.iter.next() }

    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
}

impl<T: Ord> FromIterator<T> for PriorityQueue<T> {
    fn from_iter<Iter: Iterator<T>>(iter: Iter) -> PriorityQueue<T> {
        let mut q = PriorityQueue::new();
        q.extend(iter);
        q
    }
}

impl<T: Ord> Extendable<T> for PriorityQueue<T> {
    fn extend<Iter: Iterator<T>>(&mut self, mut iter: Iter) {
        let (lower, _) = iter.size_hint();

        let len = self.capacity();
        self.reserve(len + lower);

        for elem in iter {
            self.push(elem);
        }
    }
}

#[cfg(test)]
mod tests {
    use priority_queue::PriorityQueue;

    #[test]
    fn test_iterator() {
        let data = vec!(5, 9, 3);
        let iterout = [9, 5, 3];
        let pq = PriorityQueue::from_vec(data);
        let mut i = 0;
        for el in pq.iter() {
            assert_eq!(*el, iterout[i]);
            i += 1;
        }
    }

    #[test]
    fn test_top_and_pop() {
        let data = vec!(2u, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1);
        let mut sorted = data.clone();
        sorted.sort();
        let mut heap = PriorityQueue::from_vec(data);
        while !heap.is_empty() {
            assert_eq!(heap.top(), sorted.last().unwrap());
            assert_eq!(heap.pop(), sorted.pop().unwrap());
        }
    }

    #[test]
    fn test_push() {
        let mut heap = PriorityQueue::from_vec(vec!(2, 4, 9));
        assert_eq!(heap.len(), 3);
        assert!(*heap.top() == 9);
        heap.push(11);
        assert_eq!(heap.len(), 4);
        assert!(*heap.top() == 11);
        heap.push(5);
        assert_eq!(heap.len(), 5);
        assert!(*heap.top() == 11);
        heap.push(27);
        assert_eq!(heap.len(), 6);
        assert!(*heap.top() == 27);
        heap.push(3);
        assert_eq!(heap.len(), 7);
        assert!(*heap.top() == 27);
        heap.push(103);
        assert_eq!(heap.len(), 8);
        assert!(*heap.top() == 103);
    }

    #[test]
    fn test_push_unique() {
        let mut heap = PriorityQueue::from_vec(vec!(box 2, box 4, box 9));
        assert_eq!(heap.len(), 3);
        assert!(*heap.top() == box 9);
        heap.push(box 11);
        assert_eq!(heap.len(), 4);
        assert!(*heap.top() == box 11);
        heap.push(box 5);
        assert_eq!(heap.len(), 5);
        assert!(*heap.top() == box 11);
        heap.push(box 27);
        assert_eq!(heap.len(), 6);
        assert!(*heap.top() == box 27);
        heap.push(box 3);
        assert_eq!(heap.len(), 7);
        assert!(*heap.top() == box 27);
        heap.push(box 103);
        assert_eq!(heap.len(), 8);
        assert!(*heap.top() == box 103);
    }

    #[test]
    fn test_push_pop() {
        let mut heap = PriorityQueue::from_vec(vec!(5, 5, 2, 1, 3));
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.push_pop(6), 6);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.push_pop(0), 5);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.push_pop(4), 5);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.push_pop(1), 4);
        assert_eq!(heap.len(), 5);
    }

    #[test]
    fn test_replace() {
        let mut heap = PriorityQueue::from_vec(vec!(5, 5, 2, 1, 3));
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.replace(6), 5);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.replace(0), 6);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.replace(4), 5);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.replace(1), 4);
        assert_eq!(heap.len(), 5);
    }

    fn check_to_vec(mut data: Vec<int>) {
        let heap = PriorityQueue::from_vec(data.clone());
        let mut v = heap.clone().to_vec();
        v.sort();
        data.sort();

        assert_eq!(v, data);
        assert_eq!(heap.to_sorted_vec(), data);
    }

    #[test]
    fn test_to_vec() {
        check_to_vec(vec!());
        check_to_vec(vec!(5));
        check_to_vec(vec!(3, 2));
        check_to_vec(vec!(2, 3));
        check_to_vec(vec!(5, 1, 2));
        check_to_vec(vec!(1, 100, 2, 3));
        check_to_vec(vec!(1, 3, 5, 7, 9, 2, 4, 6, 8, 0));
        check_to_vec(vec!(2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1));
        check_to_vec(vec!(9, 11, 9, 9, 9, 9, 11, 2, 3, 4, 11, 9, 0, 0, 0, 0));
        check_to_vec(vec!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
        check_to_vec(vec!(10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0));
        check_to_vec(vec!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 1, 2));
        check_to_vec(vec!(5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1));
    }

    #[test]
    #[should_fail]
    fn test_empty_pop() {
        let mut heap: PriorityQueue<int> = PriorityQueue::new();
        heap.pop();
    }

    #[test]
    fn test_empty_maybe_pop() {
        let mut heap: PriorityQueue<int> = PriorityQueue::new();
        assert!(heap.maybe_pop().is_none());
    }

    #[test]
    #[should_fail]
    fn test_empty_top() {
        let empty: PriorityQueue<int> = PriorityQueue::new();
        empty.top();
    }

    #[test]
    fn test_empty_maybe_top() {
        let empty: PriorityQueue<int> = PriorityQueue::new();
        assert!(empty.maybe_top().is_none());
    }

    #[test]
    #[should_fail]
    fn test_empty_replace() {
        let mut heap: PriorityQueue<int> = PriorityQueue::new();
        heap.replace(5);
    }

    #[test]
    fn test_from_iter() {
        let xs = vec!(9u, 8, 7, 6, 5, 4, 3, 2, 1);

        let mut q: PriorityQueue<uint> = xs.as_slice().iter().rev().map(|&x| x).collect();

        for &x in xs.iter() {
            assert_eq!(q.pop(), x);
        }
    }
}
<commit_msg>Replaced Ord by TotalOrd in priority queue<commit_after>// Copyright 2013-2014 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.

//! A priority queue implemented with a binary heap

#![allow(missing_doc)]

use std::clone::Clone;
use std::mem::{move_val_init, init, replace, swap};
use std::slice;

/// A priority queue implemented with a binary heap
#[deriving(Clone)]
pub struct PriorityQueue<T> {
    data: Vec<T>,
}

impl<T: TotalOrd> Container for PriorityQueue<T> {
    /// Returns the length of the queue
    fn len(&self) -> uint { self.data.len() }
}

impl<T: TotalOrd> Mutable for PriorityQueue<T> {
    /// Drop all items from the queue
    fn clear(&mut self) { self.data.truncate(0) }
}

impl<T: TotalOrd> PriorityQueue<T> {
    /// An iterator visiting all values in underlying vector, in
    /// arbitrary order.
    pub fn iter<'a>(&'a self) -> Items<'a, T> {
        Items { iter: self.data.iter() }
    }

    /// Returns the greatest item in the queue - fails if empty
    pub fn top<'a>(&'a self) -> &'a T { self.data.get(0) }

    /// Returns the greatest item in the queue - None if empty
    pub fn maybe_top<'a>(&'a self) -> Option<&'a T> {
        if self.is_empty() { None } else { Some(self.top()) }
    }

    /// Returns the number of elements the queue can hold without reallocating
    pub fn capacity(&self) -> uint { self.data.capacity() }

    /// Reserve capacity for exactly n elements in the PriorityQueue.
    /// Do nothing if the capacity is already sufficient.
    pub fn reserve_exact(&mut self, n: uint) { self.data.reserve_exact(n) }

    /// Reserve capacity for at least n elements in the PriorityQueue.
    /// Do nothing if the capacity is already sufficient.
    pub fn reserve(&mut self, n: uint) {
        self.data.reserve(n)
    }

    /// Pop the greatest item from the queue - fails if empty
    pub fn pop(&mut self) -> T {
        let mut item = self.data.pop().unwrap();
        if !self.is_empty() {
            swap(&mut item, self.data.get_mut(0));
            self.siftdown(0);
        }
        item
    }

    /// Pop the greatest item from the queue - None if empty
    pub fn maybe_pop(&mut self) -> Option<T> {
        if self.is_empty() { None } else { Some(self.pop()) }
    }

    /// Push an item onto the queue
    pub fn push(&mut self, item: T) {
        self.data.push(item);
        let new_len = self.len() - 1;
        self.siftup(0, new_len);
    }

    /// Optimized version of a push followed by a pop
    pub fn push_pop(&mut self, mut item: T) -> T {
        if !self.is_empty() && *self.top() > item {
            swap(&mut item, self.data.get_mut(0));
            self.siftdown(0);
        }
        item
    }

    /// Optimized version of a pop followed by a push - fails if empty
    pub fn replace(&mut self, mut item: T) -> T {
        swap(&mut item, self.data.get_mut(0));
        self.siftdown(0);
        item
    }

    /// Consume the PriorityQueue and return the underlying vector
    pub fn to_vec(self) -> Vec<T> { let PriorityQueue{data: v} = self; v }

    /// Consume the PriorityQueue and return a vector in sorted
    /// (ascending) order
    pub fn to_sorted_vec(self) -> Vec<T> {
        let mut q = self;
        let mut end = q.len();
        while end > 1 {
            end -= 1;
            q.data.as_mut_slice().swap(0, end);
            q.siftdown_range(0, end)
        }
        q.to_vec()
    }

    /// Create an empty PriorityQueue
    pub fn new() -> PriorityQueue<T> { PriorityQueue{data: vec!(),} }

    /// Create an empty PriorityQueue with capacity `capacity`
    pub fn with_capacity(capacity: uint) -> PriorityQueue<T> {
        PriorityQueue { data: Vec::with_capacity(capacity) }
    }

    /// Create a PriorityQueue from a vector (heapify)
    pub fn from_vec(xs: Vec<T>) -> PriorityQueue<T> {
        let mut q = PriorityQueue{data: xs,};
        let mut n = q.len() / 2;
        while n > 0 {
            n -= 1;
            q.siftdown(n)
        }
        q
    }

    // The implementations of siftup and siftdown use unsafe blocks in
    // order to move an element out of the vector (leaving behind a
    // zeroed element), shift along the others and move it back into the
    // vector over the junk element.  This reduces the constant factor
    // compared to using swaps, which involves twice as many moves.
    fn siftup(&mut self, start: uint, mut pos: uint) {
        unsafe {
            let new = replace(self.data.get_mut(pos), init());

            while pos > start {
                let parent = (pos - 1) >> 1;
                if new > *self.data.get(parent) {
                    let x = replace(self.data.get_mut(parent), init());
                    move_val_init(self.data.get_mut(pos), x);
                    pos = parent;
                    continue
                }
                break
            }
            move_val_init(self.data.get_mut(pos), new);
        }
    }

    fn siftdown_range(&mut self, mut pos: uint, end: uint) {
        unsafe {
            let start = pos;
            let new = replace(self.data.get_mut(pos), init());

            let mut child = 2 * pos + 1;
            while child < end {
                let right = child + 1;
                if right < end && !(*self.data.get(child) > *self.data.get(right)) {
                    child = right;
                }
                let x = replace(self.data.get_mut(child), init());
                move_val_init(self.data.get_mut(pos), x);
                pos = child;
                child = 2 * pos + 1;
            }

            move_val_init(self.data.get_mut(pos), new);
            self.siftup(start, pos);
        }
    }

    fn siftdown(&mut self, pos: uint) {
        let len = self.len();
        self.siftdown_range(pos, len);
    }
}

/// PriorityQueue iterator
pub struct Items <'a, T> {
    iter: slice::Items<'a, T>,
}

impl<'a, T> Iterator<&'a T> for Items<'a, T> {
    #[inline]
    fn next(&mut self) -> Option<(&'a T)> { self.iter.next() }

    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
}

impl<T: TotalOrd> FromIterator<T> for PriorityQueue<T> {
    fn from_iter<Iter: Iterator<T>>(iter: Iter) -> PriorityQueue<T> {
        let mut q = PriorityQueue::new();
        q.extend(iter);
        q
    }
}

impl<T: TotalOrd> Extendable<T> for PriorityQueue<T> {
    fn extend<Iter: Iterator<T>>(&mut self, mut iter: Iter) {
        let (lower, _) = iter.size_hint();

        let len = self.capacity();
        self.reserve(len + lower);

        for elem in iter {
            self.push(elem);
        }
    }
}

#[cfg(test)]
mod tests {
    use priority_queue::PriorityQueue;

    #[test]
    fn test_iterator() {
        let data = vec!(5, 9, 3);
        let iterout = [9, 5, 3];
        let pq = PriorityQueue::from_vec(data);
        let mut i = 0;
        for el in pq.iter() {
            assert_eq!(*el, iterout[i]);
            i += 1;
        }
    }

    #[test]
    fn test_top_and_pop() {
        let data = vec!(2u, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1);
        let mut sorted = data.clone();
        sorted.sort();
        let mut heap = PriorityQueue::from_vec(data);
        while !heap.is_empty() {
            assert_eq!(heap.top(), sorted.last().unwrap());
            assert_eq!(heap.pop(), sorted.pop().unwrap());
        }
    }

    #[test]
    fn test_push() {
        let mut heap = PriorityQueue::from_vec(vec!(2, 4, 9));
        assert_eq!(heap.len(), 3);
        assert!(*heap.top() == 9);
        heap.push(11);
        assert_eq!(heap.len(), 4);
        assert!(*heap.top() == 11);
        heap.push(5);
        assert_eq!(heap.len(), 5);
        assert!(*heap.top() == 11);
        heap.push(27);
        assert_eq!(heap.len(), 6);
        assert!(*heap.top() == 27);
        heap.push(3);
        assert_eq!(heap.len(), 7);
        assert!(*heap.top() == 27);
        heap.push(103);
        assert_eq!(heap.len(), 8);
        assert!(*heap.top() == 103);
    }

    #[test]
    fn test_push_unique() {
        let mut heap = PriorityQueue::from_vec(vec!(box 2, box 4, box 9));
        assert_eq!(heap.len(), 3);
        assert!(*heap.top() == box 9);
        heap.push(box 11);
        assert_eq!(heap.len(), 4);
        assert!(*heap.top() == box 11);
        heap.push(box 5);
        assert_eq!(heap.len(), 5);
        assert!(*heap.top() == box 11);
        heap.push(box 27);
        assert_eq!(heap.len(), 6);
        assert!(*heap.top() == box 27);
        heap.push(box 3);
        assert_eq!(heap.len(), 7);
        assert!(*heap.top() == box 27);
        heap.push(box 103);
        assert_eq!(heap.len(), 8);
        assert!(*heap.top() == box 103);
    }

    #[test]
    fn test_push_pop() {
        let mut heap = PriorityQueue::from_vec(vec!(5, 5, 2, 1, 3));
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.push_pop(6), 6);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.push_pop(0), 5);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.push_pop(4), 5);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.push_pop(1), 4);
        assert_eq!(heap.len(), 5);
    }

    #[test]
    fn test_replace() {
        let mut heap = PriorityQueue::from_vec(vec!(5, 5, 2, 1, 3));
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.replace(6), 5);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.replace(0), 6);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.replace(4), 5);
        assert_eq!(heap.len(), 5);
        assert_eq!(heap.replace(1), 4);
        assert_eq!(heap.len(), 5);
    }

    fn check_to_vec(mut data: Vec<int>) {
        let heap = PriorityQueue::from_vec(data.clone());
        let mut v = heap.clone().to_vec();
        v.sort();
        data.sort();

        assert_eq!(v, data);
        assert_eq!(heap.to_sorted_vec(), data);
    }

    #[test]
    fn test_to_vec() {
        check_to_vec(vec!());
        check_to_vec(vec!(5));
        check_to_vec(vec!(3, 2));
        check_to_vec(vec!(2, 3));
        check_to_vec(vec!(5, 1, 2));
        check_to_vec(vec!(1, 100, 2, 3));
        check_to_vec(vec!(1, 3, 5, 7, 9, 2, 4, 6, 8, 0));
        check_to_vec(vec!(2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1));
        check_to_vec(vec!(9, 11, 9, 9, 9, 9, 11, 2, 3, 4, 11, 9, 0, 0, 0, 0));
        check_to_vec(vec!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
        check_to_vec(vec!(10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0));
        check_to_vec(vec!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 1, 2));
        check_to_vec(vec!(5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1));
    }

    #[test]
    #[should_fail]
    fn test_empty_pop() {
        let mut heap: PriorityQueue<int> = PriorityQueue::new();
        heap.pop();
    }

    #[test]
    fn test_empty_maybe_pop() {
        let mut heap: PriorityQueue<int> = PriorityQueue::new();
        assert!(heap.maybe_pop().is_none());
    }

    #[test]
    #[should_fail]
    fn test_empty_top() {
        let empty: PriorityQueue<int> = PriorityQueue::new();
        empty.top();
    }

    #[test]
    fn test_empty_maybe_top() {
        let empty: PriorityQueue<int> = PriorityQueue::new();
        assert!(empty.maybe_top().is_none());
    }

    #[test]
    #[should_fail]
    fn test_empty_replace() {
        let mut heap: PriorityQueue<int> = PriorityQueue::new();
        heap.replace(5);
    }

    #[test]
    fn test_from_iter() {
        let xs = vec!(9u, 8, 7, 6, 5, 4, 3, 2, 1);

        let mut q: PriorityQueue<uint> = xs.as_slice().iter().rev().map(|&x| x).collect();

        for &x in xs.iter() {
            assert_eq!(q.pop(), x);
        }
    }
}
<|endoftext|>


<commit_before>use agent::*;

mod agent;

// Type Observer
pub trait Observer {
    fn see(&mut self, time: f64, crowd: &Crowd);
    fn request_at(&mut self, time: f64) -> bool;
}

//
// * Barre de progression
//
struct ProgressMeter {
    freq: uint,
    ticks: uint
}

pub impl ProgressMeter {
    fn new(freq: uint) -> ProgressMeter {
        ProgressMeter { freq: freq, ticks: 0}
    }
}

impl Observer for ProgressMeter {
    fn see(&mut self, time: f64, crowd: &Crowd) {
        println(fmt!("%f : %u cellules", time as float, crowd.size()));
    }

    fn request_at(&mut self, time: f64) -> bool {
        self.ticks+=1;
        self.ticks % self.freq == 0
    }
}
//
// * Affichage à l'écran
//
struct ScreenPrinter {
    freq: uint,
    ticks: uint
}

pub impl ScreenPrinter {
    fn new(freq: uint) -> ScreenPrinter {
        ScreenPrinter { freq: freq, ticks: 0}
    }
}

impl Observer for ScreenPrinter {
    fn see(&mut self, time: f64, crowd: &Crowd) {
        println(fmt!("%f\n", time as float));
        println(crowd.to_str());
    }

    fn request_at(&mut self, time: f64) -> bool {
        self.ticks+=1;
        self.ticks % self.freq == 0
    }
}

//
// * Sortie sur le disque
//
struct DiskWriter {
    freq: uint,
    fname: ~str,
    curr_snap: uint,
    ticks: uint
}

pub impl DiskWriter {
    fn new(freq:uint, name: ~str) -> DiskWriter {
        DiskWriter {freq: freq, fname: copy name, curr_snap: 0, ticks: 0}
    }

    fn new_filename(&mut self) -> ~str {
        self.curr_snap+=1;
        fmt!("./%s-%03u.vtk", self.fname, self.curr_snap-1)
    }
}

impl Observer for DiskWriter {
    fn see(&mut self, time: f64, crowd: &Crowd) {
        let outfile=self.new_filename();
        let writer = result::get( &io::file_writer( &Path(outfile), [io::Create, io::Truncate] ) );

        // Ecriture de l'entête
        writer.write_str("# vtk DataFile Version 3.0\n");
        writer.write_str("Rusty_Cells\n");
        writer.write_str("ASCII\n");
        writer.write_str("DATASET UNSTRUCTURED_GRID\n");
        writer.write_str(fmt!("POINTS %u float\n", crowd.size()));

        // Coordonnées des cellules
        for crowd.cells.each |&cell| {
            writer.write_str(fmt!("%f %f 0\n",cell.x() as float, cell.y() as float))
        }

        // Données sur les nœuds
        writer.write_str(fmt!("POINT_DATA %u\nSCALARS %s float\nLOOKUP_TABLE default\n", crowd.size(), self.fname));
        for crowd.cells.each |&cell| {
            writer.write_str(fmt!("%f\n", cell.age as float));
        }
    }

    fn request_at(&mut self, time: f64) -> bool {
        self.ticks+=1;
        self.ticks % self.freq == 0
    }

}
<commit_msg>Sortie de la vitesse dans les fichiers de sortie<commit_after>use agent::*;

mod agent;

// Type Observer
pub trait Observer {
    fn see(&mut self, time: f64, crowd: &Crowd);
    fn request_at(&mut self, time: f64) -> bool;
}

//
// * Barre de progression
//
struct ProgressMeter {
    freq: uint,
    ticks: uint
}

pub impl ProgressMeter {
    fn new(freq: uint) -> ProgressMeter {
        ProgressMeter { freq: freq, ticks: 0}
    }
}

impl Observer for ProgressMeter {
    fn see(&mut self, time: f64, crowd: &Crowd) {
        println(fmt!("%f : %u cellules", time as float, crowd.size()));
    }

    fn request_at(&mut self, time: f64) -> bool {
        self.ticks+=1;
        self.ticks % self.freq == 0
    }
}
//
// * Affichage à l'écran
//
struct ScreenPrinter {
    freq: uint,
    ticks: uint
}

pub impl ScreenPrinter {
    fn new(freq: uint) -> ScreenPrinter {
        ScreenPrinter { freq: freq, ticks: 0}
    }
}

impl Observer for ScreenPrinter {
    fn see(&mut self, time: f64, crowd: &Crowd) {
        println(fmt!("%f\n", time as float));
        println(crowd.to_str());
    }

    fn request_at(&mut self, time: f64) -> bool {
        self.ticks+=1;
        self.ticks % self.freq == 0
    }
}

//
// * Sortie sur le disque
//
struct DiskWriter {
    freq: uint,
    fname: ~str,
    curr_snap: uint,
    ticks: uint
}

pub impl DiskWriter {
    fn new(freq:uint, name: ~str) -> DiskWriter {
        DiskWriter {freq: freq, fname: copy name, curr_snap: 0, ticks: 0}
    }

    fn new_filename(&mut self) -> ~str {
        self.curr_snap+=1;
        fmt!("./%s-%03u.vtk", self.fname, self.curr_snap-1)
    }
}

impl Observer for DiskWriter {
    fn see(&mut self, time: f64, crowd: &Crowd) {
        let outfile=self.new_filename();
        let writer = result::get( &io::file_writer( &Path(outfile), [io::Create, io::Truncate] ) );

        // Ecriture de l'entête
        writer.write_str("# vtk DataFile Version 3.0\n");
        writer.write_str("Rusty_Cells\n");
        writer.write_str("ASCII\n");
        writer.write_str("DATASET UNSTRUCTURED_GRID\n");
        writer.write_str(fmt!("POINTS %u float\n", crowd.size()));

        // Coordonnées des cellules
        for crowd.cells.each |&cell| {
            writer.write_str(fmt!("%f %f 0\n",cell.x() as float, cell.y() as float))
        }

        // Données sur les nœuds
        // * Age
        writer.write_str(fmt!("POINT_DATA %u\nSCALARS %s float\nLOOKUP_TABLE default\n", crowd.size(), "age"));
        for crowd.cells.each |&cell| {
            writer.write_str(fmt!("%f\n", cell.age as float));
        }
        // * Vitesse
        writer.write_str(fmt!("VECTORS %s float\n",  "vitesse"));
        for crowd.cells.each |&cell| {
            let speed=cell.velocity*1e3f64;
            writer.write_str(fmt!("%f %f 0\n", speed.x as float, speed.y as float))
        }
    }

    fn request_at(&mut self, time: f64) -> bool {
        self.ticks+=1;
        self.ticks % self.freq == 0
    }

}
<|endoftext|>


<commit_before>//! Representations of voice information.

use std::fmt;

use serde::de::{self, Deserialize, Deserializer, IgnoredAny, MapAccess, Visitor};

use super::{
    guild::Member,
    id::{ChannelId, GuildId, RoleId, UserId},
    user::User,
};
#[cfg(feature = "unstable_discord_api")]
use crate::model::permissions::Permissions;
use crate::model::Timestamp;

/// Information about an available voice region.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct VoiceRegion {
    /// Whether it is a custom voice region, which is used for events.
    pub custom: bool,
    /// Whether it is a deprecated voice region, which you should avoid using.
    pub deprecated: bool,
    /// The internal Id of the voice region.
    pub id: String,
    /// A recognizable name of the location of the voice region.
    pub name: String,
    /// Whether the voice region is optimal for use by the current user.
    pub optimal: bool,
}

/// A user's state within a voice channel.
#[derive(Clone, Serialize)]
#[non_exhaustive]
pub struct VoiceState {
    pub channel_id: Option<ChannelId>,
    pub deaf: bool,
    pub guild_id: Option<GuildId>,
    pub member: Option<Member>,
    pub mute: bool,
    pub self_deaf: bool,
    pub self_mute: bool,
    pub self_stream: Option<bool>,
    pub self_video: bool,
    pub session_id: String,
    pub suppress: bool,
    pub token: Option<String>,
    pub user_id: UserId,
    /// When unsuppressed, non-bot users will have this set to the current time.
    /// Bot users will be set to [`None`]. When suppressed, the user will have
    /// their [`Self::request_to_speak_timestamp`] removed.
    pub request_to_speak_timestamp: Option<Timestamp>,
}

impl fmt::Debug for VoiceState {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("VoiceState")
            .field("channel_id", &self.channel_id)
            .field("deaf", &self.deaf)
            .field("guild_id", &self.guild_id)
            .field("member", &self.member)
            .field("mute", &self.mute)
            .field("self_deaf", &self.self_deaf)
            .field("self_mute", &self.self_mute)
            .field("self_stream", &self.self_stream)
            .field("self_video", &self.self_video)
            .field("session_id", &self.session_id)
            .field("suppress", &self.suppress)
            .field("user_id", &self.user_id)
            .field("request_to_speak_timestamp", &self.request_to_speak_timestamp)
            .finish()
    }
}

impl<'de> Deserialize<'de> for VoiceState {
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        #[derive(Deserialize)]
        #[serde(field_identifier, rename_all = "snake_case")]
        enum Field {
            ChannelId,
            Deaf,
            GuildId,
            Member,
            Mute,
            SelfDeaf,
            SelfMute,
            SelfStream,
            SelfVideo,
            SessionId,
            Suppress,
            Token,
            UserId,
            RequestToSpeakTimestamp,
        }

        #[derive(Deserialize)]
        #[non_exhaustive]
        struct PartialMember {
            deaf: bool,
            joined_at: Option<Timestamp>,
            mute: bool,
            nick: Option<String>,
            roles: Vec<RoleId>,
            user: User,
            #[serde(default)]
            pending: bool,
            premium_since: Option<Timestamp>,
            #[cfg(feature = "unstable_discord_api")]
            permissions: Option<Permissions>,
            avatar: Option<String>,
            communication_disabled_until: Option<Timestamp>,
        }

        struct VoiceStateVisitor;

        impl<'de> Visitor<'de> for VoiceStateVisitor {
            type Value = VoiceState;

            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                f.write_str("struct VoiceState")
            }

            fn visit_map<V: MapAccess<'de>>(self, mut map: V) -> Result<Self::Value, V::Error> {
                let mut channel_id = None;
                let mut deaf = None;
                let mut guild_id = None;
                let mut member = None;
                let mut mute = None;
                let mut self_deaf = None;
                let mut self_mute = None;
                let mut self_stream = None;
                let mut self_video = None;
                let mut session_id = None;
                let mut suppress = None;
                let mut token = None;
                let mut user_id = None;
                let mut request_to_speak_timestamp = None;

                loop {
                    let key = match map.next_key() {
                        Ok(Some(key)) => key,
                        Ok(None) => break,
                        Err(_) => {
                            map.next_value::<IgnoredAny>()?;
                            continue;
                        },
                    };

                    match key {
                        Field::ChannelId => {
                            if channel_id.is_some() {
                                return Err(de::Error::duplicate_field("channel_id"));
                            }
                            channel_id = map.next_value()?;
                        },
                        Field::Deaf => {
                            if deaf.is_some() {
                                return Err(de::Error::duplicate_field("deaf"));
                            }
                            deaf = Some(map.next_value()?);
                        },
                        Field::GuildId => {
                            if guild_id.is_some() {
                                return Err(de::Error::duplicate_field("guild_id"));
                            }
                            guild_id = map.next_value()?;
                        },
                        Field::Member => {
                            if member.is_some() {
                                return Err(de::Error::duplicate_field("member"));
                            }

                            let partial_member: Option<PartialMember> = map.next_value()?;
                            if let Some(partial_member) = partial_member {
                                member = Some(Member {
                                    deaf: partial_member.deaf,
                                    guild_id: GuildId(0),
                                    joined_at: partial_member.joined_at,
                                    mute: partial_member.mute,
                                    nick: partial_member.nick,
                                    roles: partial_member.roles,
                                    user: partial_member.user,
                                    pending: partial_member.pending,
                                    premium_since: partial_member.premium_since,
                                    #[cfg(feature = "unstable_discord_api")]
                                    permissions: partial_member.permissions,
                                    avatar: partial_member.avatar,
                                    communication_disabled_until: partial_member
                                        .communication_disabled_until,
                                });
                            }
                        },
                        Field::Mute => {
                            if mute.is_some() {
                                return Err(de::Error::duplicate_field("mute"));
                            }
                            mute = Some(map.next_value()?);
                        },
                        Field::SelfDeaf => {
                            if self_deaf.is_some() {
                                return Err(de::Error::duplicate_field("self_deaf"));
                            }
                            self_deaf = Some(map.next_value()?);
                        },
                        Field::SelfMute => {
                            if self_mute.is_some() {
                                return Err(de::Error::duplicate_field("self_mute"));
                            }
                            self_mute = Some(map.next_value()?);
                        },
                        Field::SelfStream => {
                            if self_stream.is_some() {
                                return Err(de::Error::duplicate_field("self_stream"));
                            }
                            self_stream = map.next_value()?;
                        },
                        Field::SelfVideo => {
                            if self_video.is_some() {
                                return Err(de::Error::duplicate_field("self_video"));
                            }
                            self_video = Some(map.next_value()?);
                        },
                        Field::SessionId => {
                            if session_id.is_some() {
                                return Err(de::Error::duplicate_field("session_id"));
                            }
                            session_id = Some(map.next_value()?);
                        },
                        Field::Suppress => {
                            if suppress.is_some() {
                                return Err(de::Error::duplicate_field("suppress"));
                            }
                            suppress = Some(map.next_value()?);
                        },
                        Field::Token => {
                            if token.is_some() {
                                return Err(de::Error::duplicate_field("token"));
                            }
                            token = map.next_value()?;
                        },
                        Field::UserId => {
                            if user_id.is_some() {
                                return Err(de::Error::duplicate_field("user_id"));
                            }
                            user_id = Some(map.next_value()?);
                        },
                        Field::RequestToSpeakTimestamp => {
                            if request_to_speak_timestamp.is_some() {
                                return Err(de::Error::duplicate_field(
                                    "request_to_speak_timestamp",
                                ));
                            }
                            request_to_speak_timestamp = Some(map.next_value()?);
                        },
                    }
                }

                let deaf = deaf.ok_or_else(|| de::Error::missing_field("deaf"))?;
                let mute = mute.ok_or_else(|| de::Error::missing_field("mute"))?;
                let self_deaf = self_deaf.ok_or_else(|| de::Error::missing_field("self_deaf"))?;
                let self_mute = self_mute.ok_or_else(|| de::Error::missing_field("self_mute"))?;
                let self_video =
                    self_video.ok_or_else(|| de::Error::missing_field("self_video"))?;
                let session_id =
                    session_id.ok_or_else(|| de::Error::missing_field("session_id"))?;
                let suppress = suppress.ok_or_else(|| de::Error::missing_field("suppress"))?;
                let user_id = user_id.ok_or_else(|| de::Error::missing_field("user_id"))?;
                let request_to_speak_timestamp = request_to_speak_timestamp.unwrap_or(None);

                if let (Some(guild_id), Some(member)) = (guild_id, member.as_mut()) {
                    member.guild_id = guild_id;
                }

                Ok(VoiceState {
                    channel_id,
                    deaf,
                    guild_id,
                    member,
                    mute,
                    self_deaf,
                    self_mute,
                    self_stream,
                    self_video,
                    session_id,
                    suppress,
                    token,
                    user_id,
                    request_to_speak_timestamp,
                })
            }
        }

        const FIELDS: &[&str] = &[
            "channel_id",
            "deaf",
            "guild_id",
            "member",
            "mute",
            "self_deaf",
            "self_mute",
            "self_stream",
            "self_video",
            "session_id",
            "suppress",
            "token",
            "user_id",
            "request_to_speak_timestamp",
        ];

        deserializer.deserialize_struct("VoiceState", FIELDS, VoiceStateVisitor)
    }
}
<commit_msg>Replace manual deserialization of `VoiceState` with helper structs (#1714)<commit_after>//! Representations of voice information.

use std::fmt;

use serde::de::{Deserialize, Deserializer};

use crate::model::guild::{InterimMember, Member};
use crate::model::id::{ChannelId, GuildId, UserId};
use crate::model::Timestamp;

/// Information about an available voice region.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct VoiceRegion {
    /// Whether it is a custom voice region, which is used for events.
    pub custom: bool,
    /// Whether it is a deprecated voice region, which you should avoid using.
    pub deprecated: bool,
    /// The internal Id of the voice region.
    pub id: String,
    /// A recognizable name of the location of the voice region.
    pub name: String,
    /// Whether the voice region is optimal for use by the current user.
    pub optimal: bool,
}

/// A user's state within a voice channel.
#[derive(Clone, Serialize)]
#[non_exhaustive]
pub struct VoiceState {
    pub channel_id: Option<ChannelId>,
    pub deaf: bool,
    pub guild_id: Option<GuildId>,
    pub member: Option<Member>,
    pub mute: bool,
    pub self_deaf: bool,
    pub self_mute: bool,
    pub self_stream: Option<bool>,
    pub self_video: bool,
    pub session_id: String,
    pub suppress: bool,
    pub token: Option<String>,
    pub user_id: UserId,
    /// When unsuppressed, non-bot users will have this set to the current time.
    /// Bot users will be set to [`None`]. When suppressed, the user will have
    /// their [`Self::request_to_speak_timestamp`] removed.
    pub request_to_speak_timestamp: Option<Timestamp>,
}

impl fmt::Debug for VoiceState {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("VoiceState")
            .field("channel_id", &self.channel_id)
            .field("deaf", &self.deaf)
            .field("guild_id", &self.guild_id)
            .field("member", &self.member)
            .field("mute", &self.mute)
            .field("self_deaf", &self.self_deaf)
            .field("self_mute", &self.self_mute)
            .field("self_stream", &self.self_stream)
            .field("self_video", &self.self_video)
            .field("session_id", &self.session_id)
            .field("suppress", &self.suppress)
            .field("user_id", &self.user_id)
            .field("request_to_speak_timestamp", &self.request_to_speak_timestamp)
            .finish()
    }
}

impl<'de> Deserialize<'de> for VoiceState {
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        #[derive(Deserialize)]
        struct InterimVoiceState {
            channel_id: Option<ChannelId>,
            deaf: bool,
            guild_id: Option<GuildId>,
            member: Option<InterimMember>,
            mute: bool,
            self_deaf: bool,
            self_mute: bool,
            self_stream: Option<bool>,
            self_video: bool,
            session_id: String,
            suppress: bool,
            token: Option<String>,
            user_id: UserId,
            request_to_speak_timestamp: Option<Timestamp>,
        }

        let mut state = InterimVoiceState::deserialize(deserializer)?;

        if let (Some(guild_id), Some(member)) = (state.guild_id, state.member.as_mut()) {
            member.guild_id = guild_id;
        }

        Ok(VoiceState {
            channel_id: state.channel_id,
            deaf: state.deaf,
            guild_id: state.guild_id,
            member: state.member.map(Member::from),
            mute: state.mute,
            self_deaf: state.self_deaf,
            self_mute: state.self_mute,
            self_stream: state.self_stream,
            self_video: state.self_video,
            session_id: state.session_id,
            suppress: state.suppress,
            token: state.token,
            user_id: state.user_id,
            request_to_speak_timestamp: state.request_to_speak_timestamp,
        })
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Thread-local random number generator

use std::cell::UnsafeCell;

use {RngCore, CryptoRng, SeedableRng, Error};
use rngs::adapter::ReseedingRng;
use rngs::EntropyRng;
use rand_hc::Hc128Core;

// Rationale for using `UnsafeCell` in `ThreadRng`:
//
// Previously we used a `RefCell`, with an overhead of ~15%. There will only
// ever be one mutable reference to the interior of the `UnsafeCell`, because
// we only have such a reference inside `next_u32`, `next_u64`, etc. Within a
// single thread (which is the definition of `ThreadRng`), there will only ever
// be one of these methods active at a time.
//
// A possible scenario where there could be multiple mutable references is if
// `ThreadRng` is used inside `next_u32` and co. But the implementation is
// completely under our control. We just have to ensure none of them use
// `ThreadRng` internally, which is nonsensical anyway. We should also never run
// `ThreadRng` in destructors of its implementation, which is also nonsensical.
//
// The additional `Rc` is not strictly neccesary, and could be removed. For now
// it ensures `ThreadRng` stays `!Send` and `!Sync`, and implements `Clone`.

// Number of generated bytes after which to reseed `TreadRng`.
//
// The time it takes to reseed HC-128 is roughly equivalent to generating 7 KiB.
// We pick a treshold here that is large enough to not reduce the average
// performance too much, but also small enough to not make reseeding something
// that basically never happens.
const THREAD_RNG_RESEED_THRESHOLD: u64 = 32*1024*1024; // 32 MiB

/// The type returned by [`thread_rng`], essentially just a reference to the
/// PRNG in thread-local memory.
///
/// `ThreadRng` uses [`ReseedingRng`] wrapping the same PRNG as [`StdRng`],
/// which is reseeded after generating 32 MiB of random data. A single instance
/// is cached per thread and the returned `ThreadRng` is a reference to this
/// instance — hence `ThreadRng` is neither `Send` nor `Sync` but is safe to use
/// within a single thread. This RNG is seeded and reseeded via [`EntropyRng`]
/// as required.
///
/// Note that the reseeding is done as an extra precaution against entropy
/// leaks and is in theory unnecessary — to predict `ThreadRng`'s output, an
/// attacker would have to either determine most of the RNG's seed or internal
/// state, or crack the algorithm used.
///
/// Like [`StdRng`], `ThreadRng` is a cryptographically secure PRNG. The current
/// algorithm used is [HC-128], which is an array-based PRNG that trades memory
/// usage for better performance. This makes it similar to ISAAC, the algorithm
/// used in `ThreadRng` before rand 0.5.
///
/// Cloning this handle just produces a new reference to the same thread-local
/// generator.
///
/// [`thread_rng`]: ../fn.thread_rng.html
/// [`ReseedingRng`]: adapter/struct.ReseedingRng.html
/// [`StdRng`]: struct.StdRng.html
/// [`EntropyRng`]: struct.EntropyRng.html
/// [HC-128]: ../../rand_hc/struct.Hc128Rng.html
#[derive(Clone, Debug)]
pub struct ThreadRng {
    // use of raw pointer implies type is neither Send nor Sync
    rng: *mut ReseedingRng<Hc128Core, EntropyRng>,
}

thread_local!(
    static THREAD_RNG_KEY: UnsafeCell<ReseedingRng<Hc128Core, EntropyRng>> = {
        let mut entropy_source = EntropyRng::new();
        let r = Hc128Core::from_rng(&mut entropy_source).unwrap_or_else(|err|
                panic!("could not initialize thread_rng: {}", err));
        let rng = ReseedingRng::new(r,
                                    THREAD_RNG_RESEED_THRESHOLD,
                                    entropy_source);
        UnsafeCell::new(rng)
    }
);

/// Retrieve the lazily-initialized thread-local random number
/// generator, seeded by the system. Intended to be used in method
/// chaining style, e.g. `thread_rng().gen::<i32>()`, or cached locally, e.g.
/// `let mut rng = thread_rng();`.
///
/// For more information see [`ThreadRng`].
///
/// [`ThreadRng`]: rngs/struct.ThreadRng.html
pub fn thread_rng() -> ThreadRng {
    ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.get()) }
}

impl RngCore for ThreadRng {
    #[inline(always)]
    fn next_u32(&mut self) -> u32 {
        unsafe { (*self.rng).next_u32() }
    }

    #[inline(always)]
    fn next_u64(&mut self) -> u64 {
        unsafe { (*self.rng).next_u64() }
    }

    fn fill_bytes(&mut self, dest: &mut [u8]) {
        unsafe { (*self.rng).fill_bytes(dest) }
    }

    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        unsafe { (*self.rng).try_fill_bytes(dest) }
    }
}

impl CryptoRng for ThreadRng {}

#[cfg(test)]
mod test {
    #[test]
    #[cfg(not(feature="stdweb"))]
    fn test_thread_rng() {
        use Rng;
        let mut r = ::thread_rng();
        r.gen::<i32>();
        assert_eq!(r.gen_range(0, 1), 0);
    }
}
<commit_msg>Add Default for ThreadRng<commit_after>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Thread-local random number generator

use std::cell::UnsafeCell;

use {RngCore, CryptoRng, SeedableRng, Error};
use rngs::adapter::ReseedingRng;
use rngs::EntropyRng;
use rand_hc::Hc128Core;

// Rationale for using `UnsafeCell` in `ThreadRng`:
//
// Previously we used a `RefCell`, with an overhead of ~15%. There will only
// ever be one mutable reference to the interior of the `UnsafeCell`, because
// we only have such a reference inside `next_u32`, `next_u64`, etc. Within a
// single thread (which is the definition of `ThreadRng`), there will only ever
// be one of these methods active at a time.
//
// A possible scenario where there could be multiple mutable references is if
// `ThreadRng` is used inside `next_u32` and co. But the implementation is
// completely under our control. We just have to ensure none of them use
// `ThreadRng` internally, which is nonsensical anyway. We should also never run
// `ThreadRng` in destructors of its implementation, which is also nonsensical.
//
// The additional `Rc` is not strictly neccesary, and could be removed. For now
// it ensures `ThreadRng` stays `!Send` and `!Sync`, and implements `Clone`.

// Number of generated bytes after which to reseed `TreadRng`.
//
// The time it takes to reseed HC-128 is roughly equivalent to generating 7 KiB.
// We pick a treshold here that is large enough to not reduce the average
// performance too much, but also small enough to not make reseeding something
// that basically never happens.
const THREAD_RNG_RESEED_THRESHOLD: u64 = 32*1024*1024; // 32 MiB

/// The type returned by [`thread_rng`], essentially just a reference to the
/// PRNG in thread-local memory.
///
/// `ThreadRng` uses [`ReseedingRng`] wrapping the same PRNG as [`StdRng`],
/// which is reseeded after generating 32 MiB of random data. A single instance
/// is cached per thread and the returned `ThreadRng` is a reference to this
/// instance — hence `ThreadRng` is neither `Send` nor `Sync` but is safe to use
/// within a single thread. This RNG is seeded and reseeded via [`EntropyRng`]
/// as required.
///
/// Note that the reseeding is done as an extra precaution against entropy
/// leaks and is in theory unnecessary — to predict `ThreadRng`'s output, an
/// attacker would have to either determine most of the RNG's seed or internal
/// state, or crack the algorithm used.
///
/// Like [`StdRng`], `ThreadRng` is a cryptographically secure PRNG. The current
/// algorithm used is [HC-128], which is an array-based PRNG that trades memory
/// usage for better performance. This makes it similar to ISAAC, the algorithm
/// used in `ThreadRng` before rand 0.5.
///
/// Cloning this handle just produces a new reference to the same thread-local
/// generator.
///
/// [`thread_rng`]: ../fn.thread_rng.html
/// [`ReseedingRng`]: adapter/struct.ReseedingRng.html
/// [`StdRng`]: struct.StdRng.html
/// [`EntropyRng`]: struct.EntropyRng.html
/// [HC-128]: ../../rand_hc/struct.Hc128Rng.html
#[derive(Clone, Debug)]
pub struct ThreadRng {
    // use of raw pointer implies type is neither Send nor Sync
    rng: *mut ReseedingRng<Hc128Core, EntropyRng>,
}

thread_local!(
    static THREAD_RNG_KEY: UnsafeCell<ReseedingRng<Hc128Core, EntropyRng>> = {
        let mut entropy_source = EntropyRng::new();
        let r = Hc128Core::from_rng(&mut entropy_source).unwrap_or_else(|err|
                panic!("could not initialize thread_rng: {}", err));
        let rng = ReseedingRng::new(r,
                                    THREAD_RNG_RESEED_THRESHOLD,
                                    entropy_source);
        UnsafeCell::new(rng)
    }
);

/// Retrieve the lazily-initialized thread-local random number
/// generator, seeded by the system. Intended to be used in method
/// chaining style, e.g. `thread_rng().gen::<i32>()`, or cached locally, e.g.
/// `let mut rng = thread_rng();`.
///
/// For more information see [`ThreadRng`].
///
/// [`ThreadRng`]: rngs/struct.ThreadRng.html
pub fn thread_rng() -> ThreadRng {
    ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.get()) }
}

impl Default for ThreadRng {
    fn default() -> ThreadRng {
        ::prelude::thread_rng()
    }
}

impl RngCore for ThreadRng {
    #[inline(always)]
    fn next_u32(&mut self) -> u32 {
        unsafe { (*self.rng).next_u32() }
    }

    #[inline(always)]
    fn next_u64(&mut self) -> u64 {
        unsafe { (*self.rng).next_u64() }
    }

    fn fill_bytes(&mut self, dest: &mut [u8]) {
        unsafe { (*self.rng).fill_bytes(dest) }
    }

    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        unsafe { (*self.rng).try_fill_bytes(dest) }
    }
}

impl CryptoRng for ThreadRng {}

#[cfg(test)]
mod test {
    #[test]
    #[cfg(not(feature="stdweb"))]
    fn test_thread_rng() {
        use Rng;
        let mut r = ::thread_rng();
        r.gen::<i32>();
        assert_eq!(r.gen_range(0, 1), 0);
    }
}
<|endoftext|>


<commit_before>/*
 * rustboy/cpu.rs
 *
 * This is the CPU of the GameBoy emulator. A technical specification
 * of the GameBoy can be found here: http://problemkaputt.de/pandocs.htm
 *
 */

/*
  16bit Hi   Lo   Name/Function
  AF    A    -    Accumulator & Flags
  BC    B    C    BC
  DE    D    E    DE
  HL    H    L    HL
  SP    -    -    Stack Pointer
  PC    -    -    Program Counter/Pointer
*/
struct Registers {
    // 8-bit registers:
    a: u8,      // acc and flags
    b: u8,      // BC
    c: u8,
    d: u8,      // DE
    e: u8,
    h: u8,      // HL
    l: u8,
    // 16-bit registers:
    af: u16,    // acc and flags
    bc: u16,    // BC
    de: u16,    // DE
    hl: u16,    // HL
    // pointers:
    sp: u16,    // stack pointer
    pc: u16     // program counter / instruction pointer
}

struct CPU;
<commit_msg>updated cpu structs<commit_after>/*
 * rustboy/cpu.rs
 *
 * This is the CPU of the GameBoy emulator. A technical specification
 * of the GameBoy can be found here: http://problemkaputt.de/pandocs.htm
 *
 */

// Declarations
// These have Z80 added to the names because eventually ARM7TDMI architecture
// will also be defined here.
struct Z80_Clock;
struct Z80_CPU;
struct Z80_Registers;

struct Z80_Clock {

}

/*
  16bit Hi   Lo   Name/Function
  AF    A    -    Accumulator & Flags
  BC    B    C    BC
  DE    D    E    DE
  HL    H    L    HL
  SP    -    -    Stack Pointer
  PC    -    -    Program Counter/Pointer
*/
struct Z80_Registers {
    // 8-bit registers:
    a: u8,      // acc and flags
    b: u8,      // BC
    c: u8,
    d: u8,      // DE
    e: u8,
    h: u8,      // HL
    l: u8,
    // 16-bit registers:
    af: u16,    // acc and flags
    bc: u16,    // BC
    de: u16,    // DE
    hl: u16,    // HL
    // pointers:
    sp: u16,    // stack pointer
    pc: u16     // program counter / instruction pointer
}

struct Z80_CPU;
<|endoftext|>