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

use borrow_check::nll::region_infer::values::ToElementIndex;
use borrow_check::nll::region_infer::{Cause, ConstraintIndex, RegionInferenceContext};
use borrow_check::nll::region_infer::{ConstraintIndex, RegionInferenceContext};
use borrow_check::nll::type_check::Locations;
use rustc::hir::def_id::DefId;
use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
use rustc::infer::InferCtxt;
use rustc::mir::{self, Location, Mir, Place, Rvalue, StatementKind, TerminatorKind};
use rustc::ty::RegionVid;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::indexed_vec::IndexVec;
use std::fmt;
use syntax_pos::Span;

/// Constraints that are considered interesting can be categorized to
/// determine why they are interesting. Order of variants indicates
/// sort order of the category, thereby influencing diagnostic output.
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)]
enum ConstraintCategory {
    Cast,
    Assignment,
    Return,
    CallArgument,
    Other,
    Boring,
}

impl fmt::Display for ConstraintCategory {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ConstraintCategory::Assignment => write!(f, "assignment"),
            ConstraintCategory::Return => write!(f, "return"),
            ConstraintCategory::Cast => write!(f, "cast"),
            ConstraintCategory::CallArgument => write!(f, "argument"),
            _ => write!(f, "free region"),
        }
    }
}

impl<'tcx> RegionInferenceContext<'tcx> {
    /// Walks the graph of constraints (where `'a: 'b` is considered
    /// an edge `'b -> 'a`) to find all paths from `from_region` to
    /// `to_region`. The paths are accumulated into the vector
    /// `results`. The paths are stored as a series of
    /// `ConstraintIndex` values -- in other words, a list of *edges*.
    ///
    /// # Parameters
    ///
    /// - `from_region`
    /// When reporting an error, it is useful to be able to determine
    /// which constraints influenced the region being reported as an
    /// error. This function finds all of the paths from the
    /// constraint.
    fn find_constraint_paths_between_regions(
        &self,
        from_region: RegionVid,
        to_region: RegionVid,
    ) -> Vec<Vec<ConstraintIndex>> {
        let mut results = vec![];
        self.find_constraint_paths_between_regions_helper(
            from_region,
            from_region,
            to_region,
            &mut FxHashSet::default(),
            &mut vec![],
            &mut results,
        );
        results
    }

    /// Helper for `find_constraint_paths_between_regions`.
    fn find_constraint_paths_between_regions_helper(
        &self,
        from_region: RegionVid,
        current_region: RegionVid,
        to_region: RegionVid,
        visited: &mut FxHashSet<RegionVid>,
        stack: &mut Vec<ConstraintIndex>,
        results: &mut Vec<Vec<ConstraintIndex>>,
    ) {
        let dependency_map = self.dependency_map.as_ref().unwrap();

        // Check if we already visited this region.
        if !visited.insert(current_region) {
            return;
        }

        // Check if we reached the region we were looking for.
        if current_region == to_region {
            // Unless we started out searching for `'a ~> 'a`, which shouldn't have caused
            // en error, then we must have traversed at least *some* constraint:
            assert!(!stack.is_empty());

            // The first constraint should be like `X: from_region`.
            assert_eq!(self.constraints[stack[0]].sub, from_region);

            // The last constraint should be like `to_region: Y`.
            assert_eq!(self.constraints[*stack.last().unwrap()].sup, to_region);

            results.push(stack.clone());
            return;
        }

        self.constraints
            .each_affected_by_dirty(dependency_map[current_region], |constraint| {
                assert_eq!(self.constraints[constraint].sub, current_region);
                stack.push(constraint);
                self.find_constraint_paths_between_regions_helper(
                    from_region,
                    self.constraints[constraint].sup,
                    to_region,
                    visited,
                    stack,
                    results,
                );
                stack.pop();
            });
    }

    /// This function will return true if a constraint is interesting and false if a constraint
    /// is not. It is useful in filtering constraint paths to only interesting points.
    fn constraint_is_interesting(&self, index: ConstraintIndex) -> bool {
        let constraint = self.constraints[index];
        debug!(
            "constraint_is_interesting: locations={:?} constraint={:?}",
            constraint.locations, constraint
        );
        if let Locations::Interesting(_) = constraint.locations {
            true
        } else {
            false
        }
    }

    /// This function classifies a constraint from a location.
    fn classify_constraint(
        &self,
        index: ConstraintIndex,
        mir: &Mir<'tcx>,
    ) -> Option<(ConstraintCategory, Span)> {
        let constraint = self.constraints[index];
        let span = constraint.locations.span(mir);
        let location = constraint.locations.from_location()?;

        if !self.constraint_is_interesting(index) {
            return Some((ConstraintCategory::Boring, span));
        }

        let data = &mir[location.block];
        let category = if location.statement_index == data.statements.len() {
            if let Some(ref terminator) = data.terminator {
                match terminator.kind {
                    TerminatorKind::DropAndReplace { .. } => ConstraintCategory::Assignment,
                    TerminatorKind::Call { .. } => ConstraintCategory::CallArgument,
                    _ => ConstraintCategory::Other,
                }
            } else {
                ConstraintCategory::Other
            }
        } else {
            let statement = &data.statements[location.statement_index];
            match statement.kind {
                StatementKind::Assign(ref place, ref rvalue) => {
                    if *place == Place::Local(mir::RETURN_PLACE) {
                        ConstraintCategory::Return
                    } else {
                        match rvalue {
                            Rvalue::Cast(..) => ConstraintCategory::Cast,
                            Rvalue::Use(..) => ConstraintCategory::Assignment,
                            _ => ConstraintCategory::Other,
                        }
                    }
                }
                _ => ConstraintCategory::Other,
            }
        };

        Some((category, span))
    }

    /// Report an error because the universal region `fr` was required to outlive
    /// `outlived_fr` but it is not known to do so. For example:
    ///
    /// ```
    /// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
    /// ```
    ///
    /// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
    pub(super) fn report_error(
        &self,
        mir: &Mir<'tcx>,
        infcx: &InferCtxt<'_, '_, 'tcx>,
        mir_def_id: DefId,
        fr: RegionVid,
        outlived_fr: RegionVid,
        blame_span: Span,
    ) {
        debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);

        let fr_name = self.to_error_region(fr);
        let outlived_fr_name = self.to_error_region(outlived_fr);

        if let (Some(f), Some(o)) = (fr_name, outlived_fr_name) {
            let tables = infcx.tcx.typeck_tables_of(mir_def_id);
            let nice = NiceRegionError::new_from_span(infcx.tcx, blame_span, o, f, Some(tables));
            if let Some(_error_reported) = nice.try_report() {
                return;
            }
        }

        let fr_string = match fr_name {
            Some(r) => format!("free region `{}`", r),
            None => format!("free region `{:?}`", fr),
        };

        let outlived_fr_string = match outlived_fr_name {
            Some(r) => format!("free region `{}`", r),
            None => format!("free region `{:?}`", outlived_fr),
        };

        // Find all paths
        let constraint_paths = self.find_constraint_paths_between_regions(outlived_fr, fr);
        debug!("report_error: constraint_paths={:#?}", constraint_paths);

        // Find the shortest such path.
        let path = constraint_paths.iter().min_by_key(|p| p.len()).unwrap();
        debug!("report_error: shortest_path={:?}", path);

        // Classify each of the constraints along the path.
        let mut categorized_path: Vec<(ConstraintCategory, Span)> = path.iter()
            .filter_map(|&index| self.classify_constraint(index, mir))
            .collect();
        debug!("report_error: categorized_path={:?}", categorized_path);

        // Find what appears to be the most interesting path to report to the user.
        categorized_path.sort_by(|p0, p1| p0.0.cmp(&p1.0));
        debug!("report_error: sorted_path={:?}", categorized_path);

        // If we found something, cite that as the main cause of the problem.
        if let Some((category, span)) = categorized_path.first() {
            let mut diag = infcx.tcx.sess.struct_span_err(
                *span,
                &format!(
                    "{} requires that data must outlive {}",
                    category, outlived_fr_string
                ),
            );

            diag.emit();
        } else {
            let mut diag = infcx.tcx.sess.struct_span_err(
                blame_span,
                &format!("{} does not outlive {}", fr_string, outlived_fr_string,),
            );

            diag.emit();
        }
    }

    // Find some constraint `X: Y` where:
    // - `fr1: X` transitively
    // - and `Y` is live at `elem`
    crate fn find_constraint(&self, fr1: RegionVid, elem: Location) -> RegionVid {
        let index = self.blame_constraint(fr1, elem);
        self.constraints[index].sub
    }

    /// Tries to finds a good span to blame for the fact that `fr1`
    /// contains `fr2`.
    pub(super) fn blame_constraint(
        &self,
        fr1: RegionVid,
        elem: impl ToElementIndex,
    ) -> ConstraintIndex {
        // Find everything that influenced final value of `fr`.
        let influenced_fr1 = self.dependencies(fr1);

        // Try to find some outlives constraint `'X: fr2` where `'X`
        // influenced `fr1`. Blame that.
        //
        // NB, this is a pretty bad choice most of the time. In
        // particular, the connection between `'X` and `fr1` may not
        // be obvious to the user -- not to mention the naive notion
        // of dependencies, which doesn't account for the locations of
        // contraints at all. But it will do for now.
        let relevant_constraint = self.constraints
            .iter_enumerated()
            .filter_map(|(i, constraint)| {
                if !self.liveness_constraints.contains(constraint.sub, elem) {
                    None
                } else {
                    influenced_fr1[constraint.sup]
                        .map(|distance| (distance, i))
                }
            })
            .min() // constraining fr1 with fewer hops *ought* to be more obvious
            .map(|(_dist, i)| i);

        relevant_constraint.unwrap_or_else(|| {
            bug!(
                "could not find any constraint to blame for {:?}: {:?}",
                fr1,
                elem,
            );
        })
    }

    /// Finds all regions whose values `'a` may depend on in some way.
    /// For each region, returns either `None` (does not influence
    /// `'a`) or `Some(d)` which indicates that it influences `'a`
    /// with distinct `d` (minimum number of edges that must be
    /// traversed).
    ///
    /// Used during error reporting, extremely naive and inefficient.
    fn dependencies(&self, r0: RegionVid) -> IndexVec<RegionVid, Option<usize>> {
        let mut result_set = IndexVec::from_elem(None, &self.definitions);
        let mut changed = true;
        result_set[r0] = Some(0); // distance 0 from `r0`

        while changed {
            changed = false;
            for constraint in &*self.constraints {
                if let Some(n) = result_set[constraint.sup] {
                    let m = n + 1;
                    if result_set[constraint.sub]
                        .map(|distance| m < distance)
                        .unwrap_or(true)
                    {
                        result_set[constraint.sub] = Some(m);
                        changed = true;
                    }
                }
            }
        }

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

use borrow_check::nll::region_infer::values::ToElementIndex;
use borrow_check::nll::region_infer::{Cause, ConstraintIndex, RegionInferenceContext};
use borrow_check::nll::region_infer::{ConstraintIndex, RegionInferenceContext};
use borrow_check::nll::type_check::Locations;
use rustc::hir::def_id::DefId;
use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
use rustc::infer::InferCtxt;
use rustc::mir::{self, Location, Mir, Place, Rvalue, StatementKind, TerminatorKind};
use rustc::ty::RegionVid;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::indexed_vec::IndexVec;
use std::fmt;
use syntax_pos::Span;

/// Constraints that are considered interesting can be categorized to
/// determine why they are interesting. Order of variants indicates
/// sort order of the category, thereby influencing diagnostic output.
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)]
enum ConstraintCategory {
    Cast,
    Assignment,
    Return,
    CallArgument,
    Other,
    Boring,
}

