<commit_before>import option::{some, none};
import syntax::{visit, ast_util};
import syntax::ast::*;
import syntax::codemap::span;
import ty::{kind, kind_copyable, kind_sendable, kind_noncopyable};

// Kind analysis pass. There are three kinds:
//
//  sendable: scalar types, and unique types containing only sendable types
//  copyable: boxes, objects, closures, and uniques containing copyable types
//  noncopyable: resources, or unique types containing resources
//
// This pass ensures that type parameters are only instantiated with types
// whose kinds are equal or less general than the way the type parameter was
// annotated (with the `send` or `copy` keyword).
//
// It also verifies that noncopyable kinds are not copied. Sendability is not
// applied, since none of our language primitives send. Instead, the sending
// primitives in the stdlib are explicitly annotated to only take sendable
// types.

fn kind_to_str(k: kind) -> str {
    alt k {
      kind_sendable. { "sendable" }
      kind_copyable. { "copyable" }
      kind_noncopyable. { "noncopyable" }
    }
}

type rval_map = std::map::hashmap<node_id, ()>;

type ctx = {tcx: ty::ctxt,
            rval_map: rval_map,
            method_map: typeck::method_map,
            last_uses: last_use::last_uses};

fn check_crate(tcx: ty::ctxt, method_map: typeck::method_map,
               last_uses: last_use::last_uses, crate: @crate)
    -> rval_map {
    let ctx = {tcx: tcx,
               rval_map: std::map::new_int_hash(),
               method_map: method_map,
               last_uses: last_uses};
    let visit = visit::mk_vt(@{
        visit_expr: check_expr,
        visit_stmt: check_stmt,
        visit_fn: check_fn
        with *visit::default_visitor()
    });
    visit::visit_crate(*crate, ctx, visit);
    tcx.sess.abort_if_errors();
    ret ctx.rval_map;
}

// Yields the appropriate function to check the kind of closed over
// variables. `id` is the node_id for some expression that creates the
// closure.
fn with_closure_check_fn(cx: ctx, id: node_id,
                         b: block(fn(ctx, ty::t, sp: span))) {
    let fty = ty::node_id_to_monotype(cx.tcx, id);
    alt ty::ty_fn_proto(cx.tcx, fty) {
      proto_send. { b(check_send); }
      proto_shared(_) { b(check_copy); }
      proto_block. | proto_bare. { /* no check needed */ }
    }
}

// Check that the free variables used in a shared/sendable closure conform
// to the copy/move kind bounds. Then recursively check the function body.
fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span,
            id: node_id, cx: ctx, v: visit::vt<ctx>) {

    // n.b.: This could be the body of either a fn decl or a fn expr.  In the
    // former case, the prototype will be proto_bare and no check occurs.  In
    // the latter case, we do not check the variables that in the capture
    // clause (as we don't have access to that here) but just those that
    // appear free.  The capture clauses are checked below, in check_expr().
    //
    // We could do this check also in check_expr(), but it seems more
    // "future-proof" to do it this way, as check_fn_body() is supposed to be
    // the common flow point for all functions that appear in the AST.

    with_closure_check_fn(cx, id) { |check_fn|
        for @{def, span} in *freevars::get_freevars(cx.tcx, id) {
            let id = ast_util::def_id_of_def(def).node;
            let ty = ty::node_id_to_type(cx.tcx, id);
            check_fn(cx, ty, span);
        }
    }

    visit::visit_fn(fk, decl, body, sp, id, cx, v);
}

fn check_fn_cap_clause(cx: ctx,
                       id: node_id,
                       cap_clause: capture_clause) {
    // Check that the variables named in the clause which are not free vars
    // (if any) are also legal.  freevars are checked above in check_fn_body.
    // This is kind of a degenerate case, as captured variables will generally
    // appear free in the body.
    let freevars = freevars::get_freevars(cx.tcx, id);
    let freevar_ids = vec::map(*freevars, { |freevar|
        ast_util::def_id_of_def(freevar.def).node
    });
    //log("freevar_ids", freevar_ids);
    with_closure_check_fn(cx, id) { |check_fn|
        let check_var = lambda(&&cap_item: @capture_item) {
            let cap_def = cx.tcx.def_map.get(cap_item.id);
            let cap_def_id = ast_util::def_id_of_def(cap_def).node;
            if !vec::member(cap_def_id, freevar_ids) {
                let ty = ty::node_id_to_type(cx.tcx, cap_def_id);
                check_fn(cx, ty, cap_item.span);
            }
        };
        vec::iter(cap_clause.copies, check_var);
        vec::iter(cap_clause.moves, check_var);
    }
}

fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {

    alt e.node {
      expr_assign(_, ex) | expr_assign_op(_, _, ex) |
      expr_block({node: {expr: some(ex), _}, _}) |
      expr_unary(box(_), ex) | expr_unary(uniq(_), ex) { maybe_copy(cx, ex); }
      expr_ret(some(ex)) { maybe_copy(cx, ex); }
      expr_copy(expr) { check_copy_ex(cx, expr, false); }
      // Vector add copies.
      expr_binary(add., ls, rs) { maybe_copy(cx, ls); maybe_copy(cx, rs); }
      expr_rec(fields, def) {
        for field in fields { maybe_copy(cx, field.node.expr); }
        alt def {
          some(ex) {
            // All noncopyable fields must be overridden
            let t = ty::expr_ty(cx.tcx, ex);
            let ty_fields = alt ty::struct(cx.tcx, t) { ty::ty_rec(f) { f } };
            for tf in ty_fields {
                if !vec::any(fields, {|f| f.node.ident == tf.ident}) &&
                    !ty::kind_can_be_copied(ty::type_kind(cx.tcx, tf.mt.ty)) {
                    cx.tcx.sess.span_err(ex.span,
                                         "copying a noncopyable value");
                }
            }
          }
          _ {}
        }
      }
      expr_tup(exprs) | expr_vec(exprs, _) {
        for expr in exprs { maybe_copy(cx, expr); }
      }
      expr_bind(_, args) {
        for a in args { alt a { some(ex) { maybe_copy(cx, ex); } _ {} } }
      }
      expr_call(f, args, _) {
        let i = 0u;
        for arg_t in ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f)) {
            alt arg_t.mode { by_copy. { maybe_copy(cx, args[i]); } _ {} }
            i += 1u;
        }
      }
      expr_path(_) {
        let substs = ty::node_id_to_ty_param_substs_opt_and_ty(cx.tcx, e.id);
        alt substs.substs {
          some(ts) {
            let did = ast_util::def_id_of_def(cx.tcx.def_map.get(e.id));
            let bounds = ty::lookup_item_type(cx.tcx, did).bounds;
            let i = 0u;
            for ty in ts {
                let kind = ty::type_kind(cx.tcx, ty);
                let p_kind = ty::param_bounds_to_kind(bounds[i]);
                if !ty::kind_lteq(p_kind, kind) {
                    cx.tcx.sess.span_err(e.span, "instantiating a " +
                                         kind_to_str(p_kind) +
                                         " type parameter with a "
                                         + kind_to_str(kind) + " type");
                }
                i += 1u;
            }
          }
          none. {}
        }
      }
      expr_ternary(_, a, b) { maybe_copy(cx, a); maybe_copy(cx, b); }
      expr_fn(_, _, _, cap_clause) {
        check_fn_cap_clause(cx, e.id, *cap_clause);
      }
      _ { }
    }
    visit::visit_expr(e, cx, v);
}

fn check_stmt(stmt: @stmt, cx: ctx, v: visit::vt<ctx>) {
    alt stmt.node {
      stmt_decl(@{node: decl_local(locals), _}, _) {
        for (_, local) in locals {
            alt local.node.init {
              some({op: init_assign., expr}) { maybe_copy(cx, expr); }
              _ {}
            }
        }
      }
      _ {}
    }
    visit::visit_stmt(stmt, cx, v);
}

fn maybe_copy(cx: ctx, ex: @expr) {
    check_copy_ex(cx, ex, true);
}

fn check_copy_ex(cx: ctx, ex: @expr, _warn: bool) {
    if ty::expr_is_lval(cx.method_map, cx.tcx, ex) &&
       !cx.last_uses.contains_key(ex.id) {
        let ty = ty::expr_ty(cx.tcx, ex);
        check_copy(cx, ty, ex.span);
        // FIXME turn this on again once vector types are no longer unique.
        // Right now, it is too annoying to be useful.
        /* if warn && ty::type_is_unique(cx.tcx, ty) {
            cx.tcx.sess.span_warn(ex.span, "copying a unique value");
        }*/
    }
}

fn check_copy(cx: ctx, ty: ty::t, sp: span) {
    if !ty::kind_can_be_copied(ty::type_kind(cx.tcx, ty)) {
        cx.tcx.sess.span_err(sp, "copying a noncopyable value");
    }
}

fn check_send(cx: ctx, ty: ty::t, sp: span) {
    if !ty::kind_can_be_sent(ty::type_kind(cx.tcx, ty)) {
        cx.tcx.sess.span_err(sp, "not a sendable value");
    }
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
<commit_msg>Properly handle expression blocks in kind.rs<commit_after>import option::{some, none};
import syntax::{visit, ast_util};
import syntax::ast::*;
import syntax::codemap::span;
import ty::{kind, kind_copyable, kind_sendable, kind_noncopyable};

// Kind analysis pass. There are three kinds:
//
//  sendable: scalar types, and unique types containing only sendable types
//  copyable: boxes, objects, closures, and uniques containing copyable types
//  noncopyable: resources, or unique types containing resources
//
// This pass ensures that type parameters are only instantiated with types
// whose kinds are equal or less general than the way the type parameter was
// annotated (with the `send` or `copy` keyword).
//
// It also verifies that noncopyable kinds are not copied. Sendability is not
// applied, since none of our language primitives send. Instead, the sending
// primitives in the stdlib are explicitly annotated to only take sendable
// types.

fn kind_to_str(k: kind) -> str {
    alt k {
      kind_sendable. { "sendable" }
      kind_copyable. { "copyable" }
      kind_noncopyable. { "noncopyable" }
    }
}

type rval_map = std::map::hashmap<node_id, ()>;

type ctx = {tcx: ty::ctxt,
            rval_map: rval_map,
            method_map: typeck::method_map,
            last_uses: last_use::last_uses};

fn check_crate(tcx: ty::ctxt, method_map: typeck::method_map,
               last_uses: last_use::last_uses, crate: @crate)
    -> rval_map {
    let ctx = {tcx: tcx,
               rval_map: std::map::new_int_hash(),
               method_map: method_map,
               last_uses: last_uses};
    let visit = visit::mk_vt(@{
        visit_expr: check_expr,
        visit_stmt: check_stmt,
        visit_block: check_block,
        visit_fn: check_fn
        with *visit::default_visitor()
    });
    visit::visit_crate(*crate, ctx, visit);
    tcx.sess.abort_if_errors();
    ret ctx.rval_map;
}

// Yields the appropriate function to check the kind of closed over
// variables. `id` is the node_id for some expression that creates the
// closure.
fn with_closure_check_fn(cx: ctx, id: node_id,
                         b: block(fn(ctx, ty::t, sp: span))) {
    let fty = ty::node_id_to_monotype(cx.tcx, id);
    alt ty::ty_fn_proto(cx.tcx, fty) {
      proto_send. { b(check_send); }
      proto_shared(_) { b(check_copy); }
      proto_block. | proto_bare. { /* no check needed */ }
    }
}

// Check that the free variables used in a shared/sendable closure conform
// to the copy/move kind bounds. Then recursively check the function body.
fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span,
            id: node_id, cx: ctx, v: visit::vt<ctx>) {

    // n.b.: This could be the body of either a fn decl or a fn expr.  In the
    // former case, the prototype will be proto_bare and no check occurs.  In
    // the latter case, we do not check the variables that in the capture
    // clause (as we don't have access to that here) but just those that
    // appear free.  The capture clauses are checked below, in check_expr().
    //
    // We could do this check also in check_expr(), but it seems more
    // "future-proof" to do it this way, as check_fn_body() is supposed to be
    // the common flow point for all functions that appear in the AST.

    with_closure_check_fn(cx, id) { |check_fn|
        for @{def, span} in *freevars::get_freevars(cx.tcx, id) {
            let id = ast_util::def_id_of_def(def).node;
            let ty = ty::node_id_to_type(cx.tcx, id);
            check_fn(cx, ty, span);
        }
    }

    visit::visit_fn(fk, decl, body, sp, id, cx, v);
}

