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

/*!
A mini version of ast::Ty, which is easier to use, and features an
explicit `Self` type to use when specifying impls to be derived.
*/

use ast;
use ast::{P,Expr,Generics,Ident};
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
use codemap::{Span,respan};
use owned_slice::OwnedSlice;
use parse::token::special_idents;

use std::gc::Gc;

/// The types of pointers
pub enum PtrTy<'a> {
    /// &'lifetime mut
    Borrowed(Option<&'a str>, ast::Mutability),
}

/// A path, e.g. `::std::option::Option::<int>` (global). Has support
/// for type parameters and a lifetime.
pub struct Path<'a> {
    pub path: Vec<&'a str> ,
    pub lifetime: Option<&'a str>,
    pub params: Vec<Box<Ty<'a>>>,
    pub global: bool,
}

impl<'a> Path<'a> {
    pub fn new<'r>(path: Vec<&'r str> ) -> Path<'r> {
        Path::new_(path, None, Vec::new(), true)
    }
    pub fn new_local<'r>(path: &'r str) -> Path<'r> {
        Path::new_(vec!( path ), None, Vec::new(), false)
    }
    pub fn new_<'r>(path: Vec<&'r str> ,
                    lifetime: Option<&'r str>,
                    params: Vec<Box<Ty<'r>>>,
                    global: bool)
                    -> Path<'r> {
        Path {
            path: path,
            lifetime: lifetime,
            params: params,
            global: global
        }
    }

    pub fn to_ty(&self,
                 cx: &ExtCtxt,
                 span: Span,
                 self_ty: Ident,
                 self_generics: &Generics)
                 -> P<ast::Ty> {
        cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None)
    }
    pub fn to_path(&self,
                   cx: &ExtCtxt,
                   span: Span,
                   self_ty: Ident,
                   self_generics: &Generics)
                   -> ast::Path {
        let idents = self.path.iter().map(|s| cx.ident_of(*s)).collect();
        let lt = mk_lifetimes(cx, span, &self.lifetime);
        let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();

        cx.path_all(span, self.global, idents, lt, tys)
    }
}

/// A type. Supports pointers (except for *), Self, and literals
pub enum Ty<'a> {
    Self,
    /// &/Box/ Ty
    Ptr(Box<Ty<'a>>, PtrTy<'a>),
    /// mod::mod::Type<[lifetime], [Params...]>, including a plain type
    /// parameter, and things like `int`
    Literal(Path<'a>),
    /// includes unit
    Tuple(Vec<Ty<'a>> )
}

pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
    Borrowed(None, ast::MutImmutable)
}
pub fn borrowed<'r>(ty: Box<Ty<'r>>) -> Ty<'r> {
    Ptr(ty, borrowed_ptrty())
}

pub fn borrowed_explicit_self<'r>() -> Option<Option<PtrTy<'r>>> {
    Some(Some(borrowed_ptrty()))
}

pub fn borrowed_self<'r>() -> Ty<'r> {
    borrowed(box Self)
}

pub fn nil_ty() -> Ty<'static> {
    Tuple(Vec::new())
}

fn mk_lifetime(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> Option<ast::Lifetime> {
    match *lt {
        Some(ref s) => Some(cx.lifetime(span, cx.ident_of(*s).name)),
        None => None
    }
}

fn mk_lifetimes(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> Vec<ast::Lifetime> {
    match *lt {
        Some(ref s) => vec!(cx.lifetime(span, cx.ident_of(*s).name)),
        None => vec!()
    }
}

impl<'a> Ty<'a> {
    pub fn to_ty(&self,
                 cx: &ExtCtxt,
                 span: Span,
                 self_ty: Ident,
                 self_generics: &Generics)
                 -> P<ast::Ty> {
        match *self {
            Ptr(ref ty, ref ptr) => {
                let raw_ty = ty.to_ty(cx, span, self_ty, self_generics);
                match *ptr {
                    Borrowed(ref lt, mutbl) => {
                        let lt = mk_lifetime(cx, span, lt);
                        cx.ty_rptr(span, raw_ty, lt, mutbl)
                    }
                }
            }
            Literal(ref p) => { p.to_ty(cx, span, self_ty, self_generics) }
            Self  => {
                cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None)
            }
            Tuple(ref fields) => {
                let ty = if fields.is_empty() {
                    ast::TyNil
                } else {
                    ast::TyTup(fields.iter()
                                     .map(|f| f.to_ty(cx, span, self_ty, self_generics))
                                     .collect())
                };

                cx.ty(span, ty)
            }
        }
    }

    pub fn to_path(&self,
                   cx: &ExtCtxt,
                   span: Span,
                   self_ty: Ident,
                   self_generics: &Generics)
                   -> ast::Path {
        match *self {
            Self => {
                let self_params = self_generics.ty_params.map(|ty_param| {
                    cx.ty_ident(span, ty_param.ident)
                });
                let lifetimes = self_generics.lifetimes.clone();

                cx.path_all(span, false, vec!(self_ty), lifetimes,
                            self_params.into_vec())
            }
            Literal(ref p) => {
                p.to_path(cx, span, self_ty, self_generics)
            }
            Ptr(..) => { cx.span_bug(span, "pointer in a path in generic `deriving`") }
            Tuple(..) => { cx.span_bug(span, "tuple in a path in generic `deriving`") }
        }
    }
}

fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str,
               bounds: &[Path], unbound: Option<ast::TyParamBound>,
               self_ident: Ident, self_generics: &Generics) -> ast::TyParam {
    let bounds =
        bounds.iter().map(|b| {
            let path = b.to_path(cx, span, self_ident, self_generics);
            cx.typarambound(path)
        }).collect();
    cx.typaram(span, cx.ident_of(name), bounds, unbound, None)
}

fn mk_generics(lifetimes: Vec<ast::Lifetime>, ty_params: Vec<ast::TyParam> ) -> Generics {
    Generics {
        lifetimes: lifetimes,
        ty_params: OwnedSlice::from_vec(ty_params)
    }
}

/// Lifetimes and bounds on type parameters
pub struct LifetimeBounds<'a> {
    pub lifetimes: Vec<&'a str>,
    pub bounds: Vec<(&'a str, Option<ast::TyParamBound>, Vec<Path<'a>>)>,
}

impl<'a> LifetimeBounds<'a> {
    pub fn empty() -> LifetimeBounds<'static> {
        LifetimeBounds {
            lifetimes: Vec::new(), bounds: Vec::new()
        }
    }
    pub fn to_generics(&self,
                       cx: &ExtCtxt,
                       span: Span,
                       self_ty: Ident,
                       self_generics: &Generics)
                       -> Generics {
        let lifetimes = self.lifetimes.iter().map(|lt| {
            cx.lifetime(span, cx.ident_of(*lt).name)
        }).collect();
        let ty_params = self.bounds.iter().map(|t| {
            match t {
                &(ref name, ref unbound, ref bounds) => {
                    mk_ty_param(cx,
                                span,
                                *name,
                                bounds.as_slice(),
                                unbound.clone(),
                                self_ty,
                                self_generics)
                }
            }
        }).collect();
        mk_generics(lifetimes, ty_params)
    }
}

pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
    -> (Gc<Expr>, ast::ExplicitSelf) {
    // this constructs a fresh `self` path, which will match the fresh `self` binding
    // created below.
    let self_path = cx.expr_self(span);
    match *self_ptr {
        None => {
            (self_path, respan(span, ast::SelfValue(special_idents::self_)))
        }
        Some(ref ptr) => {
            let self_ty = respan(
                span,
                match *ptr {
                    Borrowed(ref lt, mutbl) => {
                        let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s).name));
                        ast::SelfRegion(lt, mutbl, special_idents::self_)
                    }
                });
            let self_expr = cx.expr_deref(span, self_path);
            (self_expr, self_ty)
        }
    }
}
<commit_msg>Fixed lifetimes on syntax deriving structs, implemented Clone<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
A mini version of ast::Ty, which is easier to use, and features an
explicit `Self` type to use when specifying impls to be derived.
*/

use ast;
use ast::{P,Expr,Generics,Ident};
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
use codemap::{Span,respan};
use owned_slice::OwnedSlice;
use parse::token::special_idents;

use std::gc::Gc;

/// The types of pointers
#[deriving(Clone)]
pub enum PtrTy<'a> {
    /// &'lifetime mut
    Borrowed(Option<&'a str>, ast::Mutability),
}

/// A path, e.g. `::std::option::Option::<int>` (global). Has support
/// for type parameters and a lifetime.
#[deriving(Clone)]
pub struct Path<'a> {
    pub path: Vec<&'a str> ,
    pub lifetime: Option<&'a str>,
    pub params: Vec<Box<Ty<'a>>>,
    pub global: bool,
}

impl<'a> Path<'a> {
    pub fn new<'r>(path: Vec<&'r str> ) -> Path<'r> {
        Path::new_(path, None, Vec::new(), true)
    }
    pub fn new_local<'r>(path: &'r str) -> Path<'r> {
        Path::new_(vec!( path ), None, Vec::new(), false)
    }
    pub fn new_<'r>(path: Vec<&'r str> ,
                    lifetime: Option<&'r str>,
                    params: Vec<Box<Ty<'r>>>,
                    global: bool)
                    -> Path<'r> {
        Path {
            path: path,
            lifetime: lifetime,
            params: params,
            global: global
        }
    }

    pub fn to_ty(&self,
                 cx: &ExtCtxt,
                 span: Span,
                 self_ty: Ident,
                 self_generics: &Generics)
                 -> P<ast::Ty> {
        cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None)
    }
    pub fn to_path(&self,
                   cx: &ExtCtxt,
                   span: Span,
                   self_ty: Ident,
                   self_generics: &Generics)
                   -> ast::Path {
        let idents = self.path.iter().map(|s| cx.ident_of(*s)).collect();
        let lt = mk_lifetimes(cx, span, &self.lifetime);
        let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();

        cx.path_all(span, self.global, idents, lt, tys)
    }
}

/// A type. Supports pointers (except for *), Self, and literals
#[deriving(Clone)]
pub enum Ty<'a> {
    Self,
    /// &/Box/ Ty
    Ptr(Box<Ty<'a>>, PtrTy<'a>),
    /// mod::mod::Type<[lifetime], [Params...]>, including a plain type
    /// parameter, and things like `int`
    Literal(Path<'a>),
    /// includes unit
    Tuple(Vec<Ty<'a>> )
}

pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
    Borrowed(None, ast::MutImmutable)
}
pub fn borrowed<'r>(ty: Box<Ty<'r>>) -> Ty<'r> {
    Ptr(ty, borrowed_ptrty())
}

pub fn borrowed_explicit_self<'r>() -> Option<Option<PtrTy<'r>>> {
    Some(Some(borrowed_ptrty()))
}

