<commit_before>use neb::server::*;
use neb::ram::schema::LocalSchemasCache;
use bifrost::rpc;
use bifrost::raft;
use bifrost::membership::server::Membership;
use bifrost::raft::client::RaftClient;
use bifrost::membership::member::MemberService;
use bifrost::raft::state_machine::{master as sm_master};
use bifrost::rpc::Server;
use std::rc::Rc;
use std::sync::Arc;
use futures::prelude::*;
use std::env;
use neb::ram::schema::Schema;
use neb::ram::schema::Field;
use dovahkiin::types::type_id_of;
use neb::client;
use neb::ram::types::*;
use dovahkiin::types::custom_types::id::Id;
use dovahkiin::types::custom_types::map::Map;
use neb::ram::cell::Cell;

#[test]
pub fn init () {
    NebServer::new_from_opts(&ServerOptions {
        chunk_count: 1,
        memory_size: 16 * 1024,
        backup_storage: None,
        wal_storage: None
    },
    &String::from("127.0.0.1:5100"),
    &String::from("test"));
}

#[test]
pub fn smoke_test () {
    const DATA: &'static str = "DATA";
    let num = env::var("NEB_KV_SMOKE_TEST_ITEMS")
        .unwrap_or("1000".to_string())
        .parse::<u64>().unwrap();
    env_logger::init();
    let server_addr = String::from("127.0.0.1:5300");
    let server_group = String::from("smoke_test");
    let server = NebServer::new_from_opts(&ServerOptions {
        chunk_count: 1,
        memory_size: 512 * 1024 * 1024,
        backup_storage: None,
        wal_storage: None
    },
    &server_addr,
    &server_group);
    let schema_id = 123;
    let schema = Schema {
        id: schema_id,
        name: String::from("schema"),
        key_field: None,
        str_key_field: None,
        is_dynamic: false,
        fields: Field::new(
            "*", 0, false, false,
            Some(vec![
                Field::new(DATA, type_id_of(Type::U64), false, false, None)
            ])
        )
    };

    let client = Arc::new(client::AsyncClient::new(
        &server.rpc, &vec!(server_addr),
        &server_group).unwrap());
    client.new_schema_with_id(schema).wait();

    for i in 0..num * 2 {
        // intense upsert, half delete
        let id = Id::new(0, num);
        let mut value = Value::Map(Map::new());
        value[DATA] = Value::U64(num);
        let cell = Cell::new_with_id(schema_id, &id, value);
        client.upsert_cell(cell).wait();

        // verify
        let read_cell = client.read_cell(id).wait().unwrap().unwrap();
        assert_eq!(*(read_cell.data[DATA].U64().unwrap()), num);

        if i % 2 == 0 {
            client.remove_cell(id).wait();
        }
    }
}<commit_msg>allow update<commit_after>use neb::server::*;
use neb::ram::schema::LocalSchemasCache;
use bifrost::rpc;
use bifrost::raft;
use bifrost::membership::server::Membership;
use bifrost::raft::client::RaftClient;
use bifrost::membership::member::MemberService;
use bifrost::raft::state_machine::{master as sm_master};
use bifrost::rpc::Server;
use std::rc::Rc;
use std::sync::Arc;
use futures::prelude::*;
use std::env;
use neb::ram::schema::Schema;
use neb::ram::schema::Field;
use dovahkiin::types::type_id_of;
use neb::client;
use neb::ram::types::*;
use dovahkiin::types::custom_types::id::Id;
use dovahkiin::types::custom_types::map::Map;
use neb::ram::cell::Cell;

#[test]
pub fn init () {
    NebServer::new_from_opts(&ServerOptions {
        chunk_count: 1,
        memory_size: 16 * 1024,
        backup_storage: None,
        wal_storage: None
    },
    &String::from("127.0.0.1:5100"),
    &String::from("test"));
}

#[test]
pub fn smoke_test () {
    const DATA: &'static str = "DATA";
    let num = env::var("NEB_KV_SMOKE_TEST_ITEMS")
        .unwrap_or("1000".to_string())
        .parse::<u64>().unwrap();
    env_logger::init();
    let server_addr = String::from("127.0.0.1:5300");
    let server_group = String::from("smoke_test");
    let server = NebServer::new_from_opts(&ServerOptions {
        chunk_count: 1,
        memory_size: 512 * 1024 * 1024,
        backup_storage: None,
        wal_storage: None
    },
    &server_addr,
    &server_group);
    let schema_id = 123;
    let schema = Schema {
        id: schema_id,
        name: String::from("schema"),
        key_field: None,
        str_key_field: None,
        is_dynamic: false,
        fields: Field::new(
            "*", 0, false, false,
            Some(vec![
                Field::new(DATA, type_id_of(Type::U64), false, false, None)
            ])
        )
    };

    let client = Arc::new(client::AsyncClient::new(
        &server.rpc, &vec!(server_addr),
        &server_group).unwrap());
    client.new_schema_with_id(schema).wait();

    for i in 0..num * 2 {
        // intense upsert, half delete
        let id = Id::new(0, num / 2);
        let mut value = Value::Map(Map::new());
        value[DATA] = Value::U64(num);
        let cell = Cell::new_with_id(schema_id, &id, value);
        client.upsert_cell(cell).wait();

        // verify
        let read_cell = client.read_cell(id).wait().unwrap().unwrap();
        assert_eq!(*(read_cell.data[DATA].U64().unwrap()), num);

        if i % 2 == 0 {
            client.remove_cell(id).wait();
        }
    }
}<|endoftext|>


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

#![allow(non_snake_case)]

extern crate freetype;
extern crate fontconfig;

use fontconfig::fontconfig::{FcChar8, FcResultMatch, FcSetSystem};
use fontconfig::fontconfig::{
    FcConfigGetCurrent, FcConfigGetFonts,
    FcConfigSubstitute, FcDefaultSubstitute,
    FcFontMatch,
    FcNameParse, FcPatternGetString,
    FcPatternDestroy, FcFontSetDestroy,
    FcMatchPattern,
    FcPatternCreate, FcPatternAddString,
    FcFontSetList, FcObjectSetCreate, FcObjectSetDestroy,
    FcObjectSetAdd, FcPatternGetInteger
};

use util::str::c_str_to_string;

use libc;
use libc::{c_int, c_char};
use std::borrow::ToOwned;
use std::ffi::CString;
use std::ptr;

static FC_FAMILY: &'static [u8] = b"family\0";
static FC_FILE: &'static [u8] = b"file\0";
static FC_INDEX: &'static [u8] = b"index\0";

pub fn get_available_families<F>(mut callback: F) where F: FnMut(String) {
    unsafe {
        let config = FcConfigGetCurrent();
        let fontSet = FcConfigGetFonts(config, FcSetSystem);
        for i in 0..((*fontSet).nfont as int) {
            let font = (*fontSet).fonts.offset(i);
            let mut family: *mut FcChar8 = ptr::null_mut();
            let mut v: c_int = 0;
            while FcPatternGetString(*font, FC_FAMILY.as_ptr() as *mut c_char, v, &mut family) == FcResultMatch {
                let family_name = c_str_to_string(family as *const c_char);
                callback(family_name);
                v += 1;
            }
        }
    }
}

pub fn get_variations_for_family<F>(family_name: &str, mut callback: F)
    where F: FnMut(String)
{
    debug!("getting variations for {}", family_name);
    unsafe {
        let config = FcConfigGetCurrent();
        let mut font_set = FcConfigGetFonts(config, FcSetSystem);
        let font_set_array_ptr = &mut font_set;
        let pattern = FcPatternCreate();
        assert!(!pattern.is_null());
        let family_name_c = CString::new(family_name).unwrap();
        let family_name = family_name_c.as_ptr();
        let ok = FcPatternAddString(pattern, FC_FAMILY.as_ptr() as *mut c_char, family_name as *mut FcChar8);
        assert!(ok != 0);

        let object_set = FcObjectSetCreate();
        assert!(!object_set.is_null());

        FcObjectSetAdd(object_set, FC_FILE.as_ptr() as *mut c_char);
        FcObjectSetAdd(object_set, FC_INDEX.as_ptr() as *mut c_char);

        let matches = FcFontSetList(config, font_set_array_ptr, 1, pattern, object_set);

        debug!("found {} variations", (*matches).nfont);

        for i in 0..((*matches).nfont as int) {
            let font = (*matches).fonts.offset(i);
            let mut file: *mut FcChar8 = ptr::null_mut();
            let file = if FcPatternGetString(*font, FC_FILE.as_ptr() as *mut c_char, 0, &mut file) == FcResultMatch {
                c_str_to_string(file as *const c_char)
            } else {
                panic!();
            };
            let mut index: libc::c_int = 0;
            let index = if FcPatternGetInteger(*font, FC_INDEX.as_ptr() as *mut c_char, 0, &mut index) == FcResultMatch {
                index
            } else {
                panic!();
            };

            debug!("variation file: {}", file);
            debug!("variation index: {}", index);

            callback(file);
        }

        FcFontSetDestroy(matches);
        FcPatternDestroy(pattern);
        FcObjectSetDestroy(object_set);
    }
}

pub fn get_system_default_family(generic_name: &str) -> Option<String> {
    let generic_name_c = CString::new(generic_name).unwrap();
    let generic_name_ptr = generic_name_c.as_ptr();

    unsafe {
        let pattern = FcNameParse(generic_name_ptr as *mut FcChar8);

        FcConfigSubstitute(ptr::null_mut(), pattern, FcMatchPattern);
        FcDefaultSubstitute(pattern);

        let mut result = 0;
        let family_match = FcFontMatch(ptr::null_mut(), pattern, &mut result);

        let family_name = if result == FcResultMatch {
            let mut match_string: *mut FcChar8 = ptr::null_mut();
            FcPatternGetString(family_match, FC_FAMILY.as_ptr() as *mut c_char, 0, &mut match_string);
            let result = c_str_to_string(match_string as *const c_char);
            FcPatternDestroy(family_match);
            Some(result)
        } else {
            None
        };

        FcPatternDestroy(pattern);
        family_name
    }
}

#[cfg(target_os="linux")]
pub fn get_last_resort_font_families() -> Vec<String> {
    vec!(
        "Fira Sans".to_owned(),
        "DejaVu Sans".to_owned(),
        "Arial".to_owned()
    )
}

#[cfg(target_os="android")]
pub fn get_last_resort_font_families() -> Vec<String> {
    vec!("Roboto".to_owned())
}
<commit_msg>Stop using int in font_list.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![allow(non_snake_case)]

extern crate freetype;
extern crate fontconfig;

use fontconfig::fontconfig::{FcChar8, FcResultMatch, FcSetSystem};
use fontconfig::fontconfig::{
    FcConfigGetCurrent, FcConfigGetFonts,
    FcConfigSubstitute, FcDefaultSubstitute,
    FcFontMatch,
    FcNameParse, FcPatternGetString,
    FcPatternDestroy, FcFontSetDestroy,
    FcMatchPattern,
    FcPatternCreate, FcPatternAddString,
    FcFontSetList, FcObjectSetCreate, FcObjectSetDestroy,
    FcObjectSetAdd, FcPatternGetInteger
};

use util::str::c_str_to_string;

use libc;
use libc::{c_int, c_char};
use std::borrow::ToOwned;
use std::ffi::CString;
use std::ptr;

static FC_FAMILY: &'static [u8] = b"family\0";
static FC_FILE: &'static [u8] = b"file\0";
static FC_INDEX: &'static [u8] = b"index\0";

pub fn get_available_families<F>(mut callback: F) where F: FnMut(String) {
    unsafe {
        let config = FcConfigGetCurrent();
        let fontSet = FcConfigGetFonts(config, FcSetSystem);
        for i in 0..((*fontSet).nfont as isize) {
            let font = (*fontSet).fonts.offset(i);
            let mut family: *mut FcChar8 = ptr::null_mut();
            let mut v: c_int = 0;
            while FcPatternGetString(*font, FC_FAMILY.as_ptr() as *mut c_char, v, &mut family) == FcResultMatch {
                let family_name = c_str_to_string(family as *const c_char);
                callback(family_name);
                v += 1;
            }
        }
    }
}