fn check_fn_cap_clause(cx: ctx,
                       id: node_id,
                       cap_clause: capture_clause) {
    // Check that the variables named in the clause which are not free vars
    // (if any) are also legal.  freevars are checked above in check_fn_body.
    // This is kind of a degenerate case, as captured variables will generally
    // appear free in the body.
    let freevars = freevars::get_freevars(cx.tcx, id);
    let freevar_ids = vec::map(*freevars, { |freevar|
        ast_util::def_id_of_def(freevar.def).node
    });
    //log("freevar_ids", freevar_ids);
    with_closure_check_fn(cx, id) { |check_fn|
        let check_var = lambda(&&cap_item: @capture_item) {
            let cap_def = cx.tcx.def_map.get(cap_item.id);
            let cap_def_id = ast_util::def_id_of_def(cap_def).node;
            if !vec::member(cap_def_id, freevar_ids) {
                let ty = ty::node_id_to_type(cx.tcx, cap_def_id);
                check_fn(cx, ty, cap_item.span);
            }
        };
        vec::iter(cap_clause.copies, check_var);
        vec::iter(cap_clause.moves, check_var);
    }
}

fn check_block(b: blk, cx: ctx, v: visit::vt<ctx>) {
    alt b.node.expr {
      some(ex) { maybe_copy(cx, ex); }
      _ {}
    }
    visit::visit_block(b, cx, v);
}

fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
    alt e.node {
      expr_assign(_, ex) | expr_assign_op(_, _, ex) |
      expr_unary(box(_), ex) | expr_unary(uniq(_), ex) |
      expr_ret(some(ex)) { maybe_copy(cx, ex); }
      expr_copy(expr) { check_copy_ex(cx, expr, false); }
      // Vector add copies.
      expr_binary(add., ls, rs) { maybe_copy(cx, ls); maybe_copy(cx, rs); }
      expr_rec(fields, def) {
        for field in fields { maybe_copy(cx, field.node.expr); }
        alt def {
          some(ex) {
            // All noncopyable fields must be overridden
            let t = ty::expr_ty(cx.tcx, ex);
            let ty_fields = alt ty::struct(cx.tcx, t) { ty::ty_rec(f) { f } };
            for tf in ty_fields {
                if !vec::any(fields, {|f| f.node.ident == tf.ident}) &&
                    !ty::kind_can_be_copied(ty::type_kind(cx.tcx, tf.mt.ty)) {
                    cx.tcx.sess.span_err(ex.span,
                                         "copying a noncopyable value");
                }
            }
          }
          _ {}
        }
      }
      expr_tup(exprs) | expr_vec(exprs, _) {
        for expr in exprs { maybe_copy(cx, expr); }
      }
      expr_bind(_, args) {
        for a in args { alt a { some(ex) { maybe_copy(cx, ex); } _ {} } }
      }
      expr_call(f, args, _) {
        let i = 0u;
        for arg_t in ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f)) {
            alt arg_t.mode { by_copy. { maybe_copy(cx, args[i]); } _ {} }
            i += 1u;
        }
      }
      expr_path(_) {
        let substs = ty::node_id_to_ty_param_substs_opt_and_ty(cx.tcx, e.id);
        alt substs.substs {
          some(ts) {
            let did = ast_util::def_id_of_def(cx.tcx.def_map.get(e.id));
            let bounds = ty::lookup_item_type(cx.tcx, did).bounds;
            let i = 0u;
            for ty in ts {
                let kind = ty::type_kind(cx.tcx, ty);
                let p_kind = ty::param_bounds_to_kind(bounds[i]);
                if !ty::kind_lteq(p_kind, kind) {
                    cx.tcx.sess.span_err(e.span, "instantiating a " +
                                         kind_to_str(p_kind) +
                                         " type parameter with a "
                                         + kind_to_str(kind) + " type");
                }
                i += 1u;
            }
          }
          none. {}
        }
      }
      expr_ternary(_, a, b) { maybe_copy(cx, a); maybe_copy(cx, b); }
      expr_fn(_, _, _, cap_clause) {
        check_fn_cap_clause(cx, e.id, *cap_clause);
      }
      _ { }
    }
    visit::visit_expr(e, cx, v);
}

fn check_stmt(stmt: @stmt, cx: ctx, v: visit::vt<ctx>) {
    alt stmt.node {
      stmt_decl(@{node: decl_local(locals), _}, _) {
        for (_, local) in locals {
            alt local.node.init {
              some({op: init_assign., expr}) { maybe_copy(cx, expr); }
              _ {}
            }
        }
      }
      _ {}
    }
    visit::visit_stmt(stmt, cx, v);
}

fn maybe_copy(cx: ctx, ex: @expr) {
    check_copy_ex(cx, ex, true);
}

fn check_copy_ex(cx: ctx, ex: @expr, _warn: bool) {
    if ty::expr_is_lval(cx.method_map, cx.tcx, ex) &&
       !cx.last_uses.contains_key(ex.id) {
        let ty = ty::expr_ty(cx.tcx, ex);
        check_copy(cx, ty, ex.span);
        // FIXME turn this on again once vector types are no longer unique.
        // Right now, it is too annoying to be useful.
        /* if warn && ty::type_is_unique(cx.tcx, ty) {
            cx.tcx.sess.span_warn(ex.span, "copying a unique value");
        }*/
    }
}

fn check_copy(cx: ctx, ty: ty::t, sp: span) {
    if !ty::kind_can_be_copied(ty::type_kind(cx.tcx, ty)) {
        cx.tcx.sess.span_err(sp, "copying a noncopyable value");
    }
}

fn check_send(cx: ctx, ty: ty::t, sp: span) {
    if !ty::kind_can_be_sent(ty::type_kind(cx.tcx, ty)) {
        cx.tcx.sess.span_err(sp, "not a sendable value");
    }
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
<|endoftext|>


<commit_before>use crate::error::*;
use std::fmt;
use std::num::ParseFloatError;
use std::str::FromStr;
use std::string::ToString;

#[derive(Debug, PartialEq, Clone)]
pub struct Atom<T> {
    pub element: String,
    pub x: T,
    pub y: T,
    pub z: T,
}

impl<T> Atom<T> {
    pub fn new(element: &str, x: T, y: T, z: T) -> Self {
        Atom {
            element: element.to_string(),
            x: x,
            y: y,
            z: z,
        }
    }
}

impl<T> FromStr for Atom<T>
where
    T: FromStr<Err = ParseFloatError>,
{
    type Err = Error;

    fn from_str(s: &str) -> Result<Self> {
        let splitted: Vec<&str> = s.split_whitespace().collect();
        if splitted.len() != 4 {
            return Err(Error::IllegalState(String::from("")));
        }
        Ok(Atom::new(
            splitted[0],
            splitted[1].parse()?,
            splitted[2].parse()?,
            splitted[3].parse()?,
        ))
    }
}

impl<T: fmt::Display> fmt::Display for Atom<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {} {} {}", self.element, self.x, self.y, self.z)
    }
}

pub struct Snapshot<T> {
    pub comment: String,
    pub atoms: Vec<Atom<T>>,
}

impl<T> Snapshot<T> {
    pub fn size(&self) -> usize {
        self.atoms.len()
    }
}

impl<T: fmt::Display> fmt::Display for Snapshot<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "{}", self.size())?;
        write!(f, "{}", self.comment)?;
        for atom in &self.atoms {
            writeln!(f, "")?;
            write!(f, "{}", atom)?;
        }
        Ok(())
    }
}

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

    #[test]
    fn test_parse_atom() {
        let success = "C 10.0 11.0 12.0".parse();
        assert!(success.is_ok());
        assert_eq!(Atom::new("C", 10.0, 11.0, 12.0), success.unwrap());

        let failure: Result<Atom<f64>> = "C 1.0 2.0 a".parse();
        assert!(failure.is_err());
    }

    #[test]
    fn test_atom_to_string() {
        let atom = Atom::new("C", 11.2, 8.5, 14.8);
        assert_eq!("C 11.2 8.5 14.8", atom.to_string());
    }

    #[test]
    fn test_snapshot() {
        let snapshot = Snapshot {
            comment: "This is a comment".to_string(),
            atoms: vec![
                Atom::new("C", 10.0, 11.0, 12.0),
                Atom::new("O", 8.4, 12.8, 5.0),
                Atom::new("H", 23.0, 9.0, 11.8),
            ],
        };
        assert_eq!(3, snapshot.size());
        assert_eq!("This is a comment", snapshot.comment);
        assert_eq!(Atom::new("C", 10.0, 11.0, 12.0), snapshot.atoms[0]);
        assert_eq!(Atom::new("O", 8.4, 12.8, 5.0), snapshot.atoms[1]);
        assert_eq!(Atom::new("H", 23.0, 9.0, 11.8), snapshot.atoms[2]);
    }
}
<commit_msg>:white_check_mark: Add a test for impl Display for Snapshot<commit_after>use crate::error::*;
use std::fmt;
use std::num::ParseFloatError;
use std::str::FromStr;
use std::string::ToString;

#[derive(Debug, PartialEq, Clone)]
pub struct Atom<T> {
    pub element: String,
    pub x: T,
    pub y: T,
    pub z: T,
}

impl<T> Atom<T> {
    pub fn new(element: &str, x: T, y: T, z: T) -> Self {
        Atom {
            element: element.to_string(),
            x: x,
            y: y,
            z: z,
        }
    }
}

impl<T> FromStr for Atom<T>
where
    T: FromStr<Err = ParseFloatError>,
{
    type Err = Error;

    fn from_str(s: &str) -> Result<Self> {
        let splitted: Vec<&str> = s.split_whitespace().collect();
        if splitted.len() != 4 {
            return Err(Error::IllegalState(String::from("")));
        }
        Ok(Atom::new(
            splitted[0],
            splitted[1].parse()?,
            splitted[2].parse()?,
            splitted[3].parse()?,
        ))
    }
}

impl<T: fmt::Display> fmt::Display for Atom<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {} {} {}", self.element, self.x, self.y, self.z)
    }
}

pub struct Snapshot<T> {
    pub comment: String,
    pub atoms: Vec<Atom<T>>,
}

impl<T> Snapshot<T> {
    pub fn size(&self) -> usize {
        self.atoms.len()
    }
}