pub fn borrowed_self<'r>() -> Ty<'r> {
    borrowed(box Self)
}

pub fn nil_ty<'r>() -> Ty<'r> {
    Tuple(Vec::new())
}

fn mk_lifetime(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> Option<ast::Lifetime> {
    match *lt {
        Some(ref s) => Some(cx.lifetime(span, cx.ident_of(*s).name)),
        None => None
    }
}

fn mk_lifetimes(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> Vec<ast::Lifetime> {
    match *lt {
        Some(ref s) => vec!(cx.lifetime(span, cx.ident_of(*s).name)),
        None => vec!()
    }
}

impl<'a> Ty<'a> {
    pub fn to_ty(&self,
                 cx: &ExtCtxt,
                 span: Span,
                 self_ty: Ident,
                 self_generics: &Generics)
                 -> P<ast::Ty> {
        match *self {
            Ptr(ref ty, ref ptr) => {
                let raw_ty = ty.to_ty(cx, span, self_ty, self_generics);
                match *ptr {
                    Borrowed(ref lt, mutbl) => {
                        let lt = mk_lifetime(cx, span, lt);
                        cx.ty_rptr(span, raw_ty, lt, mutbl)
                    }
                }
            }
            Literal(ref p) => { p.to_ty(cx, span, self_ty, self_generics) }
            Self  => {
                cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None)
            }
            Tuple(ref fields) => {
                let ty = if fields.is_empty() {
                    ast::TyNil
                } else {
                    ast::TyTup(fields.iter()
                                     .map(|f| f.to_ty(cx, span, self_ty, self_generics))
                                     .collect())
                };

                cx.ty(span, ty)
            }
        }
    }

    pub fn to_path(&self,
                   cx: &ExtCtxt,
                   span: Span,
                   self_ty: Ident,
                   self_generics: &Generics)
                   -> ast::Path {
        match *self {
            Self => {
                let self_params = self_generics.ty_params.map(|ty_param| {
                    cx.ty_ident(span, ty_param.ident)
                });
                let lifetimes = self_generics.lifetimes.clone();

                cx.path_all(span, false, vec!(self_ty), lifetimes,
                            self_params.into_vec())
            }
            Literal(ref p) => {
                p.to_path(cx, span, self_ty, self_generics)
            }
            Ptr(..) => { cx.span_bug(span, "pointer in a path in generic `deriving`") }
            Tuple(..) => { cx.span_bug(span, "tuple in a path in generic `deriving`") }
        }
    }
}

fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str,
               bounds: &[Path], unbound: Option<ast::TyParamBound>,
               self_ident: Ident, self_generics: &Generics) -> ast::TyParam {
    let bounds =
        bounds.iter().map(|b| {
            let path = b.to_path(cx, span, self_ident, self_generics);
            cx.typarambound(path)
        }).collect();
    cx.typaram(span, cx.ident_of(name), bounds, unbound, None)
}

fn mk_generics(lifetimes: Vec<ast::Lifetime>, ty_params: Vec<ast::TyParam> ) -> Generics {
    Generics {
        lifetimes: lifetimes,
        ty_params: OwnedSlice::from_vec(ty_params)
    }
}

/// Lifetimes and bounds on type parameters
#[deriving(Clone)]
pub struct LifetimeBounds<'a> {
    pub lifetimes: Vec<&'a str>,
    pub bounds: Vec<(&'a str, Option<ast::TyParamBound>, Vec<Path<'a>>)>,
}

impl<'a> LifetimeBounds<'a> {
    pub fn empty() -> LifetimeBounds<'a> {
        LifetimeBounds {
            lifetimes: Vec::new(), bounds: Vec::new()
        }
    }
    pub fn to_generics(&self,
                       cx: &ExtCtxt,
                       span: Span,
                       self_ty: Ident,
                       self_generics: &Generics)
                       -> Generics {
        let lifetimes = self.lifetimes.iter().map(|lt| {
            cx.lifetime(span, cx.ident_of(*lt).name)
        }).collect();
        let ty_params = self.bounds.iter().map(|t| {
            match t {
                &(ref name, ref unbound, ref bounds) => {
                    mk_ty_param(cx,
                                span,
                                *name,
                                bounds.as_slice(),
                                unbound.clone(),
                                self_ty,
                                self_generics)
                }
            }
        }).collect();
        mk_generics(lifetimes, ty_params)
    }
}

pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
    -> (Gc<Expr>, ast::ExplicitSelf) {
    // this constructs a fresh `self` path, which will match the fresh `self` binding
    // created below.
    let self_path = cx.expr_self(span);
    match *self_ptr {
        None => {
            (self_path, respan(span, ast::SelfValue(special_idents::self_)))
        }
        Some(ref ptr) => {
            let self_ty = respan(
                span,
                match *ptr {
                    Borrowed(ref lt, mutbl) => {
                        let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s).name));
                        ast::SelfRegion(lt, mutbl, special_idents::self_)
                    }
                });
            let self_expr = cx.expr_deref(span, self_path);
            (self_expr, self_ty)
        }
    }
}
<|endoftext|>


<commit_before>#[allow(dead_code)]
fn main() {
    struct Nil;

    struct Pair(i32, f64);

    struct Point {
      x: f64;
      y: f64;
    }

    struct Rectangle {
        p1: Point;
        p2: Point;
    }

    let point = Point{x: 0.3, y: 0.4};
    println!("point coordinates: ({}, {})", point.x, point.y);
}
<commit_msg>rust custom types<commit_after>
#[allow(dead_code,unused_variables,non_upper_case_globals)]
fn main() {
    // 3.1
    struct Nil; // a unit struct
    struct Pair(i32, f64);
    struct Point {
      x: f64,
      y: f64,
    }
    struct Rectangle {
        p1: Point,
        p2: Point,
    }
    let point = Point{x: 0.3, y: 0.4};
    println!("point coordinates: ({}, {})", point.x, point.y);
    let Point { x: my_x, y: my_y } = point; // destructure point
    let rectangle = Rectangle {
        p1: Point { x: my_x, y: my_y },
        p2: point,
    };
    let nil = Nil;
    let pair = Pair(1, 0.1);
    let Pair(integer, decimal) = pair;
    println!("pair contains {:?} and {:?}", integer, decimal);

    // 3.2
    fn inspect(p: Person) {
        match p {
            Person::Skinny  => println!("Is skinny!"),
            Person::Fat     => println!("Is fat!"),
            Person::Height(i) => println!("Has height of {}.", i),
            Person::Weight(i) => println!("Has weight of {}.", i),
            Person::Info{ name, height } => {
                println!("{} is {} tall!", name, height);
            }
        }
    }
    let person = Person::Height(18);
    inspect(person);

    // 3.2.1
    {
        // "use" has to be first statement, Person must be defined outside this function
        use Person::*;
        inspect(Info{ name: "Dave".to_owned(), height: 72 });
    }

    // 3.2.2
    enum Number {
        Zero, One, Two
    }
    enum Color {
        Red = 0xff0000,
        Green = 0x00ff00,
        Blue = 0x0000ff,
    }
    println!("roses are #{:06x}", Color::Red as i32);

    // 3.2.3
    {
        enum List {
            Cons(u32, Box<List>),
            Nil
        }
        impl List {
            fn new() -> List {
                List::Nil
            }
            fn prepend(self, elem: u32) -> List {
                List::Cons(elem, Box::new(self))
            }
            fn len(&self) -> u32 {
                match *self {
                    List::Cons(_, ref tail) => 1 + tail.len(),
                    List::Nil => 0
                }
            }
            fn stringify(&self) -> String {
                match *self {
                    List::Cons(head, ref tail) => {
                        format!("{}, {}", head, tail.stringify())
                    },
                    List::Nil => {
                        format!("Nil")
                    }
                }
            }
        }
        let mut list = List::new();
        list = list.prepend(1);
        list = list.prepend(2);
        list = list.prepend(3);
        println!("linked list length: {}", list.len());
        println!("{}", list.stringify());
    }

    // 3.3
    const threshold: i32 = 10;
    // threshold = 11; // error: invalid left-hand side expression [E0070]
    static language: &'static str = "Rust";
}

#[allow(dead_code,unused_variables)]
enum Person {
    Skinny,
    Fat,
    Height(i32),
    Weight(i32),
    Info { name: String, height: i32 }
}
<|endoftext|>


<commit_before>//! The CXX code generator for constructing and compiling C++ code.
//!
//! This is intended to be used from Cargo build scripts to execute CXX's
//! C++ code generator, set up any additional compiler flags depending on
//! the use case, and make the C++ compiler invocation.
//!
//!

//!
//! # Example
//!
//! Example of a canonical Cargo build script that builds a CXX bridge:
//!
//! ```no_run
//! // build.rs
//!
//! fn main() {
//!     cxx_build::bridge("src/main.rs")
//!         .file("src/demo.cc")
//!         .flag_if_supported("-std=c++11")
//!         .compile("cxxbridge-demo");
//!
//!     println!("cargo:rerun-if-changed=src/main.rs");
//!     println!("cargo:rerun-if-changed=src/demo.cc");
//!     println!("cargo:rerun-if-changed=include/demo.h");
//! }
//! ```
//!
//! A runnable working setup with this build script is shown in the *demo*
//! directory of [https://github.com/dtolnay/cxx].
//!
//! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
//!
//!

//!
//! # Alternatives
//!
//! For use in non-Cargo builds like Bazel or Buck, CXX provides an
//! alternate way of invoking the C++ code generator as a standalone command
//! line tool. The tool is packaged as the `cxxbridge-cmd` crate.
//!
//! ```bash
//! $ cargo install cxxbridge-cmd  # or build it from the repo
//!
//! $ cxxbridge src/main.rs --header > path/to/mybridge.h
//! $ cxxbridge src/main.rs > path/to/mybridge.cc
//! ```

#![allow(
    clippy::inherent_to_string,
    clippy::needless_doctest_main,
    clippy::new_without_default,
    clippy::or_fun_call,
    clippy::toplevel_ref_arg
)]

mod cargo;
mod error;
mod gen;
mod paths;
mod syntax;

use crate::error::Result;
use crate::gen::error::report;
use crate::gen::{fs, Opt};
use crate::paths::TargetDir;
use cc::Build;
use std::io::{self, Write};
use std::iter;
use std::path::Path;
use std::process;

/// This returns a [`cc::Build`] on which you should continue to set up any
/// additional source files or compiler flags, and lastly call its [`compile`]
/// method to execute the C++ build.
///
/// [`compile`]: https://docs.rs/cc/1.0.49/cc/struct.Build.html#method.compile
#[must_use]
pub fn bridge(rust_source_file: impl AsRef<Path>) -> Build {
    bridges(iter::once(rust_source_file))
}