pub fn get_variations_for_family<F>(family_name: &str, mut callback: F)
    where F: FnMut(String)
{
    debug!("getting variations for {}", family_name);
    unsafe {
        let config = FcConfigGetCurrent();
        let mut font_set = FcConfigGetFonts(config, FcSetSystem);
        let font_set_array_ptr = &mut font_set;
        let pattern = FcPatternCreate();
        assert!(!pattern.is_null());
        let family_name_c = CString::new(family_name).unwrap();
        let family_name = family_name_c.as_ptr();
        let ok = FcPatternAddString(pattern, FC_FAMILY.as_ptr() as *mut c_char, family_name as *mut FcChar8);
        assert!(ok != 0);

        let object_set = FcObjectSetCreate();
        assert!(!object_set.is_null());

        FcObjectSetAdd(object_set, FC_FILE.as_ptr() as *mut c_char);
        FcObjectSetAdd(object_set, FC_INDEX.as_ptr() as *mut c_char);

        let matches = FcFontSetList(config, font_set_array_ptr, 1, pattern, object_set);

        debug!("found {} variations", (*matches).nfont);

        for i in 0..((*matches).nfont as isize) {
            let font = (*matches).fonts.offset(i);
            let mut file: *mut FcChar8 = ptr::null_mut();
            let file = if FcPatternGetString(*font, FC_FILE.as_ptr() as *mut c_char, 0, &mut file) == FcResultMatch {
                c_str_to_string(file as *const c_char)
            } else {
                panic!();
            };
            let mut index: libc::c_int = 0;
            let index = if FcPatternGetInteger(*font, FC_INDEX.as_ptr() as *mut c_char, 0, &mut index) == FcResultMatch {
                index
            } else {
                panic!();
            };

            debug!("variation file: {}", file);
            debug!("variation index: {}", index);

            callback(file);
        }

        FcFontSetDestroy(matches);
        FcPatternDestroy(pattern);
        FcObjectSetDestroy(object_set);
    }
}

pub fn get_system_default_family(generic_name: &str) -> Option<String> {
    let generic_name_c = CString::new(generic_name).unwrap();
    let generic_name_ptr = generic_name_c.as_ptr();

    unsafe {
        let pattern = FcNameParse(generic_name_ptr as *mut FcChar8);

        FcConfigSubstitute(ptr::null_mut(), pattern, FcMatchPattern);
        FcDefaultSubstitute(pattern);

        let mut result = 0;
        let family_match = FcFontMatch(ptr::null_mut(), pattern, &mut result);

        let family_name = if result == FcResultMatch {
            let mut match_string: *mut FcChar8 = ptr::null_mut();
            FcPatternGetString(family_match, FC_FAMILY.as_ptr() as *mut c_char, 0, &mut match_string);
            let result = c_str_to_string(match_string as *const c_char);
            FcPatternDestroy(family_match);
            Some(result)
        } else {
            None
        };

        FcPatternDestroy(pattern);
        family_name
    }
}

#[cfg(target_os="linux")]
pub fn get_last_resort_font_families() -> Vec<String> {
    vec!(
        "Fira Sans".to_owned(),
        "DejaVu Sans".to_owned(),
        "Arial".to_owned()
    )
}

#[cfg(target_os="android")]
pub fn get_last_resort_font_families() -> Vec<String> {
    vec!("Roboto".to_owned())
}
<|endoftext|>


<commit_before>//!
//! Expression Plan Representation for Tajo Kernel
//!

use common::types::{DataType, HasTypeKind, TypeKind};
use common::schema::Column;
use common::P;

#[derive(Clone)]
pub enum Datum {
  Bool(bool),
  Int1(i8),
  Int2(i16),
  Int4(i32),
  Int8(i64),
  Float4(f32),
  Float8(f64),
  Time(i64),
  Date(i32),
  Timestamp(i64),
  Interval(i64, i32),
  Char(String),
  Text(String),
  Varchar(String),
  Blob(Vec<u8>)
}

impl HasTypeKind for Datum {
  fn type_kind(&self) -> TypeKind {
    match *self {
      Datum::Bool(ref x) => TypeKind::Bool,
      Datum::Int1(ref x) => TypeKind::Int1,
      Datum::Int2(ref x) => TypeKind::Int2,
      Datum::Int4(ref x) => TypeKind::Int4,
      Datum::Int8(ref x) => TypeKind::Int8,
      Datum::Float4(ref x) => TypeKind::Float4,
      Datum::Float8(ref x) => TypeKind::Float8,
      Datum::Time(ref x) => TypeKind::Time,
      Datum::Date(ref x) => TypeKind::Date,
      Datum::Timestamp(ref x) => TypeKind::Timestamp,
      Datum::Interval(ref x,ref y) => TypeKind::Interval,
      Datum::Char(ref x) => TypeKind::Char,
      Datum::Text(ref x) => TypeKind::Text,
      Datum::Varchar(ref x) => TypeKind::Varchar,
      Datum::Blob(ref x) => TypeKind::Blob
    }
  }
}

pub struct FnDecl {
  signature: String
}

pub struct AggFnDecl {
  signature: String
}

pub struct WinFnDecl {
  signature: String
}

pub enum CompOp {
  Eq,
  NotEq,
  Lth,
  Leq,
  Gth,
  Geq
}

pub enum ArithmOp {
  Plus,
  Minus,
  Multiply,
  Divide,
  Modular,
}

pub struct Expr {
  data_ty: DataType,
  node: ExprSpec
}

pub enum ExprSpec {
  // Unary Expressions
  Not(Box<Expr>),
  IsNull(Box<Expr>, bool), // bool - 'is null' if true. 'is not null' if false.
  Sign(Box<Expr>, bool), // true - Plus, false - Minus
  Cast(Box<Expr>, Box<DataType>, Box<DataType>),

  // Binary Arithmetic Expressions
  And(Box<Expr>,Box<Expr>),
  Or(Box<Expr>,Box<Expr>),
  Comp(CompOp, Box<Expr>,Box<Expr>),
  Arithm(ArithmOp,Box<Expr>,Box<Expr>),
  Concat(Box<Expr>,Box<Expr>),

  // Functions
  Fn(Box<FnDecl>, Vec<Box<Expr>>),
  AggFn(Box<AggFnDecl>, Vec<Box<Expr>>),
  WinFn(Box<WinFnDecl>, Vec<Box<Expr>>),

  // String operators or pattern matching predicates: lhs - pattern, rhs - value
  Like(Box<Expr>,Box<Expr>, bool),
  SimilarTo(Box<Expr>,Box<Expr>, bool),
  RegexMatch(Box<Expr>,Box<Expr>, bool),

  // Other predicates
  Between(Box<Expr>,Box<Expr>,Box<Expr>), // predicand, begin, end
  In(Box<Expr>, Vec<Box<Expr>>), // predicand, a set

  // condition
  Case(Vec<Box<Expr>>, Box<Expr>), // multiple conditions, else return value
  IfThen(Box<Expr>, Box<Expr>), // condition, return value

  // values
  Row(Vec<Box<Expr>>),
  Field(Box<Column>),
  Const(Box<Datum>)
}

pub trait Visitor<'v>: Sized {
  fn visit_not(&mut self, child: &'v Expr) {
    walk_expr(self, child);
  }
  fn visit_is_null(&mut self, child: &'v Expr, not: bool) {
    walk_expr(self, child);
  }
  fn visit_sign(&mut self, child: &'v Expr, not: bool) {
    walk_expr(self, child);
  }
  fn visit_cast(&mut self, expr: &'v Expr, from: &'v DataType,
    to: &'v DataType) {
    walk_expr(self, expr);
  }

  fn visit_and(&mut self, lhs: &'v Expr, rhs: &'v Expr) {
    walk_bin_expr(self, lhs, rhs)
  }
  fn visit_or(&mut self, lhs: &'v Expr, rhs: &'v Expr) {
    walk_bin_expr(self, lhs, rhs)
  }
  fn visit_comp(&mut self, op: &CompOp, lhs: &'v Expr, rhs: &'v Expr) {
    walk_bin_expr(self, lhs, rhs)
  }
  fn visit_arithm(&mut self, op: &ArithmOp,
    lhs: &'v Expr, rhs: &'v Expr) {
    walk_bin_expr(self, lhs, rhs)
  }
  fn visit_concat(&mut self, lhs: &'v Expr, rhs: &'v Expr) {
    walk_bin_expr(self, lhs, rhs)
  }

  fn visit_fn(&mut self, fd: &'v FnDecl, args: &'v Vec<Box<Expr>>) {
    for ref arg in args {
      walk_expr(self, arg);
    }
  }
  fn visit_aggfn(&mut self, aggfd: &'v AggFnDecl, args: &'v Vec<Box<Expr>>) {
    for ref arg in args {
      walk_expr(self, arg);
    }
  }
  fn visit_winfn(&mut self, winfd: &'v WinFnDecl, args: &'v Vec<Box<Expr>>) {
    for ref arg in args {
      walk_expr(self, arg);
    }
  }

  fn visit_like(&mut self, pat: &'v Expr, pred: &'v Expr, not: bool) {
    walk_bin_expr(self, pat, pred);
  }
  fn visit_similarto(&mut self, pat: &'v Expr, pred: &'v Expr, not: bool) {
    walk_bin_expr(self, pat, pred);
  }
  fn visit_regexmatch(&mut self, pat: &'v Expr, pred: &'v Expr, not: bool) {
    walk_bin_expr(self, pat, pred);
  }

  fn visit_between(&mut self, pred: &'v Expr, begin: &'v Expr, end: &'v Expr) {
    walk_expr(self, pred);
    walk_expr(self, begin);
    walk_expr(self, end);
  }
  fn visit_in(&mut self, pred: &'v Expr, values: &'v Vec<Box<Expr>>) {
    walk_expr(self, pred);
    self.visit_row(values);
  }

  fn visit_case(&mut self, ifconds: &'v Vec<Box<Expr>>, else_result: &'v Expr) {
    for ref each_if in ifconds {
      walk_expr(self, each_if);
    }
    walk_expr(self, else_result);
  }
  fn visit_if_then(&mut self, ifcond: &'v Expr, result: &'v Expr) {
    walk_expr(self, ifcond);
    walk_expr(self, result);
  }

  fn visit_row(&mut self, values: &'v Vec<Box<Expr>>) {
    for ref v in values {
      walk_expr(self, v);
    }
  }
  fn visit_field(&mut self, field: &'v Column) {}
  fn visit_const(&mut self, datum: &'v Datum) {}
}

pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expr: &'v Expr) {

  match expr.node {

    ExprSpec::Not(ref child) => {
      visitor.visit_not(child);
    }

    ExprSpec::IsNull(ref child, positive) => {
      visitor.visit_is_null(child, positive);
    }

    ExprSpec::Sign(ref child, positive) => {
      visitor.visit_sign(child, positive);
    }

    ExprSpec::Cast(ref value, ref from, ref to) => {
      visitor.visit_cast(value, from, to)
    },

    ExprSpec::And(ref lhs, ref rhs) => {
      visitor.visit_and(lhs, rhs);
    }

    ExprSpec::Or(ref lhs, ref rhs) => {
      visitor.visit_or(lhs, rhs);
    }

    ExprSpec::Comp(ref op, ref lhs, ref rhs) => {
      visitor.visit_comp(op, lhs, rhs);
    }

    ExprSpec::Arithm(ref op, ref lhs, ref rhs) => {
      visitor.visit_arithm(op, lhs, rhs);
    }

    ExprSpec::Concat(ref lhs, ref rhs) => {
      visitor.visit_concat(lhs, rhs);
    }

    ExprSpec::Fn(ref fd, ref args) => {
      visitor.visit_fn(fd, args);
    },

    ExprSpec::AggFn(ref fd, ref args) => {
      visitor.visit_aggfn(fd, args);
    },

    ExprSpec::WinFn(ref fd, ref args) => {
      visitor.visit_winfn(fd, args);
    },

    ExprSpec::Like(ref pat, ref pred, not) => {
      visitor.visit_like(pat, pred, not)
    },

    ExprSpec::SimilarTo(ref pat, ref pred, not) => {
      visitor.visit_similarto(pat, pred, not)
    },

    ExprSpec::RegexMatch(ref pat, ref pred, not) => {
      visitor.visit_regexmatch(pat, pred, not)
    },

    ExprSpec::Between(ref pred, ref begin, ref end) => {
      visitor.visit_between(pred, begin, end)
    }

    ExprSpec::In(ref pred, ref values) => {
      visitor.visit_in(pred, values)
    }

    ExprSpec::Case(ref ifconds, ref else_result) => {
      visitor.visit_case(ifconds, else_result)
    }

    ExprSpec::IfThen(ref ifcond, ref result) => {
      visitor.visit_if_then(ifcond, result)
    },

    ExprSpec::Row(ref values) => visitor.visit_row(values),

    ExprSpec::Field(ref column) => visitor.visit_field(column),

    ExprSpec::Const(ref datum) => visitor.visit_const(datum),
  }
}

