<commit_before>use js::value::{Value, VNumber, VInteger, VFunction, VObject, ResultValue};
use js::function::{NativeFunction, NativeFunc};
use js::object::ObjectData;
use collections::treemap::TreeMap;
use std::io::stdio;
use std::f64;
use std::gc::Gc;
use std::cell::RefCell;

/// Get the absolute value of a number
pub fn abs(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().abs()
	} else {
		f64::NAN
	})))
}
/// Get the arccos of a number
pub fn acos(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().acos()
	} else {
		f64::NAN
	})))
}
/// Get the arcsine of a number
pub fn asin(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().asin()
	} else {
		f64::NAN
	})))
}
/// Get the arctangent of a number
pub fn atan(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().atan()
	} else {
		f64::NAN
	})))
}
/// Get the arctangent of a numbers
pub fn atan2(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().atan2(&args.get(1).borrow().to_num())
	} else {
		f64::NAN
	})))
}
/// Get the cubic root of a number
pub fn cbrt(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().cbrt()
	} else {
		f64::NAN
	})))
}
/// Get lowest integer above a number
pub fn ceil(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().ceil()
	} else {
		f64::NAN
	})))
}
/// Get the cosine of a number
pub fn cos(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().cos()
	} else {
		f64::NAN
	})))
}
/// Get the highest integer below a number
pub fn floor(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().floor()
	} else {
		f64::NAN
	})))
}
/// Get the sine of a number
pub fn sin(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().sin()
	} else {
		f64::NAN
	})))
}
/// Get the tangent of a number
pub fn tan(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().tan()
	} else {
		f64::NAN
	})))
}
/// Create a new 'Math' object
pub fn _create() -> Value {
	let mut math = TreeMap::new();
	math.insert(~"E", Gc::new(VNumber(f64::consts::E)));
	math.insert(~"LN2", Gc::new(VNumber(f64::consts::LN_2)));
	math.insert(~"LN10", Gc::new(VNumber(f64::consts::LN_10)));
	math.insert(~"LOG2E", Gc::new(VNumber(f64::consts::LOG2_E)));
	math.insert(~"LOG10E", Gc::new(VNumber(f64::consts::LOG10_E)));
	math.insert(~"SQRT1_2", Gc::new(VNumber(0.5f64.sqrt())));
	math.insert(~"SQRT2", Gc::new(VNumber(f64::consts::SQRT2)));
	math.insert(~"PI", Gc::new(VNumber(f64::consts::PI)));
	math.insert(~"abs", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(abs, 1))))));
	math.insert(~"acos", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(acos, 1))))));
	math.insert(~"asin", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(asin, 1))))));
	math.insert(~"atan", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(atan, 1))))));
	math.insert(~"atan2", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(atan2, 2))))));
	math.insert(~"cbrt", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(cbrt, 1))))));
	math.insert(~"ceil", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(ceil, 1))))));
	math.insert(~"cos", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(cos, 1))))));
	math.insert(~"floor", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(floor, 1))))));
	math.insert(~"sin", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(sin, 1))))));
	math.insert(~"tan", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(tan, 1))))));
	Gc::new(VObject(RefCell::new(math)))
}<commit_msg>Add Math.random() using rand::random() as backend<commit_after>use js::value::{Value, VNumber, VInteger, VFunction, VObject, ResultValue};
use js::function::{NativeFunction, NativeFunc};
use js::object::ObjectData;
use collections::treemap::TreeMap;
use rand::random;
use std::io::stdio;
use std::f64;
use std::gc::Gc;
use std::cell::RefCell;

/// Get the absolute value of a number
pub fn abs(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().abs()
	} else {
		f64::NAN
	})))
}
/// Get the arccos of a number
pub fn acos(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().acos()
	} else {
		f64::NAN
	})))
}
/// Get the arcsine of a number
pub fn asin(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().asin()
	} else {
		f64::NAN
	})))
}
/// Get the arctangent of a number
pub fn atan(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().atan()
	} else {
		f64::NAN
	})))
}
/// Get the arctangent of a numbers
pub fn atan2(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().atan2(&args.get(1).borrow().to_num())
	} else {
		f64::NAN
	})))
}
/// Get the cubic root of a number
pub fn cbrt(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().cbrt()
	} else {
		f64::NAN
	})))
}
/// Get lowest integer above a number
pub fn ceil(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().ceil()
	} else {
		f64::NAN
	})))
}
/// Get the cosine of a number
pub fn cos(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().cos()
	} else {
		f64::NAN
	})))
}
/// Get the highest integer below a number
pub fn floor(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().floor()
	} else {
		f64::NAN
	})))
}
/// Generate a random floating-point number between 0 and 1
pub fn _random(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(random())))
}
/// Get the sine of a number
pub fn sin(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().sin()
	} else {
		f64::NAN
	})))
}
/// Get the tangent of a number
pub fn tan(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().tan()
	} else {
		f64::NAN
	})))
}
/// Create a new 'Math' object
pub fn _create() -> Value {
	let mut math = TreeMap::new();
	math.insert(~"E", Gc::new(VNumber(f64::consts::E)));
	math.insert(~"LN2", Gc::new(VNumber(f64::consts::LN_2)));
	math.insert(~"LN10", Gc::new(VNumber(f64::consts::LN_10)));
	math.insert(~"LOG2E", Gc::new(VNumber(f64::consts::LOG2_E)));
	math.insert(~"LOG10E", Gc::new(VNumber(f64::consts::LOG10_E)));
	math.insert(~"SQRT1_2", Gc::new(VNumber(0.5f64.sqrt())));
	math.insert(~"SQRT2", Gc::new(VNumber(f64::consts::SQRT2)));
	math.insert(~"PI", Gc::new(VNumber(f64::consts::PI)));
	math.insert(~"abs", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(abs, 1))))));
	math.insert(~"acos", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(acos, 1))))));
	math.insert(~"asin", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(asin, 1))))));
	math.insert(~"atan", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(atan, 1))))));
	math.insert(~"atan2", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(atan2, 2))))));
	math.insert(~"cbrt", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(cbrt, 1))))));
	math.insert(~"ceil", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(ceil, 1))))));
	math.insert(~"cos", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(cos, 1))))));
	math.insert(~"floor", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(floor, 1))))));
	math.insert(~"random", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(_random, 0))))));
	math.insert(~"sin", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(sin, 1))))));
	math.insert(~"tan", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(tan, 1))))));
	Gc::new(VObject(RefCell::new(math)))
}<|endoftext|>


<commit_before>use rustc::hir::map::blocks::FnLikeNode;
use rustc::ty::query::Providers;
use rustc::ty::TyCtxt;
use rustc_attr as attr;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_span::symbol::Symbol;
use rustc_target::spec::abi::Abi;

/// Whether the `def_id` counts as const fn in your current crate, considering all active
/// feature gates
pub fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
    tcx.is_const_fn_raw(def_id)
        && match is_unstable_const_fn(tcx, def_id) {
            Some(feature_name) => {
                // has a `rustc_const_unstable` attribute, check whether the user enabled the
                // corresponding feature gate.
                tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == feature_name)
            }
            // functions without const stability are either stable user written
            // const fn or the user is using feature gates and we thus don't
            // care what they do
            None => true,
        }
}

/// Whether the `def_id` is an unstable const fn and what feature gate is necessary to enable it
pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Symbol> {
    // FIXME: check for `rustc_const_unstable` on the containing impl. This should be done by
    // propagating it down so it is return by the `lookup_const_stability` query.
    if tcx.is_const_fn_raw(def_id) {
        let const_stab = tcx.lookup_const_stability(def_id)?;
        if const_stab.level.is_unstable() { Some(const_stab.feature) } else { None }
    } else {
        None
    }
}

/// Returns `true` if this function must conform to `min_const_fn`
pub fn is_min_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
    // Bail out if the signature doesn't contain `const`
    if !tcx.is_const_fn_raw(def_id) {
        return false;
    }

    if tcx.features().staged_api {
        // In order for a libstd function to be considered min_const_fn
        // it needs to be stable and have no `rustc_const_unstable` attribute.
        match tcx.lookup_const_stability(def_id) {
            // `rustc_const_unstable` functions don't need to conform.
            Some(&attr::ConstStability { ref level, .. }) if level.is_unstable() => false,
            None => {
                if let Some(stab) = tcx.lookup_stability(def_id) {
                    if stab.level.is_stable() {
                        tcx.sess.span_err(
                            tcx.def_span(def_id),
                            "stable const functions must have either `rustc_const_stable` or \
                             `rustc_const_unstable` attribute",
                        );
                        // While we errored above, because we don't know if we need to conform, we
                        // err on the "safe" side and require min_const_fn.
                        true
                    } else {
                        // Unstable functions need not conform to min_const_fn.
                        false
                    }
                } else {
                    // Internal functions are forced to conform to min_const_fn.
                    // Annotate the internal function with a const stability attribute if
                    // you need to use unstable features.
                    // Note: this is an arbitrary choice that does not affect stability or const
                    // safety or anything, it just changes whether we need to annotate some
                    // internal functions with `rustc_const_stable` or with `rustc_const_unstable`
                    true
                }
            }
            // Everything else needs to conform, because it would be callable from
            // other `min_const_fn` functions.
            _ => true,
        }
    } else {
        // users enabling the `const_fn` feature gate can do what they want
        !tcx.features().const_fn
    }
}

pub fn provide(providers: &mut Providers<'_>) {
    /// Const evaluability whitelist is here to check evaluability at the
    /// top level beforehand.
    fn is_const_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> Option<bool> {
        if tcx.is_closure(def_id) {
            return None;
        }

        match tcx.fn_sig(def_id).abi() {
            Abi::RustIntrinsic | Abi::PlatformIntrinsic => {
                Some(tcx.lookup_const_stability(def_id).is_some())
            }
            _ => None,
        }
    }

    /// Checks whether the function has a `const` modifier or, in case it is an intrinsic, whether
    /// said intrinsic is on the whitelist for being const callable.
    fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
        let hir_id = tcx
            .hir()
            .as_local_hir_id(def_id)
            .expect("Non-local call to local provider is_const_fn");

        let node = tcx.hir().get(hir_id);

        if let Some(whitelisted) = is_const_intrinsic(tcx, def_id) {
            whitelisted
        } else if let Some(fn_like) = FnLikeNode::from_node(node) {
            if fn_like.constness() == hir::Constness::Const {
                return true;
            }

            // If the function itself is not annotated with `const`, it may still be a `const fn`
            // if it resides in a const trait impl.
            let parent_id = tcx.hir().get_parent_did(hir_id);
            if def_id != parent_id && !parent_id.is_top_level_module() {
                is_const_impl_raw(tcx, LocalDefId::from_def_id(parent_id))
            } else {
                false
            }
        } else if let hir::Node::Ctor(_) = node {
            true
        } else {
            false
        }
    }

    /// Checks whether the given item is an `impl` that has a `const` modifier.
    fn is_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
        let node = tcx.hir().get(hir_id);
        matches!(
            node,
            hir::Node::Item(hir::Item {
                kind: hir::ItemKind::Impl { constness: hir::Constness::Const, .. },
                ..
            })
        )
    }

    fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
        is_const_fn(tcx, def_id)
            && match tcx.lookup_const_stability(def_id) {
                Some(stab) => {
                    if cfg!(debug_assertions) && stab.promotable {
                        let sig = tcx.fn_sig(def_id);
                        assert_eq!(
                            sig.unsafety(),
                            hir::Unsafety::Normal,
                            "don't mark const unsafe fns as promotable",
                            // https://github.com/rust-lang/rust/pull/53851#issuecomment-418760682
                        );
                    }
                    stab.promotable
                }
                None => false,
            }
    }

    fn const_fn_is_allowed_fn_ptr(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
        is_const_fn(tcx, def_id)
            && tcx
                .lookup_const_stability(def_id)
                .map(|stab| stab.allow_const_fn_ptr)
                .unwrap_or(false)
    }

    *providers = Providers {
        is_const_fn_raw,
        is_const_impl_raw: |tcx, def_id| is_const_impl_raw(tcx, LocalDefId::from_def_id(def_id)),
        is_promotable_const_fn,
        const_fn_is_allowed_fn_ptr,
        ..*providers
    };
}
<commit_msg>Remove outdated FIXME<commit_after>use rustc::hir::map::blocks::FnLikeNode;
use rustc::ty::query::Providers;
use rustc::ty::TyCtxt;
use rustc_attr as attr;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_span::symbol::Symbol;
use rustc_target::spec::abi::Abi;