impl<T: fmt::Display> fmt::Display for Snapshot<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "{}", self.size())?;
        write!(f, "{}", self.comment)?;
        for atom in &self.atoms {
            writeln!(f, "")?;
            write!(f, "{}", atom)?;
        }
        Ok(())
    }
}

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

    #[test]
    fn test_parse_atom() {
        let success = "C 10.0 11.0 12.0".parse();
        assert!(success.is_ok());
        assert_eq!(Atom::new("C", 10.0, 11.0, 12.0), success.unwrap());

        let failure: Result<Atom<f64>> = "C 1.0 2.0 a".parse();
        assert!(failure.is_err());
    }

    #[test]
    fn test_atom_to_string() {
        let atom = Atom::new("C", 11.2, 8.5, 14.8);
        assert_eq!("C 11.2 8.5 14.8", atom.to_string());
    }

    #[test]
    fn test_snapshot() {
        let snapshot = Snapshot {
            comment: "This is a comment".to_string(),
            atoms: vec![
                Atom::new("C", 10.0, 11.0, 12.0),
                Atom::new("O", 8.4, 12.8, 5.0),
                Atom::new("H", 23.0, 9.0, 11.8),
            ],
        };
        assert_eq!(3, snapshot.size());
        assert_eq!("This is a comment", snapshot.comment);
        assert_eq!(Atom::new("C", 10.0, 11.0, 12.0), snapshot.atoms[0]);
        assert_eq!(Atom::new("O", 8.4, 12.8, 5.0), snapshot.atoms[1]);
        assert_eq!(Atom::new("H", 23.0, 9.0, 11.8), snapshot.atoms[2]);
    }

    #[test]
    fn test_format_snapshot() {
        let snapshot = Snapshot {
            comment: "This is a comment".to_string(),
            atoms: vec![
                Atom::new("C", 10.0, 11.0, 12.0),
                Atom::new("O", 8.4, 12.8, 5.0),
                Atom::new("H", 23.0, 9.0, 11.8),
            ],
        };
        assert_eq!(
            format!("{}", snapshot),
            "3\n\
             This is a comment\n\
             C 10 11 12\n\
             O 8.4 12.8 5\n\
             H 23 9 11.8"
        );
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::mem::transmute;
use std::ops::Deref;

use llvm_sys::prelude::*;
use llvm_sys::core::*;
use llvm_sys::*;

use super::*;

/// Enumeration of all the base types of the LLVM type system.
#[allow(non_camel_case_types)]
#[repr(C)]
pub enum Kind {
    Void = 0,
    Half,
    Float,
    Double,
    X86_FP80,
    FP128,
    PPC_FP128,
    Label,
    Metadata,
    X86_MMX,
    Token,

    Integer,
    Function,
    Struct,
    Array,
    Pointer,
    Vector,
}

/// Should always be used as `&Type`.
///
/// `Type`s are owned by `Context` instances such that only one instance of a
/// specific `Type` exists per `Context`, e.g. only 1 `Type` for `i64` exists
/// per context. `Type`s are also never mutated and never destroyed, living for
/// the lifetime of the `Context` that owns them.
// TODO: can this be made into an unsized type?
pub struct Type(LLVMType);

impl<'a> Into<&'a Type> for LLVMTypeRef {
    fn into(self) -> &'a Type {
        unsafe { transmute::<LLVMTypeRef, &Type>(self) }
    }
}

impl<'a> From<&'a Type> for LLVMTypeRef {
    fn from(ty: &'a Type) -> LLVMTypeRef {
        unsafe { transmute::<&Type, LLVMTypeRef>(ty) }
    }
}

impl Type {
    pub fn kind(&self) -> Kind {
        unsafe { transmute(LLVMGetTypeKind(self.into())) }
    }

    pub fn is_sized(&self) -> bool {
        unsafe { LLVMTypeIsSized(self.into()) == 1 }
    }
}

// This counts as the llvm::Type::print method from the C++ API, though the C++
// version has more options.
impl fmt::Display for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        unsafe {
            let s_ptr = LLVMPrintTypeToString(self.into());
            let r = write!(
                f,
                "{}",
                c_str_to_str!(s_ptr)
            );
            LLVMDisposeMessage(s_ptr);
            r
        }
    }
}

impl fmt::Debug for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "llvm::Type({})", self)
    }
}

macro_rules! impl_type {
    ($t:ty) => {
        impl<'a> Into<&'a $t> for LLVMTypeRef {
            fn into(self) -> &'a $t {
                unsafe { transmute::<LLVMTypeRef, &$t>(self) }
            }
        }

        impl<'a> From<&'a $t> for LLVMTypeRef {
            fn from(ty: &'a $t) -> LLVMTypeRef {
                unsafe { transmute::<&$t, LLVMTypeRef>(ty) }
            }
        }

        impl Deref for $t {
            type Target = Type;

            fn deref(&self) -> &Self::Target {
                unsafe { transmute::<&Self, &Self::Target>(self) }
            }
        }
    }
}

// Base types:

pub struct Void(Type);
impl_type!(Void);

pub struct Half(Type);
impl_type!(Half);

pub struct Float(Type);
impl_type!(Float);

pub struct Double(Type);
impl_type!(Double);

#[allow(non_camel_case_types)]
pub struct X86_FP80(Type);
impl_type!(X86_FP80);

#[allow(non_camel_case_types)]
pub struct FP128(Type);
impl_type!(FP128);

#[allow(non_camel_case_types)]
pub struct PPC_FP128(Type);
impl_type!(PPC_FP128);

pub struct Label(Type);
impl_type!(Label);

pub struct Metadata(Type);
impl_type!(Metadata);

#[allow(non_camel_case_types)]
pub struct X86_MMX(Type);
impl_type!(X86_MMX);

pub struct Token(Type);
impl_type!(Token);

/// Integer types are constructed with a size. Construct them with the methods
/// that `Context` provides.

pub struct Integer(Type);
impl_type!(Integer);

/// A function type is a tuple consisting of a return type and an array of
/// parameter types.
// TODO: check how varargs work

pub struct Function(Type);
impl_type!(Function);

impl Function {
    pub fn new<'a>(return_type: &'a Type, param_types: &[&'a Type], is_var_args: bool) -> &'a Function {
        unsafe {
            LLVMFunctionType(
                return_type.into(),
                transmute::<*const &Type, *mut LLVMTypeRef>(param_types.as_ptr()),
                param_types.len() as u32,
                is_var_args as LLVMBool
            ).into()
        }
    }
}

// TODO: Struct, Array, Pointer, Vector

/// Represents a LLVM Context Type
pub trait ContextType {
    fn get_type_in_context<'a>(context: &'a Context) -> &'a Type;
}

macro_rules! impl_context_type {
    ($t: ty, $to_type_in_context: ident) => {
        impl ContextType for $t {
            fn get_type_in_context<'a>(context: &'a Context) -> &'a Type {
                unsafe {
                    $to_type_in_context(context.ptr).into()
                }
            }
        }
    }
}

impl_context_type!(bool, LLVMInt1TypeInContext);
// This might actually not be true, Not sure
impl_context_type!(char, LLVMInt8TypeInContext);
impl_context_type!(u8, LLVMInt8TypeInContext);
impl_context_type!(u16, LLVMInt16TypeInContext);
impl_context_type!(u32, LLVMInt32TypeInContext);
impl_context_type!(u64, LLVMInt64TypeInContext);
impl_context_type!(i8, LLVMInt8TypeInContext);
impl_context_type!(i16, LLVMInt16TypeInContext);
impl_context_type!(i32, LLVMInt32TypeInContext);
impl_context_type!(i64, LLVMInt64TypeInContext);
impl_context_type!(f32, LLVMFloatTypeInContext);
impl_context_type!(f64, LLVMDoubleTypeInContext);
//TODO: Function Types
//TODO: Structure Types
//TODO: Sequential Types
//TODO: Other Types
<commit_msg>add Type comparisons<commit_after>use std::fmt;
use std::mem::transmute;
use std::ops::Deref;

use llvm_sys::prelude::*;
use llvm_sys::core::*;
use llvm_sys::*;

use super::*;

/// Enumeration of all the base types of the LLVM type system.
#[allow(non_camel_case_types)]
#[repr(C)]
pub enum Kind {
    Void = 0,
    Half,
    Float,
    Double,
    X86_FP80,
    FP128,
    PPC_FP128,
    Label,
    Metadata,
    X86_MMX,
    Token,

    Integer,
    Function,
    Struct,
    Array,
    Pointer,
    Vector,
}

/// Should always be used as `&Type`.
///
/// `Type`s are owned by `Context` instances such that only one instance of a
/// specific `Type` exists per `Context`, e.g. only 1 `Type` for `i64` exists
/// per context. `Type`s are also never mutated and never destroyed, living for
/// the lifetime of the `Context` that owns them.
// TODO: can this be made into an unsized type?
pub struct Type(LLVMType);

impl<'a> Into<&'a Type> for LLVMTypeRef {
    fn into(self) -> &'a Type {
        unsafe { transmute::<LLVMTypeRef, &Type>(self) }
    }
}

impl<'a> From<&'a Type> for LLVMTypeRef {
    fn from(ty: &'a Type) -> LLVMTypeRef {
        unsafe { transmute::<&Type, LLVMTypeRef>(ty) }
    }
}

impl Type {
    pub fn kind(&self) -> Kind {
        unsafe { transmute(LLVMGetTypeKind(self.into())) }
    }

    pub fn is_sized(&self) -> bool {
        unsafe { LLVMTypeIsSized(self.into()) == 1 }
    }
}

// This counts as the llvm::Type::print method from the C++ API, though the C++
// version has more options.
impl fmt::Display for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        unsafe {
            let s_ptr = LLVMPrintTypeToString(self.into());
            let r = write!(
                f,
                "{}",
                c_str_to_str!(s_ptr)
            );
            LLVMDisposeMessage(s_ptr);
            r
        }
    }
}

impl fmt::Debug for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "llvm::Type({})", self)
    }
}

impl PartialEq for Type {
    fn eq(&self, other: &Self) -> bool {
        LLVMTypeRef::from(self) == LLVMTypeRef::from(other)
    }
}

impl Eq for Type {}

macro_rules! impl_type {
    ($t:ty) => {
        impl<'a> Into<&'a $t> for LLVMTypeRef {
            fn into(self) -> &'a $t {
                unsafe { transmute::<LLVMTypeRef, &$t>(self) }
            }
        }

        impl<'a> From<&'a $t> for LLVMTypeRef {
            fn from(ty: &'a $t) -> LLVMTypeRef {
                unsafe { transmute::<&$t, LLVMTypeRef>(ty) }
            }
        }

        impl Deref for $t {
            type Target = Type;

            fn deref(&self) -> &Self::Target {
                unsafe { transmute::<&Self, &Self::Target>(self) }
            }
        }
    }
}

// Base types:

pub struct Void(Type);
impl_type!(Void);

pub struct Half(Type);
impl_type!(Half);

pub struct Float(Type);
impl_type!(Float);

pub struct Double(Type);
impl_type!(Double);

#[allow(non_camel_case_types)]
pub struct X86_FP80(Type);
impl_type!(X86_FP80);

#[allow(non_camel_case_types)]
pub struct FP128(Type);
impl_type!(FP128);

#[allow(non_camel_case_types)]
pub struct PPC_FP128(Type);
impl_type!(PPC_FP128);

pub struct Label(Type);
impl_type!(Label);

pub struct Metadata(Type);
impl_type!(Metadata);

#[allow(non_camel_case_types)]
pub struct X86_MMX(Type);
impl_type!(X86_MMX);

pub struct Token(Type);
impl_type!(Token);

/// Integer types are constructed with a size. Construct them with the methods
/// that `Context` provides.