#[inline]
pub fn walk_bin_expr<'v, V: Visitor<'v>>(visitor: &mut V,
                                         lhs: &'v Expr,
                                         rhs: &'v Expr) {
  walk_expr(visitor, lhs);
  walk_expr(visitor, rhs);
}<commit_msg>Add more comments for tajo::expr module.<commit_after>//!
//! Expression Plan Representation for Tajo Kernel
//!

use common::types::{DataType, HasTypeKind, TypeKind};
use common::schema::Column;
use common::P;

/// Datum representation for a single value
#[derive(Clone)]
pub enum Datum {
  Bool(bool),
  Int1(i8),
  Int2(i16),
  Int4(i32),
  Int8(i64),
  Float4(f32),
  Float8(f64),
  Time(i64),
  Date(i32),
  Timestamp(i64),
  Interval(i64, i32),
  Char(String),
  Text(String),
  Varchar(String),
  Blob(Vec<u8>)
}

impl HasTypeKind for Datum {
  fn type_kind(&self) -> TypeKind {
    match *self {
      Datum::Bool(ref x) => TypeKind::Bool,
      Datum::Int1(ref x) => TypeKind::Int1,
      Datum::Int2(ref x) => TypeKind::Int2,
      Datum::Int4(ref x) => TypeKind::Int4,
      Datum::Int8(ref x) => TypeKind::Int8,
      Datum::Float4(ref x) => TypeKind::Float4,
      Datum::Float8(ref x) => TypeKind::Float8,
      Datum::Time(ref x) => TypeKind::Time,
      Datum::Date(ref x) => TypeKind::Date,
      Datum::Timestamp(ref x) => TypeKind::Timestamp,
      Datum::Interval(ref x,ref y) => TypeKind::Interval,
      Datum::Char(ref x) => TypeKind::Char,
      Datum::Text(ref x) => TypeKind::Text,
      Datum::Varchar(ref x) => TypeKind::Varchar,
      Datum::Blob(ref x) => TypeKind::Blob
    }
  }
}

/// Function Declaration
pub struct FnDecl {
  signature: String
}

/// Aggregation Function Declaration
pub struct AggFnDecl {
  signature: String
}

/// Window Function Declaration
pub struct WinFnDecl {
  signature: String
}

/// Comparison Operator Type
pub enum CompOp {
  Eq,
  NotEq,
  Lth,
  Leq,
  Gth,
  Geq
}

/// Arithmetic Operator Type
pub enum ArithmOp {
  Plus,
  Minus,
  Multiply,
  Divide,
  Modular,
}

/// Expression Element
pub struct Expr {
  data_ty: DataType,
  node: ExprSpec
}

/// Expression Specific Element
pub enum ExprSpec {
  // Unary Expressions
  Not(Box<Expr>),
  IsNull(Box<Expr>, bool), // bool - 'is null' if true. 'is not null' if false.
  Sign(Box<Expr>, bool), // true - Plus, false - Minus
  Cast(Box<Expr>, Box<DataType>, Box<DataType>),

  // Binary Arithmetic Expressions
  And(Box<Expr>,Box<Expr>),
  Or(Box<Expr>,Box<Expr>),
  Comp(CompOp, Box<Expr>,Box<Expr>),
  Arithm(ArithmOp,Box<Expr>,Box<Expr>),
  Concat(Box<Expr>,Box<Expr>),

  // Functions
  Fn(Box<FnDecl>, Vec<Box<Expr>>),
  AggFn(Box<AggFnDecl>, Vec<Box<Expr>>),
  WinFn(Box<WinFnDecl>, Vec<Box<Expr>>),

  // String operators or pattern matching predicates: lhs - pattern, rhs - value
  Like(Box<Expr>,Box<Expr>, bool),
  SimilarTo(Box<Expr>,Box<Expr>, bool),
  RegexMatch(Box<Expr>,Box<Expr>, bool),

  // Other predicates
  Between(Box<Expr>,Box<Expr>,Box<Expr>), // predicand, begin, end
  In(Box<Expr>, Vec<Box<Expr>>), // predicand, a set

  // condition
  Case(Vec<Box<Expr>>, Box<Expr>), // multiple conditions, else return value
  IfThen(Box<Expr>, Box<Expr>), // condition, return value

  // values
  Row(Vec<Box<Expr>>),
  Field(Box<Column>),
  Const(Box<Datum>)
}

/// Visitor for Expr Tree
pub trait Visitor<'v>: Sized {
  fn visit_not(&mut self, child: &'v Expr) {
    walk_expr(self, child);
  }
  fn visit_is_null(&mut self, child: &'v Expr, not: bool) {
    walk_expr(self, child);
  }
  fn visit_sign(&mut self, child: &'v Expr, not: bool) {
    walk_expr(self, child);
  }
  fn visit_cast(&mut self, expr: &'v Expr, from: &'v DataType,
    to: &'v DataType) {
    walk_expr(self, expr);
  }

  fn visit_and(&mut self, lhs: &'v Expr, rhs: &'v Expr) {
    walk_bin_expr(self, lhs, rhs)
  }
  fn visit_or(&mut self, lhs: &'v Expr, rhs: &'v Expr) {
    walk_bin_expr(self, lhs, rhs)
  }
  fn visit_comp(&mut self, op: &CompOp, lhs: &'v Expr, rhs: &'v Expr) {
    walk_bin_expr(self, lhs, rhs)
  }
  fn visit_arithm(&mut self, op: &ArithmOp,
    lhs: &'v Expr, rhs: &'v Expr) {
    walk_bin_expr(self, lhs, rhs)
  }
  fn visit_concat(&mut self, lhs: &'v Expr, rhs: &'v Expr) {
    walk_bin_expr(self, lhs, rhs)
  }

  fn visit_fn(&mut self, fd: &'v FnDecl, args: &'v Vec<Box<Expr>>) {
    for ref arg in args {
      walk_expr(self, arg);
    }
  }
  fn visit_aggfn(&mut self, aggfd: &'v AggFnDecl, args: &'v Vec<Box<Expr>>) {
    for ref arg in args {
      walk_expr(self, arg);
    }
  }
  fn visit_winfn(&mut self, winfd: &'v WinFnDecl, args: &'v Vec<Box<Expr>>) {
    for ref arg in args {
      walk_expr(self, arg);
    }
  }

  fn visit_like(&mut self, pat: &'v Expr, pred: &'v Expr, not: bool) {
    walk_bin_expr(self, pat, pred);
  }
  fn visit_similarto(&mut self, pat: &'v Expr, pred: &'v Expr, not: bool) {
    walk_bin_expr(self, pat, pred);
  }
  fn visit_regexmatch(&mut self, pat: &'v Expr, pred: &'v Expr, not: bool) {
    walk_bin_expr(self, pat, pred);
  }

  fn visit_between(&mut self, pred: &'v Expr, begin: &'v Expr, end: &'v Expr) {
    walk_expr(self, pred);
    walk_expr(self, begin);
    walk_expr(self, end);
  }
  fn visit_in(&mut self, pred: &'v Expr, values: &'v Vec<Box<Expr>>) {
    walk_expr(self, pred);
    self.visit_row(values);
  }

  fn visit_case(&mut self, ifconds: &'v Vec<Box<Expr>>, else_result: &'v Expr) {
    for ref each_if in ifconds {
      walk_expr(self, each_if);
    }
    walk_expr(self, else_result);
  }
  fn visit_if_then(&mut self, ifcond: &'v Expr, result: &'v Expr) {
    walk_expr(self, ifcond);
    walk_expr(self, result);
  }

  fn visit_row(&mut self, values: &'v Vec<Box<Expr>>) {
    for ref v in values {
      walk_expr(self, v);
    }
  }
  fn visit_field(&mut self, field: &'v Column) {}
  fn visit_const(&mut self, datum: &'v Datum) {}
}

/// Walker for Expr Tree
pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expr: &'v Expr) {

  match expr.node {

    ExprSpec::Not(ref child) => {
      visitor.visit_not(child);
    }

    ExprSpec::IsNull(ref child, positive) => {
      visitor.visit_is_null(child, positive);
    }

    ExprSpec::Sign(ref child, positive) => {
      visitor.visit_sign(child, positive);
    }

    ExprSpec::Cast(ref value, ref from, ref to) => {
      visitor.visit_cast(value, from, to)
    },

    ExprSpec::And(ref lhs, ref rhs) => {
      visitor.visit_and(lhs, rhs);
    }

    ExprSpec::Or(ref lhs, ref rhs) => {
      visitor.visit_or(lhs, rhs);
    }

    ExprSpec::Comp(ref op, ref lhs, ref rhs) => {
      visitor.visit_comp(op, lhs, rhs);
    }

    ExprSpec::Arithm(ref op, ref lhs, ref rhs) => {
      visitor.visit_arithm(op, lhs, rhs);
    }

    ExprSpec::Concat(ref lhs, ref rhs) => {
      visitor.visit_concat(lhs, rhs);
    }

    ExprSpec::Fn(ref fd, ref args) => {
      visitor.visit_fn(fd, args);
    },

    ExprSpec::AggFn(ref fd, ref args) => {
      visitor.visit_aggfn(fd, args);
    },

    ExprSpec::WinFn(ref fd, ref args) => {
      visitor.visit_winfn(fd, args);
    },

    ExprSpec::Like(ref pat, ref pred, not) => {
      visitor.visit_like(pat, pred, not)
    },

    ExprSpec::SimilarTo(ref pat, ref pred, not) => {
      visitor.visit_similarto(pat, pred, not)
    },

    ExprSpec::RegexMatch(ref pat, ref pred, not) => {
      visitor.visit_regexmatch(pat, pred, not)
    },

    ExprSpec::Between(ref pred, ref begin, ref end) => {
      visitor.visit_between(pred, begin, end)
    }

    ExprSpec::In(ref pred, ref values) => {
      visitor.visit_in(pred, values)
    }

    ExprSpec::Case(ref ifconds, ref else_result) => {
      visitor.visit_case(ifconds, else_result)
    }

    ExprSpec::IfThen(ref ifcond, ref result) => {
      visitor.visit_if_then(ifcond, result)
    },

    ExprSpec::Row(ref values) => visitor.visit_row(values),

    ExprSpec::Field(ref column) => visitor.visit_field(column),

    ExprSpec::Const(ref datum) => visitor.visit_const(datum),
  }
}

/// Walker for Binary Expr
#[inline]
pub fn walk_bin_expr<'v, V: Visitor<'v>>(visitor: &mut V,
                                         lhs: &'v Expr,
                                         rhs: &'v Expr) {
  walk_expr(visitor, lhs);
  walk_expr(visitor, rhs);
}<|endoftext|>


<commit_before>use std::io::{Read, Seek};
use std::mem;

use Result;
use truetype::{Tape, Value};
use truetype::compound::*;

/// A font.
#[derive(Default)]
pub struct Font {
    pub offset_table: OffsetTable,
    pub char_mapping: Option<CharMapping>,
    pub font_header: Option<FontHeader>,
    pub horizontal_header: Option<HorizontalHeader>,
    pub horizontal_metrics: Option<HorizontalMetrics>,
    pub maximum_profile: Option<MaximumProfile>,
    pub naming_table: Option<NamingTable>,
    pub postscript: Option<PostScript>,
    pub windows_metrics: Option<WindowsMetrics>,
}

macro_rules! tag(
    ($value:expr) => (unsafe {
        mem::transmute::<_, [u8; 4]>(u32::from_be(mem::transmute($value)))
    });
);