/// `cxx_build::bridge` but for when more than one file contains a
/// #\[cxx::bridge\] module.
///
/// ```no_run
/// let source_files = vec!["src/main.rs", "src/path/to/other.rs"];
/// cxx_build::bridges(source_files)
///     .file("src/demo.cc")
///     .flag_if_supported("-std=c++11")
///     .compile("cxxbridge-demo");
/// ```
#[must_use]
pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) -> Build {
    let ref mut rust_source_files = rust_source_files.into_iter();
    build(rust_source_files).unwrap_or_else(|err| {
        let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {}\n\n", report(err));
        process::exit(1);
    })
}

fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
    let ref target_dir = paths::target_dir()?;
    let mut build = paths::cc_build(target_dir);
    build.cpp(true);
    build.cpp_link_stdlib(None); // linked via link-cplusplus crate
    write_header(target_dir)?;

    for path in rust_source_files {
        generate_bridge(&mut build, path.as_ref(), target_dir)?;
    }

    Ok(build)
}

fn write_header(target_dir: &TargetDir) -> Result<()> {
    let ref cxx_h = paths::include_dir(target_dir).join("rust").join("cxx.h");
    let _ = write(cxx_h, gen::include::HEADER.as_bytes());
    Ok(())
}

fn generate_bridge(
    build: &mut Build,
    rust_source_file: &Path,
    target_dir: &TargetDir,
) -> Result<()> {
    let opt = Opt::default();
    let generated = gen::generate_from_path(rust_source_file, &opt);

    let header_path = paths::out_with_extension(rust_source_file, ".h", target_dir)?;
    fs::create_dir_all(header_path.parent().unwrap())?;
    write(&header_path, &generated.header)?;
    paths::symlink_header(&header_path, rust_source_file, target_dir);

    let implementation_path = paths::out_with_extension(rust_source_file, ".cc", target_dir)?;
    write(&implementation_path, &generated.implementation)?;
    build.file(&implementation_path);
    Ok(())
}

fn write(path: &Path, content: &[u8]) -> Result<()> {
    if path.exists() {
        if let Ok(existing) = fs::read(path) {
            if existing == content {
                // Avoid bumping modified time with unchanged contents.
                return Ok(());
            }
        }
        let _ = fs::remove_file(path);
    } else {
        let _ = fs::create_dir_all(path.parent().unwrap());
    }
    fs::write(path, content)?;
    Ok(())
}
<commit_msg>Write header can be infallible<commit_after>//! The CXX code generator for constructing and compiling C++ code.
//!
//! This is intended to be used from Cargo build scripts to execute CXX's
//! C++ code generator, set up any additional compiler flags depending on
//! the use case, and make the C++ compiler invocation.
//!
//!

//!
//! # Example
//!
//! Example of a canonical Cargo build script that builds a CXX bridge:
//!
//! ```no_run
//! // build.rs
//!
//! fn main() {
//!     cxx_build::bridge("src/main.rs")
//!         .file("src/demo.cc")
//!         .flag_if_supported("-std=c++11")
//!         .compile("cxxbridge-demo");
//!
//!     println!("cargo:rerun-if-changed=src/main.rs");
//!     println!("cargo:rerun-if-changed=src/demo.cc");
//!     println!("cargo:rerun-if-changed=include/demo.h");
//! }
//! ```
//!
//! A runnable working setup with this build script is shown in the *demo*
//! directory of [https://github.com/dtolnay/cxx].
//!
//! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
//!
//!

//!
//! # Alternatives
//!
//! For use in non-Cargo builds like Bazel or Buck, CXX provides an
//! alternate way of invoking the C++ code generator as a standalone command
//! line tool. The tool is packaged as the `cxxbridge-cmd` crate.
//!
//! ```bash
//! $ cargo install cxxbridge-cmd  # or build it from the repo
//!
//! $ cxxbridge src/main.rs --header > path/to/mybridge.h
//! $ cxxbridge src/main.rs > path/to/mybridge.cc
//! ```

#![allow(
    clippy::inherent_to_string,
    clippy::needless_doctest_main,
    clippy::new_without_default,
    clippy::or_fun_call,
    clippy::toplevel_ref_arg
)]

mod cargo;
mod error;
mod gen;
mod paths;
mod syntax;

use crate::error::Result;
use crate::gen::error::report;
use crate::gen::{fs, Opt};
use crate::paths::TargetDir;
use cc::Build;
use std::io::{self, Write};
use std::iter;
use std::path::Path;
use std::process;

/// This returns a [`cc::Build`] on which you should continue to set up any
/// additional source files or compiler flags, and lastly call its [`compile`]
/// method to execute the C++ build.
///
/// [`compile`]: https://docs.rs/cc/1.0.49/cc/struct.Build.html#method.compile
#[must_use]
pub fn bridge(rust_source_file: impl AsRef<Path>) -> Build {
    bridges(iter::once(rust_source_file))
}

/// `cxx_build::bridge` but for when more than one file contains a
/// #\[cxx::bridge\] module.
///
/// ```no_run
/// let source_files = vec!["src/main.rs", "src/path/to/other.rs"];
/// cxx_build::bridges(source_files)
///     .file("src/demo.cc")
///     .flag_if_supported("-std=c++11")
///     .compile("cxxbridge-demo");
/// ```
#[must_use]
pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) -> Build {
    let ref mut rust_source_files = rust_source_files.into_iter();
    build(rust_source_files).unwrap_or_else(|err| {
        let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {}\n\n", report(err));
        process::exit(1);
    })
}

fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
    let ref target_dir = paths::target_dir()?;
    let mut build = paths::cc_build(target_dir);
    build.cpp(true);
    build.cpp_link_stdlib(None); // linked via link-cplusplus crate
    write_header(target_dir);

    for path in rust_source_files {
        generate_bridge(&mut build, path.as_ref(), target_dir)?;
    }

    Ok(build)
}

fn write_header(target_dir: &TargetDir) {
    let ref cxx_h = paths::include_dir(target_dir).join("rust").join("cxx.h");
    let _ = write(cxx_h, gen::include::HEADER.as_bytes());
}

fn generate_bridge(
    build: &mut Build,
    rust_source_file: &Path,
    target_dir: &TargetDir,
) -> Result<()> {
    let opt = Opt::default();
    let generated = gen::generate_from_path(rust_source_file, &opt);

    let header_path = paths::out_with_extension(rust_source_file, ".h", target_dir)?;
    fs::create_dir_all(header_path.parent().unwrap())?;
    write(&header_path, &generated.header)?;
    paths::symlink_header(&header_path, rust_source_file, target_dir);

    let implementation_path = paths::out_with_extension(rust_source_file, ".cc", target_dir)?;
    write(&implementation_path, &generated.implementation)?;
    build.file(&implementation_path);
    Ok(())
}

fn write(path: &Path, content: &[u8]) -> Result<()> {
    if path.exists() {
        if let Ok(existing) = fs::read(path) {
            if existing == content {
                // Avoid bumping modified time with unchanged contents.
                return Ok(());
            }
        }
        let _ = fs::remove_file(path);
    } else {
        let _ = fs::create_dir_all(path.parent().unwrap());
    }
    fs::write(path, content)?;
    Ok(())
}
<|endoftext|>


<commit_before>use std::{io,
          net::{IpAddr,
                Ipv4Addr,
                SocketAddr,
                SocketAddrV4,
                ToSocketAddrs},
          ops::{Deref,
                DerefMut},
          option};

/// Bundles up information about the user and group that a supervised
/// service should be run as. If the Supervisor itself is running with
/// root-like permissions, then these will be for `SVC_USER` and
/// `SVC_GROUP` for a service. If not, it will be for the user the
/// Supervisor itself is running as.
///
/// On Windows, all but `username` will be `None`. On Linux,
/// `username` and `groupname` may legitimately be `None`, but `uid`
/// and `gid` should always be `Some`.
#[derive(Debug, Default)]
pub struct UserInfo {
    /// Windows required, Linux optional
    pub username: Option<String>,
    /// Linux preferred
    pub uid: Option<u32>,
    /// Linux optional
    pub groupname: Option<String>,
    /// Linux preferred
    pub gid: Option<u32>,
}

/// Captures arbitrary key-value pair metadata to attach to all events
/// generated by the Supervisor.
#[derive(Clone, Debug, Default)]
pub struct EventStreamMetadata(HashMap<String, String>);

impl Into<HashMap<String, String>> for EventStreamMetadata {
    fn into(self) -> HashMap<String, String> { self.0 }
}

impl EventStreamMetadata {
    /// The name of the Clap argument we'll use for arguments of this type.
    pub const ARG_NAME: &'static str = "EVENT_STREAM_METADATA";

    /// Ensure that user input from Clap can be converted into a
    /// key-value pair we can consume.
    ///
    /// Note: this validates each value given by the user, not all the
    /// values given at once.
    #[allow(clippy::needless_pass_by_value)] // Signature required by CLAP
    pub fn validate(value: String) -> result::Result<(), String> {
        Self::split_raw(&value).map(|_| ())
    }

    /// Utility function to create a key-value pair tuple from a
    /// user-provided value in Clap.
    fn split_raw(raw: &str) -> result::Result<(String, String), String> {
        match raw.split('=').collect::<Vec<_>>().as_slice() {
            [key, value] if !key.is_empty() && !value.is_empty() => {
                Ok((key.to_string(), value.to_string()))
            }
            _ => {
                Err(format!("Invalid key-value pair given (must be \
                             '='-delimited pair of non-empty strings): {}",
                            raw))
            }
        }
    }

    /// Same as `split_raw`, but for running on already-validated
    /// input (thus, this function cannot fail).
    fn split_validated(validated_input: &str) -> (String, String) {
        Self::split_raw(validated_input).expect("EVENT_STREAM_METADATA should be validated at \
                                                 this point")
    }
}

impl<'a> From<&'a ArgMatches<'a>> for EventStreamMetadata {
    /// Create an instance of `EventStreamMetadata` from validated
    /// user input.
    fn from(m: &ArgMatches) -> Self {
        let raw_meta = m.values_of(Self::ARG_NAME).unwrap_or_default();
        Self(raw_meta.map(Self::split_validated).collect())
    }
}

/// This represents an environment variable that holds an authentication token which enables
/// integration with Automate. Supervisors use this token to connect to the messaging server
/// on the Automate side in order to send data about the services they're running via event
/// messages. If the environment variable is present, its value is the auth token. If it's not
/// present and the feature flag for the Event Stream is enabled, initialization of the Event
/// Stream will fail.
#[derive(Clone, Debug)]
pub struct AutomateAuthToken(String);