/// Whether the `def_id` counts as const fn in your current crate, considering all active
/// feature gates
pub fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
    tcx.is_const_fn_raw(def_id)
        && match is_unstable_const_fn(tcx, def_id) {
            Some(feature_name) => {
                // has a `rustc_const_unstable` attribute, check whether the user enabled the
                // corresponding feature gate.
                tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == feature_name)
            }
            // functions without const stability are either stable user written
            // const fn or the user is using feature gates and we thus don't
            // care what they do
            None => true,
        }
}

/// Whether the `def_id` is an unstable const fn and what feature gate is necessary to enable it
pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Symbol> {
    if tcx.is_const_fn_raw(def_id) {
        let const_stab = tcx.lookup_const_stability(def_id)?;
        if const_stab.level.is_unstable() { Some(const_stab.feature) } else { None }
    } else {
        None
    }
}

/// Returns `true` if this function must conform to `min_const_fn`
pub fn is_min_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
    // Bail out if the signature doesn't contain `const`
    if !tcx.is_const_fn_raw(def_id) {
        return false;
    }

    if tcx.features().staged_api {
        // In order for a libstd function to be considered min_const_fn
        // it needs to be stable and have no `rustc_const_unstable` attribute.
        match tcx.lookup_const_stability(def_id) {
            // `rustc_const_unstable` functions don't need to conform.
            Some(&attr::ConstStability { ref level, .. }) if level.is_unstable() => false,
            None => {
                if let Some(stab) = tcx.lookup_stability(def_id) {
                    if stab.level.is_stable() {
                        tcx.sess.span_err(
                            tcx.def_span(def_id),
                            "stable const functions must have either `rustc_const_stable` or \
                             `rustc_const_unstable` attribute",
                        );
                        // While we errored above, because we don't know if we need to conform, we
                        // err on the "safe" side and require min_const_fn.
                        true
                    } else {
                        // Unstable functions need not conform to min_const_fn.
                        false
                    }
                } else {
                    // Internal functions are forced to conform to min_const_fn.
                    // Annotate the internal function with a const stability attribute if
                    // you need to use unstable features.
                    // Note: this is an arbitrary choice that does not affect stability or const
                    // safety or anything, it just changes whether we need to annotate some
                    // internal functions with `rustc_const_stable` or with `rustc_const_unstable`
                    true
                }
            }
            // Everything else needs to conform, because it would be callable from
            // other `min_const_fn` functions.
            _ => true,
        }
    } else {
        // users enabling the `const_fn` feature gate can do what they want
        !tcx.features().const_fn
    }
}

pub fn provide(providers: &mut Providers<'_>) {
    /// Const evaluability whitelist is here to check evaluability at the
    /// top level beforehand.
    fn is_const_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> Option<bool> {
        if tcx.is_closure(def_id) {
            return None;
        }

        match tcx.fn_sig(def_id).abi() {
            Abi::RustIntrinsic | Abi::PlatformIntrinsic => {
                Some(tcx.lookup_const_stability(def_id).is_some())
            }
            _ => None,
        }
    }

    /// Checks whether the function has a `const` modifier or, in case it is an intrinsic, whether
    /// said intrinsic is on the whitelist for being const callable.
    fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
        let hir_id = tcx
            .hir()
            .as_local_hir_id(def_id)
            .expect("Non-local call to local provider is_const_fn");

        let node = tcx.hir().get(hir_id);

        if let Some(whitelisted) = is_const_intrinsic(tcx, def_id) {
            whitelisted
        } else if let Some(fn_like) = FnLikeNode::from_node(node) {
            if fn_like.constness() == hir::Constness::Const {
                return true;
            }

            // If the function itself is not annotated with `const`, it may still be a `const fn`
            // if it resides in a const trait impl.
            let parent_id = tcx.hir().get_parent_did(hir_id);
            if def_id != parent_id && !parent_id.is_top_level_module() {
                is_const_impl_raw(tcx, LocalDefId::from_def_id(parent_id))
            } else {
                false
            }
        } else if let hir::Node::Ctor(_) = node {
            true
        } else {
            false
        }
    }

    /// Checks whether the given item is an `impl` that has a `const` modifier.
    fn is_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
        let node = tcx.hir().get(hir_id);
        matches!(
            node,
            hir::Node::Item(hir::Item {
                kind: hir::ItemKind::Impl { constness: hir::Constness::Const, .. },
                ..
            })
        )
    }

    fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
        is_const_fn(tcx, def_id)
            && match tcx.lookup_const_stability(def_id) {
                Some(stab) => {
                    if cfg!(debug_assertions) && stab.promotable {
                        let sig = tcx.fn_sig(def_id);
                        assert_eq!(
                            sig.unsafety(),
                            hir::Unsafety::Normal,
                            "don't mark const unsafe fns as promotable",
                            // https://github.com/rust-lang/rust/pull/53851#issuecomment-418760682
                        );
                    }
                    stab.promotable
                }
                None => false,
            }
    }

    fn const_fn_is_allowed_fn_ptr(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
        is_const_fn(tcx, def_id)
            && tcx
                .lookup_const_stability(def_id)
                .map(|stab| stab.allow_const_fn_ptr)
                .unwrap_or(false)
    }

    *providers = Providers {
        is_const_fn_raw,
        is_const_impl_raw: |tcx, def_id| is_const_impl_raw(tcx, LocalDefId::from_def_id(def_id)),
        is_promotable_const_fn,
        const_fn_is_allowed_fn_ptr,
        ..*providers
    };
}
<|endoftext|>


<commit_before>use devices::DevicesDisplayInfo;
use devices::{Devices, JoystickState};
use event::RawEvent;
use std::sync::mpsc::TryRecvError;
use rawinput::{get_event, get_joystick_state};
use registrar;
use std::time::{SystemTime, UNIX_EPOCH};
use winapi::shared::minwindef::UINT;
use winapi::shared::windef::HWND;
use winapi::um::libloaderapi::GetModuleHandleW;
use winapi::um::winuser::{
    CreateWindowExW, DefWindowProcW, RegisterClassExW, CW_USEDEFAULT, HWND_MESSAGE, WNDCLASSEXW,
};

use std::collections::VecDeque;
use std::ffi::OsStr;
use std::mem;
use std::os::windows::ffi::OsStrExt;
use std::ptr;
use std::thread;
use std::thread::JoinHandle;

use std::sync::mpsc::{channel, Receiver, Sender};

enum Command {
    Register(DeviceType),
    GetEvent,
    GetJoystickState(usize),
    Finish,
    PrintDeviceList,
    GetDeviceList,
    GetDeviceStats,
}

/// Types of Raw Input Device
#[derive(PartialEq, Eq, Clone)]
pub enum DeviceType {
    Mice,
    Keyboards,
    Joysticks(XInputInclude),
}

/// Denotes if Xbox360 controllers should be used
/// Please Note: Rawinput support for official Xbox360 controllers
/// is very limited (triggers share same axis, no support for
/// rumble or the central X button)
/// Please see https://en.wikipedia.org/wiki/DirectInput#Xbox_360_Controller_support
/// for more details
#[derive(PartialEq, Eq, Clone)]
pub enum XInputInclude {
    True,
    False,
}

#[derive(Default)]
pub struct DeviceStats {
    pub number_of_mice: usize,
    pub number_of_keyboards: usize,
    pub number_of_joysticks: usize,
}

/// Manages Raw Input Processing
pub struct RawInputManager {
    joiner: Option<JoinHandle<()>>,
    sender: Sender<Command>,
    receiver: Receiver<Option<RawEvent>>,
    joystick_receiver: Receiver<Option<JoystickState>>,
    device_info_receiver: Receiver<DevicesDisplayInfo>,
    device_stats_receiver: Receiver<DeviceStats>,
}

impl RawInputManager {
    pub fn new() -> Result<RawInputManager, &'static str> {
        let (tx, rx) = channel();
        let (tx2, rx2) = channel();
        let (tx_joy, rx_joy) = channel();
        let (tx_devices, rx_devices) = channel();
        let (tx_stats, rx_stats) = channel();

        let joiner = thread::spawn(move || {
            let hwnd = setup_message_window();
            let mut event_queue = VecDeque::new();
            let mut devices = Devices::new();
            let mut exit = false;
            let mut registrar = registrar::RawInputRegistrar::new();
            while !exit {
                match rx.try_recv() {
                    Err(TryRecvError::Disconnected) => {
                        panic!("Multinput Thread Unexpectedly Disconnected!")
                    },
                    Err(TryRecvError::Empty) => {
                        std::thread::sleep(std::time::Duration::from_nanos(1));
                    },
                    Ok(Command::Register(thing)) => {
                        devices = registrar.register_devices(hwnd, thing).unwrap();
                        tx2.send(None).unwrap();
                    }
                    Ok(Command::GetEvent) => {
                        tx2.send(get_event(&mut event_queue, &mut devices)).unwrap()
                    }
                    Ok(Command::Finish) => {
                        exit = true;
                    }
                    Ok(Command::GetJoystickState(id)) => {
                        tx_joy.send(get_joystick_state(&devices, id)).unwrap()
                    }
                    Ok(Command::PrintDeviceList) => print_raw_device_list(&devices),
                    Ok(Command::GetDeviceList) => tx_devices.send(devices.clone().into()).unwrap(),
                    Ok(Command::GetDeviceStats) => tx_stats.send(get_device_stats(&devices)).unwrap(),
                };
            }
        });
        Ok(RawInputManager {
            joiner: Some(joiner),
            sender: tx,
            receiver: rx2,
            joystick_receiver: rx_joy,
            device_stats_receiver: rx_stats,
            device_info_receiver: rx_devices
        })
    }

    /// Allows Raw Input devices of type device_type to be received from the Input Manager
    pub fn register_devices(&mut self, device_type: DeviceType) {
        self.sender.send(Command::Register(device_type)).unwrap();
        self.receiver.recv().unwrap();
    }

    /// Get Event from the Input Manager
    pub fn get_event(&mut self) -> Option<RawEvent> {
        self.sender.send(Command::GetEvent).unwrap();
        match self.receiver.try_recv() {
            Ok(event) => event,
            _ => None
        }
    }

    /// Get Joystick State from the Input Manager
    pub fn get_joystick_state(&mut self, id: usize) -> Option<JoystickState> {
        self.sender.send(Command::GetJoystickState(id)).unwrap();
        self.joystick_receiver.recv().unwrap()
    }

    /// Print List of Potential Input Devices
    pub fn print_device_list(&self) {
        self.sender.send(Command::PrintDeviceList).unwrap();
    }

    /// Get Device Stats (number of connected devices)
    pub fn get_device_stats(&self) -> DeviceStats {
        self.sender.send(Command::GetDeviceStats).unwrap();
        self.device_stats_receiver.recv().unwrap()
    }

    /// Get Device list
    pub fn get_device_list(&self) -> DevicesDisplayInfo {
            self.sender.send(Command::GetDeviceList).unwrap();
            self.device_info_receiver.recv().unwrap()
    }
}