macro_rules! checksum_and_jump(
    ($record:ident, $tape:ident, $process:expr) => ({
        if !try!($record.checksum($tape, $process)) {
            raise!("found a corrupted font table");
        }
        try!($tape.jump($record.offset as u64));
    });
    ($record:ident, $tape:ident) => (
        checksum_and_jump!($record, $tape, |_, word| word);
    );
);

impl Font {
    #[inline]
    pub fn read<T: Read + Seek>(tape: &mut T) -> Result<Font> {
        macro_rules! sort(
            ($records:expr) => ({
                let mut records = $records.iter().collect::<Vec<_>>();
                records.sort_by(|one, two| {
                    priority(&tag!(one.tag)).cmp(&priority(&tag!(two.tag)))
                });
                records
            });
        );

        let mut font = Font { offset_table: try!(Value::read(tape)), .. Font::default() };
        if &tag!(font.offset_table.header.version) != b"OTTO" {
            raise!("the font format is invalid");
        }

        for record in sort!(font.offset_table.records) {
            macro_rules! set(
                ($field:ident, $value:expr) => ({
                    checksum_and_jump!(record, tape);
                    font.$field = Some(try!($value));
                });
                ($field:ident) => (set!($field, Value::read(tape)));
            );
            match &tag!(record.tag) {
                b"cmap" => set!(char_mapping),
                b"head" => {
                    checksum_and_jump!(record, tape, |i, word| if i == 2 { 0 } else { word });
                    font.font_header = Some(try!(Value::read(tape)));
                },
                b"hhea" => set!(horizontal_header),
                b"hmtx" => {
                    let header = match font.horizontal_header {
                        Some(ref table) => table,
                        _ => continue,
                    };
                    let profile = match font.maximum_profile {
                        Some(ref table) => table,
                        _ => continue,
                    };
                    set!(horizontal_metrics, HorizontalMetrics::read(tape, header, profile));
                },
                b"maxp" => set!(maximum_profile),
                b"name" => set!(naming_table),
                b"post" => set!(postscript),
                b"OS/2" => set!(windows_metrics),
                _ => {},
            }
        }

        Ok(font)
    }
}

fn priority(tag: &[u8; 4]) -> usize {
    use std::collections::HashMap;
    use std::sync::{Once, ONCE_INIT};

    unsafe {
        static mut PRIORITY: *const HashMap<[u8; 4], usize> = 0 as *const _;
        static ONCE: Once = ONCE_INIT;
        ONCE.call_once(|| {
            let mut map: HashMap<[u8; 4], usize> = HashMap::new();
            map.insert(*b"hmtx", 42);
            PRIORITY = mem::transmute(Box::new(map));
        });
        *(&*PRIORITY).get(tag).unwrap_or(&0)
    }
}
<commit_msg>Update the usage of truetype<commit_after>use std::io::{Read, Seek};
use std::mem;

use Result;
use truetype::{Tape, Value};
use truetype::compound::*;

/// A font.
#[derive(Default)]
pub struct Font {
    pub offset_table: OffsetTable,
    pub char_mapping: Option<CharMapping>,
    pub font_header: Option<FontHeader>,
    pub horizontal_header: Option<HorizontalHeader>,
    pub horizontal_metrics: Option<HorizontalMetrics>,
    pub maximum_profile: Option<MaximumProfile>,
    pub naming_table: Option<NamingTable>,
    pub postscript: Option<PostScript>,
    pub windows_metrics: Option<WindowsMetrics>,
}

macro_rules! checksum_and_jump(
    ($record:ident, $tape:ident, $process:expr) => ({
        if !try!($record.checksum($tape, $process)) {
            raise!("found a corrupted font table");
        }
        try!($tape.jump($record.offset as u64));
    });
    ($record:ident, $tape:ident) => (
        checksum_and_jump!($record, $tape, |_, word| word);
    );
);

impl Font {
    #[inline]
    pub fn read<T: Read + Seek>(tape: &mut T) -> Result<Font> {
        macro_rules! sort(
            ($records:expr) => ({
                let mut records = $records.iter().collect::<Vec<_>>();
                records.sort_by(|one, two| {
                    priority(Tag(one.tag)).cmp(&priority(Tag(two.tag)))
                });
                records
            });
        );

        let mut font = Font { offset_table: try!(Value::read(tape)), .. Font::default() };
        if Tag::from(font.offset_table.header.version) != Tag::from(b"OTTO") {
            raise!("the font format is invalid");
        }

        for record in sort!(font.offset_table.records) {
            macro_rules! set(
                ($field:ident, $value:expr) => ({
                    checksum_and_jump!(record, tape);
                    font.$field = Some(try!($value));
                });
                ($field:ident) => (set!($field, Value::read(tape)));
            );
            match &Tag(record.tag).into() {
                b"cmap" => set!(char_mapping),
                b"head" => {
                    checksum_and_jump!(record, tape, |i, word| if i == 2 { 0 } else { word });
                    font.font_header = Some(try!(Value::read(tape)));
                },
                b"hhea" => set!(horizontal_header),
                b"hmtx" => {
                    let header = match font.horizontal_header {
                        Some(ref table) => table,
                        _ => continue,
                    };
                    let profile = match font.maximum_profile {
                        Some(ref table) => table,
                        _ => continue,
                    };
                    set!(horizontal_metrics, HorizontalMetrics::read(tape, header, profile));
                },
                b"maxp" => set!(maximum_profile),
                b"name" => set!(naming_table),
                b"post" => set!(postscript),
                b"OS/2" => set!(windows_metrics),
                _ => {},
            }
        }

        Ok(font)
    }
}

fn priority(tag: Tag) -> usize {
    use std::collections::HashMap;
    use std::sync::{Once, ONCE_INIT};

    unsafe {
        static mut PRIORITY: *const HashMap<Tag, usize> = 0 as *const _;
        static ONCE: Once = ONCE_INIT;
        ONCE.call_once(|| {
            let mut map: HashMap<Tag, usize> = HashMap::new();
            map.insert(Tag::from(b"hmtx"), 42);
            PRIORITY = mem::transmute(Box::new(map));
        });
        *(&*PRIORITY).get(&tag).unwrap_or(&0)
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use self::libc::{c_char, c_uchar};

/// Creates and saves in secured Wallet identity that can be used to
/// issue and verify Identity Ledger transaction.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// identity_json: Identity information as json. For current moment it is NYM transaction
///   data with optional information for creation of sign key (DID, Verkey, Role, Alias, Seed and etc...).
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// String identifier of this Identity.
///
/// #Errors
/// No method specific errors.
/// See `SovrinError` docs for common errors description.
#[no_mangle]
pub  extern fn wallet_sovrin_create_identity(client_id: i32, command_id: i32,
                                             identity_json: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32,
                                                           identity_id: *const c_char)) {
    unimplemented!();
}

/// Returns public information for Identity stored in secured Wallet.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// identity_id: Id of Identity stored in secured Wallet.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Public Identity information as json (DID, Verkey, Role, Alias and etc...).
///
/// #Errors
/// No method specific errors.
/// See `SovrinError` docs for common errors description.
#[no_mangle]
pub  extern fn wallet_sovrin_get_identity(client_id: i32, command_id: i32,
                                          identity_id: *const c_char,
                                          cb: extern fn(xcommand_id: i32, err: i32,
                                                        identity_json: *const c_char)) {
    unimplemented!();
}

/// Returns list of ids for Identities stored in secured Wallet.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// List of stored identity ids.
///
/// #Errors
/// No method specific errors.
/// See `SovrinError` docs for common errors description.
#[no_mangle]
pub  extern fn wallet_sovrin_get_identities(client_id: i32, command_id: i32,
                                            cb: extern fn(xcommand_id: i32, err: i32,
                                                          identity_ids: [*const c_char])) {
    unimplemented!();
}

/// Creates all necessary keys and objects depends on received schema and returns schema_id.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// schema_json: Schema as a json. Includes name, version, attributes, keys, accumulator and etc.
///     Every empty field in the schema will be filled with the right value.
///     For example: if schema have an empty public key value, function will generate it. If it's
///         not necessary, value for public key field should be None.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Returns id of schema.
///
/// #Errors
/// No method specific errors.
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn wallet_anoncreds_create_schema(client_id: i32, command_id: i32,
                                             schema_json: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32,
                                                           schema_id: *const c_char)) {
    unimplemented!();
}

/// Saves received claim.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// schema_id: id of schema for which claim was generated.
/// claim_json: Claim as a json.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Returns id of claim.
///
/// #Errors
/// No method specific errors.
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn wallet_anoncreds_save_claim(client_id: i32, command_id: i32,
                                          schema_id: *const c_char,
                                          claim_json: *const c_char,
                                          cb: extern fn(xcommand_id: i32, err: i32,
                                                        claim_id: *const c_char)) {
    unimplemented!();
}<commit_msg>minor changes<commit_after>extern crate libc;

use self::libc::{c_char, c_uchar};

/// Creates and saves in secured Wallet identity that can be used to
/// issue and verify Identity Ledger transaction.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// identity_json: Identity information as json. For current moment it is NYM transaction
///   data with optional information for creation of sign key (DID, Verkey, Role, Alias, Seed and etc...).
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// String identifier of this Identity.
///
/// #Errors
/// No method specific errors.
/// See `SovrinError` docs for common errors description.
#[no_mangle]
pub  extern fn wallet_sovrin_create_identity(client_id: i32, command_id: i32,
                                             identity_json: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32,
                                                           identity_id: *const c_char)) {
    unimplemented!();
}

/// Returns public information for Identity stored in secured Wallet.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// identity_id: Id of Identity stored in secured Wallet.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Public Identity information as json (DID, Verkey, Role, Alias and etc...).
///
/// #Errors
/// No method specific errors.
/// See `SovrinError` docs for common errors description.
#[no_mangle]
pub  extern fn wallet_sovrin_get_identity(client_id: i32, command_id: i32,
                                          identity_id: *const c_char,
                                          cb: extern fn(xcommand_id: i32, err: i32,
                                                        identity_json: *const c_char)) {
    unimplemented!();
}

/// Returns list of ids for Identities stored in secured Wallet.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// List of stored identity ids.
///
/// #Errors
/// No method specific errors.
/// See `SovrinError` docs for common errors description.
#[no_mangle]
pub  extern fn wallet_sovrin_get_identities(client_id: i32, command_id: i32,
                                            cb: extern fn(xcommand_id: i32, err: i32,
                                                          identity_ids: [*const c_char])) {
    unimplemented!();
}

/// Creates all necessary keys and objects depends on received schema and returns schema_id.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// schema_json: Schema as a json. Includes name, version, attributes, keys, accumulator and etc.
///     Every empty field in the schema will be filled with the right value.
///     For example: if schema have an empty public key value, function will generate it. If it's
///         not necessary, value for public key field should be None.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Returns id of schema.
///
/// #Errors
/// No method specific errors.
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn wallet_anoncreds_create_schema(client_id: i32, command_id: i32,
                                             schema_json: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32,
                                                           schema_id: *const c_char)) {
    unimplemented!();
}

/// Creates and saves in secured Wallet received claim.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// schema_id: id of schema for which claim was generated.
/// claim_json: Claim as a json.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Returns id of claim.
///
/// #Errors
/// No method specific errors.
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn wallet_anoncreds_create_claim(client_id: i32, command_id: i32,
                                          schema_id: *const c_char,
                                          claim_json: *const c_char,
                                          cb: extern fn(xcommand_id: i32, err: i32,
                                                        claim_id: *const c_char)) {
    unimplemented!();
}<|endoftext|>


<commit_before>/// Figure 10.23 Using sigsuspend to wait for a global variable to be set
///
/// Status: everything work except the most interesting part which is
/// setting the static variable in sig_int and checking it in main..

extern crate libc;
extern crate apue;

use libc::{c_int, SIGINT, SIG_ERR, SIGQUIT, SIG_BLOCK, SIG_SETMASK};
use libc::{signal, sigemptyset, sigaddset};
use apue::my_libc::{sigprocmask, sigsuspend};
use apue::LibcResult;
use std::sync::atomic::{AtomicBool, Ordering, ATOMIC_BOOL_INIT};