impl AutomateAuthToken {
    /// The name of the Clap argument we'll use for arguments of this type.
    pub const ARG_NAME: &'static str = "EVENT_STREAM_TOKEN";
    // Ideally, we'd like to take advantage of
    // `habitat_core::env::Config` trait, but that currently requires
    // a `Default` implementation, and there isn't really a legitimate
    // default value right now.
    pub const ENVVAR: &'static str = "HAB_AUTOMATE_AUTH_TOKEN";
}

impl AutomateAuthToken {
    /// Ensure that user input from Clap can be converted an instance
    /// of a token.
    #[allow(clippy::needless_pass_by_value)] // Signature required by CLAP
    pub fn validate(value: String) -> result::Result<(), String> {
        value.parse::<Self>().map(|_| ()).map_err(|e| e.to_string())
    }
}

impl<'a> From<&'a ArgMatches<'a>> for AutomateAuthToken {
    /// Create an instance of `AutomateAuthToken` from validated
    /// user input.
    fn from(m: &ArgMatches) -> Self {
        m.value_of(Self::ARG_NAME)
         .expect("HAB_AUTOMATE_AUTH_TOKEN should be set")
         .parse()
         .expect("HAB_AUTOMATE_AUTH_TOKEN should be validated at this point")
    }
}

impl FromStr for AutomateAuthToken {
    type Err = Error;

    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
        if s.is_empty() {
            Err(Error::InvalidEventStreamToken(s.to_string()))
        } else {
            Ok(AutomateAuthToken(s.to_string()))
        }
    }
}

impl fmt::Display for AutomateAuthToken {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.0) }
}

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

    mod auth_token {
        use super::*;

        #[test]
        fn cannot_parse_from_empty_string() { assert!("".parse::<AutomateAuthToken>().is_err()) }

    }
}

habitat_core::env_config_socketaddr!(#[derive(Clone, Copy, PartialEq, Eq, Debug)],
                                     pub GossipListenAddr,
                                     HAB_LISTEN_GOSSIP,
                                     0, 0, 0, 0, Self::DEFAULT_PORT);

impl GossipListenAddr {
    pub const DEFAULT_PORT: u16 = 9638;

    /// When local gossip mode is used we still startup the gossip layer but set
    /// it to listen on 127.0.0.2 to scope it to the local node but ignore connections from
    /// 127.0.0.1. This turns out to be much simpler than the cascade of changes that would
    /// be involved in not setting up a gossip listener at all.
    pub fn local_only() -> Self {
        GossipListenAddr(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 2),
                                                          Self::DEFAULT_PORT)))
    }

    /// Generate an address at which a server configured with this
    /// GossipListenAddr can communicate with itself.
    ///
    /// In particular, a server configured to listen on `0.0.0.0` vs
    /// `192.168.1.1` should be contacted via `127.0.0.1` in the
    /// former case, but `192.168.1.1` in the latter.
    pub fn local_addr(&self) -> Self {
        let mut addr = *self;
        if addr.0.ip().is_unspecified() {
            // TODO (CM): Use Ipv4Addr::loopback() when it's no longer experimental
            // TODO (CM): Support IPV6, once we do that more broadly
            addr.0.set_ip(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
        }
        addr
    }
}

impl Deref for GossipListenAddr {
    type Target = SocketAddr;

    fn deref(&self) -> &SocketAddr { &self.0 }
}

impl DerefMut for GossipListenAddr {
    fn deref_mut(&mut self) -> &mut SocketAddr { &mut self.0 }
}

impl ToSocketAddrs for GossipListenAddr {
    type Iter = option::IntoIter<SocketAddr>;

    fn to_socket_addrs(&self) -> io::Result<Self::Iter> { self.0.to_socket_addrs() }
}

habitat_core::env_config_socketaddr!(#[derive(PartialEq, Eq, Debug, Clone, Copy)],
                                     pub HttpListenAddr,
                                     HAB_LISTEN_HTTP,
                                     0, 0, 0, 0, 9631);
impl HttpListenAddr {
    pub fn new(ip: IpAddr, port: u16) -> Self { Self(SocketAddr::new(ip, port)) }
}

impl Deref for HttpListenAddr {
    type Target = SocketAddr;

    fn deref(&self) -> &SocketAddr { &self.0 }
}

impl DerefMut for HttpListenAddr {
    fn deref_mut(&mut self) -> &mut SocketAddr { &mut self.0 }
}

impl ToSocketAddrs for HttpListenAddr {
    type Iter = option::IntoIter<SocketAddr>;

    fn to_socket_addrs(&self) -> io::Result<Self::Iter> { self.0.to_socket_addrs() }
}

habitat_core::env_config_socketaddr!(#[derive(Clone, Copy, PartialEq, Eq, Debug)],
                                     pub ListenCtlAddr,
                                     HAB_LISTEN_CTL,
                                     Ipv4Addr::LOCALHOST, Self::DEFAULT_PORT);

impl ListenCtlAddr {
    pub const DEFAULT_PORT: u16 = 9632;

    pub fn new(ip: Ipv4Addr, port: u16) -> Self {
        ListenCtlAddr(SocketAddr::V4(SocketAddrV4::new(ip, port)))
    }

    pub fn ip(&self) -> IpAddr { self.0.ip() }

    pub fn port(&self) -> u16 { self.0.port() }
}

impl AsRef<SocketAddr> for ListenCtlAddr {
    fn as_ref(&self) -> &SocketAddr { &self.0 }
}

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

    mod gossip_listen_addr {
        use super::*;
        #[test]
        fn local_addr_for_gossip_listen_addr_works_for_unspecified_address() {
            let listen_addr = GossipListenAddr::default();
            assert!(listen_addr.0.ip().is_unspecified());

            let local_addr = listen_addr.local_addr();
            assert!(local_addr.0.ip().is_loopback());
        }

        #[test]
        fn local_addr_for_gossip_listen_addr_returns_same_ip_for_a_specified_address() {
            let mut listen_addr = GossipListenAddr::default();
            listen_addr.0
                       .set_ip(IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1)));
            assert!(!listen_addr.0.ip().is_loopback());

            let local_addr = listen_addr.local_addr();
            assert_eq!(listen_addr, local_addr);
        }
    }

    // TODO: move to alongside env::Config itself; will need to move locked_env_var -> core
    mod env_config {
        use habitat_core::env::Config as EnvConfig;
        use std::{env,
                  num::ParseIntError,
                  result,
                  str::FromStr};

        #[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq)]
        struct Thingie(u64);

        impl Default for Thingie {
            fn default() -> Self { Thingie(2112) }
        }

        impl FromStr for Thingie {
            type Err = ParseIntError;

            fn from_str(s: &str) -> result::Result<Self, Self::Err> {
                let raw = s.parse::<u64>()?;
                Ok(Thingie(raw))
            }
        }

        crate::locked_env_var!(HAB_TESTING_THINGIE, lock_hab_testing_thingie);

        impl EnvConfig for Thingie {
            const ENVVAR: &'static str = "HAB_TESTING_THINGIE";
        }

        #[test]
        fn no_env_var_yields_default() {
            let _envvar = lock_hab_testing_thingie();
            assert!(env::var("HAB_TESTING_THINGIE").is_err()); // it's not set
            assert_eq!(Thingie::configured_value(), Thingie(2112));
            assert_eq!(Thingie::configured_value(), Thingie::default());
        }

        #[test]
        fn parsable_env_var_yields_parsed_value() {
            let envvar = lock_hab_testing_thingie();
            envvar.set("123");
            assert_eq!(Thingie::configured_value(), Thingie(123));
            assert_ne!(Thingie::configured_value(), Thingie::default());
        }

        #[test]
        fn unparsable_env_var_yields_default() {
            let envvar = lock_hab_testing_thingie();
            envvar.set("I'm not a number");
            assert_eq!(Thingie::configured_value(), Thingie::default());
        }
    }
}
<commit_msg>Remove TODO<commit_after>use std::{io,
          net::{IpAddr,
                Ipv4Addr,
                SocketAddr,
                SocketAddrV4,
                ToSocketAddrs},
          ops::{Deref,
                DerefMut},
          option};

/// Bundles up information about the user and group that a supervised
/// service should be run as. If the Supervisor itself is running with
/// root-like permissions, then these will be for `SVC_USER` and
/// `SVC_GROUP` for a service. If not, it will be for the user the
/// Supervisor itself is running as.
///
/// On Windows, all but `username` will be `None`. On Linux,
/// `username` and `groupname` may legitimately be `None`, but `uid`
/// and `gid` should always be `Some`.
#[derive(Debug, Default)]
pub struct UserInfo {
    /// Windows required, Linux optional
    pub username: Option<String>,
    /// Linux preferred
    pub uid: Option<u32>,
    /// Linux optional
    pub groupname: Option<String>,
    /// Linux preferred
    pub gid: Option<u32>,
}

/// Captures arbitrary key-value pair metadata to attach to all events
/// generated by the Supervisor.
#[derive(Clone, Debug, Default)]
pub struct EventStreamMetadata(HashMap<String, String>);

impl Into<HashMap<String, String>> for EventStreamMetadata {
    fn into(self) -> HashMap<String, String> { self.0 }
}

impl EventStreamMetadata {
    /// The name of the Clap argument we'll use for arguments of this type.
    pub const ARG_NAME: &'static str = "EVENT_STREAM_METADATA";

    /// Ensure that user input from Clap can be converted into a
    /// key-value pair we can consume.
    ///
    /// Note: this validates each value given by the user, not all the
    /// values given at once.
    #[allow(clippy::needless_pass_by_value)] // Signature required by CLAP
    pub fn validate(value: String) -> result::Result<(), String> {
        Self::split_raw(&value).map(|_| ())
    }

    /// Utility function to create a key-value pair tuple from a
    /// user-provided value in Clap.
    fn split_raw(raw: &str) -> result::Result<(String, String), String> {
        match raw.split('=').collect::<Vec<_>>().as_slice() {
            [key, value] if !key.is_empty() && !value.is_empty() => {
                Ok((key.to_string(), value.to_string()))
            }
            _ => {
                Err(format!("Invalid key-value pair given (must be \
                             '='-delimited pair of non-empty strings): {}",
                            raw))
            }
        }
    }

    /// Same as `split_raw`, but for running on already-validated
    /// input (thus, this function cannot fail).
    fn split_validated(validated_input: &str) -> (String, String) {
        Self::split_raw(validated_input).expect("EVENT_STREAM_METADATA should be validated at \
                                                 this point")
    }
}

impl<'a> From<&'a ArgMatches<'a>> for EventStreamMetadata {
    /// Create an instance of `EventStreamMetadata` from validated
    /// user input.
    fn from(m: &ArgMatches) -> Self {
        let raw_meta = m.values_of(Self::ARG_NAME).unwrap_or_default();
        Self(raw_meta.map(Self::split_validated).collect())
    }
}