impl fmt::Display for ConstraintCategory {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ConstraintCategory::Assignment => write!(f, "assignment"),
            ConstraintCategory::Return => write!(f, "return"),
            ConstraintCategory::Cast => write!(f, "cast"),
            ConstraintCategory::CallArgument => write!(f, "argument"),
            _ => write!(f, "free region"),
        }
    }
}

impl<'tcx> RegionInferenceContext<'tcx> {
    /// Walks the graph of constraints (where `'a: 'b` is considered
    /// an edge `'b -> 'a`) to find all paths from `from_region` to
    /// `to_region`. The paths are accumulated into the vector
    /// `results`. The paths are stored as a series of
    /// `ConstraintIndex` values -- in other words, a list of *edges*.
    ///
    /// # Parameters
    ///
    /// - `from_region`
    /// When reporting an error, it is useful to be able to determine
    /// which constraints influenced the region being reported as an
    /// error. This function finds all of the paths from the
    /// constraint.
    fn find_constraint_paths_between_regions(
        &self,
        from_region: RegionVid,
        target_test: impl Fn(RegionVid) -> bool,
    ) -> Vec<Vec<ConstraintIndex>> {
        let mut results = vec![];
        self.find_constraint_paths_between_regions_helper(
            from_region,
            from_region,
            &target_test,
            &mut FxHashSet::default(),
            &mut vec![],
            &mut results,
        );
        results
    }

    /// Helper for `find_constraint_paths_between_regions`.
    fn find_constraint_paths_between_regions_helper(
        &self,
        from_region: RegionVid,
        current_region: RegionVid,
        target_test: &impl Fn(RegionVid) -> bool,
        visited: &mut FxHashSet<RegionVid>,
        stack: &mut Vec<ConstraintIndex>,
        results: &mut Vec<Vec<ConstraintIndex>>,
    ) {
        let dependency_map = self.dependency_map.as_ref().unwrap();

        // Check if we already visited this region.
        if !visited.insert(current_region) {
            return;
        }

        // Check if we reached the region we were looking for.
        if target_test(current_region) {
            if !stack.is_empty() {
                assert_eq!(self.constraints[stack[0]].sub, from_region);
                results.push(stack.clone());
            }
            return;
        }

        self.constraints
            .each_affected_by_dirty(dependency_map[current_region], |constraint| {
                assert_eq!(self.constraints[constraint].sub, current_region);
                stack.push(constraint);
                self.find_constraint_paths_between_regions_helper(
                    from_region,
                    self.constraints[constraint].sup,
                    target_test,
                    visited,
                    stack,
                    results,
                );
                stack.pop();
            });
    }

    /// This function will return true if a constraint is interesting and false if a constraint
    /// is not. It is useful in filtering constraint paths to only interesting points.
    fn constraint_is_interesting(&self, index: ConstraintIndex) -> bool {
        let constraint = self.constraints[index];
        debug!(
            "constraint_is_interesting: locations={:?} constraint={:?}",
            constraint.locations, constraint
        );
        if let Locations::Interesting(_) = constraint.locations {
            true
        } else {
            false
        }
    }

    /// This function classifies a constraint from a location.
    fn classify_constraint(
        &self,
        index: ConstraintIndex,
        mir: &Mir<'tcx>,
    ) -> Option<(ConstraintCategory, Span)> {
        let constraint = self.constraints[index];
        let span = constraint.locations.span(mir);
        let location = constraint.locations.from_location()?;

        if !self.constraint_is_interesting(index) {
            return Some((ConstraintCategory::Boring, span));
        }

        let data = &mir[location.block];
        let category = if location.statement_index == data.statements.len() {
            if let Some(ref terminator) = data.terminator {
                match terminator.kind {
                    TerminatorKind::DropAndReplace { .. } => ConstraintCategory::Assignment,
                    TerminatorKind::Call { .. } => ConstraintCategory::CallArgument,
                    _ => ConstraintCategory::Other,
                }
            } else {
                ConstraintCategory::Other
            }
        } else {
            let statement = &data.statements[location.statement_index];
            match statement.kind {
                StatementKind::Assign(ref place, ref rvalue) => {
                    if *place == Place::Local(mir::RETURN_PLACE) {
                        ConstraintCategory::Return
                    } else {
                        match rvalue {
                            Rvalue::Cast(..) => ConstraintCategory::Cast,
                            Rvalue::Use(..) => ConstraintCategory::Assignment,
                            _ => ConstraintCategory::Other,
                        }
                    }
                }
                _ => ConstraintCategory::Other,
            }
        };

        Some((category, span))
    }

    /// Report an error because the universal region `fr` was required to outlive
    /// `outlived_fr` but it is not known to do so. For example:
    ///
    /// ```
    /// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
    /// ```
    ///
    /// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
    pub(super) fn report_error(
        &self,
        mir: &Mir<'tcx>,
        infcx: &InferCtxt<'_, '_, 'tcx>,
        mir_def_id: DefId,
        fr: RegionVid,
        outlived_fr: RegionVid,
        blame_span: Span,
    ) {
        debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);

        let fr_name = self.to_error_region(fr);
        let outlived_fr_name = self.to_error_region(outlived_fr);

        if let (Some(f), Some(o)) = (fr_name, outlived_fr_name) {
            let tables = infcx.tcx.typeck_tables_of(mir_def_id);
            let nice = NiceRegionError::new_from_span(infcx.tcx, blame_span, o, f, Some(tables));
            if let Some(_error_reported) = nice.try_report() {
                return;
            }
        }

        let fr_string = match fr_name {
            Some(r) => format!("free region `{}`", r),
            None => format!("free region `{:?}`", fr),
        };

        let outlived_fr_string = match outlived_fr_name {
            Some(r) => format!("free region `{}`", r),
            None => format!("free region `{:?}`", outlived_fr),
        };

        // Find all paths
        let constraint_paths = self.find_constraint_paths_between_regions(outlived_fr, |r| r == fr);
        debug!("report_error: constraint_paths={:#?}", constraint_paths);

        // Find the shortest such path.
        let path = constraint_paths.iter().min_by_key(|p| p.len()).unwrap();
        debug!("report_error: shortest_path={:?}", path);

        // Classify each of the constraints along the path.
        let mut categorized_path: Vec<(ConstraintCategory, Span)> = path.iter()
            .filter_map(|&index| self.classify_constraint(index, mir))
            .collect();
        debug!("report_error: categorized_path={:?}", categorized_path);

        // Find what appears to be the most interesting path to report to the user.
        categorized_path.sort_by(|p0, p1| p0.0.cmp(&p1.0));
        debug!("report_error: sorted_path={:?}", categorized_path);

        // If we found something, cite that as the main cause of the problem.
        if let Some((category, span)) = categorized_path.first() {
            let mut diag = infcx.tcx.sess.struct_span_err(
                *span,
                &format!(
                    "{} requires that data must outlive {}",
                    category, outlived_fr_string
                ),
            );

            diag.emit();
        } else {
            let mut diag = infcx.tcx.sess.struct_span_err(
                blame_span,
                &format!("{} does not outlive {}", fr_string, outlived_fr_string,),
            );

            diag.emit();
        }
    }

    // Find some constraint `X: Y` where:
    // - `fr1: X` transitively
    // - and `Y` is live at `elem`
    crate fn find_constraint(&self, fr1: RegionVid, elem: Location) -> RegionVid {
        let index = self.blame_constraint(fr1, elem);
        self.constraints[index].sub
    }

    /// Tries to finds a good span to blame for the fact that `fr1`
    /// contains `fr2`.
    pub(super) fn blame_constraint(
        &self,
        fr1: RegionVid,
        elem: impl ToElementIndex,
    ) -> ConstraintIndex {
        // Find everything that influenced final value of `fr`.
        let influenced_fr1 = self.dependencies(fr1);

        // Try to find some outlives constraint `'X: fr2` where `'X`
        // influenced `fr1`. Blame that.
        //
        // NB, this is a pretty bad choice most of the time. In
        // particular, the connection between `'X` and `fr1` may not
        // be obvious to the user -- not to mention the naive notion
        // of dependencies, which doesn't account for the locations of
        // contraints at all. But it will do for now.
        let relevant_constraint = self.constraints
            .iter_enumerated()
            .filter_map(|(i, constraint)| {
                if !self.liveness_constraints.contains(constraint.sub, elem) {
                    None
                } else {
                    influenced_fr1[constraint.sup]
                        .map(|distance| (distance, i))
                }
            })
            .min() // constraining fr1 with fewer hops *ought* to be more obvious
            .map(|(_dist, i)| i);

        relevant_constraint.unwrap_or_else(|| {
            bug!(
                "could not find any constraint to blame for {:?}: {:?}",
                fr1,
                elem,
            );
        })
    }

    /// Finds all regions whose values `'a` may depend on in some way.
    /// For each region, returns either `None` (does not influence
    /// `'a`) or `Some(d)` which indicates that it influences `'a`
    /// with distinct `d` (minimum number of edges that must be
    /// traversed).
    ///
    /// Used during error reporting, extremely naive and inefficient.
    fn dependencies(&self, r0: RegionVid) -> IndexVec<RegionVid, Option<usize>> {
        let mut result_set = IndexVec::from_elem(None, &self.definitions);
        let mut changed = true;
        result_set[r0] = Some(0); // distance 0 from `r0`

        while changed {
            changed = false;
            for constraint in &*self.constraints {
                if let Some(n) = result_set[constraint.sup] {
                    let m = n + 1;
                    if result_set[constraint.sub]
                        .map(|distance| m < distance)
                        .unwrap_or(true)
                    {
                        result_set[constraint.sub] = Some(m);
                        changed = true;
                    }
                }
            }
        }

        result_set
    }
}
<|endoftext|>


<commit_before>
extern crate slog_scope;

extern crate futures;
extern crate hyper;

use self::futures::future::FutureResult;
use self::futures::task::Task;

use self::futures::Stream;
use self::futures::future;
use self::futures::Future;

use hyper::StatusCode;
use hyper::header::{ContentLength, ContentType};
use hyper::server::{Service, Request, Response};
use hyper::Method::Extension;
use hyper::mime::{Mime, TopLevel, SubLevel};

use std::sync::{Arc, Mutex, mpsc};
use std::collections::HashMap;

use device::Device;
use weectrl::State;
use weectrl::StateNotification;
use error;
use xml;
use rpc;