// closest I could find for volatile sig_atomic_t in Rust
static mut QUITFLAG:AtomicBool = ATOMIC_BOOL_INIT;

fn sig_int(signo:c_int) {
    unsafe {
        match signo {
            SIGINT => println!("\ninterrupt"),
            SIGQUIT => {
                println!("\nquit");
                QUITFLAG = AtomicBool::new(true);
            },
            _ => panic!("unexpected signal"),
        }
    }
}

fn main() {
    unsafe {
        let (mut newmask, mut oldmask, mut zeromask) = std::mem::uninitialized();
        if signal(SIGINT, sig_int as usize) == SIG_ERR {
            panic!("signal(SIGINT) error");
        }
        if signal(SIGQUIT, sig_int as usize) == SIG_ERR {
            panic!("signal(SIGQUIT) error");
        }
        sigemptyset(&mut zeromask);
        sigemptyset(&mut newmask);
        sigaddset(&mut newmask, SIGQUIT);
        // Block SIGQUIT and save current signal mask
        sigprocmask(SIG_BLOCK, &newmask, &mut oldmask).to_option().expect("SIG_BLOCK error");

        // here comes the AtomicBool into play which goes sure that whenever
        // QUITFLAG becomes true it is immediately set to false again
        // so no other Thread could "catch" it
        QUITFLAG = AtomicBool::new(true);
        while QUITFLAG.fetch_or(true, Ordering::Relaxed) {
            sigsuspend(&zeromask);
            println!("exit of suspended, checking bool");
        }
        QUITFLAG = AtomicBool::new(false);
        sigprocmask(SIG_SETMASK, &oldmask, std::ptr::null_mut()).to_option().expect("SIG_SETMASK error");
    }
}<commit_msg>stuck at closure<commit_after>#![feature(drop_types_in_const)]

/// Figure 10.23 Using sigsuspend to wait for a global variable to be set
///
/// Status: after posting http://stackoverflow.com/questions/41655118/are-static-variables-volatile
/// I was sure that my solution needs an Arc<>, but then I cannot initiate a Arc<> static
/// variable as it doesn't let me do function calls. Next option: a closure which lets me
/// reference quitflag from within sig_int, but that doesn't work as the closure signature
/// is wrong.

extern crate libc;
extern crate apue;

use libc::{c_int, SIGINT, SIG_ERR, SIGQUIT, SIG_BLOCK, SIG_SETMASK};
use libc::{signal, sigemptyset, sigaddset};
use apue::my_libc::{sigprocmask, sigsuspend};
use apue::LibcResult;
use std::sync::atomic::{AtomicBool, Ordering, ATOMIC_BOOL_INIT};
use std::sync::Arc;

fn main() {
    unsafe {
        let (mut newmask, mut oldmask, mut zeromask) = std::mem::uninitialized();

        // closest I could find for volatile sig_atomic_t in Rust
        let mut quitflag:Arc<AtomicBool> = Arc::new(ATOMIC_BOOL_INIT);
        let sig_int = |signo| {
            match signo {
                SIGINT => println!("\ninterrupt"),
                SIGQUIT => {
                    println!("\nquit");
                    quitflag.store(true, Ordering::SeqCst);
                },
                _ => panic!("unexpected signal"),
            };
        };

        if signal(SIGINT, sig_int as usize) == SIG_ERR {
            panic!("signal(SIGINT) error");
        }
        if signal(SIGQUIT, sig_int as usize) == SIG_ERR {
            panic!("signal(SIGQUIT) error");
        }
        sigemptyset(&mut zeromask);
        sigemptyset(&mut newmask);
        sigaddset(&mut newmask, SIGQUIT);
        // Block SIGQUIT and save current signal mask
        sigprocmask(SIG_BLOCK, &newmask, &mut oldmask).to_option().expect("SIG_BLOCK error");

        // here comes the AtomicBool into play which goes sure that whenever
        // QUITFLAG becomes true it is immediately set to false again
        // so no other Thread could "catch" it
        quitflag.store(true, Ordering::SeqCst);
        while quitflag.fetch_or(true, Ordering::Relaxed) {
            sigsuspend(&zeromask);
            println!("exit of suspended, checking bool");
        }
        sigprocmask(SIG_SETMASK, &oldmask, std::ptr::null_mut()).to_option().expect("SIG_SETMASK error");
    }
}<|endoftext|>


<commit_before>use std::cmp::{self, Ordering};
use std::collections::hash_map::{HashMap, Values, IterMut};
use std::fmt::{self, Formatter};
use std::hash;
use std::path::Path;
use std::sync::Arc;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};

use url::Url;

use core::{Package, PackageId, Registry};
use sources::{PathSource, GitSource, RegistrySource};
use sources::git;
use util::{human, Config, CargoResult, ToUrl};

/// A Source finds and downloads remote packages based on names and
/// versions.
pub trait Source: Registry {
    /// The update method performs any network operations required to
    /// get the entire list of all names, versions and dependencies of
    /// packages managed by the Source.
    fn update(&mut self) -> CargoResult<()>;

    /// The download method fetches the full package for each name and
    /// version specified.
    fn download(&mut self, package: &PackageId) -> CargoResult<Package>;

    /// Generates a unique string which represents the fingerprint of the
    /// current state of the source.
    ///
    /// This fingerprint is used to determine the "fresheness" of the source
    /// later on. It must be guaranteed that the fingerprint of a source is
    /// constant if and only if the output product will remain constant.
    ///
    /// The `pkg` argument is the package which this fingerprint should only be
    /// interested in for when this source may contain multiple packages.
    fn fingerprint(&self, pkg: &Package) -> CargoResult<String>;
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
enum Kind {
    /// Kind::Git(<git reference>) represents a git repository
    Git(GitReference),
    /// represents a local path
    Path,
    /// represents the central registry
    Registry,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum GitReference {
    Tag(String),
    Branch(String),
    Rev(String),
}

/// Unique identifier for a source of packages.
#[derive(Clone, Eq, Debug)]
pub struct SourceId {
    inner: Arc<SourceIdInner>,
}

#[derive(Eq, Clone, Debug)]
struct SourceIdInner {
    url: Url,
    canonical_url: Url,
    kind: Kind,
    // e.g. the exact git revision of the specified branch for a Git Source
    precise: Option<String>,
}

impl SourceId {
    fn new(kind: Kind, url: Url) -> SourceId {
        SourceId {
            inner: Arc::new(SourceIdInner {
                kind: kind,
                canonical_url: git::canonicalize_url(&url),
                url: url,
                precise: None,
            }),
        }
    }

    /// Parses a source URL and returns the corresponding ID.
    ///
    /// ## Example
    ///
    /// ```
    /// use cargo::core::SourceId;
    /// SourceId::from_url("git+https://github.com/alexcrichton/\
    ///                     libssh2-static-sys#80e71a3021618eb05\
    ///                     656c58fb7c5ef5f12bc747f".to_string());
    /// ```
    pub fn from_url(string: String) -> SourceId {
        let mut parts = string.splitn(2, '+');
        let kind = parts.next().unwrap();
        let url = parts.next().unwrap();

        match kind {
            "git" => {
                let mut url = url.to_url().unwrap();
                let mut reference = GitReference::Branch("master".to_string());
                for (k, v) in url.query_pairs() {
                    match &k[..] {
                        // map older 'ref' to branch
                        "branch" |
                        "ref" => reference = GitReference::Branch(v.into_owned()),

                        "rev" => reference = GitReference::Rev(v.into_owned()),
                        "tag" => reference = GitReference::Tag(v.into_owned()),
                        _ => {}
                    }
                }
                let precise = url.fragment().map(|s| s.to_owned());
                url.set_fragment(None);
                url.set_query(None);
                SourceId::for_git(&url, reference).with_precise(precise)
            }
            "registry" => {
                let url = url.to_url().unwrap();
                SourceId::new(Kind::Registry, url)
                    .with_precise(Some("locked".to_string()))
            }
            "path" => {
                let url = url.to_url().unwrap();
                SourceId::new(Kind::Path, url)
            }
            _ => panic!("Unsupported serialized SourceId"),
        }
    }

    pub fn to_url(&self) -> String {
        match *self.inner {
            SourceIdInner { kind: Kind::Path, ref url, .. } => {
                format!("path+{}", url)
            }
            SourceIdInner {
                kind: Kind::Git(ref reference), ref url, ref precise, ..
            } => {
                let ref_str = url_ref(reference);

                let precise_str = if precise.is_some() {
                    format!("#{}", precise.as_ref().unwrap())
                } else {
                    "".to_string()
                };

                format!("git+{}{}{}", url, ref_str, precise_str)
            }
            SourceIdInner { kind: Kind::Registry, ref url, .. } => {
                format!("registry+{}", url)
            }
        }
    }

    // Pass absolute path
    pub fn for_path(path: &Path) -> CargoResult<SourceId> {
        let url = try!(path.to_url().map_err(human));
        Ok(SourceId::new(Kind::Path, url))
    }

    pub fn for_git(url: &Url, reference: GitReference) -> SourceId {
        SourceId::new(Kind::Git(reference), url.clone())
    }

    pub fn for_registry(url: &Url) -> SourceId {
        SourceId::new(Kind::Registry, url.clone())
    }

    /// Returns the `SourceId` corresponding to the main repository.
    ///
    /// This is the main cargo registry by default, but it can be overridden in
    /// a `.cargo/config`.
    pub fn for_central(config: &Config) -> CargoResult<SourceId> {
        Ok(SourceId::for_registry(&try!(RegistrySource::url(config))))
    }

    pub fn url(&self) -> &Url {
        &self.inner.url
    }
    pub fn is_path(&self) -> bool {
        self.inner.kind == Kind::Path
    }
    pub fn is_registry(&self) -> bool {
        self.inner.kind == Kind::Registry
    }

    pub fn is_git(&self) -> bool {
        match self.inner.kind {
            Kind::Git(_) => true,
            _ => false,
        }
    }

    /// Creates an implementation of `Source` corresponding to this ID.
    pub fn load<'a>(&self, config: &'a Config) -> Box<Source + 'a> {
        trace!("loading SourceId; {}", self);
        match self.inner.kind {
            Kind::Git(..) => Box::new(GitSource::new(self, config)),
            Kind::Path => {
                let path = match self.inner.url.to_file_path() {
                    Ok(p) => p,
                    Err(()) => panic!("path sources cannot be remote"),
                };
                Box::new(PathSource::new(&path, self, config))
            }
            Kind::Registry => Box::new(RegistrySource::new(self, config)),
        }
    }

    pub fn precise(&self) -> Option<&str> {
        self.inner.precise.as_ref().map(|s| &s[..])
    }

    pub fn git_reference(&self) -> Option<&GitReference> {
        match self.inner.kind {
            Kind::Git(ref s) => Some(s),
            _ => None,
        }
    }

    pub fn with_precise(&self, v: Option<String>) -> SourceId {
        SourceId {
            inner: Arc::new(SourceIdInner {
                precise: v,
                ..(*self.inner).clone()
            })
        }
    }

    pub fn is_default_registry(&self) -> bool {
        match self.inner.kind {
            Kind::Registry => {}
            _ => return false,
        }
        self.inner.url.to_string() == RegistrySource::default_url()
    }
}

impl PartialEq for SourceId {
    fn eq(&self, other: &SourceId) -> bool {
        (*self.inner).eq(&*other.inner)
    }
}

impl PartialOrd for SourceId {
    fn partial_cmp(&self, other: &SourceId) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for SourceId {
    fn cmp(&self, other: &SourceId) -> Ordering {
        self.inner.cmp(&other.inner)
    }
}

impl Encodable for SourceId {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        if self.is_path() {
            s.emit_option_none()
        } else {
            self.to_url().encode(s)
        }
    }
}

impl Decodable for SourceId {
    fn decode<D: Decoder>(d: &mut D) -> Result<SourceId, D::Error> {
        let string: String = Decodable::decode(d).ok().expect("Invalid encoded SourceId");
        Ok(SourceId::from_url(string))
    }
}