/// This represents an environment variable that holds an authentication token which enables
/// integration with Automate. Supervisors use this token to connect to the messaging server
/// on the Automate side in order to send data about the services they're running via event
/// messages. If the environment variable is present, its value is the auth token. If it's not
/// present and the feature flag for the Event Stream is enabled, initialization of the Event
/// Stream will fail.
#[derive(Clone, Debug)]
pub struct AutomateAuthToken(String);

impl AutomateAuthToken {
    /// The name of the Clap argument we'll use for arguments of this type.
    pub const ARG_NAME: &'static str = "EVENT_STREAM_TOKEN";
    // Ideally, we'd like to take advantage of
    // `habitat_core::env::Config` trait, but that currently requires
    // a `Default` implementation, and there isn't really a legitimate
    // default value right now.
    pub const ENVVAR: &'static str = "HAB_AUTOMATE_AUTH_TOKEN";
}

impl AutomateAuthToken {
    /// Ensure that user input from Clap can be converted an instance
    /// of a token.
    #[allow(clippy::needless_pass_by_value)] // Signature required by CLAP
    pub fn validate(value: String) -> result::Result<(), String> {
        value.parse::<Self>().map(|_| ()).map_err(|e| e.to_string())
    }
}

impl<'a> From<&'a ArgMatches<'a>> for AutomateAuthToken {
    /// Create an instance of `AutomateAuthToken` from validated
    /// user input.
    fn from(m: &ArgMatches) -> Self {
        m.value_of(Self::ARG_NAME)
         .expect("HAB_AUTOMATE_AUTH_TOKEN should be set")
         .parse()
         .expect("HAB_AUTOMATE_AUTH_TOKEN should be validated at this point")
    }
}

impl FromStr for AutomateAuthToken {
    type Err = Error;

    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
        if s.is_empty() {
            Err(Error::InvalidEventStreamToken(s.to_string()))
        } else {
            Ok(AutomateAuthToken(s.to_string()))
        }
    }
}

impl fmt::Display for AutomateAuthToken {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.0) }
}

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

    mod auth_token {
        use super::*;

        #[test]
        fn cannot_parse_from_empty_string() { assert!("".parse::<AutomateAuthToken>().is_err()) }

    }
}

habitat_core::env_config_socketaddr!(#[derive(Clone, Copy, PartialEq, Eq, Debug)],
                                     pub GossipListenAddr,
                                     HAB_LISTEN_GOSSIP,
                                     0, 0, 0, 0, Self::DEFAULT_PORT);

impl GossipListenAddr {
    pub const DEFAULT_PORT: u16 = 9638;

    /// When local gossip mode is used we still startup the gossip layer but set
    /// it to listen on 127.0.0.2 to scope it to the local node but ignore connections from
    /// 127.0.0.1. This turns out to be much simpler than the cascade of changes that would
    /// be involved in not setting up a gossip listener at all.
    pub fn local_only() -> Self {
        GossipListenAddr(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 2),
                                                          Self::DEFAULT_PORT)))
    }

    /// Generate an address at which a server configured with this
    /// GossipListenAddr can communicate with itself.
    ///
    /// In particular, a server configured to listen on `0.0.0.0` vs
    /// `192.168.1.1` should be contacted via `127.0.0.1` in the
    /// former case, but `192.168.1.1` in the latter.
    pub fn local_addr(&self) -> Self {
        let mut addr = *self;
        if addr.0.ip().is_unspecified() {
            // TODO (CM): Use Ipv4Addr::loopback() when it's no longer experimental
            // TODO (CM): Support IPV6, once we do that more broadly
            addr.0.set_ip(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
        }
        addr
    }
}

impl Deref for GossipListenAddr {
    type Target = SocketAddr;

    fn deref(&self) -> &SocketAddr { &self.0 }
}

impl DerefMut for GossipListenAddr {
    fn deref_mut(&mut self) -> &mut SocketAddr { &mut self.0 }
}

impl ToSocketAddrs for GossipListenAddr {
    type Iter = option::IntoIter<SocketAddr>;

    fn to_socket_addrs(&self) -> io::Result<Self::Iter> { self.0.to_socket_addrs() }
}

habitat_core::env_config_socketaddr!(#[derive(PartialEq, Eq, Debug, Clone, Copy)],
                                     pub HttpListenAddr,
                                     HAB_LISTEN_HTTP,
                                     0, 0, 0, 0, 9631);
impl HttpListenAddr {
    pub fn new(ip: IpAddr, port: u16) -> Self { Self(SocketAddr::new(ip, port)) }
}

impl Deref for HttpListenAddr {
    type Target = SocketAddr;

    fn deref(&self) -> &SocketAddr { &self.0 }
}

impl DerefMut for HttpListenAddr {
    fn deref_mut(&mut self) -> &mut SocketAddr { &mut self.0 }
}

impl ToSocketAddrs for HttpListenAddr {
    type Iter = option::IntoIter<SocketAddr>;

    fn to_socket_addrs(&self) -> io::Result<Self::Iter> { self.0.to_socket_addrs() }
}

habitat_core::env_config_socketaddr!(#[derive(Clone, Copy, PartialEq, Eq, Debug)],
                                     pub ListenCtlAddr,
                                     HAB_LISTEN_CTL,
                                     Ipv4Addr::LOCALHOST, Self::DEFAULT_PORT);

impl ListenCtlAddr {
    pub const DEFAULT_PORT: u16 = 9632;

    pub fn new(ip: Ipv4Addr, port: u16) -> Self {
        ListenCtlAddr(SocketAddr::V4(SocketAddrV4::new(ip, port)))
    }

    pub fn ip(&self) -> IpAddr { self.0.ip() }

    pub fn port(&self) -> u16 { self.0.port() }
}

impl AsRef<SocketAddr> for ListenCtlAddr {
    fn as_ref(&self) -> &SocketAddr { &self.0 }
}

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

    mod gossip_listen_addr {
        use super::*;
        #[test]
        fn local_addr_for_gossip_listen_addr_works_for_unspecified_address() {
            let listen_addr = GossipListenAddr::default();
            assert!(listen_addr.0.ip().is_unspecified());

            let local_addr = listen_addr.local_addr();
            assert!(local_addr.0.ip().is_loopback());
        }

        #[test]
        fn local_addr_for_gossip_listen_addr_returns_same_ip_for_a_specified_address() {
            let mut listen_addr = GossipListenAddr::default();
            listen_addr.0
                       .set_ip(IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1)));
            assert!(!listen_addr.0.ip().is_loopback());

            let local_addr = listen_addr.local_addr();
            assert_eq!(listen_addr, local_addr);
        }
    }

    mod env_config {
        use habitat_core::env::Config as EnvConfig;
        use std::{env,
                  num::ParseIntError,
                  result,
                  str::FromStr};

        #[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq)]
        struct Thingie(u64);

        impl Default for Thingie {
            fn default() -> Self { Thingie(2112) }
        }

        impl FromStr for Thingie {
            type Err = ParseIntError;

            fn from_str(s: &str) -> result::Result<Self, Self::Err> {
                let raw = s.parse::<u64>()?;
                Ok(Thingie(raw))
            }
        }

        crate::locked_env_var!(HAB_TESTING_THINGIE, lock_hab_testing_thingie);

        impl EnvConfig for Thingie {
            const ENVVAR: &'static str = "HAB_TESTING_THINGIE";
        }

        #[test]
        fn no_env_var_yields_default() {
            let _envvar = lock_hab_testing_thingie();
            assert!(env::var("HAB_TESTING_THINGIE").is_err()); // it's not set
            assert_eq!(Thingie::configured_value(), Thingie(2112));
            assert_eq!(Thingie::configured_value(), Thingie::default());
        }

        #[test]
        fn parsable_env_var_yields_parsed_value() {
            let envvar = lock_hab_testing_thingie();
            envvar.set("123");
            assert_eq!(Thingie::configured_value(), Thingie(123));
            assert_ne!(Thingie::configured_value(), Thingie::default());
        }

        #[test]
        fn unparsable_env_var_yields_default() {
            let envvar = lock_hab_testing_thingie();
            envvar.set("I'm not a number");
            assert_eq!(Thingie::configured_value(), Thingie::default());
        }
    }
}
<|endoftext|>


<commit_before>//! Node attributes.

use std::io::Read;

use parser::binary::BinaryParser;
use parser::binary::error::{Result, Warning};
use parser::binary::event::NodeHeader;
pub use self::array::{ArrayAttribute, ArrayAttributeReader};
pub use self::special::{SpecialAttribute, SpecialAttributeType};

mod array;
mod special;

/// Node attribute.
#[derive(Debug)]
pub struct Attributes<'a, R: 'a> {
    /// Number of all attributes.
    num_attributes: u64,
    /// Number of rest attributes.
    rest_attributes: u64,
    /// End offset of the previous attribute.
    prev_attr_end: Option<u64>,
    /// Parser.
    parser: &'a mut BinaryParser<R>,
}

impl<'a, R: 'a + Read> Attributes<'a, R> {
    /// Returns number of all attributes.
    pub fn num_attributes(&self) -> u64 {
        self.num_attributes
    }

    /// Returns number of rest attributes.
    pub fn rest_attributes(&self) -> u64 {
        self.rest_attributes
    }

    /// Returns the next attribute if available.
    pub fn next_attribute(&mut self) -> Result<Option<Attribute<R>>> {
        if self.rest_attributes == 0 {
            return Ok(None);
        }

        // Skip unread part of the previous attribute if available.
        if let Some(prev_attr_end) = self.prev_attr_end {
            try!(self.parser.source.skip_to(prev_attr_end));
            self.prev_attr_end = None;
        }

        self.rest_attributes -= 1;
        let type_code = try!(self.parser.source.read_u8());
        let position = self.parser.source.count();
        match type_code {
            // Primitive type attributes.
            b'C' => {
                let raw = try!(self.parser.source.read_u8());
                let val = (raw & 0x01) == 1;
                if raw != b'T' && raw != b'Y' {
                    self.parser.warn(Warning::InvalidBooleanAttributeValue {
                        got: raw,
                        assumed: val,
                        position: position,
                    });
                }
                Ok(Some(PrimitiveAttribute::Bool(val).into()))
            },
            b'Y' => Ok(Some(PrimitiveAttribute::I16(try!(self.parser.source.read_i16())).into())),
            b'I' => Ok(Some(PrimitiveAttribute::I32(try!(self.parser.source.read_i32())).into())),
            b'L' => Ok(Some(PrimitiveAttribute::I64(try!(self.parser.source.read_i64())).into())),
            b'F' => Ok(Some(PrimitiveAttribute::F32(try!(self.parser.source.read_f32())).into())),
            b'D' => Ok(Some(PrimitiveAttribute::F64(try!(self.parser.source.read_f64())).into())),
            // Special type attributes.
            b'R' | b'S' => {
                let (attr, end_offset) = try!(special::read_special_attribute(self.parser, type_code));
                self.prev_attr_end = Some(end_offset);
                Ok(Some(attr.into()))
            },
            // Array type attributes.
            b'b' | b'i' | b'l' | b'f' | b'd' => {
                let (attr, end_offset) = try!(array::read_array_attribute(self.parser, type_code));
                self.prev_attr_end = Some(end_offset);
                Ok(Some(attr.into()))
            },
            // Unknown type attributes.
            _ => unimplemented!(),
        }
    }
}