pub struct Integer(Type);
impl_type!(Integer);

/// A function type is a tuple consisting of a return type and an array of
/// parameter types.
// TODO: check how varargs work

pub struct Function(Type);
impl_type!(Function);

impl Function {
    pub fn new<'a>(return_type: &'a Type, param_types: &[&'a Type], is_var_args: bool) -> &'a Function {
        unsafe {
            LLVMFunctionType(
                return_type.into(),
                transmute::<*const &Type, *mut LLVMTypeRef>(param_types.as_ptr()),
                param_types.len() as u32,
                is_var_args as LLVMBool
            ).into()
        }
    }
}

// TODO: Struct, Array, Pointer, Vector

/// Represents a LLVM Context Type
pub trait ContextType {
    fn get_type_in_context<'a>(context: &'a Context) -> &'a Type;
}

macro_rules! impl_context_type {
    ($t: ty, $to_type_in_context: ident) => {
        impl ContextType for $t {
            fn get_type_in_context<'a>(context: &'a Context) -> &'a Type {
                unsafe {
                    $to_type_in_context(context.ptr).into()
                }
            }
        }
    }
}

impl_context_type!(bool, LLVMInt1TypeInContext);
// This might actually not be true, Not sure
impl_context_type!(char, LLVMInt8TypeInContext);
impl_context_type!(u8, LLVMInt8TypeInContext);
impl_context_type!(u16, LLVMInt16TypeInContext);
impl_context_type!(u32, LLVMInt32TypeInContext);
impl_context_type!(u64, LLVMInt64TypeInContext);
impl_context_type!(i8, LLVMInt8TypeInContext);
impl_context_type!(i16, LLVMInt16TypeInContext);
impl_context_type!(i32, LLVMInt32TypeInContext);
impl_context_type!(i64, LLVMInt64TypeInContext);
impl_context_type!(f32, LLVMFloatTypeInContext);
impl_context_type!(f64, LLVMDoubleTypeInContext);
//TODO: Function Types
//TODO: Structure Types
//TODO: Sequential Types
//TODO: Other Types
<|endoftext|>


<commit_before>//! generic types for GPX

use geo::{Bbox, LineString, MultiLineString, Point};
use geo::{Geometry, ToGeo};

use chrono::prelude::Utc;
use chrono::DateTime;

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum GpxVersion {
    Unknown,
    Gpx10,
    Gpx11,
}

impl Default for GpxVersion {
    fn default() -> GpxVersion {
        GpxVersion::Unknown
    }
}

/// Gpx is the root element in the XML file.
#[derive(Clone, Default, Debug)]
pub struct Gpx {
    /// Version of the Gpx file.
    pub version: GpxVersion,

    /// Metadata about the file.
    pub metadata: Option<Metadata>,

    /// A list of waypoints.
    pub waypoints: Vec<Waypoint>,

    /// A list of tracks.
    pub tracks: Vec<Track>,
}

/// Metadata is information about the GPX file, author, and copyright restrictions.
///
/// Providing rich, meaningful information about your GPX files allows others to
/// search for and use your GPS data.
#[derive(Clone, Default, Debug)]
pub struct Metadata {
    /// The name of the GPX file.
    pub name: Option<String>,

    /// A description of the contents of the GPX file.
    pub description: Option<String>,

    /// The person or organization who created the GPX file.
    pub author: Option<Person>,

    /// URLs associated with the location described in the file.
    pub links: Vec<Link>,

    /// The creation date of the file.
    pub time: Option<DateTime<Utc>>,

    /// Keywords associated with the file. Search engines or databases can use
    /// this information to classify the data.
    pub keywords: Option<String>,
    /*copyright: GpxCopyrightType,*/
    /// Bounds for the tracks in the GPX.
    pub bounds: Option<Bbox<f64>>,
    /*extensions: GpxExtensionsType,*/
}

/// Track represents an ordered list of points describing a path.
#[derive(Clone, Default, Debug)]
pub struct Track {
    /// GPS name of track.
    pub name: Option<String>,

    /// GPS comment for track.
    pub comment: Option<String>,

    /// User description of track.
    pub description: Option<String>,

    /// Source of data. Included to give user some idea of reliability
    /// and accuracy of data.
    pub source: Option<String>,

    /// Links to external information about the track.
    pub links: Vec<Link>,

    /// Type (classification) of track.
    pub _type: Option<String>,

    /// A Track Segment holds a list of Track Points which are logically
    /// connected in order. To represent a single GPS track where GPS reception
    /// was lost, or the GPS receiver was turned off, start a new Track Segment
    /// for each continuous span of track data.
    pub segments: Vec<TrackSegment>,
    /* pub number: u8,*/
    /* extensions */
    /* trkSeg */
}

impl Track {
    /// Gives the multi-linestring that this track represents, which is multiple
    /// linestrings.
    pub fn multilinestring(&self) -> MultiLineString<f64> {
        self.segments.iter().map(|seg| seg.linestring()).collect()
    }

    /// Creates a new Track with default values.
    ///
    /// ```
    /// use gpx::{Track, TrackSegment};
    ///
    /// let mut track: Track = Track::new();
    ///
    /// let segment = TrackSegment::new();
    /// track.segments.push(segment);
    pub fn new() -> Track {
        Default::default()
    }
}

impl ToGeo<f64> for Track {
    fn to_geo(&self) -> Geometry<f64> {
        Geometry::MultiLineString(self.multilinestring())
    }
}

/// TrackSegment represents a list of track points.
///
/// This TrackSegment holds a list of Track Points which are logically
/// connected in order. To represent a single GPS track where GPS reception
/// was lost, or the GPS receiver was turned off, start a new Track Segment
/// for each continuous span of track data.
#[derive(Clone, Default, Debug)]
pub struct TrackSegment {
    /// Each Waypoint holds the coordinates, elevation, timestamp, and metadata
    /// for a single point in a track.
    pub points: Vec<Waypoint>,
    /* extensions */
}

impl TrackSegment {
    /// Gives the linestring of the segment's points, the sequence of points that
    /// comprises the track segment.
    pub fn linestring(&self) -> LineString<f64> {
        self.points.iter().map(|wpt| wpt.point()).collect()
    }

    /// Creates a new TrackSegment with default values.
    ///
    /// ```
    /// extern crate gpx;
    /// extern crate geo;
    ///
    /// use gpx::{TrackSegment, Waypoint};
    /// use geo::Point;
    ///
    /// fn main() {
    ///     let mut trkseg: TrackSegment = TrackSegment::new();
    ///
    ///     let point = Waypoint::new(Point::new(-121.97, 37.24));
    ///     trkseg.points.push(point);
    /// }
    pub fn new() -> TrackSegment {
        Default::default()
    }
}

impl ToGeo<f64> for TrackSegment {
    fn to_geo(&self) -> Geometry<f64> {
        Geometry::LineString(self.linestring())
    }
}

// A Version of geo::Point that has the Default trait implemented, which
// allows us to initialise the GpxPoint with default values compactly
// in the Waypoint::new function below
#[derive(Clone, Debug)]
struct GpxPoint(Point<f64>);

impl Default for GpxPoint {
    fn default() -> GpxPoint {
        GpxPoint(Point::new(0 as f64, 0 as f64))
    }
}

/// Waypoint represents a waypoint, point of interest, or named feature on a
/// map.
#[derive(Clone, Default, Debug)]
pub struct Waypoint {
    /// The geographical point.
    point: GpxPoint,

    /// Elevation (in meters) of the point.
    pub elevation: Option<f64>,

    /// Speed (in meters per second) (only in GPX 1.0)
    pub speed: Option<f64>,

    /// Creation/modification timestamp for element. Date and time in are in
    /// Univeral Coordinated Time (UTC), not local time! Conforms to ISO 8601
    /// specification for date/time representation. Fractional seconds are
    /// allowed for millisecond timing in tracklogs.
    pub time: Option<DateTime<Utc>>,

    /// The GPS name of the waypoint. This field will be transferred to and
    /// from the GPS. GPX does not place restrictions on the length of this
    /// field or the characters contained in it. It is up to the receiving
    /// application to validate the field before sending it to the GPS.
    pub name: Option<String>,

    /// GPS waypoint comment. Sent to GPS as comment.
    pub comment: Option<String>,

    /// A text description of the element. Holds additional information about
    /// the element intended for the user, not the GPS.
    pub description: Option<String>,

    /// Source of data. Included to give user some idea of reliability and
    /// accuracy of data. "Garmin eTrex", "USGS quad Boston North", e.g.
    pub source: Option<String>,

    /// Links to additional information about the waypoint.
    pub links: Vec<Link>,

    /// Text of GPS symbol name. For interchange with other programs, use the
    /// exact spelling of the symbol as displayed on the GPS. If the GPS
    /// abbreviates words, spell them out.
    pub symbol: Option<String>,

    /// Type (classification) of the waypoint.
    pub _type: Option<String>,

    // <magvar> degreesType </magvar> [0..1] ?
    /// Heigh of geoid in meters above WGS 84. This correspond to the sea level.
    pub geoidheight: Option<f64>,

    /// Type of GPS fix. `none` means GPS had no fix. To signify "the fix info
    /// is unknown", leave out `fix` entirely. Value comes from the list
    /// `{'none'|'2d'|'3d'|'dgps'|'pps'}`, where `pps` means that the military
    /// signal was used.
    pub fix: Option<Fix>,

    /// Number of satellites used to calculate the GPX fix.
    pub sat: Option<u64>,

    /// Horizontal dilution of precision.
    pub hdop: Option<f64>,

    /// Vertical dilution of precision.
    pub vdop: Option<f64>,

    /// Positional dilution of precision.
    pub pdop: Option<f64>,

    /// Number of seconds since last DGPS update, from the <ageofgpsdata> element.
    pub age: Option<f64>,

    /// ID of DGPS station used in differential correction, in the range [0, 1023].
    pub dgpsid: Option<u16>,
    // <extensions> extensionsType </extensions> [0..1] ?
}

impl Waypoint {
    /// Gives the geographical point of the waypoint.
    ///
    /// ```
    /// extern crate geo;
    /// extern crate gpx;
    ///
    /// use gpx::Waypoint;
    /// use geo::Point;
    ///
    /// fn main() {
    ///     // Kind of useless, but it shows the point.
    ///     let wpt = Waypoint::new(Point::new(-121.97, 37.24));
    ///     let point = wpt.point();
    ///
    ///     println!("waypoint latitude: {}, longitude: {}", point.lat(), point.lng());
    /// }
    /// ```
    pub fn point(&self) -> Point<f64> {
        self.point.0 //.0 to extract the geo::Point from the tuple struct GpxPoint
    }

    /// Creates a new Waypoint from a given geographical point.
    ///
    /// ```
    /// extern crate geo;
    /// extern crate gpx;
    ///
    /// use gpx::Waypoint;
    /// use geo::Point;
    ///
    /// fn main() {
    ///     let point = Point::new(-121.97, 37.24);
    ///
    ///     let mut wpt = Waypoint::new(point);
    ///     wpt.elevation = Some(553.21);
    /// }
    /// ```
    pub fn new(point: Point<f64>) -> Waypoint {
        Waypoint {
            point: GpxPoint(point),
            ..Default::default()
        }
    }
}

impl ToGeo<f64> for Waypoint {
    fn to_geo(&self) -> Geometry<f64> {
        Geometry::Point(self.point())
    }
}

/// Person represents a person or organization.
#[derive(Clone, Default, Debug)]
pub struct Person {
    /// Name of person or organization.
    pub name: Option<String>,