impl fmt::Display for SourceId {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match *self.inner {
            SourceIdInner { kind: Kind::Path, ref url, .. } => {
                fmt::Display::fmt(url, f)
            }
            SourceIdInner { kind: Kind::Git(ref reference), ref url,
                            ref precise, .. } => {
                try!(write!(f, "{}{}", url, url_ref(reference)));

                if let Some(ref s) = *precise {
                    let len = cmp::min(s.len(), 8);
                    try!(write!(f, "#{}", &s[..len]));
                }
                Ok(())
            }
            SourceIdInner { kind: Kind::Registry, ref url, .. } => {
                write!(f, "registry {}", url)
            }
        }
    }
}

// This custom implementation handles situations such as when two git sources
// point at *almost* the same URL, but not quite, even when they actually point
// to the same repository.
impl PartialEq for SourceIdInner {
    fn eq(&self, other: &SourceIdInner) -> bool {
        if self.kind != other.kind {
            return false;
        }
        if self.url == other.url {
            return true;
        }

        match (&self.kind, &other.kind) {
            (&Kind::Git(ref ref1), &Kind::Git(ref ref2)) => {
                ref1 == ref2 && self.canonical_url == other.canonical_url
            }
            _ => false,
        }
    }
}

impl PartialOrd for SourceIdInner {
    fn partial_cmp(&self, other: &SourceIdInner) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for SourceIdInner {
    fn cmp(&self, other: &SourceIdInner) -> Ordering {
        match self.kind.cmp(&other.kind) {
            Ordering::Equal => {}
            ord => return ord,
        }
        match self.url.cmp(&other.url) {
            Ordering::Equal => {}
            ord => return ord,
        }
        match (&self.kind, &other.kind) {
            (&Kind::Git(ref ref1), &Kind::Git(ref ref2)) => {
                (ref1, &self.canonical_url).cmp(&(ref2, &other.canonical_url))
            }
            _ => self.kind.cmp(&other.kind),
        }
    }
}

impl hash::Hash for SourceId {
    fn hash<S: hash::Hasher>(&self, into: &mut S) {
        self.inner.kind.hash(into);
        match *self.inner {
            SourceIdInner { kind: Kind::Git(..), ref canonical_url, .. } => {
                canonical_url.hash(into)
            }
            _ => self.inner.url.hash(into),
        }
    }
}

fn url_ref(r: &GitReference) -> String {
    match r.to_ref_string() {
        None => "".to_string(),
        Some(s) => format!("?{}", s),
    }
}

impl GitReference {
    pub fn to_ref_string(&self) -> Option<String> {
        match *self {
            GitReference::Branch(ref s) => {
                if *s == "master" {
                    None
                } else {
                    Some(format!("branch={}", s))
                }
            }
            GitReference::Tag(ref s) => Some(format!("tag={}", s)),
            GitReference::Rev(ref s) => Some(format!("rev={}", s)),
        }
    }
}

pub struct SourceMap<'src> {
    map: HashMap<SourceId, Box<Source + 'src>>,
}

pub type Sources<'a, 'src> = Values<'a, SourceId, Box<Source + 'src>>;

pub struct SourcesMut<'a, 'src: 'a> {
    inner: IterMut<'a, SourceId, Box<Source + 'src>>,
}

impl<'src> SourceMap<'src> {
    pub fn new() -> SourceMap<'src> {
        SourceMap { map: HashMap::new() }
    }

    pub fn contains(&self, id: &SourceId) -> bool {
        self.map.contains_key(id)
    }

    pub fn get(&self, id: &SourceId) -> Option<&(Source + 'src)> {
        let source = self.map.get(id);

        source.map(|s| {
            let s: &(Source + 'src) = &**s;
            s
        })
    }

    pub fn get_mut(&mut self, id: &SourceId) -> Option<&mut (Source + 'src)> {
        self.map.get_mut(id).map(|s| {
            let s: &mut (Source + 'src) = &mut **s;
            s
        })
    }

    pub fn get_by_package_id(&self, pkg_id: &PackageId) -> Option<&(Source + 'src)> {
        self.get(pkg_id.source_id())
    }

    pub fn insert(&mut self, id: &SourceId, source: Box<Source + 'src>) {
        self.map.insert(id.clone(), source);
    }

    pub fn is_empty(&self) -> bool {
        self.map.is_empty()
    }

    pub fn len(&self) -> usize {
        self.map.len()
    }

    pub fn sources<'a>(&'a self) -> Sources<'a, 'src> {
        self.map.values()
    }

    pub fn sources_mut<'a>(&'a mut self) -> SourcesMut<'a, 'src> {
        SourcesMut { inner: self.map.iter_mut() }
    }
}

impl<'a, 'src> Iterator for SourcesMut<'a, 'src> {
    type Item = (&'a SourceId, &'a mut (Source + 'src));
    fn next(&mut self) -> Option<(&'a SourceId, &'a mut (Source + 'src))> {
        self.inner.next().map(|(a, b)| (a, &mut **b))
    }
}

#[cfg(test)]
mod tests {
    use super::{SourceId, Kind, GitReference};
    use util::ToUrl;

    #[test]
    fn github_sources_equal() {
        let loc = "https://github.com/foo/bar".to_url().unwrap();
        let master = Kind::Git(GitReference::Branch("master".to_string()));
        let s1 = SourceId::new(master.clone(), loc);

        let loc = "git://github.com/foo/bar".to_url().unwrap();
        let s2 = SourceId::new(master, loc.clone());

        assert_eq!(s1, s2);

        let foo = Kind::Git(GitReference::Branch("foo".to_string()));
        let s3 = SourceId::new(foo, loc);
        assert!(s1 != s3);
    }
}
<commit_msg>Turn `url_ref` utility function into method.<commit_after>use std::cmp::{self, Ordering};
use std::collections::hash_map::{HashMap, Values, IterMut};
use std::fmt::{self, Formatter};
use std::hash;
use std::path::Path;
use std::sync::Arc;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};

use url::Url;

use core::{Package, PackageId, Registry};
use sources::{PathSource, GitSource, RegistrySource};
use sources::git;
use util::{human, Config, CargoResult, ToUrl};

/// A Source finds and downloads remote packages based on names and
/// versions.
pub trait Source: Registry {
    /// The update method performs any network operations required to
    /// get the entire list of all names, versions and dependencies of
    /// packages managed by the Source.
    fn update(&mut self) -> CargoResult<()>;

    /// The download method fetches the full package for each name and
    /// version specified.
    fn download(&mut self, package: &PackageId) -> CargoResult<Package>;

    /// Generates a unique string which represents the fingerprint of the
    /// current state of the source.
    ///
    /// This fingerprint is used to determine the "fresheness" of the source
    /// later on. It must be guaranteed that the fingerprint of a source is
    /// constant if and only if the output product will remain constant.
    ///
    /// The `pkg` argument is the package which this fingerprint should only be
    /// interested in for when this source may contain multiple packages.
    fn fingerprint(&self, pkg: &Package) -> CargoResult<String>;
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
enum Kind {
    /// Kind::Git(<git reference>) represents a git repository
    Git(GitReference),
    /// represents a local path
    Path,
    /// represents the central registry
    Registry,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum GitReference {
    Tag(String),
    Branch(String),
    Rev(String),
}

/// Unique identifier for a source of packages.
#[derive(Clone, Eq, Debug)]
pub struct SourceId {
    inner: Arc<SourceIdInner>,
}

#[derive(Eq, Clone, Debug)]
struct SourceIdInner {
    url: Url,
    canonical_url: Url,
    kind: Kind,
    // e.g. the exact git revision of the specified branch for a Git Source
    precise: Option<String>,
}

impl SourceId {
    fn new(kind: Kind, url: Url) -> SourceId {
        SourceId {
            inner: Arc::new(SourceIdInner {
                kind: kind,
                canonical_url: git::canonicalize_url(&url),
                url: url,
                precise: None,
            }),
        }
    }

    /// Parses a source URL and returns the corresponding ID.
    ///
    /// ## Example
    ///
    /// ```
    /// use cargo::core::SourceId;
    /// SourceId::from_url("git+https://github.com/alexcrichton/\
    ///                     libssh2-static-sys#80e71a3021618eb05\
    ///                     656c58fb7c5ef5f12bc747f".to_string());
    /// ```
    pub fn from_url(string: String) -> SourceId {
        let mut parts = string.splitn(2, '+');
        let kind = parts.next().unwrap();
        let url = parts.next().unwrap();

        match kind {
            "git" => {
                let mut url = url.to_url().unwrap();
                let mut reference = GitReference::Branch("master".to_string());
                for (k, v) in url.query_pairs() {
                    match &k[..] {
                        // map older 'ref' to branch
                        "branch" |
                        "ref" => reference = GitReference::Branch(v.into_owned()),

                        "rev" => reference = GitReference::Rev(v.into_owned()),
                        "tag" => reference = GitReference::Tag(v.into_owned()),
                        _ => {}
                    }
                }
                let precise = url.fragment().map(|s| s.to_owned());
                url.set_fragment(None);
                url.set_query(None);
                SourceId::for_git(&url, reference).with_precise(precise)
            }
            "registry" => {
                let url = url.to_url().unwrap();
                SourceId::new(Kind::Registry, url)
                    .with_precise(Some("locked".to_string()))
            }
            "path" => {
                let url = url.to_url().unwrap();
                SourceId::new(Kind::Path, url)
            }
            _ => panic!("Unsupported serialized SourceId"),
        }
    }

    pub fn to_url(&self) -> String {
        match *self.inner {
            SourceIdInner { kind: Kind::Path, ref url, .. } => {
                format!("path+{}", url)
            }
            SourceIdInner {
                kind: Kind::Git(ref reference), ref url, ref precise, ..
            } => {
                let ref_str = reference.url_ref();

                let precise_str = if precise.is_some() {
                    format!("#{}", precise.as_ref().unwrap())
                } else {
                    "".to_string()
                };

                format!("git+{}{}{}", url, ref_str, precise_str)
            }
            SourceIdInner { kind: Kind::Registry, ref url, .. } => {
                format!("registry+{}", url)
            }
        }
    }

    // Pass absolute path
    pub fn for_path(path: &Path) -> CargoResult<SourceId> {
        let url = try!(path.to_url().map_err(human));
        Ok(SourceId::new(Kind::Path, url))
    }

    pub fn for_git(url: &Url, reference: GitReference) -> SourceId {
        SourceId::new(Kind::Git(reference), url.clone())
    }

    pub fn for_registry(url: &Url) -> SourceId {
        SourceId::new(Kind::Registry, url.clone())
    }

    /// Returns the `SourceId` corresponding to the main repository.
    ///
    /// This is the main cargo registry by default, but it can be overridden in
    /// a `.cargo/config`.
    pub fn for_central(config: &Config) -> CargoResult<SourceId> {
        Ok(SourceId::for_registry(&try!(RegistrySource::url(config))))
    }

    pub fn url(&self) -> &Url {
        &self.inner.url
    }
    pub fn is_path(&self) -> bool {
        self.inner.kind == Kind::Path
    }
    pub fn is_registry(&self) -> bool {
        self.inner.kind == Kind::Registry
    }

    pub fn is_git(&self) -> bool {
        match self.inner.kind {
            Kind::Git(_) => true,
            _ => false,
        }
    }

    /// Creates an implementation of `Source` corresponding to this ID.
    pub fn load<'a>(&self, config: &'a Config) -> Box<Source + 'a> {
        trace!("loading SourceId; {}", self);
        match self.inner.kind {
            Kind::Git(..) => Box::new(GitSource::new(self, config)),
            Kind::Path => {
                let path = match self.inner.url.to_file_path() {
                    Ok(p) => p,
                    Err(()) => panic!("path sources cannot be remote"),
                };
                Box::new(PathSource::new(&path, self, config))
            }
            Kind::Registry => Box::new(RegistrySource::new(self, config)),
        }
    }

    pub fn precise(&self) -> Option<&str> {
        self.inner.precise.as_ref().map(|s| &s[..])
    }

    pub fn git_reference(&self) -> Option<&GitReference> {
        match self.inner.kind {
            Kind::Git(ref s) => Some(s),
            _ => None,
        }
    }

    pub fn with_precise(&self, v: Option<String>) -> SourceId {
        SourceId {
            inner: Arc::new(SourceIdInner {
                precise: v,
                ..(*self.inner).clone()
            })
        }
    }

    pub fn is_default_registry(&self) -> bool {
        match self.inner.kind {
            Kind::Registry => {}
            _ => return false,
        }
        self.inner.url.to_string() == RegistrySource::default_url()
    }
}

impl PartialEq for SourceId {
    fn eq(&self, other: &SourceId) -> bool {
        (*self.inner).eq(&*other.inner)
    }
}

impl PartialOrd for SourceId {
    fn partial_cmp(&self, other: &SourceId) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for SourceId {
    fn cmp(&self, other: &SourceId) -> Ordering {
        self.inner.cmp(&other.inner)
    }
}

impl Encodable for SourceId {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        if self.is_path() {
            s.emit_option_none()
        } else {
            self.to_url().encode(s)
        }
    }
}

impl Decodable for SourceId {
    fn decode<D: Decoder>(d: &mut D) -> Result<SourceId, D::Error> {
        let string: String = Decodable::decode(d).ok().expect("Invalid encoded SourceId");
        Ok(SourceId::from_url(string))
    }
}

impl fmt::Display for SourceId {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match *self.inner {
            SourceIdInner { kind: Kind::Path, ref url, .. } => {
                fmt::Display::fmt(url, f)
            }
            SourceIdInner { kind: Kind::Git(ref reference), ref url,
                            ref precise, .. } => {
                try!(write!(f, "{}{}", url, reference.url_ref()));

                if let Some(ref s) = *precise {
                    let len = cmp::min(s.len(), 8);
                    try!(write!(f, "#{}", &s[..len]));
                }
                Ok(())
            }
            SourceIdInner { kind: Kind::Registry, ref url, .. } => {
                write!(f, "registry {}", url)
            }
        }
    }
}

// This custom implementation handles situations such as when two git sources
// point at *almost* the same URL, but not quite, even when they actually point
// to the same repository.
impl PartialEq for SourceIdInner {
    fn eq(&self, other: &SourceIdInner) -> bool {
        if self.kind != other.kind {
            return false;
        }
        if self.url == other.url {
            return true;
        }

        match (&self.kind, &other.kind) {
            (&Kind::Git(ref ref1), &Kind::Git(ref ref2)) => {
                ref1 == ref2 && self.canonical_url == other.canonical_url
            }
            _ => false,
        }
    }
}

impl PartialOrd for SourceIdInner {
    fn partial_cmp(&self, other: &SourceIdInner) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for SourceIdInner {
    fn cmp(&self, other: &SourceIdInner) -> Ordering {
        match self.kind.cmp(&other.kind) {
            Ordering::Equal => {}
            ord => return ord,
        }
        match self.url.cmp(&other.url) {
            Ordering::Equal => {}
            ord => return ord,
        }
        match (&self.kind, &other.kind) {
            (&Kind::Git(ref ref1), &Kind::Git(ref ref2)) => {
                (ref1, &self.canonical_url).cmp(&(ref2, &other.canonical_url))
            }
            _ => self.kind.cmp(&other.kind),
        }
    }
}

impl hash::Hash for SourceId {
    fn hash<S: hash::Hasher>(&self, into: &mut S) {
        self.inner.kind.hash(into);
        match *self.inner {
            SourceIdInner { kind: Kind::Git(..), ref canonical_url, .. } => {
                canonical_url.hash(into)
            }
            _ => self.inner.url.hash(into),
        }
    }
}

impl GitReference {
    pub fn to_ref_string(&self) -> Option<String> {
        match *self {
            GitReference::Branch(ref s) => {
                if *s == "master" {
                    None
                } else {
                    Some(format!("branch={}", s))
                }
            }
            GitReference::Tag(ref s) => Some(format!("tag={}", s)),
            GitReference::Rev(ref s) => Some(format!("rev={}", s)),
        }
    }