#[derive(Clone)]
pub struct IncomingNotification {
	pub tx: Arc<Mutex<mpsc::Sender<Option<StateNotification>>>>,
    pub devices: Arc<Mutex<HashMap<String, Device>>>,
	pub task: Arc<Mutex<Option<Task>>>,
}

impl Service for IncomingNotification {
    type Request = Request;
    type Response = Response;
    type Error = hyper::Error;
    // type Future = FutureResult<Response, hyper::Error>;
    type Future = Box<Future<Item = Response, Error = hyper::Error>>;

    fn call(&self, req: Request) -> Self::Future {

        info!(slog_scope::logger(), "MESSAGE: {:?}", req.method());

		let notification_sid = match rpc::extract_sid(req.headers()) {
			Some(sid) => sid,
			None => String::new()
		};

		let devices = self.devices.clone();
		let tx = self.tx.clone();
		let task = self.task.clone();

        req.body()
            .for_each(move |chunk| {
                let data = String::from_utf8(Vec::from(&chunk[..])).unwrap();

				let mut state = State::Unknown;
 				if let Some(s) = xml::get_binary_state(&data) {
					state = State::from(s);
				}

				if state!=State::Unknown && !notification_sid.is_empty() {

					for (unique_id, dev) in devices.lock().expect(error::FATAL_LOCK).iter() {
						if let Some(device_sid) = dev.sid() {

							// Found a match, send notification to the client
							if notification_sid == device_sid {
								info!(slog_scope::logger(),
									  "Got switch update for {:?}. sid: {:?}. State: {:?}.",
									  unique_id,
									  notification_sid,
									  state);

								let n = Some(StateNotification {
									unique_id: unique_id.to_owned(),
									state: state,
								});

								let r = tx.lock().expect(error::FATAL_LOCK).send(n);

								use std::ops::Deref;
								// If channel/future closed, forget Task.
								match r {
									Ok(_) => {
										let mtx = task.lock().expect(error::FATAL_LOCK);
										match mtx.deref() {
											&Some(ref s) => s.unpark(),
											&None => (),
										}
									}
									Err(e) => {
										let mut task = task.lock().expect(error::FATAL_LOCK);
										*task = None;
										info!(slog_scope::logger(),
											  "Future cancelled. {:?}",
											  e);
									}
								}
								break; // Found match
							}
						}
					}
					return Ok(());
				}
				Err(hyper::Error::Incomplete)
            })
            .map(move |_| {
                let body: &[u8] = b"
200 OK
";
                Response::new()
                    .with_header(ContentLength(body.len() as u64))
                    .with_header(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![])))
                    .with_body(body)

            })
            .boxed()
    }
}
<commit_msg>Fixed warnings.<commit_after>
extern crate slog_scope;

extern crate futures;
extern crate hyper;

use self::futures::task::Task;

use self::futures::Stream;
use self::futures::Future;

use hyper::header::{ContentLength, ContentType};
use hyper::server::{Service, Request, Response};
use hyper::mime::{Mime, TopLevel, SubLevel};

use std::sync::{Arc, Mutex, mpsc};
use std::collections::HashMap;

use device::Device;
use weectrl::State;
use weectrl::StateNotification;
use error;
use xml;
use rpc;

#[derive(Clone)]
pub struct IncomingNotification {
	pub tx: Arc<Mutex<mpsc::Sender<Option<StateNotification>>>>,
    pub devices: Arc<Mutex<HashMap<String, Device>>>,
	pub task: Arc<Mutex<Option<Task>>>,
}

impl Service for IncomingNotification {
    type Request = Request;
    type Response = Response;
    type Error = hyper::Error;
    // type Future = FutureResult<Response, hyper::Error>;
    type Future = Box<Future<Item = Response, Error = hyper::Error>>;

    fn call(&self, req: Request) -> Self::Future {

        info!(slog_scope::logger(), "MESSAGE: {:?}", req.method());

		let notification_sid = match rpc::extract_sid(req.headers()) {
			Some(sid) => sid,
			None => String::new()
		};

		let devices = self.devices.clone();
		let tx = self.tx.clone();
		let task = self.task.clone();

        req.body()
            .for_each(move |chunk| {
                let data = String::from_utf8(Vec::from(&chunk[..])).unwrap();

				let mut state = State::Unknown;
 				if let Some(s) = xml::get_binary_state(&data) {
					state = State::from(s);
				}

				if state!=State::Unknown && !notification_sid.is_empty() {

					for (unique_id, dev) in devices.lock().expect(error::FATAL_LOCK).iter() {
						if let Some(device_sid) = dev.sid() {

							// Found a match, send notification to the client
							if notification_sid == device_sid {
								info!(slog_scope::logger(),
									  "Got switch update for {:?}. sid: {:?}. State: {:?}.",
									  unique_id,
									  notification_sid,
									  state);

								let n = Some(StateNotification {
									unique_id: unique_id.to_owned(),
									state: state,
								});

								let r = tx.lock().expect(error::FATAL_LOCK).send(n);

								use std::ops::Deref;
								// If channel/future closed, forget Task.
								match r {
									Ok(_) => {
										let mtx = task.lock().expect(error::FATAL_LOCK);
										match mtx.deref() {
											&Some(ref s) => s.unpark(),
											&None => (),
										}
									}
									Err(e) => {
										let mut task = task.lock().expect(error::FATAL_LOCK);
										*task = None;
										info!(slog_scope::logger(),
											  "Future cancelled. {:?}",
											  e);
									}
								}
								break; // Found match
							}
						}
					}
					return Ok(());
				}
				Err(hyper::Error::Incomplete)
            })
            .map(move |_| {
                let body: &[u8] = b"
200 OK
";
                Response::new()
                    .with_header(ContentLength(body.len() as u64))
                    .with_header(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![])))
                    .with_body(body)

            })
            .boxed()
    }
}
<|endoftext|>


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

use Rng;
use distributions::Distribution;

/// The Bernoulli distribution.
///
/// This is a special case of the Binomial distribution where `n = 1`.
///
/// # Example
///
/// ```rust
/// use rand::distributions::{Bernoulli, Distribution};
///
/// let d = Bernoulli::new(0.3);
/// let v = d.sample(&mut rand::thread_rng());
/// println!("{} is from a Bernoulli distribution", v);
/// ```
///
/// # Precision
///
/// This `Bernoulli` distribution uses 64 bits from the RNG (a `u64`),
/// so only probabilities that are multiples of 2-64 can be
/// represented.
#[derive(Clone, Copy, Debug)]
pub struct Bernoulli {
    /// Probability of success, relative to the maximal integer.
    p_int: u64,
}

impl Bernoulli {
    /// Construct a new `Bernoulli` with the given probability of success `p`.
    ///
    /// # Panics
    ///
    /// If `p < 0` or `p > 1`.
    ///
    /// # Precision
    ///
    /// For `p = 1.0`, the resulting distribution will always generate true.
    /// For `p = 0.0`, the resulting distribution will always generate false.
    /// Due to the limitations of floating point numbers, not all internally
    /// supported probabilities (multiples of 2-64) can be specified
    /// using this constructor. If you need more precision, use
    /// `Bernoulli::from_int` instead.
    #[inline]
    pub fn new(p: f64) -> Bernoulli {
        assert!(p >= 0.0, "Bernoulli::new called with p < 0");
        assert!(p <= 1.0, "Bernoulli::new called with p > 1");
        let p_int = if p < 1.0 {
            (p * (::core::u64::MAX as f64)) as u64
        } else {
            // Avoid overflow: u64::MAX as f64 cannot be represented as u64.
            ::core::u64::MAX
        };
        Bernoulli { p_int }
    }

    /// Construct a new `Bernoulli` with the probability of success given as an
    /// integer `p_int = p * 2^64`.
    ///
    /// `p_int = 0` corresponds to `p = 0.0`.
    /// `p_int = u64::MAX` corresponds to `p = 1.0`.
    ///
    /// This is more precise than using `Bernoulli::new`.
    #[inline]
    pub fn from_int(p_int: u64) -> Bernoulli {
        Bernoulli { p_int }
    }
}

impl Distribution<bool> for Bernoulli {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> bool {
        // Make sure to always return true for p = 1.0.
        if self.p_int == ::core::u64::MAX {
            return true;
        }
        let r: u64 = rng.gen();
        r < self.p_int
    }
}

#[cfg(test)]
mod test {
    use {Rng, SmallRng, FromEntropy};
    use distributions::Distribution;
    use super::Bernoulli;

    #[test]
    fn test_trivial() {
        let mut r = SmallRng::from_entropy();
        let always_false = Bernoulli::new(0.0);
        let always_true = Bernoulli::new(1.0);
        for _ in 0..5 {
            assert_eq!(r.sample::<bool, _>(&always_false), false);
            assert_eq!(r.sample::<bool, _>(&always_true), true);
            assert_eq!(Distribution::<bool>::sample(&always_false, &mut r), false);
            assert_eq!(Distribution::<bool>::sample(&always_true, &mut r), true);
        }
    }

    #[test]
    fn test_average() {
        const P: f64 = 0.3;
        let d = Bernoulli::new(P);
        const N: u32 = 10_000_000;

        let mut sum: u32 = 0;
        let mut rng = SmallRng::from_entropy();
        for _ in 0..N {
            if d.sample(&mut rng) {
                sum += 1;
            }
        }
        let avg = (sum as f64) / (N as f64);

        assert!((avg - P).abs() < 1e-3);
    }
}
<commit_msg>Address review feedback<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! The Bernoulli distribution.

use Rng;
use distributions::Distribution;

/// The Bernoulli distribution.
///
/// This is a special case of the Binomial distribution where `n = 1`.
///
/// # Example
///
/// ```rust
/// use rand::distributions::{Bernoulli, Distribution};
///
/// let d = Bernoulli::new(0.3);
/// let v = d.sample(&mut rand::thread_rng());
/// println!("{} is from a Bernoulli distribution", v);
/// ```
///
/// # Precision
///
/// This `Bernoulli` distribution uses 64 bits from the RNG (a `u64`),
/// so only probabilities that are multiples of 2-64 can be
/// represented.
#[derive(Clone, Copy, Debug)]
pub struct Bernoulli {
    /// Probability of success, relative to the maximal integer.
    p_int: u64,
}

impl Bernoulli {
    /// Construct a new `Bernoulli` with the given probability of success `p`.
    ///
    /// # Panics
    ///
    /// If `p < 0` or `p > 1`.
    ///
    /// # Precision
    ///
    /// For `p = 1.0`, the resulting distribution will always generate true.
    /// For `p = 0.0`, the resulting distribution will always generate false.
    ///
    /// This method is accurate for any input `p` in the range `[0, 1]` which is
    /// a multiple of 2-64. If you need more precision, use `Uniform`
    /// and a comparison instead. (Note that not all multiples of
    /// 2-64 in `[0, 1]` can be represented as a `f64`.)
    #[inline]
    pub fn new(p: f64) -> Bernoulli {
        assert!(p >= 0.0 & p <= 1.0, "Bernoulli::new not called with 0 <= p <= 0");
        let p_int = if p < 1.0 {
            (p * (::core::u64::MAX as f64)) as u64
        } else {
            // Avoid overflow: u64::MAX as f64 cannot be represented as u64.
            ::core::u64::MAX
        };
        Bernoulli { p_int }
    }
}