    /// Email address.
    pub email: Option<String>,

    /// Link to Web site or other external information about person.
    pub link: Option<Link>,
}

/// Link represents a link to an external resource.
///
/// An external resource could be a web page, digital photo,
/// video clip, etc., with additional information.
#[derive(Clone, Default, Debug)]
pub struct Link {
    /// URL of hyperlink.
    pub href: String,

    /// Text of hyperlink.
    pub text: Option<String>,

    /// Mime type of content (image/jpeg)
    pub _type: Option<String>,
}

/// Type of the GPS fix.
#[derive(Clone, Debug, PartialEq)]
pub enum Fix {
    /// The GPS had no fix. To signify "the fix info is unknown", leave out the Fix entirely.
    None,
    /// 2D fix gives only longitude and latitude. It needs a minimum of 3 satellites.
    TwoDimensional,
    /// 3D fix gives longitude, latitude and altitude. It needs a minimum of 4 satellites.
    ThreeDimensional,
    /// Differential Global Positioning System.
    DGPS,
    /// Military signal.
    PPS,
    /// Other values that are not in the specification.
    Other(String),
}
<commit_msg>Fix 'heigh' typo.<commit_after>//! generic types for GPX

use geo::{Bbox, LineString, MultiLineString, Point};
use geo::{Geometry, ToGeo};

use chrono::prelude::Utc;
use chrono::DateTime;

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum GpxVersion {
    Unknown,
    Gpx10,
    Gpx11,
}

impl Default for GpxVersion {
    fn default() -> GpxVersion {
        GpxVersion::Unknown
    }
}

/// Gpx is the root element in the XML file.
#[derive(Clone, Default, Debug)]
pub struct Gpx {
    /// Version of the Gpx file.
    pub version: GpxVersion,

    /// Metadata about the file.
    pub metadata: Option<Metadata>,

    /// A list of waypoints.
    pub waypoints: Vec<Waypoint>,

    /// A list of tracks.
    pub tracks: Vec<Track>,
}

/// Metadata is information about the GPX file, author, and copyright restrictions.
///
/// Providing rich, meaningful information about your GPX files allows others to
/// search for and use your GPS data.
#[derive(Clone, Default, Debug)]
pub struct Metadata {
    /// The name of the GPX file.
    pub name: Option<String>,

    /// A description of the contents of the GPX file.
    pub description: Option<String>,

    /// The person or organization who created the GPX file.
    pub author: Option<Person>,

    /// URLs associated with the location described in the file.
    pub links: Vec<Link>,

    /// The creation date of the file.
    pub time: Option<DateTime<Utc>>,

    /// Keywords associated with the file. Search engines or databases can use
    /// this information to classify the data.
    pub keywords: Option<String>,
    /*copyright: GpxCopyrightType,*/
    /// Bounds for the tracks in the GPX.
    pub bounds: Option<Bbox<f64>>,
    /*extensions: GpxExtensionsType,*/
}

/// Track represents an ordered list of points describing a path.
#[derive(Clone, Default, Debug)]
pub struct Track {
    /// GPS name of track.
    pub name: Option<String>,

    /// GPS comment for track.
    pub comment: Option<String>,

    /// User description of track.
    pub description: Option<String>,

    /// Source of data. Included to give user some idea of reliability
    /// and accuracy of data.
    pub source: Option<String>,

    /// Links to external information about the track.
    pub links: Vec<Link>,

    /// Type (classification) of track.
    pub _type: Option<String>,

    /// A Track Segment holds a list of Track Points which are logically
    /// connected in order. To represent a single GPS track where GPS reception
    /// was lost, or the GPS receiver was turned off, start a new Track Segment
    /// for each continuous span of track data.
    pub segments: Vec<TrackSegment>,
    /* pub number: u8,*/
    /* extensions */
    /* trkSeg */
}

impl Track {
    /// Gives the multi-linestring that this track represents, which is multiple
    /// linestrings.
    pub fn multilinestring(&self) -> MultiLineString<f64> {
        self.segments.iter().map(|seg| seg.linestring()).collect()
    }

    /// Creates a new Track with default values.
    ///
    /// ```
    /// use gpx::{Track, TrackSegment};
    ///
    /// let mut track: Track = Track::new();
    ///
    /// let segment = TrackSegment::new();
    /// track.segments.push(segment);
    pub fn new() -> Track {
        Default::default()
    }
}

impl ToGeo<f64> for Track {
    fn to_geo(&self) -> Geometry<f64> {
        Geometry::MultiLineString(self.multilinestring())
    }
}

/// TrackSegment represents a list of track points.
///
/// This TrackSegment holds a list of Track Points which are logically
/// connected in order. To represent a single GPS track where GPS reception
/// was lost, or the GPS receiver was turned off, start a new Track Segment
/// for each continuous span of track data.
#[derive(Clone, Default, Debug)]
pub struct TrackSegment {
    /// Each Waypoint holds the coordinates, elevation, timestamp, and metadata
    /// for a single point in a track.
    pub points: Vec<Waypoint>,
    /* extensions */
}

impl TrackSegment {
    /// Gives the linestring of the segment's points, the sequence of points that
    /// comprises the track segment.
    pub fn linestring(&self) -> LineString<f64> {
        self.points.iter().map(|wpt| wpt.point()).collect()
    }

    /// Creates a new TrackSegment with default values.
    ///
    /// ```
    /// extern crate gpx;
    /// extern crate geo;
    ///
    /// use gpx::{TrackSegment, Waypoint};
    /// use geo::Point;
    ///
    /// fn main() {
    ///     let mut trkseg: TrackSegment = TrackSegment::new();
    ///
    ///     let point = Waypoint::new(Point::new(-121.97, 37.24));
    ///     trkseg.points.push(point);
    /// }
    pub fn new() -> TrackSegment {
        Default::default()
    }
}

impl ToGeo<f64> for TrackSegment {
    fn to_geo(&self) -> Geometry<f64> {
        Geometry::LineString(self.linestring())
    }
}

// A Version of geo::Point that has the Default trait implemented, which
// allows us to initialise the GpxPoint with default values compactly
// in the Waypoint::new function below
#[derive(Clone, Debug)]
struct GpxPoint(Point<f64>);

impl Default for GpxPoint {
    fn default() -> GpxPoint {
        GpxPoint(Point::new(0 as f64, 0 as f64))
    }
}

/// Waypoint represents a waypoint, point of interest, or named feature on a
/// map.
#[derive(Clone, Default, Debug)]
pub struct Waypoint {
    /// The geographical point.
    point: GpxPoint,

    /// Elevation (in meters) of the point.
    pub elevation: Option<f64>,

    /// Speed (in meters per second) (only in GPX 1.0)
    pub speed: Option<f64>,

    /// Creation/modification timestamp for element. Date and time in are in
    /// Univeral Coordinated Time (UTC), not local time! Conforms to ISO 8601
    /// specification for date/time representation. Fractional seconds are
    /// allowed for millisecond timing in tracklogs.
    pub time: Option<DateTime<Utc>>,

    /// The GPS name of the waypoint. This field will be transferred to and
    /// from the GPS. GPX does not place restrictions on the length of this
    /// field or the characters contained in it. It is up to the receiving
    /// application to validate the field before sending it to the GPS.
    pub name: Option<String>,

    /// GPS waypoint comment. Sent to GPS as comment.
    pub comment: Option<String>,

    /// A text description of the element. Holds additional information about
    /// the element intended for the user, not the GPS.
    pub description: Option<String>,

    /// Source of data. Included to give user some idea of reliability and
    /// accuracy of data. "Garmin eTrex", "USGS quad Boston North", e.g.
    pub source: Option<String>,

    /// Links to additional information about the waypoint.
    pub links: Vec<Link>,

    /// Text of GPS symbol name. For interchange with other programs, use the
    /// exact spelling of the symbol as displayed on the GPS. If the GPS
    /// abbreviates words, spell them out.
    pub symbol: Option<String>,

    /// Type (classification) of the waypoint.
    pub _type: Option<String>,

    // <magvar> degreesType </magvar> [0..1] ?
    /// Height of geoid in meters above WGS 84. This correspond to the sea level.
    pub geoidheight: Option<f64>,

    /// Type of GPS fix. `none` means GPS had no fix. To signify "the fix info
    /// is unknown", leave out `fix` entirely. Value comes from the list
    /// `{'none'|'2d'|'3d'|'dgps'|'pps'}`, where `pps` means that the military
    /// signal was used.
    pub fix: Option<Fix>,

    /// Number of satellites used to calculate the GPX fix.
    pub sat: Option<u64>,

    /// Horizontal dilution of precision.
    pub hdop: Option<f64>,

    /// Vertical dilution of precision.
    pub vdop: Option<f64>,

    /// Positional dilution of precision.
    pub pdop: Option<f64>,

    /// Number of seconds since last DGPS update, from the <ageofgpsdata> element.
    pub age: Option<f64>,

    /// ID of DGPS station used in differential correction, in the range [0, 1023].
    pub dgpsid: Option<u16>,
    // <extensions> extensionsType </extensions> [0..1] ?
}

impl Waypoint {
    /// Gives the geographical point of the waypoint.
    ///
    /// ```
    /// extern crate geo;
    /// extern crate gpx;
    ///
    /// use gpx::Waypoint;
    /// use geo::Point;
    ///
    /// fn main() {
    ///     // Kind of useless, but it shows the point.
    ///     let wpt = Waypoint::new(Point::new(-121.97, 37.24));
    ///     let point = wpt.point();
    ///
    ///     println!("waypoint latitude: {}, longitude: {}", point.lat(), point.lng());
    /// }
    /// ```
    pub fn point(&self) -> Point<f64> {
        self.point.0 //.0 to extract the geo::Point from the tuple struct GpxPoint
    }

    /// Creates a new Waypoint from a given geographical point.
    ///
    /// ```
    /// extern crate geo;
    /// extern crate gpx;
    ///
    /// use gpx::Waypoint;
    /// use geo::Point;
    ///
    /// fn main() {
    ///     let point = Point::new(-121.97, 37.24);
    ///
    ///     let mut wpt = Waypoint::new(point);
    ///     wpt.elevation = Some(553.21);
    /// }
    /// ```
    pub fn new(point: Point<f64>) -> Waypoint {
        Waypoint {
            point: GpxPoint(point),
            ..Default::default()
        }
    }
}

impl ToGeo<f64> for Waypoint {
    fn to_geo(&self) -> Geometry<f64> {
        Geometry::Point(self.point())
    }
}

/// Person represents a person or organization.
#[derive(Clone, Default, Debug)]
pub struct Person {
    /// Name of person or organization.
    pub name: Option<String>,

    /// Email address.
    pub email: Option<String>,

    /// Link to Web site or other external information about person.
    pub link: Option<Link>,
}

/// Link represents a link to an external resource.
///
/// An external resource could be a web page, digital photo,
/// video clip, etc., with additional information.
#[derive(Clone, Default, Debug)]
pub struct Link {
    /// URL of hyperlink.
    pub href: String,

    /// Text of hyperlink.
    pub text: Option<String>,

    /// Mime type of content (image/jpeg)
    pub _type: Option<String>,
}