    fn url_ref(&self) -> String {
        match self.to_ref_string() {
            None => "".to_string(),
            Some(s) => format!("?{}", s),
        }
    }
}

pub struct SourceMap<'src> {
    map: HashMap<SourceId, Box<Source + 'src>>,
}

pub type Sources<'a, 'src> = Values<'a, SourceId, Box<Source + 'src>>;

pub struct SourcesMut<'a, 'src: 'a> {
    inner: IterMut<'a, SourceId, Box<Source + 'src>>,
}

impl<'src> SourceMap<'src> {
    pub fn new() -> SourceMap<'src> {
        SourceMap { map: HashMap::new() }
    }

    pub fn contains(&self, id: &SourceId) -> bool {
        self.map.contains_key(id)
    }

    pub fn get(&self, id: &SourceId) -> Option<&(Source + 'src)> {
        let source = self.map.get(id);

        source.map(|s| {
            let s: &(Source + 'src) = &**s;
            s
        })
    }

    pub fn get_mut(&mut self, id: &SourceId) -> Option<&mut (Source + 'src)> {
        self.map.get_mut(id).map(|s| {
            let s: &mut (Source + 'src) = &mut **s;
            s
        })
    }

    pub fn get_by_package_id(&self, pkg_id: &PackageId) -> Option<&(Source + 'src)> {
        self.get(pkg_id.source_id())
    }

    pub fn insert(&mut self, id: &SourceId, source: Box<Source + 'src>) {
        self.map.insert(id.clone(), source);
    }

    pub fn is_empty(&self) -> bool {
        self.map.is_empty()
    }

    pub fn len(&self) -> usize {
        self.map.len()
    }

    pub fn sources<'a>(&'a self) -> Sources<'a, 'src> {
        self.map.values()
    }

    pub fn sources_mut<'a>(&'a mut self) -> SourcesMut<'a, 'src> {
        SourcesMut { inner: self.map.iter_mut() }
    }
}

impl<'a, 'src> Iterator for SourcesMut<'a, 'src> {
    type Item = (&'a SourceId, &'a mut (Source + 'src));
    fn next(&mut self) -> Option<(&'a SourceId, &'a mut (Source + 'src))> {
        self.inner.next().map(|(a, b)| (a, &mut **b))
    }
}

#[cfg(test)]
mod tests {
    use super::{SourceId, Kind, GitReference};
    use util::ToUrl;

    #[test]
    fn github_sources_equal() {
        let loc = "https://github.com/foo/bar".to_url().unwrap();
        let master = Kind::Git(GitReference::Branch("master".to_string()));
        let s1 = SourceId::new(master.clone(), loc);

        let loc = "git://github.com/foo/bar".to_url().unwrap();
        let s2 = SourceId::new(master, loc.clone());

        assert_eq!(s1, s2);

        let foo = Kind::Git(GitReference::Branch("foo".to_string()));
        let s3 = SourceId::new(foo, loc);
        assert!(s1 != s3);
    }
}
<|endoftext|>


<commit_before>use std::error::{FromError, Error};
use std::ffi;
use std::fmt;
use std::old_io::IoError;
use std::old_io::process::{ProcessOutput, ProcessExit, ExitStatus, ExitSignal};
use std::str;

use semver;
use rustc_serialize::json;

use curl;
use git2;
use toml;
use url;

pub type CargoResult<T> = Result<T, Box<CargoError>>;

// =============================================================================
// CargoError trait

pub trait CargoError: Error + Send + 'static {
    fn is_human(&self) -> bool { false }
    fn cargo_cause(&self) -> Option<&CargoError>{ None }
}

impl fmt::Debug for Box<CargoError> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self, f)
    }
}

impl Error for Box<CargoError> {
    fn description(&self) -> &str { (**self).description() }
    fn cause(&self) -> Option<&Error> { (**self).cause() }
}

impl CargoError for Box<CargoError> {
    fn is_human(&self) -> bool { (**self).is_human() }
    fn cargo_cause(&self) -> Option<&CargoError> { (**self).cargo_cause() }
}

// =============================================================================
// Chaining errors

pub trait ChainError<T> {
    fn chain_error<E, F>(self, callback: F) -> CargoResult<T>
                         where E: CargoError, F: FnOnce() -> E;
}

struct ChainedError<E> {
    error: E,
    cause: Box<CargoError>,
}

impl<'a, T, F> ChainError<T> for F where F: FnOnce() -> CargoResult<T> {
    fn chain_error<E, C>(self, callback: C) -> CargoResult<T>
                         where E: CargoError, C: FnOnce() -> E {
        self().chain_error(callback)
    }
}

impl<T, E: CargoError + 'static> ChainError<T> for Result<T, E> {
    fn chain_error<E2: 'static, C>(self, callback: C) -> CargoResult<T>
                         where E2: CargoError, C: FnOnce() -> E2 {
        self.map_err(move |err| {
            Box::new(ChainedError {
                error: callback(),
                cause: Box::new(err),
            }) as Box<CargoError>
        })
    }
}

impl<T> ChainError<T> for Option<T> {
    fn chain_error<E: 'static, C>(self, callback: C) -> CargoResult<T>
                         where E: CargoError, C: FnOnce() -> E {
        match self {
            Some(t) => Ok(t),
            None => Err(Box::new(callback()) as Box<CargoError>),
        }
    }
}

impl<E: Error> Error for ChainedError<E> {
    fn description(&self) -> &str { self.error.description() }
}

impl<E: fmt::Display> fmt::Display for ChainedError<E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.error, f)
    }
}

impl<E: CargoError> CargoError for ChainedError<E> {
    fn is_human(&self) -> bool { self.error.is_human() }
    fn cargo_cause(&self) -> Option<&CargoError> { Some(&*self.cause) }
}

// =============================================================================
// Process errors

pub struct ProcessError {
    pub desc: String,
    pub exit: Option<ProcessExit>,
    pub output: Option<ProcessOutput>,
    cause: Option<IoError>,
}

impl Error for ProcessError {
    fn description(&self) -> &str { &self.desc }
    fn cause(&self) -> Option<&Error> {
        self.cause.as_ref().map(|s| s as &Error)
    }
}

impl fmt::Display for ProcessError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.desc, f)
    }
}
impl fmt::Debug for ProcessError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self, f)
    }
}

// =============================================================================
// Concrete errors

struct ConcreteCargoError {
    description: String,
    detail: Option<String>,
    cause: Option<Box<Error+Send>>,
    is_human: bool,
}

impl fmt::Display for ConcreteCargoError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "{}", self.description));
        if let Some(ref s) = self.detail {
            try!(write!(f, " ({})", s));
        }
        Ok(())
    }
}
impl fmt::Debug for ConcreteCargoError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self, f)
    }
}

impl Error for ConcreteCargoError {
    fn description(&self) -> &str { &self.description }
    fn cause(&self) -> Option<&Error> {
        self.cause.as_ref().map(|c| {
            let e: &Error = &**c; e
        })
    }
}

impl CargoError for ConcreteCargoError {
    fn is_human(&self) -> bool {
        self.is_human
    }
}

// =============================================================================
// Human errors

pub struct Human<E>(pub E);

impl<E: Error> Error for Human<E> {
    fn description(&self) -> &str { self.0.description() }
    fn cause(&self) -> Option<&Error> { self.0.cause() }
}

impl<E: fmt::Display> fmt::Display for Human<E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

impl<E: CargoError> CargoError for Human<E> {
    fn is_human(&self) -> bool { true }
    fn cargo_cause(&self) -> Option<&CargoError> { self.0.cargo_cause() }
}

// =============================================================================
// CLI errors

pub type CliResult<T> = Result<T, CliError>;

#[derive(Debug)]
pub struct CliError {
    pub error: Box<CargoError>,
    pub unknown: bool,
    pub exit_code: i32
}

impl Error for CliError {
    fn description(&self) -> &str { self.error.description() }
    fn cause(&self) -> Option<&Error> { self.error.cause() }
}

impl fmt::Display for CliError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.error, f)
    }
}

impl CliError {
    pub fn new(error: &str, code: i32) -> CliError {
        let error = human(error.to_string());
        CliError::from_boxed(error, code)
    }

    pub fn from_error<E: CargoError>(error: E, code: i32) -> CliError {
        let error = Box::new(error) as Box<CargoError>;
        CliError::from_boxed(error, code)
    }

    pub fn from_boxed(error: Box<CargoError>, code: i32) -> CliError {
        let human = error.is_human();
        CliError { error: error, exit_code: code, unknown: !human }
    }
}

impl FromError<Box<CargoError>> for CliError {
    fn from_error(err: Box<CargoError>) -> CliError {
        CliError::from_boxed(err, 101)
    }
}