impl Distribution<bool> for Bernoulli {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> bool {
        // Make sure to always return true for p = 1.0.
        if self.p_int == ::core::u64::MAX {
            return true;
        }
        let r: u64 = rng.gen();
        r < self.p_int
    }
}

#[cfg(test)]
mod test {
    use {Rng, SmallRng, FromEntropy};
    use distributions::Distribution;
    use super::Bernoulli;

    #[test]
    fn test_trivial() {
        let mut r = SmallRng::from_entropy();
        let always_false = Bernoulli::new(0.0);
        let always_true = Bernoulli::new(1.0);
        for _ in 0..5 {
            assert_eq!(r.sample::<bool, _>(&always_false), false);
            assert_eq!(r.sample::<bool, _>(&always_true), true);
            assert_eq!(Distribution::<bool>::sample(&always_false, &mut r), false);
            assert_eq!(Distribution::<bool>::sample(&always_true, &mut r), true);
        }
    }

    #[test]
    fn test_average() {
        const P: f64 = 0.3;
        let d = Bernoulli::new(P);
        const N: u32 = 10_000_000;

        let mut sum: u32 = 0;
        let mut rng = SmallRng::from_entropy();
        for _ in 0..N {
            if d.sample(&mut rng) {
                sum += 1;
            }
        }
        let avg = (sum as f64) / (N as f64);

        assert!((avg - P).abs() < 1e-3);
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::cell::RefCell;
use std::sync::mpsc;
use std::fmt;
use stream::Stream;
use maybe_owned::MaybeOwned;

/// Represents a continuous value that changes over time.
///
/// Signals are usually constructed by stream operations and can be read using the `sample` or
/// `sample_with` methods.
///
/// This type is meant to be used as a black box, but you can fiddle with the enum variants if
/// you know what you're doing.
pub enum Signal<T>
{
    /// A signal with constant value.
    Constant(Rc<T>),
    /// A signal that generates it's values from a function.
    ///
    /// This is produced by `Signal::map`
    Dynamic(Rc<Fn() -> T>),
    /// A signal that contains shared data.
    ///
    /// This is produced by stream methods that create a signal.
    Shared(Rc<Fn() -> Rc<RefCell<Option<T>>>>),
    /// A signal that contains a signal, and allows sampling the inner signal directly.
    ///
    /// This is produced by `Signal::switch`
    Nested(Rc<Fn() -> Signal<T>>),
}

impl<T> Signal<T>
{
    /// Creates a signal with constant value.
    pub fn constant<V: Into<Rc<T>>>(val: V) -> Self
    {
        Signal::Constant(val.into())
    }

    /// Creates a signal that samples it's values from the supplied function.
    pub fn from_fn<F>(f: F) -> Self
        where F: Fn() -> T + 'static
    {
        Signal::Dynamic(Rc::new(f))
    }

    /// Sample by reference.
    ///
    /// This is meant to be the most efficient way when cloning is undesirable,
    /// but it requires a callback to prevent outliving internal `RwLock` borrows.
    pub fn sample_with<F, R>(&self, cb: F) -> R
        where F: FnOnce(MaybeOwned<T>) -> R
    {
        match *self
        {
            Signal::Constant(ref val) => cb(MaybeOwned::Borrowed(val)),
            Signal::Dynamic(ref f) => cb(MaybeOwned::Owned(f())),
            Signal::Shared(ref f) => {
                let st = f();
                let v = st.borrow();
                cb(MaybeOwned::Borrowed(v.as_ref().expect("storage empty")))
            },
            Signal::Nested(ref f) => f().sample_with(cb),
        }
    }
}

impl<T: Clone> Signal<T>
{
    /// Sample by value.
    ///
    /// This will clone the content of the signal.
    pub fn sample(&self) -> T
    {
        match *self
        {
            Signal::Constant(ref val) => (**val).clone(),
            Signal::Dynamic(ref f) => f(),
            Signal::Shared(ref f) => {
                let st = f();
                let v = st.borrow();
                v.clone().expect("storage empty")
            },
            Signal::Nested(ref f) => f().sample(),
        }
    }
}

impl<T: 'static> Signal<T>
{
    /// Maps a signal with the provided function.
    pub fn map<F, R>(&self, f: F) -> Signal<R>
        where F: Fn(MaybeOwned<T>) -> R + 'static,
        R: 'static
    {
        let this = self.clone();
        Signal::from_fn(move || this.sample_with(&f))
    }

    /// Samples the value of this signal every time the trigger stream fires.
    pub fn snapshot<S, F, R>(&self, trigger: &Stream<S>, f: F) -> Stream<R>
        where F: Fn(MaybeOwned<T>, MaybeOwned<S>) -> R + 'static,
        S: 'static, R: 'static
    {
        let this = self.clone();
        trigger.map(move |b| this.sample_with(|a| f(a, b)))
    }

    /// Creates a signal from a shared value.
    pub(crate) fn from_storage<A: 'static>(storage: Rc<RefCell<Option<T>>>, keepalive: A) -> Self
    {
        Signal::Shared(Rc::new(move || {
            let _keepalive = &keepalive;
            storage.clone()
        }))
    }

    /// Stores the last value sent to a channel.
    ///
    /// When sampled, the resulting signal consumes all the current values on the channel
    /// (using non-blocking operations) and returns the last value seen.
    pub fn from_channel(initial: T, rx: mpsc::Receiver<T>) -> Self
    {
        let storage = Rc::new(RefCell::new(Some(initial)));
        Signal::Shared(Rc::new(move || {
            let last = rx.try_iter().last();
            if last.is_some() { *storage.borrow_mut() = last; }
            storage.clone()
        }))
    }

    /// Creates a signal that folds the values from a channel.
    ///
    /// When sampled, the resulting signal consumes all the current values on the channel
    /// (using non-blocking operations) and folds them using the current signal value as the
    /// initial accumulator state.
    pub fn fold_channel<V, F>(initial: T, rx: mpsc::Receiver<V>, f: F) -> Self
        where F: Fn(T, V) -> T + 'static,
        V: 'static
    {
        let storage = Rc::new(RefCell::new(Some(initial)));
        Signal::Shared(Rc::new(move || {
            let acc = storage.borrow_mut().take().expect("storage empty");
            let current = rx.try_iter().fold(acc, &f);
            *storage.borrow_mut() = Some(current);
            storage.clone()
        }))
    }
}

impl<T: 'static> Signal<Signal<T>>
{
    /// Creates a new signal that samples the inner value of a nested signal.
    pub fn switch(&self) -> Signal<T>
    {
        let this = self.clone();
        Signal::Nested(Rc::new(move || this.sample()))
    }
}

impl<T> From<T> for Signal<T>
{
    fn from(val: T) -> Self
    {
        Signal::constant(val)
    }
}

impl<T> From<Rc<T>> for Signal<T>
{
    fn from(val: Rc<T>) -> Self
    {
        Signal::Constant(val)
    }
}

// the derive impl adds a `T: Clone` we don't want
impl<T> Clone for Signal<T>
{
    fn clone(&self) -> Self
    {
        match *self
        {
            Signal::Constant(ref val) => Signal::Constant(val.clone()),
            Signal::Dynamic(ref rf) => Signal::Dynamic(rf.clone()),
            Signal::Shared(ref rf) => Signal::Shared(rf.clone()),
            Signal::Nested(ref rf) => Signal::Nested(rf.clone()),
        }
    }
}

impl<T: fmt::Debug> fmt::Debug for Signal<T>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        match *self
        {
            Signal::Constant(ref val) => write!(f, "Signal::Constant({:?})", val),
            Signal::Dynamic(ref rf) => write!(f, "Signal::Dynamic(Fn@{:p})", rf),
            Signal::Shared(ref rf) => write!(f, "Signal::Shared(Fn@{:p})", rf),
            Signal::Nested(ref rf) => write!(f, "Signal::Nested(Fn@{:p})", rf),
        }
    }
}

#[cfg(test)]
mod tests
{
    use super::*;
    use std::rc::Rc;
    use std::cell::Cell;
    use std::time::Instant;

    #[test]
    fn signal_basic()
    {
        let signal = Signal::constant(42);
        assert_eq!(signal.sample(), 42);
        signal.sample_with(|val| assert_eq!(*val, 42));

        let t = Instant::now();
        let signal = Signal::from_fn(move || t);
        assert_eq!(signal.sample(), t);
        signal.sample_with(|val| assert_eq!(*val, t));

        let n = Rc::new(Cell::new(1));
        let cloned = n.clone();
        let signal = Signal::from_fn(move || cloned.get());
        let double = signal.map(|a| *a * 2);
        assert_eq!(signal.sample(), 1);
        assert_eq!(double.sample(), 2);
        n.set(13);
        assert_eq!(signal.sample(), 13);
        assert_eq!(double.sample(), 26);
    }
}
<commit_msg>implemented Display for Signal<commit_after>use std::rc::Rc;
use std::cell::RefCell;
use std::sync::mpsc;
use std::fmt;
use stream::Stream;
use maybe_owned::MaybeOwned;

/// Represents a continuous value that changes over time.
///
/// Signals are usually constructed by stream operations and can be read using the `sample` or
/// `sample_with` methods.
///
/// This type is meant to be used as a black box, but you can fiddle with the enum variants if
/// you know what you're doing.
pub enum Signal<T>
{
    /// A signal with constant value.
    Constant(Rc<T>),
    /// A signal that generates it's values from a function.
    ///
    /// This is produced by `Signal::map`
    Dynamic(Rc<Fn() -> T>),
    /// A signal that contains shared data.
    ///
    /// This is produced by stream methods that create a signal.
    Shared(Rc<Fn() -> Rc<RefCell<Option<T>>>>),
    /// A signal that contains a signal, and allows sampling the inner signal directly.
    ///
    /// This is produced by `Signal::switch`
    Nested(Rc<Fn() -> Signal<T>>),
}

impl<T> Signal<T>
{
    /// Creates a signal with constant value.
    pub fn constant<V: Into<Rc<T>>>(val: V) -> Self
    {
        Signal::Constant(val.into())
    }

    /// Creates a signal that samples it's values from the supplied function.
    pub fn from_fn<F>(f: F) -> Self
        where F: Fn() -> T + 'static
    {
        Signal::Dynamic(Rc::new(f))
    }

    /// Sample by reference.
    ///
    /// This is meant to be the most efficient way when cloning is undesirable,
    /// but it requires a callback to prevent outliving internal `RwLock` borrows.
    pub fn sample_with<F, R>(&self, cb: F) -> R
        where F: FnOnce(MaybeOwned<T>) -> R
    {
        match *self
        {
            Signal::Constant(ref val) => cb(MaybeOwned::Borrowed(val)),
            Signal::Dynamic(ref f) => cb(MaybeOwned::Owned(f())),
            Signal::Shared(ref f) => {
                let st = f();
                let v = st.borrow();
                cb(MaybeOwned::Borrowed(v.as_ref().expect("storage empty")))
            },
            Signal::Nested(ref f) => f().sample_with(cb),
        }
    }
}