impl Drop for RawInputManager {
    fn drop(&mut self) {
        self.sender.send(Command::Finish).unwrap();
        self.joiner.take().unwrap().join().unwrap();
    }
}

fn setup_message_window() -> HWND {
    let hwnd: HWND;
    unsafe {
        let hinstance = GetModuleHandleW(ptr::null());
        if hinstance == ptr::null_mut() {
            panic!("Instance Generation Failed");
        }

        let current_time = SystemTime::now();
        let classname_str = format!(
            "RawInput Hidden Window - {:?}",
            current_time.duration_since(UNIX_EPOCH).unwrap()
        );

        let classname = OsStr::new(&classname_str)
            .encode_wide()
            .chain(Some(0).into_iter())
            .collect::<Vec<_>>();

        let wcex = WNDCLASSEXW {
            cbSize: (mem::size_of::<WNDCLASSEXW>()) as UINT,
            cbClsExtra: 0,
            cbWndExtra: 0,
            hbrBackground: ptr::null_mut(),
            hCursor: ptr::null_mut(),
            hIcon: ptr::null_mut(),
            hIconSm: ptr::null_mut(),
            hInstance: hinstance,
            lpfnWndProc: Some(DefWindowProcW),
            lpszClassName: classname.as_ptr(),
            lpszMenuName: ptr::null_mut(),
            style: 0,
        };
        let a = RegisterClassExW(&wcex);
        if a == 0 {
            panic!("Registering WindowClass Failed!");
        }

        hwnd = CreateWindowExW(
            0,
            classname.as_ptr(),
            classname.as_ptr(),
            0,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            HWND_MESSAGE,
            ptr::null_mut(),
            hinstance,
            ptr::null_mut(),
        );
        if hwnd.is_null() {
            panic!("Window Creation Failed!");
        }
    }
    hwnd
}

/// Prints a list of all available raw input devices
fn print_raw_device_list(devices: &Devices) {
    println!("Mice:");
    for mouse in &devices.mice {
        println!("{:?}", mouse);
    }
    println!("Keyboards:");
    for keyboard in &devices.keyboards {
        println!("{:?}", keyboard);
    }
    println!("Hids:");
    for joystick in &devices.joysticks {
        println!("{:?}", joystick);
    }
}

fn get_device_stats(devices: &Devices) -> DeviceStats {
    DeviceStats {
        number_of_mice: devices.mice.len(),
        number_of_keyboards: devices.keyboards.len(),
        number_of_joysticks: devices.joysticks.len(),
    }
}
<commit_msg>Add get_events() method<commit_after>use std::sync::mpsc::TryIter;
use devices::DevicesDisplayInfo;
use devices::{Devices, JoystickState};
use event::RawEvent;
use std::sync::mpsc::TryRecvError;
use rawinput::{get_event, get_joystick_state};
use registrar;
use std::time::{SystemTime, UNIX_EPOCH};
use winapi::shared::minwindef::UINT;
use winapi::shared::windef::HWND;
use winapi::um::libloaderapi::GetModuleHandleW;
use winapi::um::winuser::{
    CreateWindowExW, DefWindowProcW, RegisterClassExW, CW_USEDEFAULT, HWND_MESSAGE, WNDCLASSEXW,
};

use std::collections::VecDeque;
use std::ffi::OsStr;
use std::mem;
use std::os::windows::ffi::OsStrExt;
use std::ptr;
use std::thread;
use std::thread::JoinHandle;

use std::sync::mpsc::{channel, Receiver, Sender};

enum Command {
    Register(DeviceType),
    GetEvent,
    GetJoystickState(usize),
    Finish,
    PrintDeviceList,
    GetDeviceList,
    GetDeviceStats,
}

/// Types of Raw Input Device
#[derive(PartialEq, Eq, Clone)]
pub enum DeviceType {
    Mice,
    Keyboards,
    Joysticks(XInputInclude),
}

/// Denotes if Xbox360 controllers should be used
/// Please Note: Rawinput support for official Xbox360 controllers
/// is very limited (triggers share same axis, no support for
/// rumble or the central X button)
/// Please see https://en.wikipedia.org/wiki/DirectInput#Xbox_360_Controller_support
/// for more details
#[derive(PartialEq, Eq, Clone)]
pub enum XInputInclude {
    True,
    False,
}

#[derive(Default)]
pub struct DeviceStats {
    pub number_of_mice: usize,
    pub number_of_keyboards: usize,
    pub number_of_joysticks: usize,
}

/// Manages Raw Input Processing
pub struct RawInputManager {
    joiner: Option<JoinHandle<()>>,
    sender: Sender<Command>,
    receiver: Receiver<RawEvent>,
    joystick_receiver: Receiver<Option<JoystickState>>,
    device_info_receiver: Receiver<DevicesDisplayInfo>,
    device_stats_receiver: Receiver<DeviceStats>,
}

impl RawInputManager {
    pub fn new() -> Result<RawInputManager, &'static str> {
        let (tx, rx) = channel();
        let (tx2, rx2) = channel();
        let (tx_joy, rx_joy) = channel();
        let (tx_devices, rx_devices) = channel();
        let (tx_stats, rx_stats) = channel();

        let joiner = thread::spawn(move || {
            let hwnd = setup_message_window();
            let mut event_queue = VecDeque::new();
            let mut devices = Devices::new();
            let mut exit = false;
            let mut registrar = registrar::RawInputRegistrar::new();
            while !exit {
                match rx.try_recv() {
                    Err(TryRecvError::Disconnected) => {
                        panic!("Multinput Thread Unexpectedly Disconnected!")
                    },
                    Err(TryRecvError::Empty) => {
                        std::thread::sleep(std::time::Duration::from_nanos(1));
                    },
                    Ok(Command::Register(thing)) => {
                        devices = registrar.register_devices(hwnd, thing).unwrap();
                    }
                    Ok(Command::GetEvent) => {
                        if let Some(event) = get_event(&mut event_queue, &mut devices) {
                            tx2.send(event).unwrap()
                        }
                    }
                    Ok(Command::Finish) => {
                        exit = true;
                    }
                    Ok(Command::GetJoystickState(id)) => {
                        tx_joy.send(get_joystick_state(&devices, id)).unwrap()
                    }
                    Ok(Command::PrintDeviceList) => print_raw_device_list(&devices),
                    Ok(Command::GetDeviceList) => tx_devices.send(devices.clone().into()).unwrap(),
                    Ok(Command::GetDeviceStats) => tx_stats.send(get_device_stats(&devices)).unwrap(),
                };
            }
        });
        Ok(RawInputManager {
            joiner: Some(joiner),
            sender: tx,
            receiver: rx2,
            joystick_receiver: rx_joy,
            device_stats_receiver: rx_stats,
            device_info_receiver: rx_devices
        })
    }

    /// Allows Raw Input devices of type device_type to be received from the Input Manager
    pub fn register_devices(&mut self, device_type: DeviceType) {
        self.sender.send(Command::Register(device_type)).unwrap();
    }

    /// Get Event from the Input Manager
    pub fn get_event(&mut self) -> Option<RawEvent> {
        self.sender.send(Command::GetEvent).unwrap();
        match self.receiver.try_recv() {
            Ok(event) => Some(event),
            _ => None
        }
    }

    /// Get All Events from the Input Manager
    pub fn get_events(&mut self) -> TryIter<RawEvent> {
        self.sender.send(Command::GetEvent).unwrap();
        self.receiver.try_iter()
    }

    /// Get Joystick State from the Input Manager
    pub fn get_joystick_state(&mut self, id: usize) -> Option<JoystickState> {
        self.sender.send(Command::GetJoystickState(id)).unwrap();
        self.joystick_receiver.recv().unwrap()
    }

    /// Print List of Potential Input Devices
    pub fn print_device_list(&self) {
        self.sender.send(Command::PrintDeviceList).unwrap();
    }

    /// Get Device Stats (number of connected devices)
    pub fn get_device_stats(&self) -> DeviceStats {
        self.sender.send(Command::GetDeviceStats).unwrap();
        self.device_stats_receiver.recv().unwrap()
    }

    /// Get Device list
    pub fn get_device_list(&self) -> DevicesDisplayInfo {
            self.sender.send(Command::GetDeviceList).unwrap();
            self.device_info_receiver.recv().unwrap()
    }
}

impl Drop for RawInputManager {
    fn drop(&mut self) {
        self.sender.send(Command::Finish).unwrap();
        self.joiner.take().unwrap().join().unwrap();
    }
}

fn setup_message_window() -> HWND {
    let hwnd: HWND;
    unsafe {
        let hinstance = GetModuleHandleW(ptr::null());
        if hinstance == ptr::null_mut() {
            panic!("Instance Generation Failed");
        }

        let current_time = SystemTime::now();
        let classname_str = format!(
            "RawInput Hidden Window - {:?}",
            current_time.duration_since(UNIX_EPOCH).unwrap()
        );

        let classname = OsStr::new(&classname_str)
            .encode_wide()
            .chain(Some(0).into_iter())
            .collect::<Vec<_>>();

        let wcex = WNDCLASSEXW {
            cbSize: (mem::size_of::<WNDCLASSEXW>()) as UINT,
            cbClsExtra: 0,
            cbWndExtra: 0,
            hbrBackground: ptr::null_mut(),
            hCursor: ptr::null_mut(),
            hIcon: ptr::null_mut(),
            hIconSm: ptr::null_mut(),
            hInstance: hinstance,
            lpfnWndProc: Some(DefWindowProcW),
            lpszClassName: classname.as_ptr(),
            lpszMenuName: ptr::null_mut(),
            style: 0,
        };
        let a = RegisterClassExW(&wcex);
        if a == 0 {
            panic!("Registering WindowClass Failed!");
        }

        hwnd = CreateWindowExW(
            0,
            classname.as_ptr(),
            classname.as_ptr(),
            0,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            HWND_MESSAGE,
            ptr::null_mut(),
            hinstance,
            ptr::null_mut(),
        );
        if hwnd.is_null() {
            panic!("Window Creation Failed!");
        }
    }
    hwnd
}

/// Prints a list of all available raw input devices
fn print_raw_device_list(devices: &Devices) {
    println!("Mice:");
    for mouse in &devices.mice {
        println!("{:?}", mouse);
    }
    println!("Keyboards:");
    for keyboard in &devices.keyboards {
        println!("{:?}", keyboard);
    }
    println!("Hids:");
    for joystick in &devices.joysticks {
        println!("{:?}", joystick);
    }
}