/// Type of the GPS fix.
#[derive(Clone, Debug, PartialEq)]
pub enum Fix {
    /// The GPS had no fix. To signify "the fix info is unknown", leave out the Fix entirely.
    None,
    /// 2D fix gives only longitude and latitude. It needs a minimum of 3 satellites.
    TwoDimensional,
    /// 3D fix gives longitude, latitude and altitude. It needs a minimum of 4 satellites.
    ThreeDimensional,
    /// Differential Global Positioning System.
    DGPS,
    /// Military signal.
    PPS,
    /// Other values that are not in the specification.
    Other(String),
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate libqmlbind_sys as ffi;

use libc::c_char;
use libc::c_int;

use std::ffi::CString;
use std::ffi::CStr;

fn main() {
    println!("libqmlbind-sys example");

    // Port of https://github.com/seanchas116/libqmlbind/blob/master/examples/hello_world_window/main.c

    // http://stackoverflow.com/a/34379937/178154
    // create a vector of zero terminated strings
    let args = std::env::args().map(|arg| CString::new(arg).unwrap() ).collect::<Vec<CString>>();
    // convert the strings to raw pointers
    let c_args = args.iter().map(|arg| arg.as_ptr()).collect::<Vec<*const c_char>>();
    unsafe {
        let app = ffi::qmlbind_application_new(c_args.len() as c_int, c_args.as_ptr());
        let engine = ffi::qmlbind_engine_new();
        let component = ffi::qmlbind_component_new(engine);
        // ffi::qmlbind_component_load_path(component, CString::new("examples/gallery.qml").unwrap().as_ptr());
        ffi::qmlbind_component_load_url(component, CString::new("qrc:/gallery.qml").unwrap().as_ptr());

        let errorString = ffi::qmlbind_component_get_error_string(component);
        println!("errorString: {:?}", errorString);
        // let errorChar = CString::from_raw(ffi::qmlbind_string_get_chars(errorString));
        let errorChar = CStr::from_ptr(ffi::qmlbind_string_get_chars(errorString));

        // let errorChar = std::str::from_utf8(ffi::qmlbind_string_get_chars(errorString));
        println!("errorChar: {:?}", errorChar);

        let instance = ffi::qmlbind_component_create(component);

        let exit_code = ffi::qmlbind_application_exec(app);

        ffi::qmlbind_value_release(instance);
        ffi::qmlbind_component_release(component);
        ffi::qmlbind_engine_release(engine);
        ffi::qmlbind_application_release(app);
    }
}
<commit_msg>Example should run, don't dereference null pointer<commit_after>extern crate libc;
extern crate libqmlbind_sys as ffi;

use libc::c_char;
use libc::c_int;

use std::ffi::CString;
use std::ffi::CStr;

fn main() {
    println!("libqmlbind-sys example");

    // Port of https://github.com/seanchas116/libqmlbind/blob/master/examples/hello_world_window/main.c

    // http://stackoverflow.com/a/34379937/178154
    // create a vector of zero terminated strings
    let args = std::env::args().map(|arg| CString::new(arg).unwrap() ).collect::<Vec<CString>>();
    // convert the strings to raw pointers
    let c_args = args.iter().map(|arg| arg.as_ptr()).collect::<Vec<*const c_char>>();
    unsafe {
        let app = ffi::qmlbind_application_new(c_args.len() as c_int, c_args.as_ptr());
        let engine = ffi::qmlbind_engine_new();
        let component = ffi::qmlbind_component_new(engine);
        // ffi::qmlbind_component_load_path(component, CString::new("examples/gallery.qml").unwrap().as_ptr());
        ffi::qmlbind_component_load_url(component, CString::new("qrc:/gallery.qml").unwrap().as_ptr());

        let errorString = ffi::qmlbind_component_get_error_string(component);
        println!("errorString: {:?}", errorString);
        // let errorChar = CString::from_raw(ffi::qmlbind_string_get_chars(errorString));
        // let errorChar = CStr::from_ptr(ffi::qmlbind_string_get_chars(errorString));

        // let errorChar = std::str::from_utf8(ffi::qmlbind_string_get_chars(errorString));
        // println!("errorChar: {:?}", errorChar);

        let instance = ffi::qmlbind_component_create(component);

        let exit_code = ffi::qmlbind_application_exec(app);

        ffi::qmlbind_value_release(instance);
        ffi::qmlbind_component_release(component);
        ffi::qmlbind_engine_release(engine);
        ffi::qmlbind_application_release(app);
    }
}
<|endoftext|>


<commit_before>
use ::TryInto;

use std::fmt;

/// Parses a String into a Value, first attempting bool, i64, and f64.
///
/// Examples:
///
/// ```
/// # use value::Value; use nccl::parse_into_value;
/// match parse_into_value("32.3".into()) {
///     Value::Float(f) => println!("value is float: {}", f),
///     _ => panic!("it's broke yo"),
/// }
///
/// match parse_into_value("something silly".into()) {
///     Value::String(s) => println!("none of the above: {}", s),
///     _ => panic!("it's really broke yo")
/// }
/// ```
pub fn parse_into_value(into: String) -> Value {
    match into.parse::<bool>() {
        Ok(b) => return Value::Bool(b),
        Err(_) => {},
    }

    match into.parse::<i64>() {
        Ok(i) => return Value::Integer(i),
        Err(_) => {},
    }

    match into.parse::<f64>() {
        Ok(f) => return Value::Float(f),
        Err(_) => {},
    }

    Value::String(into)
}

#[derive(Debug, PartialEq, Clone)]
/// Wrapper type for possible types in nccl configuration.
pub enum Value {
    String(String),
    Bool(bool),
    Integer(i64),
    Float(f64),
}

impl Value {
    fn into_string(self) -> Result<String, ()> {
        match self {
            Value::String(s) => Ok(s),
            _ => Err(())
        }
    }

    fn into_bool(self) -> Result<bool, ()> {
        match self {
            Value::Bool(b) => Ok(b),
            _ => Err(())
        }
    }

    fn into_integer(self) -> Result<i64, ()> {
        match self {
            Value::Integer(i) => Ok(i),
            _ => Err(())
        }
    }

    fn into_float(self) -> Result<f64, ()> {
        match self {
            Value::Float(f) => Ok(f),
            _ => Err(())
        }
    }
}

impl TryInto<String> for Value {
    type Error = ();
    fn try_into(self) -> Result<String, Self::Error> {
        self.into_string()
    }
}

impl TryInto<bool> for Value {
    type Error = ();
    fn try_into(self) -> Result<bool, Self::Error> {
        self.into_bool()
    }
}

impl TryInto<i64> for Value {
    type Error = ();
    fn try_into(self) -> Result<i64, Self::Error> {
        self.into_integer()
    }
}

impl TryInto<f64> for Value {
    type Error = ();
    fn try_into(self) -> Result<f64, Self::Error> {
        self.into_float()
    }
}

impl<'a> From<&'a Value> for Value {
    fn from(v: &'a Value) -> Self {
        v.clone()
    }
}

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

impl<'a> From<&'a String> for Value {
    fn from(s: &'a String) -> Self {
        Value::String(s.to_owned())
    }
}

impl<'a> From<&'a str> for Value {
    fn from(s: &'a str) -> Self {
        Value::String(s.to_owned())
    }
}

impl From<bool> for Value {
    fn from(b: bool) -> Self {
        Value::Bool(b)
    }
}

impl From<i64> for Value {
    fn from(i: i64) -> Self {
        Value::Integer(i)
    }
}

impl From<f64> for Value {
    fn from(f: f64) -> Self {
        Value::Float(f)
    }
}

impl Into<String> for Value {
    fn into(self) -> String {
        self.into_string().unwrap()
    }
}

impl Into<bool> for Value {
    fn into(self) -> bool {
        self.into_bool().unwrap()
    }
}

impl Into<i64> for Value {
    fn into(self) -> i64 {
        self.into_integer().unwrap()
    }
}

impl Into<f64> for Value {
    fn into(self) -> f64 {
        self.into_float().unwrap()
    }
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Value::Bool(b) => write!(f, "{}", b),
            &Value::String(ref s) => write!(f, "{}", s),
            &Value::Float(fl) => write!(f, "{}", fl),
            &Value::Integer(i) => write!(f, "{}", i),
        }
    }
}

<commit_msg>Update value.rs<commit_after>
use ::TryInto;

use std::fmt;

/// Parses a String into a Value, first attempting bool, i64, and f64.
///
/// Examples:
///
/// ```
/// # use nccl::value::Value; use nccl::parse_into_value;
/// match parse_into_value("32.3".into()) {
///     Value::Float(f) => println!("value is float: {}", f),
///     _ => panic!("it's broke yo"),
/// }
///
/// match parse_into_value("something silly".into()) {
///     Value::String(s) => println!("none of the above: {}", s),
///     _ => panic!("it's really broke yo")
/// }
/// ```
pub fn parse_into_value(into: String) -> Value {
    match into.parse::<bool>() {
        Ok(b) => return Value::Bool(b),
        Err(_) => {},
    }

    match into.parse::<i64>() {
        Ok(i) => return Value::Integer(i),
        Err(_) => {},
    }

    match into.parse::<f64>() {
        Ok(f) => return Value::Float(f),
        Err(_) => {},
    }

    Value::String(into)
}

#[derive(Debug, PartialEq, Clone)]
/// Wrapper type for possible types in nccl configuration.
pub enum Value {
    String(String),
    Bool(bool),
    Integer(i64),
    Float(f64),
}

impl Value {
    fn into_string(self) -> Result<String, ()> {
        match self {
            Value::String(s) => Ok(s),
            _ => Err(())
        }
    }

    fn into_bool(self) -> Result<bool, ()> {
        match self {
            Value::Bool(b) => Ok(b),
            _ => Err(())
        }
    }

    fn into_integer(self) -> Result<i64, ()> {
        match self {
            Value::Integer(i) => Ok(i),
            _ => Err(())
        }
    }

    fn into_float(self) -> Result<f64, ()> {
        match self {
            Value::Float(f) => Ok(f),
            _ => Err(())
        }
    }
}

impl TryInto<String> for Value {
    type Error = ();
    fn try_into(self) -> Result<String, Self::Error> {
        self.into_string()
    }
}

impl TryInto<bool> for Value {
    type Error = ();
    fn try_into(self) -> Result<bool, Self::Error> {
        self.into_bool()
    }
}

impl TryInto<i64> for Value {
    type Error = ();
    fn try_into(self) -> Result<i64, Self::Error> {
        self.into_integer()
    }
}

impl TryInto<f64> for Value {
    type Error = ();
    fn try_into(self) -> Result<f64, Self::Error> {
        self.into_float()
    }
}

impl<'a> From<&'a Value> for Value {
    fn from(v: &'a Value) -> Self {
        v.clone()
    }
}

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

impl<'a> From<&'a String> for Value {
    fn from(s: &'a String) -> Self {
        Value::String(s.to_owned())
    }
}

impl<'a> From<&'a str> for Value {
    fn from(s: &'a str) -> Self {
        Value::String(s.to_owned())
    }
}

impl From<bool> for Value {
    fn from(b: bool) -> Self {
        Value::Bool(b)
    }
}

impl From<i64> for Value {
    fn from(i: i64) -> Self {
        Value::Integer(i)
    }
}

impl From<f64> for Value {
    fn from(f: f64) -> Self {
        Value::Float(f)
    }
}

impl Into<String> for Value {
    fn into(self) -> String {
        self.into_string().unwrap()
    }
}

impl Into<bool> for Value {
    fn into(self) -> bool {
        self.into_bool().unwrap()
    }
}

impl Into<i64> for Value {
    fn into(self) -> i64 {
        self.into_integer().unwrap()
    }
}