impl<T: Clone> Signal<T>
{
    /// Sample by value.
    ///
    /// This will clone the content of the signal.
    pub fn sample(&self) -> T
    {
        match *self
        {
            Signal::Constant(ref val) => (**val).clone(),
            Signal::Dynamic(ref f) => f(),
            Signal::Shared(ref f) => {
                let st = f();
                let v = st.borrow();
                v.clone().expect("storage empty")
            },
            Signal::Nested(ref f) => f().sample(),
        }
    }
}

impl<T: 'static> Signal<T>
{
    /// Maps a signal with the provided function.
    pub fn map<F, R>(&self, f: F) -> Signal<R>
        where F: Fn(MaybeOwned<T>) -> R + 'static,
        R: 'static
    {
        let this = self.clone();
        Signal::from_fn(move || this.sample_with(&f))
    }

    /// Samples the value of this signal every time the trigger stream fires.
    pub fn snapshot<S, F, R>(&self, trigger: &Stream<S>, f: F) -> Stream<R>
        where F: Fn(MaybeOwned<T>, MaybeOwned<S>) -> R + 'static,
        S: 'static, R: 'static
    {
        let this = self.clone();
        trigger.map(move |b| this.sample_with(|a| f(a, b)))
    }

    /// Creates a signal from a shared value.
    pub(crate) fn from_storage<A: 'static>(storage: Rc<RefCell<Option<T>>>, keepalive: A) -> Self
    {
        Signal::Shared(Rc::new(move || {
            let _keepalive = &keepalive;
            storage.clone()
        }))
    }

    /// Stores the last value sent to a channel.
    ///
    /// When sampled, the resulting signal consumes all the current values on the channel
    /// (using non-blocking operations) and returns the last value seen.
    pub fn from_channel(initial: T, rx: mpsc::Receiver<T>) -> Self
    {
        let storage = Rc::new(RefCell::new(Some(initial)));
        Signal::Shared(Rc::new(move || {
            let last = rx.try_iter().last();
            if last.is_some() { *storage.borrow_mut() = last; }
            storage.clone()
        }))
    }

    /// Creates a signal that folds the values from a channel.
    ///
    /// When sampled, the resulting signal consumes all the current values on the channel
    /// (using non-blocking operations) and folds them using the current signal value as the
    /// initial accumulator state.
    pub fn fold_channel<V, F>(initial: T, rx: mpsc::Receiver<V>, f: F) -> Self
        where F: Fn(T, V) -> T + 'static,
        V: 'static
    {
        let storage = Rc::new(RefCell::new(Some(initial)));
        Signal::Shared(Rc::new(move || {
            let acc = storage.borrow_mut().take().expect("storage empty");
            let current = rx.try_iter().fold(acc, &f);
            *storage.borrow_mut() = Some(current);
            storage.clone()
        }))
    }
}

impl<T: 'static> Signal<Signal<T>>
{
    /// Creates a new signal that samples the inner value of a nested signal.
    pub fn switch(&self) -> Signal<T>
    {
        let this = self.clone();
        Signal::Nested(Rc::new(move || this.sample()))
    }
}

impl<T> From<T> for Signal<T>
{
    fn from(val: T) -> Self
    {
        Signal::constant(val)
    }
}

impl<T> From<Rc<T>> for Signal<T>
{
    fn from(val: Rc<T>) -> Self
    {
        Signal::Constant(val)
    }
}

// the derive impl adds a `T: Clone` we don't want
impl<T> Clone for Signal<T>
{
    fn clone(&self) -> Self
    {
        match *self
        {
            Signal::Constant(ref val) => Signal::Constant(val.clone()),
            Signal::Dynamic(ref rf) => Signal::Dynamic(rf.clone()),
            Signal::Shared(ref rf) => Signal::Shared(rf.clone()),
            Signal::Nested(ref rf) => Signal::Nested(rf.clone()),
        }
    }
}

impl<T: fmt::Debug> fmt::Debug for Signal<T>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        match *self
        {
            Signal::Constant(ref val) => write!(f, "Signal::Constant({:?})", val),
            Signal::Dynamic(ref rf) => write!(f, "Signal::Dynamic(Fn@{:p})", rf),
            Signal::Shared(ref rf) => write!(f, "Signal::Shared(Fn@{:p})", rf),
            Signal::Nested(ref rf) => write!(f, "Signal::Nested(Fn@{:p})", rf),
        }
    }
}

impl<T: fmt::Display> fmt::Display for Signal<T>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        self.sample_with(|val| fmt::Display::fmt(&*val, f))
    }
}

#[cfg(test)]
mod tests
{
    use super::*;
    use std::rc::Rc;
    use std::cell::Cell;
    use std::time::Instant;

    #[test]
    fn signal_basic()
    {
        let signal = Signal::constant(42);
        assert_eq!(signal.sample(), 42);
        signal.sample_with(|val| assert_eq!(*val, 42));

        let t = Instant::now();
        let signal = Signal::from_fn(move || t);
        assert_eq!(signal.sample(), t);
        signal.sample_with(|val| assert_eq!(*val, t));

        let n = Rc::new(Cell::new(1));
        let cloned = n.clone();
        let signal = Signal::from_fn(move || cloned.get());
        let double = signal.map(|a| *a * 2);
        assert_eq!(signal.sample(), 1);
        assert_eq!(double.sample(), 2);
        n.set(13);
        assert_eq!(signal.sample(), 13);
        assert_eq!(double.sample(), 26);
    }
}
<|endoftext|>


<commit_before>use std::io::{IoResult, IoError, IoErrorKind, TcpStream, ConnectionRefused,
              ConnectionFailed, OtherIoError, InvalidInput};
use std::io::net::ip::{ IpAddr, Ipv4Addr };

pub struct Socks4<'a> {
    socks_host: &'a str,
    socks_port: u16,
}

impl<'a> Socks4<'a> {
    pub fn new(host: &'a str, port: u16) -> Socks4 {
        Socks4 { socks_host: host, socks_port: port }
    }

    pub fn connect(&mut self, host: IpAddr, port: u16) -> IoResult<TcpStream> {
        let mut stream = try!(TcpStream::connect(self.socks_host, self.socks_port));
        try!(stream.write([0x04, 0x01]));
        try!(stream.write_be_u16(port));
        match host {
            Ipv4Addr(oct1, oct2, oct3, oct4) => {
                try!(stream.write([oct1, oct2, oct3, oct4]));
            },
            _ => { return io_err(InvalidInput, "Must be IPv4 address"); }
        };
        try!(stream.write([0x00]));

        // read null byte
        if 0 != try!(stream.read_u8()) {
            return io_err(OtherIoError, "Expected null byte not found");
        }

        // read status
        match try!(stream.read_u8()) {
            // request granted
            0x5a => {
                let _port = try!(stream.read_be_u16());
                let _ip = try!(stream.read_be_u32());

                Ok(stream)
            }
            // request rejected or failed
            0x5b => io_err(ConnectionRefused, "Request rejected or failed"),
            // request failed because client is not running identd (or unreachable)
            0x5c => io_err(ConnectionFailed, "Client unreachable"),
            // request failed because client's identd could not confirm the user ID
            // string in the request
            0x5d => io_err(ConnectionRefused, "Unknown user"),
            x => fail!("Unexpected status byte: {}", x)
        }
    }
}

fn io_err<T>(kind: IoErrorKind, desc: &'static str) -> IoResult<T> {
    Err(IoError { kind: kind, desc: desc, detail: None })
}

<commit_msg>Minor adjustments<commit_after>use std::io::{IoResult, IoError, IoErrorKind, TcpStream, ConnectionRefused,
              ConnectionFailed, OtherIoError, InvalidInput};
use std::io::net::ip::{ IpAddr, Ipv4Addr };

pub struct Socks4<'a> {
    socks_host: &'a str,
    socks_port: u16,
}

impl<'a> Socks4<'a> {
    pub fn new(host: &'a str, port: u16) -> Socks4 {
        Socks4 { socks_host: host, socks_port: port }
    }

    pub fn connect(&mut self, host: IpAddr, port: u16) -> IoResult<TcpStream> {
        let mut stream = try!(TcpStream::connect(self.socks_host, self.socks_port));
        try!(stream.write([0x04, 0x01]));
        try!(stream.write_be_u16(port));
        match host {
            Ipv4Addr(oct1, oct2, oct3, oct4) => {
                try!(stream.write([oct1, oct2, oct3, oct4]));
            },
            _ => { return io_err(InvalidInput, "Must be IPv4 address"); }
        };
        try!(stream.write([0x00]));

        // read null byte
        if 0 != try!(stream.read_u8()) {
            return io_err(OtherIoError, "Expected null byte not found");
        }

        // read status
        match try!(stream.read_u8()) {
            // request granted
            0x5a => Ok(stream),
            // request rejected or failed
            0x5b => io_err(ConnectionRefused, "Request rejected or failed"),
            // request failed because client is not running identd (or unreachable)
            0x5c => io_err(ConnectionFailed, "Client unreachable"),
            // request failed because client's identd could not confirm the user ID
            // string in the request
            0x5d => io_err(ConnectionRefused, "Unknown user"),
            x => fail!("Unexpected status byte: {}", x)
        }
    }
}

fn io_err<T>(kind: IoErrorKind, desc: &'static str) -> IoResult<T> {
    Err(IoError { kind: kind, desc: desc, detail: None })
}

<|endoftext|>


<commit_before>extern crate libc;

use libc::{c_int, c_uchar};

pub mod ffi {
    use libc::{c_int, c_uchar, c_float, c_void};
    use std::ptr;

    pub struct FontInfo {
       userdata: *const c_void,

       // pointer to .ttf file
       data: *const c_uchar,

       // offset of start of font
       fontstart: c_int,

       // number of glyphs, needed for range checking
       numGlyphs: c_int,

       // table locations as offset from start of .ttf
       loca: c_int,
       head: c_int,
       glyf: c_int,
       hhea: c_int,
       hmtx: c_int,
       kern: c_int,

       // a cmap mapping for our chosen character encoding
       index_map: c_int,

       // format needed to map from glyph index to glyph
       indexToLocFormat: c_int,
    }

    impl FontInfo {
        pub fn new() -> FontInfo {
            FontInfo {
                userdata: ptr::null(),
                data: ptr::null(),
                fontstart: 0,
                numGlyphs: 0,
                loca: 0,
                head: 0,
                glyf: 0,
                hhea: 0,
                hmtx: 0,
                kern: 0,
                index_map: 0,
                indexToLocFormat: 0,
            }
        }
    }