fn get_device_stats(devices: &Devices) -> DeviceStats {
    DeviceStats {
        number_of_mice: devices.mice.len(),
        number_of_keyboards: devices.keyboards.len(),
        number_of_joysticks: devices.joysticks.len(),
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::convert::{From, Into};
use std::str::from_utf8;
use std::result::Result as StdResult;

use protocol::OpCode;
use result::Result;

use self::Message::*;

/// An enum representing the various forms of a WebSocket message.
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum Message {
    /// A text WebSocket message
    Text(String),
    /// A binary WebSocket message
    Binary(Vec<u8>),
}

impl Message {

    /// Create a new text WebSocket message from a stringable.
    pub fn text<S>(string: S) -> Message
        where S: Into<String>
    {
        Message::Text(string.into())
    }

    /// Create a new binary WebSocket message by converting to Vec<u8>.
    pub fn binary<B>(bin: B) -> Message
        where B: Into<Vec<u8>>
    {
        Message::Binary(bin.into())
    }

    /// Indicates whether a message is a text message.
    pub fn is_text(&self) -> bool {
        match *self {
            Text(_) => true,
            Binary(_) => false,
        }
    }

    /// Indicates whether a message is a binary message.
    pub fn is_binary(&self) -> bool {
        match *self {
            Text(_) => false,
            Binary(_) => true,
        }
    }

    /// Get the length of the WebSocket message.
    pub fn len(&self) -> usize {
        match *self {
            Text(ref string) => string.len(),
            Binary(ref data) => data.len(),
        }
    }

    /// Returns true if the WebSocket message has no content.
    /// For example, if the other side of the connection sent an empty string.
    pub fn is_empty(&self) -> bool {
        match *self {
            Text(ref string) => string.is_empty(),
            Binary(ref data) => data.is_empty(),
        }
    }

    #[doc(hidden)]
    pub fn opcode(&self) -> OpCode {
        match *self {
            Text(_) => OpCode::Text,
            Binary(_) => OpCode::Binary,
        }
    }

    /// Consume the WebSocket and return it as binary data.
    pub fn into_data(self) -> Vec<u8> {
        match self {
            Text(string) => string.into_bytes(),
            Binary(data) => data,
        }
    }

    /// Attempt to consume the WebSocket message and convert it to a String.
    pub fn into_text(self) -> Result<String> {
        match self {
            Text(string) => Ok(string),
            Binary(data) => Ok(try!(
                String::from_utf8(data).map_err(|err| err.utf8_error()))),
        }
    }

    /// Attempt to get a &str from the WebSocket message,
    /// this will try to convert binary data to utf8.
    pub fn as_text(&self) -> Result<&str> {
        match *self {
            Text(ref string) => Ok(string),
            Binary(ref data) => Ok(try!(from_utf8(data))),
        }
    }
}

impl From<String> for Message {

    fn from(string: String) -> Message {
        Message::text(string)
    }
}

impl<'s> From<&'s str> for Message {

    fn from(string: &'s str) -> Message {
        Message::text(string)
    }
}

impl<'b> From<&'b [u8]> for Message {

    fn from(data: &'b [u8]) -> Message {
        Message::binary(data)
    }
}

impl fmt::Display for Message {
    fn fmt(&self, f: &mut fmt::Formatter) -> StdResult<(), fmt::Error> {
        if let Ok(string) = self.as_text() {
            write!(f, "{}", string)
        } else {
            write!(f, "Binary Data<length={}>", self.len())
        }
    }
}

mod test {
    #![allow(unused_imports, unused_variables, dead_code)]
    use super::*;

    #[test]
    fn display() {
        let t = Message::text(format!("test"));
        assert_eq!(t.to_string(), "test".to_owned());

        let bin = Message::binary(vec![0, 1, 3, 4, 241]);
        assert_eq!(bin.to_string(), "Binary Data<length=5>".to_owned());
    }

    #[test]
    fn binary_convert() {
        let bin = [6u8, 7, 8, 9, 10, 241];
        let msg = Message::from(&bin[..]);
        assert!(msg.is_binary());
        assert!(msg.into_text().is_err());
    }

    #[test]
    fn text_convert() {
        let s = "kiwotsukete";
        let msg = Message::from(s);
        assert!(msg.is_text());
    }
}
<commit_msg>impl From<Vec<u8>> for Message<commit_after>use std::fmt;
use std::convert::{From, Into};
use std::str::from_utf8;
use std::result::Result as StdResult;

use protocol::OpCode;
use result::Result;

use self::Message::*;

/// An enum representing the various forms of a WebSocket message.
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum Message {
    /// A text WebSocket message
    Text(String),
    /// A binary WebSocket message
    Binary(Vec<u8>),
}

impl Message {

    /// Create a new text WebSocket message from a stringable.
    pub fn text<S>(string: S) -> Message
        where S: Into<String>
    {
        Message::Text(string.into())
    }

    /// Create a new binary WebSocket message by converting to Vec<u8>.
    pub fn binary<B>(bin: B) -> Message
        where B: Into<Vec<u8>>
    {
        Message::Binary(bin.into())
    }

    /// Indicates whether a message is a text message.
    pub fn is_text(&self) -> bool {
        match *self {
            Text(_) => true,
            Binary(_) => false,
        }
    }

    /// Indicates whether a message is a binary message.
    pub fn is_binary(&self) -> bool {
        match *self {
            Text(_) => false,
            Binary(_) => true,
        }
    }

    /// Get the length of the WebSocket message.
    pub fn len(&self) -> usize {
        match *self {
            Text(ref string) => string.len(),
            Binary(ref data) => data.len(),
        }
    }

    /// Returns true if the WebSocket message has no content.
    /// For example, if the other side of the connection sent an empty string.
    pub fn is_empty(&self) -> bool {
        match *self {
            Text(ref string) => string.is_empty(),
            Binary(ref data) => data.is_empty(),
        }
    }

    #[doc(hidden)]
    pub fn opcode(&self) -> OpCode {
        match *self {
            Text(_) => OpCode::Text,
            Binary(_) => OpCode::Binary,
        }
    }

    /// Consume the WebSocket and return it as binary data.
    pub fn into_data(self) -> Vec<u8> {
        match self {
            Text(string) => string.into_bytes(),
            Binary(data) => data,
        }
    }

    /// Attempt to consume the WebSocket message and convert it to a String.
    pub fn into_text(self) -> Result<String> {
        match self {
            Text(string) => Ok(string),
            Binary(data) => Ok(try!(
                String::from_utf8(data).map_err(|err| err.utf8_error()))),
        }
    }

    /// Attempt to get a &str from the WebSocket message,
    /// this will try to convert binary data to utf8.
    pub fn as_text(&self) -> Result<&str> {
        match *self {
            Text(ref string) => Ok(string),
            Binary(ref data) => Ok(try!(from_utf8(data))),
        }
    }
}

impl From<String> for Message {

    fn from(string: String) -> Message {
        Message::text(string)
    }
}

impl<'s> From<&'s str> for Message {

    fn from(string: &'s str) -> Message {
        Message::text(string)
    }
}

impl<'b> From<&'b [u8]> for Message {

    fn from(data: &'b [u8]) -> Message {
        Message::binary(data)
    }
}

impl From<Vec<u8>> for Message {

    fn from(data: Vec<u8>) -> Message {
        Message::binary(data)
    }
}

impl fmt::Display for Message {
    fn fmt(&self, f: &mut fmt::Formatter) -> StdResult<(), fmt::Error> {
        if let Ok(string) = self.as_text() {
            write!(f, "{}", string)
        } else {
            write!(f, "Binary Data<length={}>", self.len())
        }
    }
}

mod test {
    #![allow(unused_imports, unused_variables, dead_code)]
    use super::*;

    #[test]
    fn display() {
        let t = Message::text(format!("test"));
        assert_eq!(t.to_string(), "test".to_owned());

        let bin = Message::binary(vec![0, 1, 3, 4, 241]);
        assert_eq!(bin.to_string(), "Binary Data<length=5>".to_owned());
    }

    #[test]
    fn binary_convert() {
        let bin = [6u8, 7, 8, 9, 10, 241];
        let msg = Message::from(&bin);
        assert!(msg.is_binary());
        assert!(msg.into_text().is_err());
    }

    #[test]
    fn binary_convert_vec() {
        let bin = vec![6u8, 7, 8, 9, 10, 241];
        let msg = Message::from(bin);
        assert!(msg.is_binary());
        assert!(msg.into_text().is_err());
    }

    #[test]
    fn text_convert() {
        let s = "kiwotsukete";
        let msg = Message::from(s);
        assert!(msg.is_text());
    }
}
<|endoftext|>


<commit_before>use env::{MultiEnv, MultiEnvDiscrete};
use features::{MultiEnvObserve};

use stopwatch::{Stopwatch};

use rand::{Rng};
use std::cell::{Cell};
//use std::rc::{Rc};
//use std::sync::{Arc};
use std::sync::mpsc::{SyncSender, Receiver, RecvTimeoutError, sync_channel};
use std::thread::{JoinHandle, spawn};
use std::time::{Duration};

#[derive(Clone, Copy, Debug)]
pub enum MonitorAction {
  CtrlStop,
  StartEvent(MonitorEvent),
  EndEvent(MonitorEvent),
}

#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum MonitorEvent {
  Shutdown,
  Reset,
  Step,
  IsTerminal,
  GetNumPlayers,
  GetIsActivePlayer,
  GetIsLegalAction,
  Observe,
}

pub struct MonitorWorker {
  //stopwatch:    Stopwatch,
  rx:   Receiver<(u64, MonitorAction)>,
  active_event: Option<(u64, MonitorEvent)>,
}

impl MonitorWorker {
  pub fn runloop(&mut self) {
    loop {
      match self.rx.recv_timeout(Duration::from_millis(5000)) {
        Err(RecvTimeoutError::Timeout) => {
          if let Some((tick, event)) = self.active_event {
            panic!("PANIC: MonitorEnv: timed out during an event: {} {:?}",
                tick, event);
          }
        }
        Err(RecvTimeoutError::Disconnected) => {
          break;
        }
        Ok((tick, action)) => {
          match action {
            MonitorAction::CtrlStop => {
              break;
            }
            MonitorAction::StartEvent(event) => {
              assert!(self.active_event.is_none());
              self.active_event = Some((tick, event));
            }
            MonitorAction::EndEvent(event) => {
              assert!(self.active_event.is_some());
              assert_eq!(self.active_event.unwrap().0, tick);
              assert_eq!(self.active_event.unwrap().1, event);
              self.active_event = None;
            }
          }
        }
      }
    }
  }
}

pub struct MonitorEnv<E> {
  tick: Cell<u64>,
  tx:   SyncSender<(u64, MonitorAction)>,
  h:    Option<JoinHandle<()>>,
  env:  E,
}

impl<E> Drop for MonitorEnv<E> {
  fn drop(&mut self) {
    self.tick.set(self.tick.get() + 1);
    let t = self.tick.get();
    self.tx.send((t, MonitorAction::CtrlStop)).unwrap();
    self.h.take().unwrap().join().unwrap();
  }
}

impl<E> Default for MonitorEnv<E> where E: MultiEnv {
  fn default() -> Self {
    let (tx, rx) = sync_channel(1024);
    let h = spawn(move || {
      let mut worker = MonitorWorker{
        //stopwatch:  Stopwatch::new(),
        rx: rx,
        active_event:   None,
      };
      worker.runloop();
    });
    MonitorEnv{
      tick: Cell::new(0),
      tx:   tx,
      h:    Some(h),
      env:  E::default(),
    }
  }
}

impl<E> MultiEnv for MonitorEnv<E> where E: MultiEnv {
  type Restart = E::Restart;
  type Action = E::Action;
  type Response = E::Response;

  fn shutdown(&self) {
    self.env.shutdown();
  }

  fn reset<R>(&self, restart: &Self::Restart, rng: &mut R) where R: Rng + Sized {
    self.tick.set(self.tick.get() + 1);
    let t = self.tick.get();
    self.tx.send((t, MonitorAction::StartEvent(MonitorEvent::Reset))).unwrap();
    self.env.reset(restart, rng);
    self.tx.send((t, MonitorAction::EndEvent(MonitorEvent::Reset))).unwrap();
  }

  fn step(&self, multi_action: &[Option<Self::Action>]) -> Result<Vec<Option<Self::Response>>, ()> {
    self.tick.set(self.tick.get() + 1);
    let t = self.tick.get();
    self.tx.send((t, MonitorAction::StartEvent(MonitorEvent::Step))).unwrap();
    let res = self.env.step(multi_action);
    self.tx.send((t, MonitorAction::EndEvent(MonitorEvent::Step))).unwrap();
    res
  }

  fn is_terminal(&self) -> bool {
    self.tick.set(self.tick.get() + 1);
    let t = self.tick.get();
    self.tx.send((t, MonitorAction::StartEvent(MonitorEvent::IsTerminal))).unwrap();
    let res = self.env.is_terminal();
    self.tx.send((t, MonitorAction::EndEvent(MonitorEvent::IsTerminal))).unwrap();
    res
  }

  fn num_players(&self) -> usize {
    self.env.num_players()
  }

  fn is_active_player(&self, player_rank: usize) -> bool {
    self.env.is_active_player(player_rank)
  }

  fn is_legal_multi_action(&self, multi_action: &[Option<Self::Action>]) -> bool {
    self.env.is_legal_multi_action(multi_action)
  }
}

impl<E> MultiEnvDiscrete for MonitorEnv<E> where E: MultiEnvDiscrete {
  fn num_discrete_actions(&self) -> usize {
    self.env.num_discrete_actions()
  }

  fn get_discrete_action(&self, player_rank: usize, act_idx: u32) -> Self::Action {
    self.env.get_discrete_action(player_rank, act_idx)
  }

  fn get_discrete_action_index(&self, player_rank: usize, action: &Self::Action) -> u32 {
    self.env.get_discrete_action_index(player_rank, action)
  }
}

impl<E, Obs> MultiEnvObserve<Obs> for MonitorEnv<E> where E: MultiEnvObserve<Obs> {
  fn observe<R>(&self, observer_rank: usize, rng: &mut R) -> Obs where R: Rng + Sized {
    self.tick.set(self.tick.get() + 1);
    let t = self.tick.get();
    self.tx.send((t, MonitorAction::StartEvent(MonitorEvent::Observe))).unwrap();
    let res = self.env.observe(observer_rank, rng);
    self.tx.send((t, MonitorAction::EndEvent(MonitorEvent::Observe))).unwrap();
    res
  }
}
<commit_msg>`MonitorEnv` monitors the default constructor event.<commit_after>use env::{MultiEnv, MultiEnvDiscrete};
use features::{MultiEnvObserve};

use stopwatch::{Stopwatch};

use rand::{Rng};
use std::cell::{Cell};
//use std::rc::{Rc};
//use std::sync::{Arc};
use std::sync::mpsc::{SyncSender, Receiver, RecvTimeoutError, sync_channel};
use std::thread::{JoinHandle, spawn};
use std::time::{Duration};

#[derive(Clone, Copy, Debug)]
pub enum MonitorAction {
  CtrlStop,
  StartEvent(MonitorEvent),
  EndEvent(MonitorEvent),
}

#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum MonitorEvent {
  Shutdown,
  Construct,
  Reset,
  Step,
  IsTerminal,
  GetNumPlayers,
  GetIsActivePlayer,
  GetIsLegalAction,
  Observe,
}