impl Into<f64> for Value {
    fn into(self) -> f64 {
        self.into_float().unwrap()
    }
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Value::Bool(b) => write!(f, "{}", b),
            &Value::String(ref s) => write!(f, "{}", s),
            &Value::Float(fl) => write!(f, "{}", fl),
            &Value::Integer(i) => write!(f, "{}", i),
        }
    }
}

<|endoftext|>


<commit_before>use std::str::FromStr;
use std::io;
use std::io::Write;
use error::MemcacheError;

pub enum Flags {
    Bytes = 0,
}

/// determine how the value is serialize to memcache
pub trait ToMemcacheValue<W: Write> {
    fn get_flags(&self) -> u32;
    fn get_exptime(&self) -> u32;
    fn get_length(&self) -> usize;
    fn write_to(&self, stream: &mut W) -> io::Result<()>;
}

impl<'a, W: Write> ToMemcacheValue<W> for &'a [u8] {
    fn get_flags(&self) -> u32 {
        return Flags::Bytes as u32;
    }

    fn get_exptime(&self) -> u32 {
        return 0;
    }

    fn get_length(&self) -> usize {
        return self.len();
    }

    fn write_to(&self, stream: &mut W) -> io::Result<()> {
        match stream.write(self) {
            Ok(_) => Ok(()),
            Err(e) => Err(e),
        }
    }
}

impl<W: Write> ToMemcacheValue<W> for String {
    fn get_flags(&self) -> u32 {
        return Flags::Bytes as u32;
    }

    fn get_exptime(&self) -> u32 {
        return 0;
    }

    fn get_length(&self) -> usize {
        return self.as_bytes().len();
    }

    fn write_to(&self, stream: &mut W) -> io::Result<()> {
        match stream.write(self.as_bytes()) {
            Ok(_) => Ok(()),
            Err(e) => Err(e),
        }
    }
}

impl<'a, W: Write> ToMemcacheValue<W> for &'a str {
    fn get_flags(&self) -> u32 {
        return Flags::Bytes as u32;
    }

    fn get_exptime(&self) -> u32 {
        return 0;
    }

    fn get_length(&self) -> usize {
        return self.as_bytes().len();
    }

    fn write_to(&self, stream: &mut W) -> io::Result<()> {
        match stream.write(self.as_bytes()) {
            Ok(_) => Ok(()),
            Err(e) => Err(e),
        }
    }
}

macro_rules! impl_to_memcache_value_for_number{
    ($ty:ident) => {
        impl<W: Write> ToMemcacheValue<W> for $ty {
            fn get_flags(&self) -> u32 {
                return Flags::Bytes as u32;
            }

            fn get_exptime(&self) -> u32 {
                return 0;
            }

            fn get_length(&self) -> usize {
                return self.to_string().as_bytes().len();
            }

            fn write_to(&self, stream: &mut W) -> io::Result<()> {
                match stream.write(self.to_string().as_bytes()) {
                    Ok(_) => Ok(()),
                    Err(e) => Err(e),
                }
            }
        }
    }
}

impl_to_memcache_value_for_number!(bool);
impl_to_memcache_value_for_number!(u8);
impl_to_memcache_value_for_number!(u16);
impl_to_memcache_value_for_number!(u32);
impl_to_memcache_value_for_number!(u64);
impl_to_memcache_value_for_number!(i8);
impl_to_memcache_value_for_number!(i16);
impl_to_memcache_value_for_number!(i32);
impl_to_memcache_value_for_number!(i64);
impl_to_memcache_value_for_number!(f32);
impl_to_memcache_value_for_number!(f64);

type MemcacheValue<T> = Result<T, MemcacheError>;

/// determine how the value is unserialize to memcache
pub trait FromMemcacheValue: Sized {
    fn from_memcache_value(Vec<u8>, u32) -> MemcacheValue<Self>;
}

impl FromMemcacheValue for (Vec<u8>, u32) {
    fn from_memcache_value(value: Vec<u8>, flags: u32) -> MemcacheValue<Self> {
        return Ok((value, flags));
    }
}

impl FromMemcacheValue for Vec<u8> {
    fn from_memcache_value(value: Vec<u8>, _: u32) -> MemcacheValue<Self> {
        return Ok(value);
    }
}

impl FromMemcacheValue for String {
    fn from_memcache_value(value: Vec<u8>, _: u32) -> MemcacheValue<Self> {
        return Ok(String::from_utf8(value)?);
    }
}

macro_rules! impl_from_memcache_value_for_number{
    ($ty:ident) => {
        impl FromMemcacheValue for $ty {
            fn from_memcache_value(value: Vec<u8>, _: u32) -> MemcacheValue<Self> {
                let s: String = String::from_memcache_value(value, 0)?;
                match Self::from_str(s.as_str()) {
                    Ok(v) => return Ok(v),
                    Err(e) => Err(MemcacheError::from(e)),
                }
            }
        }
    }
}

impl_from_memcache_value_for_number!(bool);
impl_from_memcache_value_for_number!(u8);
impl_from_memcache_value_for_number!(u16);
impl_from_memcache_value_for_number!(u32);
impl_from_memcache_value_for_number!(u64);
impl_from_memcache_value_for_number!(i8);
impl_from_memcache_value_for_number!(i16);
impl_from_memcache_value_for_number!(i32);
impl_from_memcache_value_for_number!(i64);
impl_from_memcache_value_for_number!(f32);
impl_from_memcache_value_for_number!(f64);
<commit_msg>:fire: remove unused get_exptime from ToMemcacheValue<commit_after>use std::str::FromStr;
use std::io;
use std::io::Write;
use error::MemcacheError;

pub enum Flags {
    Bytes = 0,
}

/// determine how the value is serialize to memcache
pub trait ToMemcacheValue<W: Write> {
    fn get_flags(&self) -> u32;
    fn get_length(&self) -> usize;
    fn write_to(&self, stream: &mut W) -> io::Result<()>;
}

impl<'a, W: Write> ToMemcacheValue<W> for &'a [u8] {
    fn get_flags(&self) -> u32 {
        return Flags::Bytes as u32;
    }

    fn get_length(&self) -> usize {
        return self.len();
    }

    fn write_to(&self, stream: &mut W) -> io::Result<()> {
        match stream.write(self) {
            Ok(_) => Ok(()),
            Err(e) => Err(e),
        }
    }
}

impl<W: Write> ToMemcacheValue<W> for String {
    fn get_flags(&self) -> u32 {
        return Flags::Bytes as u32;
    }

    fn get_length(&self) -> usize {
        return self.as_bytes().len();
    }

    fn write_to(&self, stream: &mut W) -> io::Result<()> {
        match stream.write(self.as_bytes()) {
            Ok(_) => Ok(()),
            Err(e) => Err(e),
        }
    }
}

impl<'a, W: Write> ToMemcacheValue<W> for &'a str {
    fn get_flags(&self) -> u32 {
        return Flags::Bytes as u32;
    }

    fn get_length(&self) -> usize {
        return self.as_bytes().len();
    }

    fn write_to(&self, stream: &mut W) -> io::Result<()> {
        match stream.write(self.as_bytes()) {
            Ok(_) => Ok(()),
            Err(e) => Err(e),
        }
    }
}

macro_rules! impl_to_memcache_value_for_number{
    ($ty:ident) => {
        impl<W: Write> ToMemcacheValue<W> for $ty {
            fn get_flags(&self) -> u32 {
                return Flags::Bytes as u32;
            }

            fn get_length(&self) -> usize {
                return self.to_string().as_bytes().len();
            }

            fn write_to(&self, stream: &mut W) -> io::Result<()> {
                match stream.write(self.to_string().as_bytes()) {
                    Ok(_) => Ok(()),
                    Err(e) => Err(e),
                }
            }
        }
    }
}

impl_to_memcache_value_for_number!(bool);
impl_to_memcache_value_for_number!(u8);
impl_to_memcache_value_for_number!(u16);
impl_to_memcache_value_for_number!(u32);
impl_to_memcache_value_for_number!(u64);
impl_to_memcache_value_for_number!(i8);
impl_to_memcache_value_for_number!(i16);
impl_to_memcache_value_for_number!(i32);
impl_to_memcache_value_for_number!(i64);
impl_to_memcache_value_for_number!(f32);
impl_to_memcache_value_for_number!(f64);

type MemcacheValue<T> = Result<T, MemcacheError>;

/// determine how the value is unserialize to memcache
pub trait FromMemcacheValue: Sized {
    fn from_memcache_value(Vec<u8>, u32) -> MemcacheValue<Self>;
}

impl FromMemcacheValue for (Vec<u8>, u32) {
    fn from_memcache_value(value: Vec<u8>, flags: u32) -> MemcacheValue<Self> {
        return Ok((value, flags));
    }
}

impl FromMemcacheValue for Vec<u8> {
    fn from_memcache_value(value: Vec<u8>, _: u32) -> MemcacheValue<Self> {
        return Ok(value);
    }
}

impl FromMemcacheValue for String {
    fn from_memcache_value(value: Vec<u8>, _: u32) -> MemcacheValue<Self> {
        return Ok(String::from_utf8(value)?);
    }
}

macro_rules! impl_from_memcache_value_for_number{
    ($ty:ident) => {
        impl FromMemcacheValue for $ty {
            fn from_memcache_value(value: Vec<u8>, _: u32) -> MemcacheValue<Self> {
                let s: String = String::from_memcache_value(value, 0)?;
                match Self::from_str(s.as_str()) {
                    Ok(v) => return Ok(v),
                    Err(e) => Err(MemcacheError::from(e)),
                }
            }
        }
    }
}

impl_from_memcache_value_for_number!(bool);
impl_from_memcache_value_for_number!(u8);
impl_from_memcache_value_for_number!(u16);
impl_from_memcache_value_for_number!(u32);
impl_from_memcache_value_for_number!(u64);
impl_from_memcache_value_for_number!(i8);
impl_from_memcache_value_for_number!(i16);
impl_from_memcache_value_for_number!(i32);
impl_from_memcache_value_for_number!(i64);
impl_from_memcache_value_for_number!(f32);
impl_from_memcache_value_for_number!(f64);
<|endoftext|>


<commit_before>extern crate kiss3d;
extern crate nalgebra as na;

use kiss3d::light::Light;
use kiss3d::window::Window;
use na::vector;
use na::{Translation, UnitQuaternion, Vector3};

fn main() {
    env_logger::init();
    let mut window = Window::new("Kiss3d: cube");
    window.set_light(Light::StickToCamera);

    let mut cubes = Vec::new();
    for _ in 0..27 {
        let c = window.add_cube(0.08, 0.08, 0.08);
        cubes.push(c);
    }

    for i in 0..9 {
        cubes[i].set_color(1., 0., 0.);
    }
    for i in 9..27 {
        cubes[i].set_color(0., 1., 0.);
    }
    for i in 18..27 {
        cubes[i].set_color(0., 0., 1.);
    }

    let rot1 = UnitQuaternion::from_axis_angle(&Vector3::x_axis(), -0.5);
    for i in 0..27 {
        cubes[i].append_rotation(&rot1);
    }

    for i in 0..27 {
        let r = (i % 3) as f32 * 0.1;
        let c = (i / 9) as f32 * 0.1;
        let d = (i % 9) as f32 * 0.05;
        cubes[i].append_translation(&Translation { vector: vector!(r, c, d) });
    }

    let rot = UnitQuaternion::from_axis_angle(&Vector3::y_axis(), 0.014);
    while window.render() {
        for i in 0..27 {
            cubes[i].append_rotation(&rot);
        }
    }
}<commit_msg>Simplify the code.<commit_after>extern crate kiss3d;
extern crate nalgebra as na;