    #[link(name = "stb_truetype")]
    extern {
        pub fn stbtt_GetFontOffsetForIndex(
            data: *const c_uchar,
            index: c_int,
        ) -> c_int;

        pub fn stbtt_InitFont(
            info: *mut FontInfo,
            data2: *const c_uchar,
            fontstart: c_int,
        );

        pub fn stbtt_GetFontVMetrics(
            info: *const FontInfo,
            ascent: *mut c_int,
            descent: *mut c_int,
            lineGap: *mut c_int,
        );

        pub fn stbtt_FindGlyphIndex(
            info: *const FontInfo,
            unicode_codepoint: c_int,
        ) -> c_int;

        pub fn stbtt_GetGlyphHMetrics(
            info: *const FontInfo,
            glyph_index: c_int,
            advanceWidth: *mut c_int,
            eftSideBearing: *mut c_int,
        );

        pub fn stbtt_GetGlyphBitmapBox(
            font: *const FontInfo,
            glyph: c_int,
            scale_x: c_float,
            scale_y: c_float,
            ix0: *mut c_int,
            iy0: *mut c_int,
            ix1: *mut c_int,
            iy1: *mut c_int,
        );

        pub fn stbtt_GetGlyphKernAdvance(
            info: *const FontInfo,
            glyph1: c_int,
            glyph2: c_int,
        );

        pub fn stbtt_MakeGlyphBitmap(
            info: *const FontInfo,
            output: *const c_uchar,
            out_w: c_int,
            out_h: c_int,
            out_stride: c_int,
            scale_x: c_float,
            scale_y: c_float,
            glyph: c_int,
        );

        pub fn stbtt_ScaleForPixelHeight(
            info: *const FontInfo,
            height: c_float,
        ) -> c_float;

        pub fn stbtt_GetGlyphBitmap(
            info: *const FontInfo,
            scale_x: c_float,
            scale_y: c_float,
            glyph: c_int,
            width: *mut c_int,
            height: *mut c_int,
            xoff: *mut c_int,
            yoff: *mut c_int,
        ) -> *const c_uchar;
    }
}

pub struct Font {
    font_info: ffi::FontInfo,
    data: Vec<c_uchar>,
    height: f32,
    scale: f32,
    ascent: i32,
    descent: i32,
    line_gap: i32,
}

impl Font {
    pub fn new(font_path: &Path, height: f32) -> Font {
        let data = {
            use std::io::{BufferedReader, File};
            if !font_path.exists() {
                fail!("Wrong font path: {}", font_path.display());
            }
            let file = File::open(font_path);
            let mut reader = BufferedReader::new(file);
            reader.read_to_end().unwrap()
        };
        let mut font_info = ffi::FontInfo::new();
        unsafe {
            let font_offset = ffi::stbtt_GetFontOffsetForIndex(data.get(0) as *const u8, 0);
            ffi::stbtt_InitFont(&mut font_info, data.get(0) as *const u8, font_offset);
        }
        let scale = unsafe {
            ffi::stbtt_ScaleForPixelHeight(&font_info, height)
        };
        let mut c_ascent: c_int = 0;
        let mut c_descent: c_int = 0;
        let mut c_line_gap: c_int = 0;
        unsafe {
            ffi::stbtt_GetFontVMetrics(&font_info,
                &mut c_ascent, &mut c_descent, &mut c_line_gap);
        }
        let ascent = (c_ascent as f32 * scale) as i32;
        let descent = (c_descent as f32 * scale) as i32;
        let line_gap = (c_line_gap as f32 * scale) as i32;
        Font {
            font_info: font_info,
            data: data,
            height: height,
            scale: scale,
            ascent: ascent,
            descent: descent,
            line_gap: line_gap,
        }
    }

    pub fn get_glyph(&self, glyph_index: i32) -> (Vec<c_uchar>, i32, i32, i32, i32) {
        use std::vec::raw::from_buf;
        let mut w = 0;
        let mut h = 0;
        let mut xoff = 0;
        let mut yoff = 0;
        let bitmap = unsafe {
            let scale_x = 0.0;
            let scale_y = self.scale;
            let buf = ffi::stbtt_GetGlyphBitmap(
                &self.font_info,
                scale_x,
                scale_y,
                glyph_index as c_int,
                &mut w,
                &mut h,
                &mut xoff,
                &mut yoff,
            );
            from_buf(buf, (w * h) as uint)
        };
        (bitmap, w as i32, h as i32, xoff as i32, yoff as i32)
    }

    pub fn find_glyph_index(&self, c: char) -> i32 {
        unsafe {
            ffi::stbtt_FindGlyphIndex(&self.font_info, c as c_int) as i32
        }
    }