// =============================================================================
// various impls

macro_rules! from_error {
    ($($p:ty,)*) => (
        $(impl FromError<$p> for Box<CargoError> {
            fn from_error(t: $p) -> Box<CargoError> { Box::new(t) }
        })*
    )
}

from_error! {
    semver::ReqParseError,
    IoError,
    ProcessError,
    git2::Error,
    json::DecoderError,
    curl::ErrCode,
    CliError,
    toml::Error,
    url::ParseError,
    toml::DecodeError,
    ffi::NulError,
}

impl<E: CargoError> FromError<Human<E>> for Box<CargoError> {
    fn from_error(t: Human<E>) -> Box<CargoError> { Box::new(t) }
}

impl CargoError for semver::ReqParseError {}
impl CargoError for IoError {}
impl CargoError for git2::Error {}
impl CargoError for json::DecoderError {}
impl CargoError for curl::ErrCode {}
impl CargoError for ProcessError {}
impl CargoError for CliError {}
impl CargoError for toml::Error {}
impl CargoError for toml::DecodeError {}
impl CargoError for url::ParseError {}
impl CargoError for str::Utf8Error {}
impl CargoError for ffi::NulError {}

// =============================================================================
// Construction helpers

pub fn process_error(msg: &str,
                     cause: Option<IoError>,
                     status: Option<&ProcessExit>,
                     output: Option<&ProcessOutput>) -> ProcessError {
    let exit = match status {
        Some(&ExitStatus(i)) | Some(&ExitSignal(i)) => i.to_string(),
        None => "never executed".to_string(),
    };
    let mut desc = format!("{} (status={})", &msg, exit);

    if let Some(out) = output {
        match str::from_utf8(&out.output) {
            Ok(s) if s.trim().len() > 0 => {
                desc.push_str("\n--- stdout\n");
                desc.push_str(s);
            }
            Ok(..) | Err(..) => {}
        }
        match str::from_utf8(&out.error) {
            Ok(s) if s.trim().len() > 0 => {
                desc.push_str("\n--- stderr\n");
                desc.push_str(s);
            }
            Ok(..) | Err(..) => {}
        }
    }

    ProcessError {
        desc: desc,
        exit: status.map(|a| a.clone()),
        output: output.map(|a| a.clone()),
        cause: cause,
    }
}

pub fn internal_error(error: &str, detail: &str) -> Box<CargoError> {
    Box::new(ConcreteCargoError {
        description: error.to_string(),
        detail: Some(detail.to_string()),
        cause: None,
        is_human: false
    })
}

pub fn internal<S: fmt::Display>(error: S) -> Box<CargoError> {
    Box::new(ConcreteCargoError {
        description: error.to_string(),
        detail: None,
        cause: None,
        is_human: false
    })
}

pub fn human<S: fmt::Display>(error: S) -> Box<CargoError> {
    Box::new(ConcreteCargoError {
        description: error.to_string(),
        detail: None,
        cause: None,
        is_human: true
    })
}

pub fn caused_human<S: fmt::Display, E: Error + Send + 'static>(error: S, cause: E) -> Box<CargoError> {
    Box::new(ConcreteCargoError {
        description: error.to_string(),
        detail: None,
        cause: Some(Box::new(cause) as Box<Error + Send>),
        is_human: true
    })
}
<commit_msg>fix style<commit_after>use std::error::{FromError, Error};
use std::ffi;
use std::fmt;
use std::old_io::IoError;
use std::old_io::process::{ProcessOutput, ProcessExit, ExitStatus, ExitSignal};
use std::str;

use semver;
use rustc_serialize::json;

use curl;
use git2;
use toml;
use url;

pub type CargoResult<T> = Result<T, Box<CargoError>>;

// =============================================================================
// CargoError trait

pub trait CargoError: Error + Send + 'static {
    fn is_human(&self) -> bool { false }
    fn cargo_cause(&self) -> Option<&CargoError>{ None }
}

impl fmt::Debug for Box<CargoError> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self, f)
    }
}

impl Error for Box<CargoError> {
    fn description(&self) -> &str { (**self).description() }
    fn cause(&self) -> Option<&Error> { (**self).cause() }
}

impl CargoError for Box<CargoError> {
    fn is_human(&self) -> bool { (**self).is_human() }
    fn cargo_cause(&self) -> Option<&CargoError> { (**self).cargo_cause() }
}

// =============================================================================
// Chaining errors

pub trait ChainError<T> {
    fn chain_error<E, F>(self, callback: F) -> CargoResult<T>
                         where E: CargoError, F: FnOnce() -> E;
}

struct ChainedError<E> {
    error: E,
    cause: Box<CargoError>,
}

impl<'a, T, F> ChainError<T> for F where F: FnOnce() -> CargoResult<T> {
    fn chain_error<E, C>(self, callback: C) -> CargoResult<T>
                         where E: CargoError, C: FnOnce() -> E {
        self().chain_error(callback)
    }
}

impl<T, E: CargoError + 'static> ChainError<T> for Result<T, E> {
    fn chain_error<E2: 'static, C>(self, callback: C) -> CargoResult<T>
                         where E2: CargoError, C: FnOnce() -> E2 {
        self.map_err(move |err| {
            Box::new(ChainedError {
                error: callback(),
                cause: Box::new(err),
            }) as Box<CargoError>
        })
    }
}

impl<T> ChainError<T> for Option<T> {
    fn chain_error<E: 'static, C>(self, callback: C) -> CargoResult<T>
                         where E: CargoError, C: FnOnce() -> E {
        match self {
            Some(t) => Ok(t),
            None => Err(Box::new(callback()) as Box<CargoError>),
        }
    }
}

impl<E: Error> Error for ChainedError<E> {
    fn description(&self) -> &str { self.error.description() }
}

impl<E: fmt::Display> fmt::Display for ChainedError<E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.error, f)
    }
}

impl<E: CargoError> CargoError for ChainedError<E> {
    fn is_human(&self) -> bool { self.error.is_human() }
    fn cargo_cause(&self) -> Option<&CargoError> { Some(&*self.cause) }
}

// =============================================================================
// Process errors

pub struct ProcessError {
    pub desc: String,
    pub exit: Option<ProcessExit>,
    pub output: Option<ProcessOutput>,
    cause: Option<IoError>,
}

impl Error for ProcessError {
    fn description(&self) -> &str { &self.desc }
    fn cause(&self) -> Option<&Error> {
        self.cause.as_ref().map(|s| s as &Error)
    }
}

impl fmt::Display for ProcessError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.desc, f)
    }
}
impl fmt::Debug for ProcessError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self, f)
    }
}

// =============================================================================
// Concrete errors

struct ConcreteCargoError {
    description: String,
    detail: Option<String>,
    cause: Option<Box<Error+Send>>,
    is_human: bool,
}

impl fmt::Display for ConcreteCargoError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "{}", self.description));
        if let Some(ref s) = self.detail {
            try!(write!(f, " ({})", s));
        }
        Ok(())
    }
}
impl fmt::Debug for ConcreteCargoError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self, f)
    }
}

impl Error for ConcreteCargoError {
    fn description(&self) -> &str { &self.description }
    fn cause(&self) -> Option<&Error> {
        self.cause.as_ref().map(|c| {
            let e: &Error = &**c; e
        })
    }
}

impl CargoError for ConcreteCargoError {
    fn is_human(&self) -> bool {
        self.is_human
    }
}

// =============================================================================
// Human errors

pub struct Human<E>(pub E);

impl<E: Error> Error for Human<E> {
    fn description(&self) -> &str { self.0.description() }
    fn cause(&self) -> Option<&Error> { self.0.cause() }
}

impl<E: fmt::Display> fmt::Display for Human<E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

impl<E: CargoError> CargoError for Human<E> {
    fn is_human(&self) -> bool { true }
    fn cargo_cause(&self) -> Option<&CargoError> { self.0.cargo_cause() }
}

// =============================================================================
// CLI errors

pub type CliResult<T> = Result<T, CliError>;

#[derive(Debug)]
pub struct CliError {
    pub error: Box<CargoError>,
    pub unknown: bool,
    pub exit_code: i32
}

impl Error for CliError {
    fn description(&self) -> &str { self.error.description() }
    fn cause(&self) -> Option<&Error> { self.error.cause() }
}

impl fmt::Display for CliError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.error, f)
    }
}

impl CliError {
    pub fn new(error: &str, code: i32) -> CliError {
        let error = human(error.to_string());
        CliError::from_boxed(error, code)
    }

    pub fn from_error<E: CargoError>(error: E, code: i32) -> CliError {
        let error = Box::new(error) as Box<CargoError>;
        CliError::from_boxed(error, code)
    }

    pub fn from_boxed(error: Box<CargoError>, code: i32) -> CliError {
        let human = error.is_human();
        CliError { error: error, exit_code: code, unknown: !human }
    }
}

impl FromError<Box<CargoError>> for CliError {
    fn from_error(err: Box<CargoError>) -> CliError {
        CliError::from_boxed(err, 101)
    }
}

// =============================================================================
// various impls

macro_rules! from_error {
    ($($p:ty,)*) => (
        $(impl FromError<$p> for Box<CargoError> {
            fn from_error(t: $p) -> Box<CargoError> { Box::new(t) }
        })*
    )
}

from_error! {
    semver::ReqParseError,
    IoError,
    ProcessError,
    git2::Error,
    json::DecoderError,
    curl::ErrCode,
    CliError,
    toml::Error,
    url::ParseError,
    toml::DecodeError,
    ffi::NulError,
}

impl<E: CargoError> FromError<Human<E>> for Box<CargoError> {
    fn from_error(t: Human<E>) -> Box<CargoError> { Box::new(t) }
}

impl CargoError for semver::ReqParseError {}
impl CargoError for IoError {}
impl CargoError for git2::Error {}
impl CargoError for json::DecoderError {}
impl CargoError for curl::ErrCode {}
impl CargoError for ProcessError {}
impl CargoError for CliError {}
impl CargoError for toml::Error {}
impl CargoError for toml::DecodeError {}
impl CargoError for url::ParseError {}
impl CargoError for str::Utf8Error {}
impl CargoError for ffi::NulError {}

// =============================================================================
// Construction helpers

pub fn process_error(msg: &str,
                     cause: Option<IoError>,
                     status: Option<&ProcessExit>,
                     output: Option<&ProcessOutput>) -> ProcessError {
    let exit = match status {
        Some(&ExitStatus(i)) | Some(&ExitSignal(i)) => i.to_string(),
        None => "never executed".to_string(),
    };
    let mut desc = format!("{} (status={})", &msg, exit);

    if let Some(out) = output {
        match str::from_utf8(&out.output) {
            Ok(s) if s.trim().len() > 0 => {
                desc.push_str("\n--- stdout\n");
                desc.push_str(s);
            }
            Ok(..) | Err(..) => {}
        }
        match str::from_utf8(&out.error) {
            Ok(s) if s.trim().len() > 0 => {
                desc.push_str("\n--- stderr\n");
                desc.push_str(s);
            }
            Ok(..) | Err(..) => {}
        }
    }

    ProcessError {
        desc: desc,
        exit: status.map(|a| a.clone()),
        output: output.map(|a| a.clone()),
        cause: cause,
    }
}

pub fn internal_error(error: &str, detail: &str) -> Box<CargoError> {
    Box::new(ConcreteCargoError {
        description: error.to_string(),
        detail: Some(detail.to_string()),
        cause: None,
        is_human: false
    })
}

pub fn internal<S: fmt::Display>(error: S) -> Box<CargoError> {
    Box::new(ConcreteCargoError {
        description: error.to_string(),
        detail: None,
        cause: None,
        is_human: false
    })
}

pub fn human<S: fmt::Display>(error: S) -> Box<CargoError> {
    Box::new(ConcreteCargoError {
        description: error.to_string(),
        detail: None,
        cause: None,
        is_human: true
    })
}

pub fn caused_human<S, E>(error: S, cause: E) -> Box<CargoError>
    where S: fmt::Display,
          E: Error + Send + 'static
{
    Box::new(ConcreteCargoError {
        description: error.to_string(),
        detail: None,
        cause: Some(Box::new(cause) as Box<Error + Send>),
        is_human: true
    })
}
<|endoftext|>