pub struct MonitorWorker {
  //stopwatch:    Stopwatch,
  rx:   Receiver<(u64, MonitorAction)>,
  active_event: Option<(u64, MonitorEvent)>,
}

impl MonitorWorker {
  pub fn runloop(&mut self) {
    loop {
      match self.rx.recv_timeout(Duration::from_millis(5000)) {
        Err(RecvTimeoutError::Timeout) => {
          if let Some((tick, event)) = self.active_event {
            panic!("PANIC: MonitorEnv: timed out during an event: {} {:?}",
                tick, event);
          }
        }
        Err(RecvTimeoutError::Disconnected) => {
          break;
        }
        Ok((tick, action)) => {
          match action {
            MonitorAction::CtrlStop => {
              break;
            }
            MonitorAction::StartEvent(event) => {
              assert!(self.active_event.is_none());
              self.active_event = Some((tick, event));
            }
            MonitorAction::EndEvent(event) => {
              assert!(self.active_event.is_some());
              assert_eq!(self.active_event.unwrap().0, tick);
              assert_eq!(self.active_event.unwrap().1, event);
              self.active_event = None;
            }
          }
        }
      }
    }
  }
}

pub struct MonitorEnv<E> {
  tick: Cell<u64>,
  tx:   SyncSender<(u64, MonitorAction)>,
  h:    Option<JoinHandle<()>>,
  env:  E,
}

impl<E> Drop for MonitorEnv<E> {
  fn drop(&mut self) {
    self.tick.set(self.tick.get() + 1);
    let t = self.tick.get();
    self.tx.send((t, MonitorAction::CtrlStop)).ok();
    self.h.take().unwrap().join().unwrap();
  }
}

impl<E> Default for MonitorEnv<E> where E: MultiEnv {
  fn default() -> Self {
    let (tx, rx) = sync_channel(1024);
    let h = spawn(move || {
      let mut worker = MonitorWorker{
        //stopwatch:  Stopwatch::new(),
        rx: rx,
        active_event:   None,
      };
      worker.runloop();
    });
    let tick = Cell::new(0);
    tick.set(tick.get() + 1);
    let t = tick.get();
    tx.send((t, MonitorAction::StartEvent(MonitorEvent::Construct))).unwrap();
    let env = E::default();
    tx.send((t, MonitorAction::EndEvent(MonitorEvent::Construct))).unwrap();
    MonitorEnv{
      tick: tick,
      tx:   tx,
      h:    Some(h),
      env:  env,
    }
  }
}

impl<E> MultiEnv for MonitorEnv<E> where E: MultiEnv {
  type Restart = E::Restart;
  type Action = E::Action;
  type Response = E::Response;

  fn shutdown(&self) {
    self.env.shutdown();
  }

  fn reset<R>(&self, restart: &Self::Restart, rng: &mut R) where R: Rng + Sized {
    self.tick.set(self.tick.get() + 1);
    let t = self.tick.get();
    self.tx.send((t, MonitorAction::StartEvent(MonitorEvent::Reset))).unwrap();
    self.env.reset(restart, rng);
    self.tx.send((t, MonitorAction::EndEvent(MonitorEvent::Reset))).unwrap();
  }

  fn step(&self, multi_action: &[Option<Self::Action>]) -> Result<Vec<Option<Self::Response>>, ()> {
    self.tick.set(self.tick.get() + 1);
    let t = self.tick.get();
    self.tx.send((t, MonitorAction::StartEvent(MonitorEvent::Step))).unwrap();
    let res = self.env.step(multi_action);
    self.tx.send((t, MonitorAction::EndEvent(MonitorEvent::Step))).unwrap();
    res
  }

  fn is_terminal(&self) -> bool {
    self.tick.set(self.tick.get() + 1);
    let t = self.tick.get();
    self.tx.send((t, MonitorAction::StartEvent(MonitorEvent::IsTerminal))).unwrap();
    let res = self.env.is_terminal();
    self.tx.send((t, MonitorAction::EndEvent(MonitorEvent::IsTerminal))).unwrap();
    res
  }

  fn num_players(&self) -> usize {
    self.env.num_players()
  }

  fn is_active_player(&self, player_rank: usize) -> bool {
    self.env.is_active_player(player_rank)
  }

  fn is_legal_multi_action(&self, multi_action: &[Option<Self::Action>]) -> bool {
    self.env.is_legal_multi_action(multi_action)
  }
}

impl<E> MultiEnvDiscrete for MonitorEnv<E> where E: MultiEnvDiscrete {
  fn num_discrete_actions(&self) -> usize {
    self.env.num_discrete_actions()
  }

  fn get_discrete_action(&self, player_rank: usize, act_idx: u32) -> Self::Action {
    self.env.get_discrete_action(player_rank, act_idx)
  }

  fn get_discrete_action_index(&self, player_rank: usize, action: &Self::Action) -> u32 {
    self.env.get_discrete_action_index(player_rank, action)
  }
}

impl<E, Obs> MultiEnvObserve<Obs> for MonitorEnv<E> where E: MultiEnvObserve<Obs> {
  fn observe<R>(&self, observer_rank: usize, rng: &mut R) -> Obs where R: Rng + Sized {
    self.tick.set(self.tick.get() + 1);
    let t = self.tick.get();
    self.tx.send((t, MonitorAction::StartEvent(MonitorEvent::Observe))).unwrap();
    let res = self.env.observe(observer_rank, rng);
    self.tx.send((t, MonitorAction::EndEvent(MonitorEvent::Observe))).unwrap();
    res
  }
}
<|endoftext|>


<commit_before>use std::cmp;

use ::expr::Expr;

#[cfg(test)] mod spec;

#[derive(PartialEq,Debug,Clone,Eq,Hash)]
pub enum Condition {
    One(u8), // ascii encoded char
    Class(Vec<u8>), // list of valid ascii encoded chars
    Any,
    None
}

impl Condition {
    pub fn one(c: char) -> Condition {
        Condition::One(Self::to_ascii(c))
    }

    fn to_ascii(c: char) -> u8 {
        let mut buf = [0; 1];
        match c.encode_utf8(&mut buf) {
            Some(1) => buf[0],
            _ => panic!("attempted to create condition with non-ascii char")
        }
    }

    pub fn class(chars: Vec<char>) -> Condition {
        let ascii_bytes = chars.iter().map(|&c| Self::to_ascii(c)).collect::<Vec<_>>();

        Condition::Class(ascii_bytes)
    }
}

#[derive(PartialEq,Debug,Clone,Eq,Hash)]
pub enum Transition {
    Id(usize),
    Detached,
    End
}

#[derive(PartialEq,Debug,Clone,Eq,Hash)]
pub enum State {
    State{condition: Condition, out: Transition},
    Split{out1: Transition, out2: Transition}
}

impl State {
    pub fn state(condition: Condition, out: Transition) -> State {
        State::State{condition: condition, out: out}
    }

    pub fn split(out1: Transition, out2: Transition) -> State {
        State::Split{out1: out1,
                     out2: out2}
    }

    pub fn get_priority_key(&self, nfa: &NFA) -> usize {
        // key by greediness and lexographical order of condition char

        match self {
            &State::State{ref condition, ref out} => {
                Self::get_transition_priority_key(condition, out, nfa)
            },
            &State::Split{ref out1, ref out2} => {
                cmp::min(
                    Self::get_transition_priority_key(&Condition::None, out1, nfa),
                    Self::get_transition_priority_key(&Condition::None, out2, nfa))
            }
        }
    }

    fn get_transition_priority_key(condition: &Condition, out: &Transition, nfa: &NFA) -> usize {
        match condition {
            &Condition::One(c) => c as usize, // there is a cost
            &Condition::Any => 0, // prioritize any
            &Condition::None => {
                match out {
                    &Transition::Id(id) => {
                        let next_state = nfa.get_state(id).unwrap();
                        next_state.get_priority_key(&nfa)
                    },
                    _ => usize::max_value() // state terminates with no cost
                }
            },
            &Condition::Class(ref chars) => 0
        }
    }
}