    pub fn get_glyph_bitmap_box(&self, glyph_index: i32) -> (i32, i32, i32, i32) {
        let scale_x = 0.0;
        let scale_y = self.scale;
        let mut ix0 = 0;
        let mut iy0 = 0;
        let mut ix1 = 0;
        let mut iy1 = 0;
        unsafe {
            ffi::stbtt_GetGlyphBitmapBox(
                &self.font_info,
                glyph_index as c_int,
                scale_x,
                scale_y,
                &mut ix0,
                &mut iy0,
                &mut ix1,
                &mut iy1,
            );
        }
        (ix0 as i32, iy0 as i32, ix1 as i32, iy1 as i32)
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>Fixed link attribute<commit_after>extern crate libc;

use libc::{c_int, c_uchar};

#[link(name = "stb_truetype")]
extern { }

pub mod ffi {
    use libc::{c_int, c_uchar, c_float, c_void};
    use std::ptr;

    pub struct FontInfo {
       userdata: *const c_void,

       // pointer to .ttf file
       data: *const c_uchar,

       // offset of start of font
       fontstart: c_int,

       // number of glyphs, needed for range checking
       numGlyphs: c_int,

       // table locations as offset from start of .ttf
       loca: c_int,
       head: c_int,
       glyf: c_int,
       hhea: c_int,
       hmtx: c_int,
       kern: c_int,

       // a cmap mapping for our chosen character encoding
       index_map: c_int,

       // format needed to map from glyph index to glyph
       indexToLocFormat: c_int,
    }

    impl FontInfo {
        pub fn new() -> FontInfo {
            FontInfo {
                userdata: ptr::null(),
                data: ptr::null(),
                fontstart: 0,
                numGlyphs: 0,
                loca: 0,
                head: 0,
                glyf: 0,
                hhea: 0,
                hmtx: 0,
                kern: 0,
                index_map: 0,
                indexToLocFormat: 0,
            }
        }
    }

    extern {
        pub fn stbtt_GetFontOffsetForIndex(
            data: *const c_uchar,
            index: c_int,
        ) -> c_int;

        pub fn stbtt_InitFont(
            info: *mut FontInfo,
            data2: *const c_uchar,
            fontstart: c_int,
        );

        pub fn stbtt_GetFontVMetrics(
            info: *const FontInfo,
            ascent: *mut c_int,
            descent: *mut c_int,
            lineGap: *mut c_int,
        );

        pub fn stbtt_FindGlyphIndex(
            info: *const FontInfo,
            unicode_codepoint: c_int,
        ) -> c_int;

        pub fn stbtt_GetGlyphHMetrics(
            info: *const FontInfo,
            glyph_index: c_int,
            advanceWidth: *mut c_int,
            eftSideBearing: *mut c_int,
        );

        pub fn stbtt_GetGlyphBitmapBox(
            font: *const FontInfo,
            glyph: c_int,
            scale_x: c_float,
            scale_y: c_float,
            ix0: *mut c_int,
            iy0: *mut c_int,
            ix1: *mut c_int,
            iy1: *mut c_int,
        );

        pub fn stbtt_GetGlyphKernAdvance(
            info: *const FontInfo,
            glyph1: c_int,
            glyph2: c_int,
        );

        pub fn stbtt_MakeGlyphBitmap(
            info: *const FontInfo,
            output: *const c_uchar,
            out_w: c_int,
            out_h: c_int,
            out_stride: c_int,
            scale_x: c_float,
            scale_y: c_float,
            glyph: c_int,
        );

        pub fn stbtt_ScaleForPixelHeight(
            info: *const FontInfo,
            height: c_float,
        ) -> c_float;

        pub fn stbtt_GetGlyphBitmap(
            info: *const FontInfo,
            scale_x: c_float,
            scale_y: c_float,
            glyph: c_int,
            width: *mut c_int,
            height: *mut c_int,
            xoff: *mut c_int,
            yoff: *mut c_int,
        ) -> *const c_uchar;
    }
}

pub struct Font {
    font_info: ffi::FontInfo,
    data: Vec<c_uchar>,
    height: f32,
    scale: f32,
    ascent: i32,
    descent: i32,
    line_gap: i32,
}

impl Font {
    pub fn new(font_path: &Path, height: f32) -> Font {
        let data = {
            use std::io::{BufferedReader, File};
            if !font_path.exists() {
                fail!("Wrong font path: {}", font_path.display());
            }
            let file = File::open(font_path);
            let mut reader = BufferedReader::new(file);
            reader.read_to_end().unwrap()
        };
        let mut font_info = ffi::FontInfo::new();
        unsafe {
            let font_offset = ffi::stbtt_GetFontOffsetForIndex(data.get(0) as *const u8, 0);
            ffi::stbtt_InitFont(&mut font_info, data.get(0) as *const u8, font_offset);
        }
        let scale = unsafe {
            ffi::stbtt_ScaleForPixelHeight(&font_info, height)
        };
        let mut c_ascent: c_int = 0;
        let mut c_descent: c_int = 0;
        let mut c_line_gap: c_int = 0;
        unsafe {
            ffi::stbtt_GetFontVMetrics(&font_info,
                &mut c_ascent, &mut c_descent, &mut c_line_gap);
        }
        let ascent = (c_ascent as f32 * scale) as i32;
        let descent = (c_descent as f32 * scale) as i32;
        let line_gap = (c_line_gap as f32 * scale) as i32;
        Font {
            font_info: font_info,
            data: data,
            height: height,
            scale: scale,
            ascent: ascent,
            descent: descent,
            line_gap: line_gap,
        }
    }

    pub fn get_glyph(&self, glyph_index: i32) -> (Vec<c_uchar>, i32, i32, i32, i32) {
        use std::vec::raw::from_buf;
        let mut w = 0;
        let mut h = 0;
        let mut xoff = 0;
        let mut yoff = 0;
        let bitmap = unsafe {
            let scale_x = 0.0;
            let scale_y = self.scale;
            let buf = ffi::stbtt_GetGlyphBitmap(
                &self.font_info,
                scale_x,
                scale_y,
                glyph_index as c_int,
                &mut w,
                &mut h,
                &mut xoff,
                &mut yoff,
            );
            from_buf(buf, (w * h) as uint)
        };
        (bitmap, w as i32, h as i32, xoff as i32, yoff as i32)
    }

    pub fn find_glyph_index(&self, c: char) -> i32 {
        unsafe {
            ffi::stbtt_FindGlyphIndex(&self.font_info, c as c_int) as i32
        }
    }

    pub fn get_glyph_bitmap_box(&self, glyph_index: i32) -> (i32, i32, i32, i32) {
        let scale_x = 0.0;
        let scale_y = self.scale;
        let mut ix0 = 0;
        let mut iy0 = 0;
        let mut ix1 = 0;
        let mut iy1 = 0;
        unsafe {
            ffi::stbtt_GetGlyphBitmapBox(
                &self.font_info,
                glyph_index as c_int,
                scale_x,
                scale_y,
                &mut ix0,
                &mut iy0,
                &mut ix1,
                &mut iy1,
            );
        }
        (ix0 as i32, iy0 as i32, ix1 as i32, iy1 as i32)
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>use std::num::{Int, Float, cast};
#[cfg(any(test, feature = "arbitrary"))]
use quickcheck::{Arbitrary, Gen};
use nalgebra::{Vec2, BaseFloat};
use partition::{Partition, Subdivide};

/// A partition of the unit quad [0, 1) × [0, 1)
#[derive(Copy, Clone, Show)]
pub struct UnitQuad {
    scale: u8,
    offset: [u32; 2],
}

impl UnitQuad {
    /// Create a new `UnitQuad`
    ///
    /// This asserts that the offset is valid given the scale level.
    pub fn new(scale: u8, offset: [u32; 2]) -> UnitQuad {
        assert!(scale < 32); // Otherwise exponentiation will overflow
        let max_offset = 2.pow(scale as usize);
        assert!(offset.iter().all(|&x| x < max_offset));
        UnitQuad { scale: scale, offset: offset }
    }
}

impl Subdivide for UnitQuad {
    fn subdivide(&self) -> Vec<UnitQuad> {
        [(0, 0), (0, 1), (1, 0), (1, 1)]
            .iter()
            .map(|&(di, dj)| {
                let [i, j] = self.offset;
                UnitQuad::new(self.scale + 1, [i * 2 + di, j * 2 + dj])
            })
            .collect()
    }
}

impl<T: BaseFloat> Partition<Vec2<T>> for UnitQuad
{
    fn contains(&self, elem: &Vec2<T>) -> bool {
        let width = cast::<_, T>(0.5).unwrap().powi(self.scale as i32);
        let offset = Vec2::new(
            width * cast(self.offset[0]).unwrap(),
            width * cast(self.offset[1]).unwrap(),
        );
        (offset.x < elem.x) && (elem.x < offset.x + width) &&
        (offset.y < elem.y) && (elem.y < offset.y + width)
    }
}

#[cfg(any(test, feature = "arbitrary"))]
impl Arbitrary for UnitQuad {
    fn arbitrary<G: Gen>(g: &mut G) -> UnitQuad {
        use std::cmp;
        let scale: u8 = {
            // scale >= 32 is invalid (overflow)
            // At scale >= 31 subdivision fails
            let max_scale = cmp::min(31, g.size()) as u8;
            g.gen_range(0, max_scale)
        };
        let max_offset = 2.pow(scale as usize);
        UnitQuad::new(scale, [
            g.gen_range(0, max_offset),
            g.gen_range(0, max_offset),
        ])
    }
}

#[cfg(test)]
mod test {
    pub use nalgebra::Vec2;
    pub use super::*;
    use quickcheck::{quickcheck, TestResult};
    use partition::Partition;

    partition_quickcheck!(unitquad_vec2_f32, UnitQuad, Vec2<f32>);
    partition_quickcheck!(unitquad_vec2_f64, UnitQuad, Vec2<f64>);

    #[test]
    fn unitquad_base_contains_region() {
        fn check(v: Vec2<f64>) -> TestResult {
            if v.x < 0.0 || v.x >= 1.0 || v.y < 0.0 || v.y >= 1.0 {
                TestResult::discard()
            } else {
                TestResult::from_bool(UnitQuad::new(0, [0, 0]).contains(&v))
            }
        }
        quickcheck(check as fn(Vec2<f64>) -> TestResult);
    }
}
<commit_msg>Work around strange trait privacy bug<commit_after>use std::num::{Int, Float, cast};
#[cfg(any(test, feature = "arbitrary"))]
use quickcheck::{Arbitrary, Gen};
use nalgebra::{Vec2, BaseFloat};
use partition::{Partition, Subdivide};

/// A partition of the unit quad [0, 1) × [0, 1)
#[derive(Copy, Clone, Show)]
pub struct UnitQuad {
    scale: u8,
    offset: [u32; 2],
}

impl UnitQuad {
    /// Create a new `UnitQuad`
    ///
    /// This asserts that the offset is valid given the scale level.
    pub fn new(scale: u8, offset: [u32; 2]) -> UnitQuad {
        assert!(scale < 32); // Otherwise exponentiation will overflow
        let max_offset = 2.pow(scale as usize);
        assert!(offset.iter().all(|&x| x < max_offset));
        UnitQuad { scale: scale, offset: offset }
    }
}

impl Subdivide for UnitQuad {
    fn subdivide(&self) -> Vec<UnitQuad> {
        [(0, 0), (0, 1), (1, 0), (1, 1)]
            .iter()
            .map(|&(di, dj)| {
                let [i, j] = self.offset;
                UnitQuad::new(self.scale + 1, [i * 2 + di, j * 2 + dj])
            })
            .collect()
    }
}

impl<T: BaseFloat> Partition<Vec2<T>> for UnitQuad
{
    fn contains(&self, elem: &Vec2<T>) -> bool {
        let width = cast::<_, T>(0.5).unwrap().powi(self.scale as i32);
        let offset = Vec2::new(
            width * cast(self.offset[0]).unwrap(),
            width * cast(self.offset[1]).unwrap(),
        );
        (offset.x < elem.x) && (elem.x < offset.x + width) &&
        (offset.y < elem.y) && (elem.y < offset.y + width)
    }
}

#[cfg(any(test, feature = "arbitrary"))]
impl Arbitrary for UnitQuad {
    fn arbitrary<G: Gen>(g: &mut G) -> UnitQuad {
        use std::cmp;
        // FIXME: somehow this explicit usage of the `Rng` trait is required for
        // the `.gen_range` calls, even though `Rng: Gen`. The compiler
        // complains that the "source trait is private". Curiously, adding this
        // import here fixes the same situation in the `cubemap` module as well.
        use std::rand::Rng;
        let scale: u8 = {
            // scale >= 32 is invalid (overflow)
            // At scale >= 31 subdivision fails
            let max_scale = cmp::min(31, g.size()) as u8;
            g.gen_range(0, max_scale)
        };
        let max_offset = 2.pow(scale as usize);
        UnitQuad::new(scale, [
            g.gen_range(0, max_offset),
            g.gen_range(0, max_offset),
        ])
    }
}

#[cfg(test)]
mod test {
    pub use nalgebra::Vec2;
    pub use super::*;
    use quickcheck::{quickcheck, TestResult};
    use partition::Partition;

    partition_quickcheck!(unitquad_vec2_f32, UnitQuad, Vec2<f32>);
    partition_quickcheck!(unitquad_vec2_f64, UnitQuad, Vec2<f64>);

    #[test]
    fn unitquad_base_contains_region() {
        fn check(v: Vec2<f64>) -> TestResult {
            if v.x < 0.0 || v.x >= 1.0 || v.y < 0.0 || v.y >= 1.0 {
                TestResult::discard()
            } else {
                TestResult::from_bool(UnitQuad::new(0, [0, 0]).contains(&v))
            }
        }
        quickcheck(check as fn(Vec2<f64>) -> TestResult);
    }
}
<|endoftext|>


<commit_before>//! Target information

use super::prelude::*;

#[repr(C)]
pub enum LLVMByteOrdering {
    LLVMBigEndian = 0,
    LLVMLittleEndian = 1,
}

pub enum LLVMOpaqueTargetData {}
pub type LLVMTargetDataRef = *mut LLVMOpaqueTargetData;

pub enum LLVMOpaqueTargetLibraryInfotData {}
pub type LLVMTargetLibraryInfoRef = *mut LLVMOpaqueTargetLibraryInfotData;

extern "C" {
    pub fn LLVMInitializeR600TargetInfo();
    pub fn LLVMInitializeSystemZTargetInfo();
    pub fn LLVMInitializeHexagonTargetInfo();
    pub fn LLVMInitializeNVPTXTargetInfo();
    pub fn LLVMInitializeCppBackendTargetInfo();
    pub fn LLVMInitializeMSP430TargetInfo();
    pub fn LLVMInitializeXCoreTargetInfo();
    pub fn LLVMInitializeMipsTargetInfo();
    pub fn LLVMInitializeAArch64TargetInfo();
    pub fn LLVMInitializeARMTargetInfo();
    pub fn LLVMInitializePowerPCTargetInfo();
    pub fn LLVMInitializeSparcTargetInfo();
    pub fn LLVMInitializeX86TargetInfo();
    pub fn LLVMInitializeR600Target();
    pub fn LLVMInitializeSystemZTarget();
    pub fn LLVMInitializeHexagonTarget();
    pub fn LLVMInitializeNVPTXTarget();
    pub fn LLVMInitializeCppBackendTarget();
    pub fn LLVMInitializeMSP430Target();
    pub fn LLVMInitializeXCoreTarget();
    pub fn LLVMInitializeMipsTarget();
    pub fn LLVMInitializeAArch64Target();
    pub fn LLVMInitializeARMTarget();
    pub fn LLVMInitializePowerPCTarget();
    pub fn LLVMInitializeSparcTarget();
    pub fn LLVMInitializeX86Target();
    pub fn LLVMInitializeR600TargetMC();
    pub fn LLVMInitializeSystemZTargetMC();
    pub fn LLVMInitializeHexagonTargetMC();
    pub fn LLVMInitializeNVPTXTargetMC();
    pub fn LLVMInitializeCppBackendTargetMC();
    pub fn LLVMInitializeMSP430TargetMC();
    pub fn LLVMInitializeXCoreTargetMC();
    pub fn LLVMInitializeMipsTargetMC();
    pub fn LLVMInitializeAArch64TargetMC();
    pub fn LLVMInitializeARMTargetMC();
    pub fn LLVMInitializePowerPCTargetMC();
    pub fn LLVMInitializeSparcTargetMC();
    pub fn LLVMInitializeX86TargetMC();
    pub fn LLVMInitializeR600AsmPrinter();
    pub fn LLVMInitializeSystemZAsmPrinter();
    pub fn LLVMInitializeHexagonAsmPrinter();
    pub fn LLVMInitializeNVPTXAsmPrinter();
    pub fn LLVMInitializeMSP430AsmPrinter();
    pub fn LLVMInitializeXCoreAsmPrinter();
    pub fn LLVMInitializeMipsAsmPrinter();
    pub fn LLVMInitializeAArch64AsmPrinter();
    pub fn LLVMInitializeARMAsmPrinter();
    pub fn LLVMInitializePowerPCAsmPrinter();
    pub fn LLVMInitializeSparcAsmPrinter();
    pub fn LLVMInitializeX86AsmPrinter();
    pub fn LLVMInitializeR600AsmParser();
    pub fn LLVMInitializeSystemZAsmParser();
    pub fn LLVMInitializeMipsAsmParser();
    pub fn LLVMInitializeAArch64AsmParser();
    pub fn LLVMInitializeARMAsmParser();
    pub fn LLVMInitializePowerPCAsmParser();
    pub fn LLVMInitializeSparcAsmParser();
    pub fn LLVMInitializeX86AsmParser();
    pub fn LLVMInitializeSystemZDisassembler();
    pub fn LLVMInitializeHexagonDisassembler();
    pub fn LLVMInitializeXCoreDisassembler();
    pub fn LLVMInitializeMipsDisassembler();
    pub fn LLVMInitializeAArch64Disassembler();
    pub fn LLVMInitializeARMDisassembler();
    pub fn LLVMInitializePowerPCDisassembler();
    pub fn LLVMInitializeSparcDisassembler();
    pub fn LLVMInitializeX86Disassembler();
}

extern "C" {
    /// Get the data layout for a module.
    pub fn LLVMGetModuleDataLayout(M: LLVMModuleRef) -> LLVMTargetDataRef;
    /// Set the data layout for a module.
    pub fn LLVMSetModuleDataLayout(M: LLVMModuleRef, R: LLVMTargetDataRef);
    /// Create target data from a target layout string.
    pub fn LLVMCreateTargetData(StringRep: *const ::libc::c_char) -> LLVMTargetDataRef;
    pub fn LLVMAddTargetLibraryInfo(TLI: LLVMTargetLibraryInfoRef, PM: LLVMPassManagerRef);
    pub fn LLVMCopyStringRepOfTargetData(TD: LLVMTargetDataRef) -> *mut ::libc::c_char;
    pub fn LLVMByteOrder(TD: LLVMTargetDataRef) -> LLVMByteOrdering;
    pub fn LLVMPointerSize(TD: LLVMTargetDataRef) -> ::libc::c_uint;
    pub fn LLVMPointerSizeForAS(TD: LLVMTargetDataRef, AS: ::libc::c_uint) -> ::libc::c_uint;
    pub fn LLVMIntPtrType(TD: LLVMTargetDataRef) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeForAS(TD: LLVMTargetDataRef, AS: ::libc::c_uint) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeInContext(C: LLVMContextRef, TD: LLVMTargetDataRef) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeForASInContext(C: LLVMContextRef,
                                        TD: LLVMTargetDataRef,
                                        AS: ::libc::c_uint)
                                        -> LLVMTypeRef;
    pub fn LLVMSizeOfTypeInBits(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMStoreSizeOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMABISizeOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMABIAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMCallFrameAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMPreferredAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMPreferredAlignmentOfGlobal(TD: LLVMTargetDataRef,
                                          GlobalVar: LLVMValueRef)
                                          -> ::libc::c_uint;
    pub fn LLVMElementAtOffset(TD: LLVMTargetDataRef,
                               StructTy: LLVMTypeRef,
                               Offset: ::libc::c_ulonglong)
                               -> ::libc::c_uint;
    pub fn LLVMOffsetOfElement(TD: LLVMTargetDataRef,
                               StructTy: LLVMTypeRef,
                               Element: ::libc::c_uint)
                               -> ::libc::c_ulonglong;
    pub fn LLVMDisposeTargetData(TD: LLVMTargetDataRef);
}

// Functions from our target wrappers, since the C interface defines them with
// macros (wrappers/target.c).
extern "C" {
    pub fn LLVM_InitializeAllTargetInfos();
    pub fn LLVM_InitializeAllTargets();
    pub fn LLVM_InitializeAllTargetMCs();
    pub fn LLVM_InitializeAllAsmPrinters();
    pub fn LLVM_InitializeAllAsmParsers();
    pub fn LLVM_InitializeAllDisassemblers();

    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeTarget() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeAsmParser() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeAsmPrinter() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeDisassembler() -> LLVMBool;
}
<commit_msg>R600 target renamed to AMDGPU.<commit_after>//! Target information

use super::prelude::*;

#[repr(C)]
pub enum LLVMByteOrdering {
    LLVMBigEndian = 0,
    LLVMLittleEndian = 1,
}

pub enum LLVMOpaqueTargetData {}
pub type LLVMTargetDataRef = *mut LLVMOpaqueTargetData;

pub enum LLVMOpaqueTargetLibraryInfotData {}
pub type LLVMTargetLibraryInfoRef = *mut LLVMOpaqueTargetLibraryInfotData;

extern "C" {
    pub fn LLVMInitializeAMDGPUTargetInfo();
    pub fn LLVMInitializeSystemZTargetInfo();
    pub fn LLVMInitializeHexagonTargetInfo();
    pub fn LLVMInitializeNVPTXTargetInfo();
    pub fn LLVMInitializeCppBackendTargetInfo();
    pub fn LLVMInitializeMSP430TargetInfo();
    pub fn LLVMInitializeXCoreTargetInfo();
    pub fn LLVMInitializeMipsTargetInfo();
    pub fn LLVMInitializeAArch64TargetInfo();
    pub fn LLVMInitializeARMTargetInfo();
    pub fn LLVMInitializePowerPCTargetInfo();
    pub fn LLVMInitializeSparcTargetInfo();
    pub fn LLVMInitializeX86TargetInfo();
    pub fn LLVMInitializeAMDGPUTarget();
    pub fn LLVMInitializeSystemZTarget();
    pub fn LLVMInitializeHexagonTarget();
    pub fn LLVMInitializeNVPTXTarget();
    pub fn LLVMInitializeCppBackendTarget();
    pub fn LLVMInitializeMSP430Target();
    pub fn LLVMInitializeXCoreTarget();
    pub fn LLVMInitializeMipsTarget();
    pub fn LLVMInitializeAArch64Target();
    pub fn LLVMInitializeARMTarget();
    pub fn LLVMInitializePowerPCTarget();
    pub fn LLVMInitializeSparcTarget();
    pub fn LLVMInitializeX86Target();
    pub fn LLVMInitializeAMDGPUTargetMC();
    pub fn LLVMInitializeSystemZTargetMC();
    pub fn LLVMInitializeHexagonTargetMC();
    pub fn LLVMInitializeNVPTXTargetMC();
    pub fn LLVMInitializeCppBackendTargetMC();
    pub fn LLVMInitializeMSP430TargetMC();
    pub fn LLVMInitializeXCoreTargetMC();
    pub fn LLVMInitializeMipsTargetMC();
    pub fn LLVMInitializeAArch64TargetMC();
    pub fn LLVMInitializeARMTargetMC();
    pub fn LLVMInitializePowerPCTargetMC();
    pub fn LLVMInitializeSparcTargetMC();
    pub fn LLVMInitializeX86TargetMC();
    pub fn LLVMInitializeAMDGPUAsmPrinter();
    pub fn LLVMInitializeSystemZAsmPrinter();
    pub fn LLVMInitializeHexagonAsmPrinter();
    pub fn LLVMInitializeNVPTXAsmPrinter();
    pub fn LLVMInitializeMSP430AsmPrinter();
    pub fn LLVMInitializeXCoreAsmPrinter();
    pub fn LLVMInitializeMipsAsmPrinter();
    pub fn LLVMInitializeAArch64AsmPrinter();
    pub fn LLVMInitializeARMAsmPrinter();
    pub fn LLVMInitializePowerPCAsmPrinter();
    pub fn LLVMInitializeSparcAsmPrinter();
    pub fn LLVMInitializeX86AsmPrinter();
    pub fn LLVMInitializeAMDGPUAsmParser();
    pub fn LLVMInitializeSystemZAsmParser();
    pub fn LLVMInitializeMipsAsmParser();
    pub fn LLVMInitializeAArch64AsmParser();
    pub fn LLVMInitializeARMAsmParser();
    pub fn LLVMInitializePowerPCAsmParser();
    pub fn LLVMInitializeSparcAsmParser();
    pub fn LLVMInitializeX86AsmParser();
    pub fn LLVMInitializeSystemZDisassembler();
    pub fn LLVMInitializeHexagonDisassembler();
    pub fn LLVMInitializeXCoreDisassembler();
    pub fn LLVMInitializeMipsDisassembler();
    pub fn LLVMInitializeAArch64Disassembler();
    pub fn LLVMInitializeARMDisassembler();
    pub fn LLVMInitializePowerPCDisassembler();
    pub fn LLVMInitializeSparcDisassembler();
    pub fn LLVMInitializeX86Disassembler();
}

extern "C" {
    /// Get the data layout for a module.
    pub fn LLVMGetModuleDataLayout(M: LLVMModuleRef) -> LLVMTargetDataRef;
    /// Set the data layout for a module.
    pub fn LLVMSetModuleDataLayout(M: LLVMModuleRef, R: LLVMTargetDataRef);
    /// Create target data from a target layout string.
    pub fn LLVMCreateTargetData(StringRep: *const ::libc::c_char) -> LLVMTargetDataRef;
    pub fn LLVMAddTargetLibraryInfo(TLI: LLVMTargetLibraryInfoRef, PM: LLVMPassManagerRef);
    pub fn LLVMCopyStringRepOfTargetData(TD: LLVMTargetDataRef) -> *mut ::libc::c_char;
    pub fn LLVMByteOrder(TD: LLVMTargetDataRef) -> LLVMByteOrdering;
    pub fn LLVMPointerSize(TD: LLVMTargetDataRef) -> ::libc::c_uint;
    pub fn LLVMPointerSizeForAS(TD: LLVMTargetDataRef, AS: ::libc::c_uint) -> ::libc::c_uint;
    pub fn LLVMIntPtrType(TD: LLVMTargetDataRef) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeForAS(TD: LLVMTargetDataRef, AS: ::libc::c_uint) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeInContext(C: LLVMContextRef, TD: LLVMTargetDataRef) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeForASInContext(C: LLVMContextRef,
                                        TD: LLVMTargetDataRef,
                                        AS: ::libc::c_uint)
                                        -> LLVMTypeRef;
    pub fn LLVMSizeOfTypeInBits(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMStoreSizeOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMABISizeOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMABIAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMCallFrameAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMPreferredAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMPreferredAlignmentOfGlobal(TD: LLVMTargetDataRef,
                                          GlobalVar: LLVMValueRef)
                                          -> ::libc::c_uint;
    pub fn LLVMElementAtOffset(TD: LLVMTargetDataRef,
                               StructTy: LLVMTypeRef,
                               Offset: ::libc::c_ulonglong)
                               -> ::libc::c_uint;
    pub fn LLVMOffsetOfElement(TD: LLVMTargetDataRef,
                               StructTy: LLVMTypeRef,
                               Element: ::libc::c_uint)
                               -> ::libc::c_ulonglong;
    pub fn LLVMDisposeTargetData(TD: LLVMTargetDataRef);
}

// Functions from our target wrappers, since the C interface defines them with
// macros (wrappers/target.c).
extern "C" {
    pub fn LLVM_InitializeAllTargetInfos();
    pub fn LLVM_InitializeAllTargets();
    pub fn LLVM_InitializeAllTargetMCs();
    pub fn LLVM_InitializeAllAsmPrinters();
    pub fn LLVM_InitializeAllAsmParsers();
    pub fn LLVM_InitializeAllDisassemblers();

    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeTarget() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeAsmParser() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeAsmPrinter() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeDisassembler() -> LLVMBool;
}
<|endoftext|>