impl<'a, R: 'a> From<PrimitiveAttribute> for Attribute<'a, R> {
    fn from(a: PrimitiveAttribute) -> Self {
        Attribute::Primitive(a)
    }
}

impl<'a, R: 'a> From<SpecialAttribute<'a, R>> for Attribute<'a, R> {
    fn from(a: SpecialAttribute<'a, R>) -> Self {
        Attribute::Special(a)
    }
}

impl<'a, R: 'a> From<ArrayAttribute<'a, R>> for Attribute<'a, R> {
    fn from(a: ArrayAttribute<'a, R>) -> Self {
        Attribute::Array(a)
    }
}

/// Creates a new `Attributes`.
pub fn new_attributes<'a, R: 'a>(
    parser: &'a mut BinaryParser<R>,
    header: &NodeHeader
) -> Attributes<'a, R> {
    Attributes {
        num_attributes: header.num_attributes,
        rest_attributes: header.num_attributes,
        prev_attr_end: None,
        parser: parser,
    }
}

/// Node attribute.
#[derive(Debug)]
pub enum Attribute<'a, R: 'a> {
    /// Primitive type value.
    Primitive(PrimitiveAttribute),
    /// Array type value.
    Array(ArrayAttribute<'a, R>),
    /// Special type value.
    Special(SpecialAttribute<'a, R>),
}

/// Attribute type of primitive value.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PrimitiveAttribute {
    /// Single `bool`.
    Bool(bool),
    /// Single `i16`.
    I16(i16),
    /// Single `i32`.
    I32(i32),
    /// Single `i64`.
    I64(i64),
    /// Single `f32`.
    F32(f32),
    /// Single `f64`.
    F64(f64),
}

impl PrimitiveAttribute {
    /// Converts floating-point number into `f32`.
    pub fn as_f32(&self) -> Option<f32> {
        match *self {
            PrimitiveAttribute::F32(v) => Some(v),
            PrimitiveAttribute::F64(v) => Some(v as f32),
            _ => None,
        }
    }

    /// Converts floating-point number into `f32`.
    pub fn as_f64(&self) -> Option<f64> {
        match *self {
            PrimitiveAttribute::F32(v) => Some(v as f64),
            PrimitiveAttribute::F64(v) => Some(v),
            _ => None,
        }
    }
}
<commit_msg>Simplify code by using `use`<commit_after>//! Node attributes.

use std::io::Read;

use parser::binary::BinaryParser;
use parser::binary::error::{Result, Warning};
use parser::binary::event::NodeHeader;
use self::array::read_array_attribute;
pub use self::array::{ArrayAttribute, ArrayAttributeReader};
use self::special::read_special_attribute;
pub use self::special::{SpecialAttribute, SpecialAttributeType};

mod array;
mod special;

/// Node attribute.
#[derive(Debug)]
pub struct Attributes<'a, R: 'a> {
    /// Number of all attributes.
    num_attributes: u64,
    /// Number of rest attributes.
    rest_attributes: u64,
    /// End offset of the previous attribute.
    prev_attr_end: Option<u64>,
    /// Parser.
    parser: &'a mut BinaryParser<R>,
}

impl<'a, R: 'a + Read> Attributes<'a, R> {
    /// Returns number of all attributes.
    pub fn num_attributes(&self) -> u64 {
        self.num_attributes
    }

    /// Returns number of rest attributes.
    pub fn rest_attributes(&self) -> u64 {
        self.rest_attributes
    }

    /// Returns the next attribute if available.
    pub fn next_attribute(&mut self) -> Result<Option<Attribute<R>>> {
        if self.rest_attributes == 0 {
            return Ok(None);
        }

        // Skip unread part of the previous attribute if available.
        if let Some(prev_attr_end) = self.prev_attr_end {
            try!(self.parser.source.skip_to(prev_attr_end));
            self.prev_attr_end = None;
        }

        self.rest_attributes -= 1;
        let type_code = try!(self.parser.source.read_u8());
        let position = self.parser.source.count();
        match type_code {
            // Primitive type attributes.
            b'C' => {
                let raw = try!(self.parser.source.read_u8());
                let val = (raw & 0x01) == 1;
                if raw != b'T' && raw != b'Y' {
                    self.parser.warn(Warning::InvalidBooleanAttributeValue {
                        got: raw,
                        assumed: val,
                        position: position,
                    });
                }
                Ok(Some(PrimitiveAttribute::Bool(val).into()))
            },
            b'Y' => Ok(Some(PrimitiveAttribute::I16(try!(self.parser.source.read_i16())).into())),
            b'I' => Ok(Some(PrimitiveAttribute::I32(try!(self.parser.source.read_i32())).into())),
            b'L' => Ok(Some(PrimitiveAttribute::I64(try!(self.parser.source.read_i64())).into())),
            b'F' => Ok(Some(PrimitiveAttribute::F32(try!(self.parser.source.read_f32())).into())),
            b'D' => Ok(Some(PrimitiveAttribute::F64(try!(self.parser.source.read_f64())).into())),
            // Special type attributes.
            b'R' | b'S' => {
                let (attr, end_offset) = try!(read_special_attribute(self.parser, type_code));
                self.prev_attr_end = Some(end_offset);
                Ok(Some(attr.into()))
            },
            // Array type attributes.
            b'b' | b'i' | b'l' | b'f' | b'd' => {
                let (attr, end_offset) = try!(read_array_attribute(self.parser, type_code));
                self.prev_attr_end = Some(end_offset);
                Ok(Some(attr.into()))
            },
            // Unknown type attributes.
            _ => unimplemented!(),
        }
    }
}

impl<'a, R: 'a> From<PrimitiveAttribute> for Attribute<'a, R> {
    fn from(a: PrimitiveAttribute) -> Self {
        Attribute::Primitive(a)
    }
}

impl<'a, R: 'a> From<SpecialAttribute<'a, R>> for Attribute<'a, R> {
    fn from(a: SpecialAttribute<'a, R>) -> Self {
        Attribute::Special(a)
    }
}

impl<'a, R: 'a> From<ArrayAttribute<'a, R>> for Attribute<'a, R> {
    fn from(a: ArrayAttribute<'a, R>) -> Self {
        Attribute::Array(a)
    }
}

/// Creates a new `Attributes`.
pub fn new_attributes<'a, R: 'a>(
    parser: &'a mut BinaryParser<R>,
    header: &NodeHeader
) -> Attributes<'a, R> {
    Attributes {
        num_attributes: header.num_attributes,
        rest_attributes: header.num_attributes,
        prev_attr_end: None,
        parser: parser,
    }
}

/// Node attribute.
#[derive(Debug)]
pub enum Attribute<'a, R: 'a> {
    /// Primitive type value.
    Primitive(PrimitiveAttribute),
    /// Array type value.
    Array(ArrayAttribute<'a, R>),
    /// Special type value.
    Special(SpecialAttribute<'a, R>),
}

/// Attribute type of primitive value.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PrimitiveAttribute {
    /// Single `bool`.
    Bool(bool),
    /// Single `i16`.
    I16(i16),
    /// Single `i32`.
    I32(i32),
    /// Single `i64`.
    I64(i64),
    /// Single `f32`.
    F32(f32),
    /// Single `f64`.
    F64(f64),
}

impl PrimitiveAttribute {
    /// Converts floating-point number into `f32`.
    pub fn as_f32(&self) -> Option<f32> {
        match *self {
            PrimitiveAttribute::F32(v) => Some(v),
            PrimitiveAttribute::F64(v) => Some(v as f32),
            _ => None,
        }
    }