#[derive(PartialEq,Debug,Clone)]
pub struct NFA {
    start: usize,
    states: Vec<State>
}

impl NFA {

    pub fn new() -> NFA {
        NFA {
            start: 0,
            states: Vec::new()
        }
    }

    pub fn from_states(states: Vec<State>) -> NFA {
        NFA {
            start: 0,
            states: states
        }
    }

    pub fn get_start(&self) -> Option<State> {
        if self.start >= self.states.len() {
            None
        } else {
            Some(self.states[self.start].clone())
        }
    }

    pub fn get_state(&self, index: usize) -> Option<State> {
        if index >= self.states.len() {
            None
        } else {
            Some(self.states[index].clone())
        }

    }

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

    pub fn from_expr(expr: &Expr) -> NFA {
        let mut nfa = Self::new();

        let start = nfa.build_expr(expr);
        nfa.update_outputs(start, Transition::End);
        nfa.start = start;
        nfa
    }

    fn build_expr(&mut self, expr: &Expr) -> usize {
        let id = match expr {
            &Expr::Any => {
                let s = State::state(Condition::Any, Transition::Detached);
                self.states.push(s);

                self.states.len() - 1
            },
            &Expr::Single(c) => {
                let s = State::state(Condition::one(c), Transition::Detached);
                self.states.push(s);

                self.states.len() - 1
            },
            &Expr::Class(ref chars) => {
                let s = State::state(Condition::class(chars.clone()),
                                     Transition::Detached);
                self.states.push(s);

                self.states.len() - 1
            },
            &Expr::Sequence(ref a, ref b) => {
                let left_id = self.build_expr(a);
                let right_id = self.build_expr(b);
                self.update_outputs(left_id, Transition::Id(right_id));

                left_id
            },
            &Expr::Optional(ref expr) => {
                let expr_id = self.build_expr(expr);
                let s = State::split(Transition::Id(expr_id), Transition::Detached);
                self.states.push(s);

                self.states.len() - 1
            },
            &Expr::OneOrMore(ref expr) => {
                let expr_id = self.build_expr(expr);
                let s = State::split(Transition::Id(expr_id), Transition::Detached);

                self.states.push(s);
                let split_id = self.states.len() - 1;
                self.update_outputs(expr_id, Transition::Id(split_id));

                expr_id
            },
            &Expr::ZeroOrMore(ref expr) => {
                let expr_id = self.build_expr(expr);
                let s = State::split(Transition::Id(expr_id), Transition::Detached);

                self.states.push(s);
                let split_id = self.states.len() - 1;
                self.update_outputs(expr_id, Transition::Id(split_id));

                split_id
            },
            &Expr::Or(ref expr1, ref expr2) => {
                let expr1_id = self.build_expr(expr1);
                let expr2_id = self.build_expr(expr2);

                let s = State::split(Transition::Id(expr1_id),
                                     Transition::Id(expr2_id));

                self.states.push(s);

                self.states.len() - 1
            }
        };

        id
    }

    fn update_outputs(&mut self, start_id: usize, new_edge: Transition) {
        self.update_outputs_rec(start_id, &mut vec![start_id], new_edge);
    }

    fn update_outputs_rec(&mut self, start_id: usize, visited: &mut Vec<usize>, new_edge: Transition) {
        let state = self.states[start_id].clone();
        let state = match state {
            State::State{ref condition, ref out} => {
                State::state(condition.clone(),
                             self.replace_edge(out.clone(), new_edge, visited)
)
            },
            State::Split{ref out1, ref out2} => {
                let edge1 = self.replace_edge(out1.clone(), new_edge.clone(), visited);
                let edge2 = self.replace_edge(out2.clone(), new_edge.clone(), visited);

                State::split(edge1,
                             edge2)
            }
        };
        self.states[start_id] = state;
    }

    fn replace_edge(&mut self, edge: Transition, replacement: Transition, visited: &mut Vec<usize>) -> Transition {
        match &edge {
            &Transition::Detached => {
                replacement
            },
            &Transition::Id(id) => {
                if !visited.contains(&id) { // don't recurse further
                    visited.push(id);
                    self.update_outputs_rec(id, visited, replacement);
                }

                edge
            },
            _ => edge
        }
    }

}

<commit_msg>update encode_utf8 usage<commit_after>use std::cmp;

use ::expr::Expr;

#[cfg(test)] mod spec;

#[derive(PartialEq,Debug,Clone,Eq,Hash)]
pub enum Condition {
    One(u8), // ascii encoded char
    Class(Vec<u8>), // list of valid ascii encoded chars
    Any,
    None
}

impl Condition {
    pub fn one(c: char) -> Condition {
        Condition::One(Self::to_ascii(c))
    }

    fn to_ascii(c: char) -> u8 {
        c.encode_utf8().as_slice()[0]
    }

    pub fn class(chars: Vec<char>) -> Condition {
        let ascii_bytes = chars.iter().map(|&c| Self::to_ascii(c)).collect::<Vec<_>>();

        Condition::Class(ascii_bytes)
    }
}

#[derive(PartialEq,Debug,Clone,Eq,Hash)]
pub enum Transition {
    Id(usize),
    Detached,
    End
}

#[derive(PartialEq,Debug,Clone,Eq,Hash)]
pub enum State {
    State{condition: Condition, out: Transition},
    Split{out1: Transition, out2: Transition}
}

impl State {
    pub fn state(condition: Condition, out: Transition) -> State {
        State::State{condition: condition, out: out}
    }

    pub fn split(out1: Transition, out2: Transition) -> State {
        State::Split{out1: out1,
                     out2: out2}
    }

    pub fn get_priority_key(&self, nfa: &NFA) -> usize {
        // key by greediness and lexographical order of condition char

        match self {
            &State::State{ref condition, ref out} => {
                Self::get_transition_priority_key(condition, out, nfa)
            },
            &State::Split{ref out1, ref out2} => {
                cmp::min(
                    Self::get_transition_priority_key(&Condition::None, out1, nfa),
                    Self::get_transition_priority_key(&Condition::None, out2, nfa))
            }
        }
    }

    fn get_transition_priority_key(condition: &Condition, out: &Transition, nfa: &NFA) -> usize {
        match condition {
            &Condition::One(c) => c as usize, // there is a cost
            &Condition::Any => 0, // prioritize any
            &Condition::None => {
                match out {
                    &Transition::Id(id) => {
                        let next_state = nfa.get_state(id).unwrap();
                        next_state.get_priority_key(&nfa)
                    },
                    _ => usize::max_value() // state terminates with no cost
                }
            },
            &Condition::Class(ref chars) => 0
        }
    }
}

#[derive(PartialEq,Debug,Clone)]
pub struct NFA {
    start: usize,
    states: Vec<State>
}

impl NFA {

    pub fn new() -> NFA {
        NFA {
            start: 0,
            states: Vec::new()
        }
    }

    pub fn from_states(states: Vec<State>) -> NFA {
        NFA {
            start: 0,
            states: states
        }
    }

    pub fn get_start(&self) -> Option<State> {
        if self.start >= self.states.len() {
            None
        } else {
            Some(self.states[self.start].clone())
        }
    }

    pub fn get_state(&self, index: usize) -> Option<State> {
        if index >= self.states.len() {
            None
        } else {
            Some(self.states[index].clone())
        }

    }

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

    pub fn from_expr(expr: &Expr) -> NFA {
        let mut nfa = Self::new();

        let start = nfa.build_expr(expr);
        nfa.update_outputs(start, Transition::End);
        nfa.start = start;
        nfa
    }

    fn build_expr(&mut self, expr: &Expr) -> usize {
        let id = match expr {
            &Expr::Any => {
                let s = State::state(Condition::Any, Transition::Detached);
                self.states.push(s);

                self.states.len() - 1
            },
            &Expr::Single(c) => {
                let s = State::state(Condition::one(c), Transition::Detached);
                self.states.push(s);

                self.states.len() - 1
            },
            &Expr::Class(ref chars) => {
                let s = State::state(Condition::class(chars.clone()),
                                     Transition::Detached);
                self.states.push(s);

                self.states.len() - 1
            },
            &Expr::Sequence(ref a, ref b) => {
                let left_id = self.build_expr(a);
                let right_id = self.build_expr(b);
                self.update_outputs(left_id, Transition::Id(right_id));

                left_id
            },
            &Expr::Optional(ref expr) => {
                let expr_id = self.build_expr(expr);
                let s = State::split(Transition::Id(expr_id), Transition::Detached);
                self.states.push(s);

                self.states.len() - 1
            },
            &Expr::OneOrMore(ref expr) => {
                let expr_id = self.build_expr(expr);
                let s = State::split(Transition::Id(expr_id), Transition::Detached);

                self.states.push(s);
                let split_id = self.states.len() - 1;
                self.update_outputs(expr_id, Transition::Id(split_id));

                expr_id
            },
            &Expr::ZeroOrMore(ref expr) => {
                let expr_id = self.build_expr(expr);
                let s = State::split(Transition::Id(expr_id), Transition::Detached);

                self.states.push(s);
                let split_id = self.states.len() - 1;
                self.update_outputs(expr_id, Transition::Id(split_id));

                split_id
            },
            &Expr::Or(ref expr1, ref expr2) => {
                let expr1_id = self.build_expr(expr1);
                let expr2_id = self.build_expr(expr2);

                let s = State::split(Transition::Id(expr1_id),
                                     Transition::Id(expr2_id));

                self.states.push(s);

                self.states.len() - 1
            }
        };

        id
    }

    fn update_outputs(&mut self, start_id: usize, new_edge: Transition) {
        self.update_outputs_rec(start_id, &mut vec![start_id], new_edge);
    }

    fn update_outputs_rec(&mut self, start_id: usize, visited: &mut Vec<usize>, new_edge: Transition) {
        let state = self.states[start_id].clone();
        let state = match state {
            State::State{ref condition, ref out} => {
                State::state(condition.clone(),
                             self.replace_edge(out.clone(), new_edge, visited)
)
            },
            State::Split{ref out1, ref out2} => {
                let edge1 = self.replace_edge(out1.clone(), new_edge.clone(), visited);
                let edge2 = self.replace_edge(out2.clone(), new_edge.clone(), visited);

                State::split(edge1,
                             edge2)
            }
        };
        self.states[start_id] = state;
    }

    fn replace_edge(&mut self, edge: Transition, replacement: Transition, visited: &mut Vec<usize>) -> Transition {
        match &edge {
            &Transition::Detached => {
                replacement
            },
            &Transition::Id(id) => {
                if !visited.contains(&id) { // don't recurse further
                    visited.push(id);
                    self.update_outputs_rec(id, visited, replacement);
                }

                edge
            },
            _ => edge
        }
    }

}

<|endoftext|>


<commit_before>use errors::prelude::*;
use rust_base58::{FromBase58, ToBase58};
use services::crypto::DEFAULT_CRYPTO_TYPE;