use kiss3d::light::Light;
use kiss3d::window::Window;
use na::vector;
use na::{Translation, UnitQuaternion, Vector3};

fn main() {
    env_logger::init();
    let mut window = Window::new("Kiss3d: cube");
    window.set_light(Light::StickToCamera);

    let mut cubes = Vec::new();
    let rot1 = UnitQuaternion::from_axis_angle(&Vector3::x_axis(), -0.5);
    for i in 0..27 {
        let c = window.add_cube(0.08, 0.08, 0.08);
        cubes.push(c);

        cubes[i].append_rotation(&rot1);

        let r = (i % 3) as f32 * 0.1;
        let c = (i / 9) as f32 * 0.1;
        let d = (i % 9) as f32 * 0.05;
        cubes[i].append_translation(&Translation { vector: vector!(r, c, d) });
    }

    for i in 0..9 {
        cubes[i].set_color(1., 0., 0.);
    }
    for i in 9..27 {
        cubes[i].set_color(0., 1., 0.);
    }
    for i in 18..27 {
        cubes[i].set_color(0., 0., 1.);
    }

    let rot = UnitQuaternion::from_axis_angle(&Vector3::y_axis(), 0.014);
    while window.render() {
        for i in 0..27 {
            cubes[i].append_rotation(&rot);
        }
    }
}<|endoftext|>


<commit_before>use std::num::Float;
use std::collections::binary_heap::BinaryHeap; // pq
use std::cmp::Ordering;

type float = f64;
type time = u64;

const TIME_RESOLUTION: time = 1000_000; // in micro seconds.

#[derive(Debug)]
struct Config {
    arp:       time,
    tau_m:     float,
    tau_r:     float,
    weight_r:  float,
    threshold: float,
}

#[derive(Debug)]
struct Neuron {
    /// End of absolute refractory period
    arp_end:         time,
    last_spike_time: time,
    mem_pot:         float,

    /// An index into a [Config] table.
    config_id:       usize,
}

#[derive(Debug)]
enum NeuronResult {
    InArp,
    NoFire,
    Fire
}

impl Neuron {
    fn new(config_id: usize) -> Neuron {
        Neuron {
            arp_end: 0,
            last_spike_time: 0,
            mem_pot: 0.0,
            config_id: config_id,
        }
    }

    fn spike(&mut self, timestamp: time, weight: float, cfg: &Config) -> NeuronResult {
        assert!(timestamp >= self.last_spike_time);

        // Return early if still in absolute refractory period (arp)
        if timestamp < self.arp_end {
            return NeuronResult::InArp;
        }

        // Time since end of last absolute refractory period (arp)
        assert!(timestamp >= self.arp_end);
        let delta = timestamp - self.arp_end;

        // Convert delta to float
        let delta: float = (delta as float) / TIME_RESOLUTION as float;

        // Calculate dynamic threshold
        let dyn_threshold = cfg.threshold +
                            cfg.weight_r * (-delta / cfg.tau_r).exp();

        // Update memory potential
        if cfg.tau_m > 0.0 {

            let d = timestamp - self.last_spike_time;
            // Convert delta to float
            let d: float = (d as float) / TIME_RESOLUTION as float;

            let decay = (-d / cfg.tau_m).exp();
            self.mem_pot *= decay;
            self.mem_pot += weight;
        }
        else {
            self.mem_pot = weight;
        }

        // Update last spike time
        self.last_spike_time = timestamp;

        if self.mem_pot >= dyn_threshold {
            self.arp_end = timestamp + cfg.arp;
            NeuronResult::Fire
        }
        else {
            NeuronResult::NoFire
        }
    }
}

#[derive(Debug)]
struct Event {
    time:   time,
    weight: float,
    target: usize
}

impl PartialEq for Event {
    fn eq(&self, other: &Self) -> bool {
        self.time == other.time
    }
}

impl Eq for Event {}

impl PartialOrd for Event {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.time.partial_cmp(&other.time).map(|o| o.reverse())
    }
}

impl Ord for Event {
    fn cmp(&self, other: &Self) -> Ordering {
        self.time.cmp(&other.time).reverse()
    }
}

fn ms(n: time) -> time { n * 1000 }
fn us(n: time) -> time { n }

struct Net {
    neurons: Vec<Neuron>,
    neuron_configs: Vec<Config>,
    events: BinaryHeap<Event>,
}

impl Net {
    fn new() -> Net {
        Net {
            neurons: vec![],
            neuron_configs: vec![],
            events: BinaryHeap::new(),
        }
    }

    /// Returns the config_id
    fn add_neuron_config(&mut self, config: Config) -> usize {
        self.neuron_configs.push(config);
        self.neuron_configs.len() - 1
    }

    /// Returns the neuron_id
    fn add_neuron(&mut self, config_id: usize) -> usize {
        self.neurons.push(Neuron::new(config_id));
        self.neurons.len() - 1
    }

    fn add_event(&mut self, event: Event) {
        self.events.push(event);
    }

    fn simulate(&mut self) {
	loop {
	    println!("-------------------------------------");

	    if let Some(ev) = self.events.pop() {
		println!("{:?}", ev);
		let neuron = &mut (self.neurons.as_mut_slice())[ev.target];
		let cfg = &(self.neuron_configs.as_slice())[neuron.config_id];
		let fire = neuron.spike(ev.time, ev.weight, cfg);
		println!("{:?}", fire);
		println!("{:?}", neuron);
	    }
	    else {
		break;
	    }
	}
    }
}

fn main() {

    let mut net = Net::new();

    // Koinzidenz neurons
    let cfg_k = net.add_neuron_config(Config {
        arp: us(500), // 0.5 ms = 500 us
        tau_m: 0.04,
        tau_r: 0.5,
        weight_r: 0.0,
        threshold: 1.1,
    });

    // Input neurons
    let cfg_i = net.add_neuron_config(Config {
        arp: ms(1),
        tau_m: 0.0,
        tau_r: 0.5,
        weight_r: 0.0,
        threshold: 0.6,
    });

    let n1 = net.add_neuron(cfg_i);

    // Fill event queue with events
    for i in 1..100 {
        let ev = Event {
            time:   ms(i) / 10,
            weight: 0.6,
            target: n1
        };

        net.add_event(ev);
        //pq.push(ev);
    }

    net.simulate();
}
<commit_msg>Rename Config -> NeuronConfig and add_neuron* -> create_neuron*<commit_after>use std::num::Float;
use std::collections::binary_heap::BinaryHeap; // pq
use std::cmp::Ordering;

type float = f64;
type time = u64;

const TIME_RESOLUTION: time = 1000_000; // in micro seconds.

#[derive(Debug)]
struct NeuronConfig {
    arp:       time,
    tau_m:     float,
    tau_r:     float,
    weight_r:  float,
    threshold: float,
}

#[derive(Debug)]
struct Neuron {
    /// End of absolute refractory period
    arp_end:         time,
    last_spike_time: time,
    mem_pot:         float,

    /// An index into a [NeuronConfig] table.
    config_id:       usize,
}

#[derive(Debug)]
enum NeuronResult {
    InArp,
    NoFire,
    Fire
}

impl Neuron {
    fn new(config_id: usize) -> Neuron {
        Neuron {
            arp_end: 0,
            last_spike_time: 0,
            mem_pot: 0.0,
            config_id: config_id,
        }
    }

    fn spike(&mut self, timestamp: time, weight: float, cfg: &NeuronConfig) -> NeuronResult {
        assert!(timestamp >= self.last_spike_time);

        // Return early if still in absolute refractory period (arp)
        if timestamp < self.arp_end {
            return NeuronResult::InArp;
        }

        // Time since end of last absolute refractory period (arp)
        assert!(timestamp >= self.arp_end);
        let delta = timestamp - self.arp_end;

        // Convert delta to float
        let delta: float = (delta as float) / TIME_RESOLUTION as float;

        // Calculate dynamic threshold
        let dyn_threshold = cfg.threshold +
                            cfg.weight_r * (-delta / cfg.tau_r).exp();

        // Update memory potential
        if cfg.tau_m > 0.0 {

            let d = timestamp - self.last_spike_time;
            // Convert delta to float
            let d: float = (d as float) / TIME_RESOLUTION as float;

            let decay = (-d / cfg.tau_m).exp();
            self.mem_pot *= decay;
            self.mem_pot += weight;
        }
        else {
            self.mem_pot = weight;
        }

        // Update last spike time
        self.last_spike_time = timestamp;

        if self.mem_pot >= dyn_threshold {
            self.arp_end = timestamp + cfg.arp;
            NeuronResult::Fire
        }
        else {
            NeuronResult::NoFire
        }
    }
}

#[derive(Debug)]
struct Event {
    time:   time,
    weight: float,
    target: usize
}

impl PartialEq for Event {
    fn eq(&self, other: &Self) -> bool {
        self.time == other.time
    }
}

impl Eq for Event {}

impl PartialOrd for Event {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.time.partial_cmp(&other.time).map(|o| o.reverse())
    }
}

impl Ord for Event {
    fn cmp(&self, other: &Self) -> Ordering {
        self.time.cmp(&other.time).reverse()
    }
}

fn ms(n: time) -> time { n * 1000 }
fn us(n: time) -> time { n }

struct Net {
    neurons: Vec<Neuron>,
    neuron_configs: Vec<NeuronConfig>,
    events: BinaryHeap<Event>,
}

impl Net {
    fn new() -> Net {
        Net {
            neurons: vec![],
            neuron_configs: vec![],
            events: BinaryHeap::new(),
        }
    }

    /// Returns the config_id
    fn create_neuron_config(&mut self, config: NeuronConfig) -> usize {
        self.neuron_configs.push(config);
        self.neuron_configs.len() - 1
    }

    /// Returns the neuron_id
    fn create_neuron(&mut self, config_id: usize) -> usize {
        self.neurons.push(Neuron::new(config_id));
        self.neurons.len() - 1
    }

    fn add_event(&mut self, event: Event) {
        self.events.push(event);
    }

    fn simulate(&mut self) {
	loop {
	    println!("-------------------------------------");

	    if let Some(ev) = self.events.pop() {
		println!("{:?}", ev);
		let neuron = &mut (self.neurons.as_mut_slice())[ev.target];
		let cfg = &(self.neuron_configs.as_slice())[neuron.config_id];
		let fire = neuron.spike(ev.time, ev.weight, cfg);
		println!("{:?}", fire);
		println!("{:?}", neuron);
	    }
	    else {
		break;
	    }
	}
    }
}

fn main() {

    let mut net = Net::new();

    // Koinzidenz neurons
    let cfg_k = net.create_neuron_config(NeuronConfig {
        arp: us(500), // 0.5 ms = 500 us
        tau_m: 0.04,
        tau_r: 0.5,
        weight_r: 0.0,
        threshold: 1.1,
    });

    // Input neurons
    let cfg_i = net.create_neuron_config(NeuronConfig {
        arp: ms(1),
        tau_m: 0.0,
        tau_r: 0.5,
        weight_r: 0.0,
        threshold: 0.6,
    });

    let n1 = net.create_neuron(cfg_i);

    // Fill event queue with events
    for i in 1..100 {
        let ev = Event {
            time:   ms(i) / 10,
            weight: 0.6,
            target: n1
        };

        net.add_event(ev);
        //pq.push(ev);
    }

    net.simulate();
}
<|endoftext|>