    /// Converts floating-point number into `f32`.
    pub fn as_f64(&self) -> Option<f64> {
        match *self {
            PrimitiveAttribute::F32(v) => Some(v as f64),
            PrimitiveAttribute::F64(v) => Some(v),
            _ => None,
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::sync::mpsc::{Sender, Receiver, channel};
use std::sync::mpsc::TryRecvError;
use std::sync::{Arc, Mutex};
use std::old_io::timer;
use std::time::Duration;

use messages::{ActorMessages, TransactionRequest, MarketMessages, MarketHistory};
use messages::ActorMessages::{StockRequest, MoneyRequest, CommitTransaction, AbortTransaction, History, Time};
use messages::MarketMessages::{BuyRequest, SellRequest, Commit, Cancel, RegisterActor, MatchRequest};
use actor::Actor;

// Smarter actor
// (monitors price last sold at and put a sell request if any stocks are above their purchase price)

pub fn start_smarter_actor(actor_id: usize, existing_markets: HashMap<usize, Sender<MarketMessages>>, actor_tx: Sender<ActorMessages>, actor_rx: Receiver<ActorMessages>) {
  println!("Starting Smarter_Actor {}", actor_id);
  let mut init_history = false;
  let mut actor = Actor { id: actor_id,
                          money: 100,
                          stocks: HashMap::new(),
                          pending_money: 0,
                          pending_stock: (0, 0),
                          markets: existing_markets,
                          history: Arc::new(Mutex::new(MarketHistory {history: HashMap::new(), stocks: vec![]}))
                          };
  // Stocks = HashMap<market_id, HashMap<stock_id, (price,quantity)>>
  let mut buy_requests : HashMap<usize, HashMap<usize,(usize,usize)>> = HashMap::new();
  let mut unique_id : usize = 0;

  for (_, market_tx) in actor.markets.iter() {
    market_tx.send(RegisterActor(actor.id, actor_tx.clone())).unwrap();
  }

  loop {
    //Logic
    let mark_clone = actor.markets.clone();
    let stock_clone = actor.stocks.clone();

    if(init_history){
      let hist = actor.history.lock().unwrap();

      // For each stock in history
      for stock in hist.stocks.iter(){
        match(hist.history.get(stock)){
          Some(mut transactions) => {
            println!("Length of transactions is {} for {}.",transactions.len(),stock);
            if(transactions.len() > 0){
              let (buyer,seller) = transactions[transactions.len()-1].clone();
              match buy_requests.get(&0){
                Some(stock_requests) => {
                  match stock_requests.get(stock){
                    Some(&(request_price,request_quantity)) => {
                      // If price is above out request a sell
                      if(buyer.price > request_price){
                        send_message(0,&mark_clone,BuyRequest(TransactionRequest {transaction_id: unique_id, actor_id:actor_id, stock_id: stock.clone(), price:buyer.price, quantity:buyer.quantity }));
                        unique_id = unique_id + 1;
                      }
                    },
                    None => {
                      // Submit new buy request
                    }
                  }
                },
                None =>{} // Market didn't exist?

              }
            }

            },
          None => {}
        }

      }

      println!("History has length {} for smarter_actor.",hist.stocks.len());
    }

    match actor_rx.try_recv() {
      Ok(message) => {
          match message {
            StockRequest(stock_request) => {
              println!("Started Stock Request in smarter_actor {}", actor.id);
              let market_tx;
              let tx_text = mark_clone.get(&stock_request.market_id);
              match tx_text {
                Some(tx) => {
                  market_tx = tx;
                },
                None => {
                  return; //HOW DID WE GET A MISSING MARKET?
                }
              }
              if has_pending_transaction(&actor) {
                market_tx.send(Cancel(actor.id)).unwrap();
              }
              else {
                //if we have the stock. set it aside.
                let stock_id = stock_request.stock_id;
                let quantity = stock_request.quantity;
                let stock = stock_clone.get(&stock_id);
                match stock {
                  Some(owned_quantity) => {
                    if *owned_quantity >= quantity {
                      remove_stock(&mut actor, (stock_id, quantity));
                      actor.pending_stock = (stock_id, quantity);
                      market_tx.send(Commit(actor.id)).unwrap();
                    }
                    else {
                      market_tx.send(Cancel(actor.id)).unwrap();
                    }
                  },
                  None => {
                    market_tx.send(Cancel(actor.id)).unwrap();
                  }
                }
              }
              print_status(&actor);
              },
            MoneyRequest(money_request) => {
              let market_tx;
              let tx_text = actor.markets.get(&money_request.market_id);
              match tx_text {
                Some(tx) => {
                  market_tx = tx;
                },
                None => {
                  return; //HOW DID WE GET A MISSING MARKET?
                }
              }
              if has_pending_transaction(&actor) {
                market_tx.send(Cancel(actor.id)).unwrap();
              }
              else {
                //if we have the money. set it aside.
                if actor.money >= money_request.amount {
                  actor.money = actor.money - money_request.amount;
                  actor.pending_money = money_request.amount;
                  market_tx.send(Commit(actor.id)).unwrap();
                }
                else {
                  market_tx.send(Cancel(actor.id)).unwrap();
                }
              }
              print_status(&actor);
              },
            CommitTransaction(commit_transaction_request) => {
              //if we have money pending, then look up the stock id and add that quantity purchased.
              //remove the pending money
              if actor.pending_money > 0 {
                let price_per_unit = commit_transaction_request.price;
                let units = commit_transaction_request.quantity;
                let leftover_money = actor.pending_money - price_per_unit * units;

                //make a function for adding stock.
                add_stock(&mut actor, (commit_transaction_request.stock_id, units));
                actor.money = actor.money + leftover_money;

                actor.pending_money = 0;
              }

              //if we have stock pending, look up the quantity purchased and add the money.
              //remove the pending stock
              if actor.pending_stock.1 > 0 {
                let money = commit_transaction_request.price * commit_transaction_request.quantity;
                let restore_stock = (commit_transaction_request.stock_id, actor.pending_stock.1 - commit_transaction_request.quantity);
                if restore_stock.1 > 0 {
                  add_stock(&mut actor, restore_stock);
                }
                actor.money = actor.money + money;
                actor.pending_stock = (0,0);
              }
              println!("After a committed transaction in smarter_actor {} ", actor.id);
              print_status(&actor);
              },
            AbortTransaction => {
              //move pending stock back into stocks.
              if actor.pending_stock.1 != 0 {
                let pending_stock_clone = actor.pending_stock.clone();
                add_stock(&mut actor, pending_stock_clone);
                //now that we have moved it. Clear out the pending stock.
                actor.pending_stock = (0,0); //setting the quantity to zero clears it.
              }
              for (stock_id, quantity) in actor.stocks.iter() {
                println!("After aborting the transaction, smarter_actor {} now has StockId: {} Quantity: {}", actor.id, *stock_id, *quantity);
              }

              //move pending money back into money.
              if actor.pending_money > 0 {
                actor.money = actor.money + actor.pending_money;
                actor.pending_money = 0;
              }
              println!("After aborting the transaction, smarter_actor {} now has {} money.", actor.id, actor.money);
            },
            History(history) => {
              println!("Smarter_actor {} received history {}", actor.id, *(history.lock().unwrap()));
              actor.history = history;
              init_history = true;
              },
            Time(current, max) => {
              println!("Smarter_actor {} received time {}", actor.id, current);
            }
          }
        },
      Err(TryRecvError::Empty) => {timer::sleep(Duration::milliseconds(10));},
      Err(TryRecvError::Disconnected) => {println!("ERROR: Smarter_actor {} disconnected", actor.id);}
    }
  }
}

fn add_stock(actor: &mut Actor, stock_to_add: (usize, usize)) {
  let stock_clone = actor.stocks.clone();
  let held_stock = stock_clone.get(&stock_to_add.0);
  match held_stock {
    Some(stock_count) => {
        //we have some stock. We need to add to our reserve.
        actor.stocks.insert(stock_to_add.0, stock_to_add.1 + *stock_count);
      },
    None => {
      //we don't have any stock left. Just add it back.
      actor.stocks.insert(stock_to_add.0, stock_to_add.1);
    }
  }
}

// send_message(0,actor.markets,BuyRequest(TransactionRequest {transaction_id: unique_id, actor_id:actor_id, stock_id: stock, price:buyer.price, quantity:buyer.quantity }));

fn send_message(market_id : usize, markets: &HashMap<usize, Sender<MarketMessages>>, message: MarketMessages){
  match markets.get(&market_id){
    Some(market) => {
      market.send(message);
      },
    None => {}
  }
}

fn remove_stock(actor: &mut Actor, stock_to_remove: (usize, usize)) {
  let stock_clone = actor.stocks.clone();
  let held_stock = stock_clone.get(&stock_to_remove.0);
  match held_stock {
    Some(stock_count) => {
        //we have some stock. We need to add to our reserve.
        actor.stocks.insert(stock_to_remove.0, *stock_count - stock_to_remove.1);
      },
    None => {} //TODO Should we error handle here?
  }
}

fn print_status(actor: &Actor) {
  for (stock_id, quantity) in (*actor).stocks.iter() {
    println!("Actor {} now has StockId: {} Quantity: {}", (*actor).id, *stock_id, *quantity);
  }
  println!("Actor {} has {} money.", (*actor).id, (*actor).money);
}

fn has_pending_transaction(actor: &Actor) -> bool {
  (*actor).pending_money > 0 || (*actor).pending_stock.1 > 0
}
<commit_msg>Post commit<commit_after>use std::collections::HashMap;
use std::sync::mpsc::{Sender, Receiver, channel};
use std::sync::mpsc::TryRecvError;
use std::sync::{Arc, Mutex};
use std::old_io::timer;
use std::time::Duration;

use messages::{ActorMessages, TransactionRequest, MarketMessages, MarketHistory};
use messages::ActorMessages::{StockRequest, MoneyRequest, CommitTransaction, AbortTransaction, History, Time, ReceiveActivityCount};
use messages::MarketMessages::{BuyRequest, SellRequest, Commit, Cancel, RegisterActor, MatchRequest};
use actor::Actor;

// Smarter actor
// (monitors price last sold at and put a sell request if any stocks are above their purchase price)

pub fn start_smarter_actor(actor_id: usize, existing_markets: HashMap<usize, Sender<MarketMessages>>, actor_tx: Sender<ActorMessages>, actor_rx: Receiver<ActorMessages>) {
  println!("Starting Smarter_Actor {}", actor_id);
  let mut init_history = false;
  let mut actor = Actor { id: actor_id,
                          money: 100,
                          stocks: HashMap::new(),
                          pending_money: 0,
                          pending_stock: (0, 0),
                          markets: existing_markets,
                          history: Arc::new(Mutex::new(MarketHistory {history: HashMap::new(), stocks: vec![]}))
                          };
  // Stocks = HashMap<market_id, HashMap<stock_id, (price,quantity)>>
  let mut buy_requests : HashMap<usize, HashMap<usize,(usize,usize)>> = HashMap::new();
  let mut unique_id : usize = 0;

  for (_, market_tx) in actor.markets.iter() {
    market_tx.send(RegisterActor(actor.id, actor_tx.clone())).unwrap();
  }

  loop {
    //Logic
    let mark_clone = actor.markets.clone();
    let stock_clone = actor.stocks.clone();

    if(init_history){
      let hist = actor.history.lock().unwrap();

      // For each stock in history
      for stock in hist.stocks.iter(){
        match(hist.history.get(stock)){
          Some(mut transactions) => {
            println!("Length of transactions is {} for {}.",transactions.len(),stock);
            if(transactions.len() > 0){
              let (buyer,seller) = transactions[transactions.len()-1].clone();
              match buy_requests.get(&0){
                Some(stock_requests) => {
                  match stock_requests.get(stock){
                    Some(&(request_price,request_quantity)) => {
                      // If price is above out request a sell
                      if(buyer.price > request_price){
                        send_message(0,&mark_clone,BuyRequest(TransactionRequest {transaction_id: unique_id, actor_id:actor_id, stock_id: stock.clone(), price:buyer.price, quantity:buyer.quantity }));
                        unique_id = unique_id + 1;
                      }
                    },
                    None => {
                      // Submit new buy request
                    }
                  }
                },
                None =>{} // Market didn't exist?

              }
            }

            },
          None => {}
        }

      }

      println!("History has length {} for smarter_actor.",hist.stocks.len());
    }

    match actor_rx.try_recv() {
      Ok(message) => {
          match message {
            StockRequest(stock_request) => {
              println!("Started Stock Request in smarter_actor {}", actor.id);
              let market_tx;
              let tx_text = mark_clone.get(&stock_request.market_id);
              match tx_text {
                Some(tx) => {
                  market_tx = tx;
                },
                None => {
                  return; //HOW DID WE GET A MISSING MARKET?
                }
              }
              if has_pending_transaction(&actor) {
                market_tx.send(Cancel(actor.id)).unwrap();
              }
              else {
                //if we have the stock. set it aside.
                let stock_id = stock_request.stock_id;
                let quantity = stock_request.quantity;
                let stock = stock_clone.get(&stock_id);
                match stock {
                  Some(owned_quantity) => {
                    if *owned_quantity >= quantity {
                      remove_stock(&mut actor, (stock_id, quantity));
                      actor.pending_stock = (stock_id, quantity);
                      market_tx.send(Commit(actor.id)).unwrap();
                    }
                    else {
                      market_tx.send(Cancel(actor.id)).unwrap();
                    }
                  },
                  None => {
                    market_tx.send(Cancel(actor.id)).unwrap();
                  }
                }
              }
              print_status(&actor);
              },
            MoneyRequest(money_request) => {
              let market_tx;
              let tx_text = actor.markets.get(&money_request.market_id);
              match tx_text {
                Some(tx) => {
                  market_tx = tx;
                },
                None => {
                  return; //HOW DID WE GET A MISSING MARKET?
                }
              }
              if has_pending_transaction(&actor) {
                market_tx.send(Cancel(actor.id)).unwrap();
              }
              else {
                //if we have the money. set it aside.
                if actor.money >= money_request.amount {
                  actor.money = actor.money - money_request.amount;
                  actor.pending_money = money_request.amount;
                  market_tx.send(Commit(actor.id)).unwrap();
                }
                else {
                  market_tx.send(Cancel(actor.id)).unwrap();
                }
              }
              print_status(&actor);
              },
            CommitTransaction(commit_transaction_request) => {
              //if we have money pending, then look up the stock id and add that quantity purchased.
              //remove the pending money
              if actor.pending_money > 0 {
                let price_per_unit = commit_transaction_request.price;
                let units = commit_transaction_request.quantity;
                let leftover_money = actor.pending_money - price_per_unit * units;

                //make a function for adding stock.
                add_stock(&mut actor, (commit_transaction_request.stock_id, units));
                actor.money = actor.money + leftover_money;

                actor.pending_money = 0;
              }

              //if we have stock pending, look up the quantity purchased and add the money.
              //remove the pending stock
              if actor.pending_stock.1 > 0 {
                let money = commit_transaction_request.price * commit_transaction_request.quantity;
                let restore_stock = (commit_transaction_request.stock_id, actor.pending_stock.1 - commit_transaction_request.quantity);
                if restore_stock.1 > 0 {
                  add_stock(&mut actor, restore_stock);
                }
                actor.money = actor.money + money;
                actor.pending_stock = (0,0);
              }
              println!("After a committed transaction in smarter_actor {} ", actor.id);
              print_status(&actor);
              },
            AbortTransaction => {
              //move pending stock back into stocks.
              if actor.pending_stock.1 != 0 {
                let pending_stock_clone = actor.pending_stock.clone();
                add_stock(&mut actor, pending_stock_clone);
                //now that we have moved it. Clear out the pending stock.
                actor.pending_stock = (0,0); //setting the quantity to zero clears it.
              }
              for (stock_id, quantity) in actor.stocks.iter() {
                println!("After aborting the transaction, smarter_actor {} now has StockId: {} Quantity: {}", actor.id, *stock_id, *quantity);
              }

              //move pending money back into money.
              if actor.pending_money > 0 {
                actor.money = actor.money + actor.pending_money;
                actor.pending_money = 0;
              }
              println!("After aborting the transaction, smarter_actor {} now has {} money.", actor.id, actor.money);
            },
            History(history) => {
              println!("Smarter_actor {} received history {}", actor.id, *(history.lock().unwrap()));
              actor.history = history;
              init_history = true;
              },
            Time(current, max) => {
              println!("Smarter_actor {} received time {}", actor.id, current);
            },
            ReceiveActivityCount(_,_,_) => {},
          }
        },
      Err(TryRecvError::Empty) => {timer::sleep(Duration::milliseconds(10));},
      Err(TryRecvError::Disconnected) => {println!("ERROR: Smarter_actor {} disconnected", actor.id);}
    }
  }
}

fn add_stock(actor: &mut Actor, stock_to_add: (usize, usize)) {
  let stock_clone = actor.stocks.clone();
  let held_stock = stock_clone.get(&stock_to_add.0);
  match held_stock {
    Some(stock_count) => {
        //we have some stock. We need to add to our reserve.
        actor.stocks.insert(stock_to_add.0, stock_to_add.1 + *stock_count);
      },
    None => {
      //we don't have any stock left. Just add it back.
      actor.stocks.insert(stock_to_add.0, stock_to_add.1);
    }
  }
}

// send_message(0,actor.markets,BuyRequest(TransactionRequest {transaction_id: unique_id, actor_id:actor_id, stock_id: stock, price:buyer.price, quantity:buyer.quantity }));

fn send_message(market_id : usize, markets: &HashMap<usize, Sender<MarketMessages>>, message: MarketMessages){
  match markets.get(&market_id){
    Some(market) => {
      market.send(message);
      },
    None => {}
  }
}

fn remove_stock(actor: &mut Actor, stock_to_remove: (usize, usize)) {
  let stock_clone = actor.stocks.clone();
  let held_stock = stock_clone.get(&stock_to_remove.0);
  match held_stock {
    Some(stock_count) => {
        //we have some stock. We need to add to our reserve.
        actor.stocks.insert(stock_to_remove.0, *stock_count - stock_to_remove.1);
      },
    None => {} //TODO Should we error handle here?
  }
}

fn print_status(actor: &Actor) {
  for (stock_id, quantity) in (*actor).stocks.iter() {
    println!("Actor {} now has StockId: {} Quantity: {}", (*actor).id, *stock_id, *quantity);
  }
  println!("Actor {} has {} money.", (*actor).id, (*actor).money);
}

fn has_pending_transaction(actor: &Actor) -> bool {
  (*actor).pending_money > 0 || (*actor).pending_stock.1 > 0
}
<|endoftext|>


<commit_before>// Copyright 2017 TiKV Project Authors. Licensed under Apache-2.0.

use std::error::Error;
use tikv_util::config::ReadableDuration;

/// The configuration for a PD Client.
///
/// By default during initialization the client will attempt to reconnect every 300s
/// for infinity, logging only every 10th duplicate error.
#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
#[serde(default)]
#[serde(rename_all = "kebab-case")]
pub struct Config {
    /// The PD endpoints for the client.
    ///
    /// Default is empty.
    pub endpoints: Vec<String>,
    /// The interval at which to retry a PD connection initialization.
    ///
    /// Default is 300ms.
    pub retry_interval: ReadableDuration,
    /// The maximum number of times to retry a PD connection initialization.
    ///
    /// Default is isize::MAX, represented by -1.
    pub retry_max_count: isize,
    /// If the client observes the same error message on retry, it can repeat the message only
    /// every `n` times.
    ///
    /// Default is 10. Set to 1 to disable this feature.
    pub retry_log_every: usize,
}

impl Default for Config {
    fn default() -> Self {
        Config {
            endpoints: Default::default(),
            retry_interval: ReadableDuration::millis(300),
            retry_max_count: std::isize::MAX,
            retry_log_every: 10,
        }
    }
}

impl Config {
    pub fn new(endpoints: Vec<String>) -> Self {
        Config {
            endpoints,
            ..Default::default()
        }
    }

    pub fn validate(&self) -> Result<(), Box<dyn Error>> {
        if self.endpoints.is_empty() {
            return Err("please specify pd.endpoints.".into());
        }

        if self.retry_log_every == 0 {
            return Err("pd.retry_log_every cannot be <=0".into());
        }

        if self.retry_max_count < -1 {
            return Err("pd.retry_max_count cannot be < -1".into());
        }

        Ok(())
    }
}

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

    #[test]
    fn test_pd_cfg() {
        let mut cfg = Config::default();
        // endpoints is required.
        cfg.validate().unwrap_err();
        cfg.endpoints = vec!["127.0.0.1:2333".to_owned()];
        cfg.validate().unwrap();
    }
}
<commit_msg>Configure default pd endpoint for tikv-server (#5427)<commit_after>// Copyright 2017 TiKV Project Authors. Licensed under Apache-2.0.

use std::error::Error;
use tikv_util::config::ReadableDuration;

/// The configuration for a PD Client.
///
/// By default during initialization the client will attempt to reconnect every 300s
/// for infinity, logging only every 10th duplicate error.
#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
#[serde(default)]
#[serde(rename_all = "kebab-case")]
pub struct Config {
    /// The PD endpoints for the client.
    ///
    /// Default is empty.
    pub endpoints: Vec<String>,
    /// The interval at which to retry a PD connection initialization.
    ///
    /// Default is 300ms.
    pub retry_interval: ReadableDuration,
    /// The maximum number of times to retry a PD connection initialization.
    ///
    /// Default is isize::MAX, represented by -1.
    pub retry_max_count: isize,
    /// If the client observes the same error message on retry, it can repeat the message only
    /// every `n` times.
    ///
    /// Default is 10. Set to 1 to disable this feature.
    pub retry_log_every: usize,
}

impl Default for Config {
    fn default() -> Self {
        Config {
            endpoints: vec!["127.0.0.1:2379".to_string()],
            retry_interval: ReadableDuration::millis(300),
            retry_max_count: std::isize::MAX,
            retry_log_every: 10,
        }
    }
}

impl Config {
    pub fn new(endpoints: Vec<String>) -> Self {
        Config {
            endpoints,
            ..Default::default()
        }
    }

    pub fn validate(&self) -> Result<(), Box<dyn Error>> {
        if self.endpoints.is_empty() {
            return Err("please specify pd.endpoints.".into());
        }

        if self.retry_log_every == 0 {
            return Err("pd.retry_log_every cannot be <=0".into());
        }

        if self.retry_max_count < -1 {
            return Err("pd.retry_max_count cannot be < -1".into());
        }

        Ok(())
    }
}

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

    #[test]
    fn test_pd_cfg() {
        let cfg = Config::default();
        cfg.validate().unwrap();
    }
}
<|endoftext|>


<commit_before>#![feature(core)]
extern crate core;

#[cfg(test)]
mod tests {
    struct A {
	value: u32
    }

    impl Clone for A {
	fn clone(&self) -> Self
	{
	    A { value: self.value  }
	}
    }

    #[test]
    fn clone_test1() {
	let mut x: A = A { value: 68 };
	assert_eq!(x.value, 68);

	x.value = 500;
	let y: A = x.clone();
	assert_eq!(y.value, 500);
    }
}
<commit_msg>fix the variable x that unchecked movable<commit_after>#![feature(core)]
extern crate core;

#[cfg(test)]
mod tests {
    struct A {
	value: u32
    }

    impl Clone for A {
	fn clone(&self) -> Self
	{
	    A { value: self.value  }
	}
    }

    #[test]
    fn clone_test1() {
	let x: A = A { value: 68 };
	assert_eq!(x.value, 68);

	let mut y: A = x.clone();
	y.value = 500;
	assert_eq!(x.value, 68);
	assert_eq!(y.value, 500);
    }
}
<|endoftext|>