pub fn build_full_verkey(dest: &str, verkey: Option<&str>) -> Result<String, IndyError> {
    if let Some(verkey) = verkey {
        let (verkey, crypto_type) = if verkey.contains(':') {
            let splits: Vec<&str> = verkey.split(':').collect();
            (splits[0], Some(splits[1]))
        } else {
            (verkey, None)
        };

        let verkey = if verkey.starts_with('~') {
            let mut result = dest.from_base58()?;
            let mut end = verkey[1..].from_base58()?;
            result.append(&mut end );
            result.to_base58()
        } else {
            verkey.to_owned()
        };

        let verkey = if let Some(crypto_type) = crypto_type {
            format!("{}:{}", verkey, crypto_type)
        } else {
            verkey
        };

        Ok(verkey)
    } else {
        // Cryptonym
        Ok(dest.to_owned())
    }
}

pub fn split_verkey(verkey: &str) -> (&str, &str) {
    if verkey.contains(':') {
        let splits: Vec<&str> = verkey.split(':').collect();
        (splits[0], splits[1])
    } else {
        (verkey, DEFAULT_CRYPTO_TYPE)
    }
}

pub fn verkey_get_cryptoname(verkey: &str) -> &str {
    if verkey.contains(':') {
        let splits: Vec<&str> = verkey.split(':').collect();
        splits[1]
    } else {
        DEFAULT_CRYPTO_TYPE
    }
}<commit_msg>tweaks and more tests<commit_after>use errors::prelude::*;
use rust_base58::{FromBase58, ToBase58};
use services::crypto::DEFAULT_CRYPTO_TYPE;

pub fn build_full_verkey(dest: &str, verkey: Option<&str>) -> Result<String, IndyError> {
    if let Some(verkey) = verkey {
        let (verkey, crypto_type) = if verkey.contains(':') {
            let splits: Vec<&str> = verkey.split(':').collect();
            (splits[0], Some(splits[1]))
        } else {
            (verkey, None)
        };

        let verkey = if verkey.starts_with('~') {
            let mut result = dest.from_base58()?;
            let mut end = verkey[1..].from_base58()?;
            result.append(&mut end );
            result.to_base58()
        } else {
            verkey.to_owned()
        };

        let verkey = if let Some(crypto_type) = crypto_type {
            format!("{}:{}", verkey, crypto_type)
        } else {
            verkey
        };

        Ok(verkey)
    } else {
        // Cryptonym
        Ok(dest.to_owned())
    }
}

pub fn split_verkey(verkey: &str) -> (&str, &str) {
    let position = verkey.find(':');
    match position {
        Some(p) => {
            let cryptoname = if p + 1 < verkey.len() {
                verkey[p + 1..].as_ref()
            } else {
                DEFAULT_CRYPTO_TYPE
            };
            let v = if p > 0 {
                verkey[..p].as_ref()
            } else {
                ""
            };
            (v, cryptoname)
        },
        None => (verkey, DEFAULT_CRYPTO_TYPE)
    }
}

pub fn verkey_get_cryptoname(verkey: &str) -> &str {
    let position = verkey.find(':');
    match position {
        Some(p) => {
            if p + 1 < verkey.len() {
                verkey[p + 1..].as_ref()
            } else {
                DEFAULT_CRYPTO_TYPE
            }
    },
        None => DEFAULT_CRYPTO_TYPE
    }
}

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

    # [test]
    fn split_verkey_empty() {
        assert_eq!(split_verkey(""), ("", DEFAULT_CRYPTO_TYPE))
    }

    # [test]
    fn split_verkey_single_colon() {
        assert_eq!(split_verkey(":"), ("", DEFAULT_CRYPTO_TYPE))
    }

    # [test]
    fn split_verkey_ends_with_colon() {
        assert_eq!(split_verkey("foo:"), ("foo", DEFAULT_CRYPTO_TYPE))
    }

    # [test]
    fn split_verkey_starts_with_colon() {
        assert_eq!(split_verkey(":bar"), ("", "bar"))
    }

    # [test]
    fn split_verkey_works() {
        assert_eq!(split_verkey("foo:bar:baz"), ("foo", "bar:baz"))
    }

    # [test]
    fn verkey_get_cryptoname_empty() {
        assert_eq!(verkey_get_cryptoname(""), DEFAULT_CRYPTO_TYPE)
    }

    # [test]
    fn verkey_get_cryptoname_single_colon() {
        assert_eq!(verkey_get_cryptoname(":"), DEFAULT_CRYPTO_TYPE)
    }

    # [test]
    fn verkey_get_cryptoname_ends_with_colon() {
        assert_eq!(verkey_get_cryptoname("foo:"), DEFAULT_CRYPTO_TYPE)
    }

    # [test]
    fn verkey_get_cryptoname_works() {
        assert_eq!(verkey_get_cryptoname("foo:bar"), "bar")
    }

}<|endoftext|>


<commit_before>use crate::sys::mutex::Mutex;
use crate::time::Duration;

pub struct Condvar {}

pub type MovableCondvar = Box<Condvar>;

impl Condvar {
    pub const fn new() -> Condvar {
        Condvar {}
    }

    #[inline]
    pub unsafe fn init(&mut self) {}

    #[inline]
    pub unsafe fn notify_one(&self) {}

    #[inline]
    pub unsafe fn notify_all(&self) {}

    pub unsafe fn wait(&self, _mutex: &Mutex) {
        panic!("condvar wait not supported")
    }

    pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
        panic!("condvar wait not supported");
    }

    #[inline]
    pub unsafe fn destroy(&self) {}
}
<commit_msg>No longer put condvars on the 'unsupported' platform in a box.<commit_after>use crate::sys::mutex::Mutex;
use crate::time::Duration;

pub struct Condvar {}

pub type MovableCondvar = Condvar;

impl Condvar {
    pub const fn new() -> Condvar {
        Condvar {}
    }

    #[inline]
    pub unsafe fn init(&mut self) {}

    #[inline]
    pub unsafe fn notify_one(&self) {}

    #[inline]
    pub unsafe fn notify_all(&self) {}

    pub unsafe fn wait(&self, _mutex: &Mutex) {
        panic!("condvar wait not supported")
    }

    pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
        panic!("condvar wait not supported");
    }

    #[inline]
    pub unsafe fn destroy(&self) {}
}
<|endoftext|>


<commit_before>//! A set of exports which can be helpful to use.
//!
//! Note that the `SerenityError` re-export is equivalent to
//! [`serenity::Error`], although is re-exported as a separate name to remove
//! likely ambiguity with other crate error enums.
//!
//! # Examples
//!
//! Import all of the exports:
//!
//! ```rust
//! use serenity::prelude::*;
//! ```
//!
//! [`serenity::Error`]: ../enum.Error.html

pub use error::Error as SerenityError;
pub use model::Mentionable;
pub use parking_lot::{Mutex, RwLock};

#[cfg(feature = "client")]
pub use client::{Client, ClientError as ClientError, Context, EventHandler};
#[cfg(feature = "gateway")]
pub use gateway::GatewayError;
#[cfg(feature = "http")]
pub use http::HttpError;
#[cfg(feature = "model")]
pub use model::ModelError;
#[cfg(feature = "voice")]
pub use voice::VoiceError;
<commit_msg>Fix no-parking_lot compilation<commit_after>//! A set of exports which can be helpful to use.
//!
//! Note that the `SerenityError` re-export is equivalent to
//! [`serenity::Error`], although is re-exported as a separate name to remove
//! likely ambiguity with other crate error enums.
//!
//! # Examples
//!
//! Import all of the exports:
//!
//! ```rust
//! use serenity::prelude::*;
//! ```
//!
//! [`serenity::Error`]: ../enum.Error.html

pub use error::Error as SerenityError;
pub use model::Mentionable;

#[cfg(feature = "client")]
pub use client::{Client, ClientError as ClientError, Context, EventHandler};
#[cfg(feature = "gateway")]
pub use gateway::GatewayError;
#[cfg(feature = "http")]
pub use http::HttpError;
#[cfg(feature = "model")]
pub use model::ModelError;
#[cfg(feature = "parking_lot")]
pub use parking_lot::{Mutex, RwLock};
#[cfg(feature = "voice")]
pub use voice::VoiceError;
<|endoftext|>


<commit_before>use crate::{Error, Result};
use chrono::{DateTime, Utc};
use plist;
use plist::PlistEvent;
use std::fs::File;
use std::io::{self, Read};
use std::path::{Path, PathBuf};
use std::time::SystemTime;

/// Represents a file with a provisioning profile info.
#[derive(Debug, Clone)]
pub struct Profile {
    pub path: PathBuf,
    pub info: ProfileInfo,
}

impl Profile {
    /// Returns instance of the `Profile` parsed from a file.
    pub fn from_file(path: &Path) -> Result<Self> {
        let mut buf = Vec::new();
        File::open(path)?.read_to_end(&mut buf)?;
        let info = ProfileInfo::from_xml_data(&buf)
            .ok_or_else(|| Error::Own("Couldn't parse file.".into()))?;
        Ok(Self {
            path: path.to_owned(),
            info,
        })
    }
}

/// Represents provisioning profile info.
#[derive(Debug, Clone)]
pub struct ProfileInfo {
    pub uuid: String,
    pub name: String,
    pub app_identifier: String,
    pub creation_date: SystemTime,
    pub expiration_date: SystemTime,
}

impl ProfileInfo {
    /// Returns instance of the `Profile` parsed from a `data`.
    pub fn from_xml_data(data: &[u8]) -> Option<Self> {
        if let Some(data) = crate::plist_extractor::find(data) {
            let mut profile = Self::empty();
            let mut iter = plist::xml::EventReader::new(io::Cursor::new(data));
            while let Some(item) = iter.next() {
                if let Ok(PlistEvent::StringValue(key)) = item {
                    if key == "UUID" {
                        if let Some(Ok(PlistEvent::StringValue(value))) = iter.next() {
                            profile.uuid = value;
                        }
                    }
                    if key == "Name" {
                        if let Some(Ok(PlistEvent::StringValue(value))) = iter.next() {
                            profile.name = value;
                        }
                    }
                    if key == "application-identifier" {
                        if let Some(Ok(PlistEvent::StringValue(value))) = iter.next() {
                            profile.app_identifier = value;
                        }
                    }
                    if key == "CreationDate" {
                        if let Some(Ok(PlistEvent::DateValue(value))) = iter.next() {
                            profile.creation_date = value.into();
                        }
                    }
                    if key == "ExpirationDate" {
                        if let Some(Ok(PlistEvent::DateValue(value))) = iter.next() {
                            profile.expiration_date = value.into();
                        }
                    }
                }
            }
            Some(profile)
        } else {
            None
        }
    }

    /// Returns an empty profile info.
    pub fn empty() -> Self {
        Self {
            uuid: "".into(),
            name: "".into(),
            app_identifier: "".into(),
            creation_date: SystemTime::UNIX_EPOCH,
            expiration_date: SystemTime::UNIX_EPOCH,
        }
    }

    /// Returns `true` if one or more fields of the profile contain `string`.
    pub fn contains(&self, string: &str) -> bool {
        let s = string.to_lowercase();
        let items = &[&self.name, &self.app_identifier, &self.uuid];
        for item in items {
            if item.to_lowercase().contains(&s) {
                return true;
            }
        }
        false
    }

    /// Returns a bundle id of a profile.
    pub fn bundle_id(&self) -> Option<&str> {
        self.app_identifier
            .find(|ch| ch == '.')
            .map(|i| &self.app_identifier[(i + 1)..])
    }

    /// Returns profile in a text form.
    pub fn description(&self) -> String {
        let mut desc = String::new();
        desc.push_str(&self.uuid);
        desc.push_str("\n");
        desc.push_str(&self.app_identifier);
        desc.push_str("\n");
        desc.push_str(&self.name);
        desc.push_str("\n");
        desc.push_str(&format!(
            "{} - {}",
            DateTime::<Utc>::from(self.creation_date),
            DateTime::<Utc>::from(self.expiration_date)
        ));
        desc
    }
}

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

    #[test]
    fn contains() {
        let profile = ProfileInfo {
            uuid: "123".into(),
            name: "name".into(),
            app_identifier: "id".into(),
            creation_date: SystemTime::UNIX_EPOCH,
            expiration_date: SystemTime::UNIX_EPOCH,
        };
        expect!(profile.contains("12")).to(be_true());
        expect!(profile.contains("me")).to(be_true());
        expect!(profile.contains("id")).to(be_true());
    }

    #[test]
    fn correct_bundle_id() {
        let mut profile = ProfileInfo::empty();
        profile.app_identifier = "12345ABCDE.com.exmaple.app".to_owned();
        expect!(profile.bundle_id()).to(be_some().value("com.exmaple.app"));
    }

    #[test]
    fn incorrect_bundle_id() {
        let mut profile = ProfileInfo::empty();
        profile.app_identifier = "12345ABCDE".to_owned();
        expect!(profile.bundle_id()).to(be_none());
    }

    #[test]
    fn wildcard_bundle_id() {
        let mut profile = ProfileInfo::empty();
        profile.app_identifier = "12345ABCDE.*".to_owned();
        expect!(profile.bundle_id()).to(be_some().value("*"));
    }
}
<commit_msg>Rename ProfileInfo to Info<commit_after>use crate::{Error, Result};
use chrono::{DateTime, Utc};
use plist;
use plist::PlistEvent;
use std::fs::File;
use std::io::{self, Read};
use std::path::{Path, PathBuf};
use std::time::SystemTime;

/// Represents a file with a provisioning profile info.
#[derive(Debug, Clone)]
pub struct Profile {
    pub path: PathBuf,
    pub info: Info,
}

impl Profile {
    /// Returns instance of the `Profile` parsed from a file.
    pub fn from_file(path: &Path) -> Result<Self> {
        let mut buf = Vec::new();
        File::open(path)?.read_to_end(&mut buf)?;
        let info =
            Info::from_xml_data(&buf).ok_or_else(|| Error::Own("Couldn't parse file.".into()))?;
        Ok(Self {
            path: path.to_owned(),
            info,
        })
    }
}

/// Represents provisioning profile info.
#[derive(Debug, Clone)]
pub struct Info {
    pub uuid: String,
    pub name: String,
    pub app_identifier: String,
    pub creation_date: SystemTime,
    pub expiration_date: SystemTime,
}

impl Info {
    /// Returns instance of the `Profile` parsed from a `data`.
    pub fn from_xml_data(data: &[u8]) -> Option<Self> {
        if let Some(data) = crate::plist_extractor::find(data) {
            let mut profile = Self::empty();
            let mut iter = plist::xml::EventReader::new(io::Cursor::new(data));
            while let Some(item) = iter.next() {
                if let Ok(PlistEvent::StringValue(key)) = item {
                    if key == "UUID" {
                        if let Some(Ok(PlistEvent::StringValue(value))) = iter.next() {
                            profile.uuid = value;
                        }
                    }
                    if key == "Name" {
                        if let Some(Ok(PlistEvent::StringValue(value))) = iter.next() {
                            profile.name = value;
                        }
                    }
                    if key == "application-identifier" {
                        if let Some(Ok(PlistEvent::StringValue(value))) = iter.next() {
                            profile.app_identifier = value;
                        }
                    }
                    if key == "CreationDate" {
                        if let Some(Ok(PlistEvent::DateValue(value))) = iter.next() {
                            profile.creation_date = value.into();
                        }
                    }
                    if key == "ExpirationDate" {
                        if let Some(Ok(PlistEvent::DateValue(value))) = iter.next() {
                            profile.expiration_date = value.into();
                        }
                    }
                }
            }
            Some(profile)
        } else {
            None
        }
    }

    /// Returns an empty profile info.
    pub fn empty() -> Self {
        Self {
            uuid: "".into(),
            name: "".into(),
            app_identifier: "".into(),
            creation_date: SystemTime::UNIX_EPOCH,
            expiration_date: SystemTime::UNIX_EPOCH,
        }
    }

    /// Returns `true` if one or more fields of the profile contain `string`.
    pub fn contains(&self, string: &str) -> bool {
        let s = string.to_lowercase();
        let items = &[&self.name, &self.app_identifier, &self.uuid];
        for item in items {
            if item.to_lowercase().contains(&s) {
                return true;
            }
        }
        false
    }

    /// Returns a bundle id of a profile.
    pub fn bundle_id(&self) -> Option<&str> {
        self.app_identifier
            .find(|ch| ch == '.')
            .map(|i| &self.app_identifier[(i + 1)..])
    }

    /// Returns profile in a text form.
    pub fn description(&self) -> String {
        let mut desc = String::new();
        desc.push_str(&self.uuid);
        desc.push_str("\n");
        desc.push_str(&self.app_identifier);
        desc.push_str("\n");
        desc.push_str(&self.name);
        desc.push_str("\n");
        desc.push_str(&format!(
            "{} - {}",
            DateTime::<Utc>::from(self.creation_date),
            DateTime::<Utc>::from(self.expiration_date)
        ));
        desc
    }
}

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

    #[test]
    fn contains() {
        let profile = Info {
            uuid: "123".into(),
            name: "name".into(),
            app_identifier: "id".into(),
            creation_date: SystemTime::UNIX_EPOCH,
            expiration_date: SystemTime::UNIX_EPOCH,
        };
        expect!(profile.contains("12")).to(be_true());
        expect!(profile.contains("me")).to(be_true());
        expect!(profile.contains("id")).to(be_true());
    }

    #[test]
    fn correct_bundle_id() {
        let mut profile = Info::empty();
        profile.app_identifier = "12345ABCDE.com.exmaple.app".to_owned();
        expect!(profile.bundle_id()).to(be_some().value("com.exmaple.app"));
    }

    #[test]
    fn incorrect_bundle_id() {
        let mut profile = Info::empty();
        profile.app_identifier = "12345ABCDE".to_owned();
        expect!(profile.bundle_id()).to(be_none());
    }

    #[test]
    fn wildcard_bundle_id() {
        let mut profile = Info::empty();
        profile.app_identifier = "12345ABCDE.*".to_owned();
        expect!(profile.bundle_id()).to(be_some().value("*"));
    }
}
<|endoftext|>


<commit_before>use curl::Error as CurlError;
use curl::easy::Easy;
use futures::Future;
use tokio_curl::Session;
use tokio_curl::Perform;
use futures::Poll;
use tokio_curl::PerformError;
use curl::easy::WriteError;
use std::sync::{Arc,Mutex};
use futures::Async;
use super::Task;
use super::Error;
use std::cell::Cell;
use std::error::Error as StdError;
use std::sync::mpsc::SyncSender;

#[derive(Debug,Clone)]
pub struct Response {
	pub content: Vec<u8>,
}

impl Response {
	fn write(&mut self,data: &[u8]) -> Result<usize,WriteError> {
		self.content.extend_from_slice(data);
		Ok(data.len())
	}
}

#[derive(Clone)]
pub struct RequestDownloader {
	inner: Arc<Mutex<Cell<Option<Response>>>>,
	request: Arc<Perform>,
	sender: SyncSender<RequestDownloaderResult>,
}

impl Future for RequestDownloader {
	type Item = Easy;
    type Error = PerformError;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
    	let result = Arc::get_mut(&mut self.request).unwrap().poll();
    	match result {
    		Ok(Async::Ready(_)) => {
    			let response = self.inner.lock().expect(
					"Unable to lock mutex"
				).replace(None).expect(
					"Unable to get response"
				);
				self.sender.send(Ok(response)).expect("Unable to send response result");
    		},
    		Ok(Async::NotReady) => {},
    		Err(ref error) => {
    			self.sender.send(
	    			Err(Error::EventLoop (
	    				String::from(error.description()),
	    				format!("{:?}",error)
	    			))
    			).expect("Unable to send response error");
    		}
    	}
    	return result;
    }
}

/// Result of working network manager.
pub type RequestDownloaderResult = Result<Response,Error>;

impl RequestDownloader {
	pub fn new(task:Task,session: &Session,result_tx: SyncSender<RequestDownloaderResult>) -> Result<RequestDownloader,CurlError> {
		let inner = Arc::new(
			Mutex::new(
				Cell::new(
					Some(
						Response{
							content: vec![],
						}
					)
				)
			)
		);
		let curl_inner = inner.clone();
		let download_content = task.download();
		let mut curl_request = task.get_request();
		if download_content {
			let _ = curl_request.write_function(move |data| {
				curl_inner.lock().expect(
					"Unable to unwrap curl_inner"
				).get_mut().as_mut().expect(
					"Unable to write recv data"
				).write(data)
			})?;
		}

		let downloader = RequestDownloader {
			inner: inner,
			request: Arc::new(session.perform(curl_request)),
			sender: result_tx,
		};
		return Ok(downloader);
	}
}<commit_msg>Refactoring.<commit_after>use curl::Error as CurlError;
use curl::easy::Easy;
use futures::Future;
use tokio_curl::Session;
use tokio_curl::Perform;
use futures::Poll;
use tokio_curl::PerformError;
use curl::easy::WriteError;
use std::sync::Arc;
use futures::Async;
use std::mem::swap as swap_variable;
use super::Task;
use super::Error;
use std::error::Error as StdError;
use std::sync::mpsc::SyncSender;

#[derive(Debug,Clone)]
pub struct Response {
	pub content: Vec<u8>,
}

impl Response {
	fn write(&mut self,data: &[u8]) -> Result<usize,WriteError> {
		self.content.extend_from_slice(data);
		Ok(data.len())
	}
}

#[derive(Clone)]
pub struct RequestDownloader {
	inner: Option<Response>,
	request: Arc<Perform>,
	sender: SyncSender<RequestDownloaderResult>,
}

impl Future for RequestDownloader {
	type Item = Easy;
    type Error = PerformError;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
    	let result = Arc::get_mut(&mut self.request).unwrap().poll();
    	match result {
    		Ok(Async::Ready(_)) => {
    			let mut response = None;
				swap_variable(&mut response,&mut self.inner);
				self.sender.send(Ok(response.unwrap())).expect("Unable to send response result");
    		},
    		Ok(Async::NotReady) => {},
    		Err(ref error) => {
    			self.sender.send(
	    			Err(Error::EventLoop (
	    				String::from(error.description()),
	    				format!("{:?}",error)
	    			))
    			).expect("Unable to send response error");
    		}
    	}
    	return result;
    }
}

/// Result of working network manager.
pub type RequestDownloaderResult = Result<Response,Error>;

impl RequestDownloader {
	pub fn new(task:Task,session: &Session,result_tx: SyncSender<RequestDownloaderResult>) -> Result<RequestDownloader,CurlError> {
		let inner = Some(
			Response{
				content: vec![],
			}
		);
		let mut curl_inner = inner.clone();
		let download_content = task.download();
		let mut curl_request = task.get_request();
		if download_content {
			let _ = curl_request.write_function(move |data| {
				curl_inner.as_mut().expect(
					"Unable to write recv data"
				).write(data)
			})?;
		}

		let downloader = RequestDownloader {
			inner: inner,
			request: Arc::new(session.perform(curl_request)),
			sender: result_tx,
		};
		return Ok(downloader);
	}
}<|endoftext|>