<commit_before>use rand::Rng;
use std::fmt;

/// Simple implementation of [Reservoir Sampling](https://en.wikipedia.org/wiki/Reservoir_sampling)
/// with [fast approximation](https://erikerlandson.github.io/blog/2015/11/20/very-fast-reservoir-sampling/)
pub struct ReservoirSampling<T, R>
where
    R: Rng,
{
    k: usize,
    rng: R,
    reservoir: Vec<T>,
    i: usize,
    skip_until: usize,
}

impl<T, R> ReservoirSampling<T, R>
where
    R: Rng,
{
    /// Create new reservoir sampler that keeps `k` samples and uses `rng` for its random
    /// decisions.
    pub fn new(k: usize, rng: R) -> ReservoirSampling<T, R> {
        ReservoirSampling {
            k: k,
            rng: rng,
            reservoir: vec![],
            i: 0,
            skip_until: 0,
        }
    }

    /// Number of samples that should be kept.
    pub fn k(&self) -> usize {
        self.k
    }

    /// Read-only copy of the reservoir. Contains at most `k` entries.
    pub fn reservoir(&self) -> &Vec<T> {
        &self.reservoir
    }

    /// Number of data points seen.
    pub fn i(&self) -> usize {
        self.i
    }

    /// Observe new data point.
    pub fn add(&mut self, obj: T) {
        let t = self.k * 4; // TODO: make this a parameter

        if self.i < self.k {
            // initial fill-up
            self.reservoir.push(obj)
        } else if self.i < t {
            // normal reservoir sampling
            let j = self.rng.gen_range::<usize>(0, self.i);
            if j < self.k {
                self.reservoir[j] = obj;
            }
        } else if self.i >= self.skip_until {
            // fast skipping approximation
            let j = self.rng.gen_range::<usize>(0, self.k);
            self.reservoir[j] = obj;

            // calculate next skip
            let p = (self.k as f64) / ((self.i + 1) as f64);
            let u = 1. - self.rng.gen_range::<f64>(0., 1.); // (0.0, 1.0]
            let g = (u.ln() / (1. - p).ln()).floor() as usize;
            self.skip_until = self.i + g;
        }

        self.i += 1;
    }

    /// Checks if reservoir is empty (i.e. no data points where observed)
    pub fn is_empty(&self) -> bool {
        self.i == 0
    }

    /// Clear sampler state. It now behaves like a fresh one (i.e. no data points seen so far).
    pub fn clear(&mut self) {
        self.i = 0;
        self.skip_until = 0;
        self.reservoir.clear();
    }
}

impl<T, R> fmt::Debug for ReservoirSampling<T, R>
where
    R: Rng,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ReservoirSampling {{ k: {} }}", self.k)
    }
}

impl<T, R> Extend<T> for ReservoirSampling<T, R>
where
    R: Rng,
{
    fn extend<S: IntoIterator<Item = T>>(&mut self, iter: S) {
        for elem in iter {
            self.add(elem);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::ReservoirSampling;
    use rand::ChaChaRng;

    #[test]
    fn getter() {
        let rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        assert_eq!(rs.k(), 10);
        assert_eq!(rs.i(), 0);
        assert_eq!(rs.reservoir(), &vec![]);
    }

    #[test]
    fn empty() {
        let rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        assert!(rs.is_empty());
        assert!(rs.reservoir().is_empty());
    }

    #[test]
    fn add_k() {
        let mut rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        for i in 0..10 {
            rs.add(i);
        }
        assert_eq!(rs.i(), 10);
        assert_eq!(rs.reservoir(), &vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
    }

    #[test]
    fn add_parts() {
        let mut rs = ReservoirSampling::<u64, ChaChaRng>::new(100, ChaChaRng::new_unseeded());
        for _ in 0..1500 {
            rs.add(0);
        }
        for _ in 0..7500 {
            rs.add(1);
        }
        for _ in 0..1000 {
            rs.add(0);
        }
        assert!((rs.reservoir().iter().sum::<u64>() as i64 - 75).abs() < 5);
    }

    #[test]
    fn debug() {
        let rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        assert_eq!(format!("{:?}", rs), "ReservoirSampling { k: 10 }");
    }

    #[test]
    fn clear() {
        let mut rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        for i in 0..10 {
            rs.add(i);
        }
        rs.clear();
        for i in 10..20 {
            rs.add(i);
        }
        assert_eq!(rs.i(), 10);
        assert_eq!(
            rs.reservoir(),
            &vec![10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
        );
    }

    #[test]
    fn extend() {
        let mut rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        rs.extend(0..10);
        assert_eq!(rs.i(), 10);
        assert_eq!(rs.reservoir(), &vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
    }
}
<commit_msg>reservoirsampling: impl Clone<commit_after>use rand::Rng;
use std::fmt;

/// Simple implementation of [Reservoir Sampling](https://en.wikipedia.org/wiki/Reservoir_sampling)
/// with [fast approximation](https://erikerlandson.github.io/blog/2015/11/20/very-fast-reservoir-sampling/)
#[derive(Clone)]
pub struct ReservoirSampling<T, R>
where
    R: Rng,
{
    k: usize,
    rng: R,
    reservoir: Vec<T>,
    i: usize,
    skip_until: usize,
}

impl<T, R> ReservoirSampling<T, R>
where
    R: Rng,
{
    /// Create new reservoir sampler that keeps `k` samples and uses `rng` for its random
    /// decisions.
    pub fn new(k: usize, rng: R) -> ReservoirSampling<T, R> {
        ReservoirSampling {
            k: k,
            rng: rng,
            reservoir: vec![],
            i: 0,
            skip_until: 0,
        }
    }

    /// Number of samples that should be kept.
    pub fn k(&self) -> usize {
        self.k
    }

    /// Read-only copy of the reservoir. Contains at most `k` entries.
    pub fn reservoir(&self) -> &Vec<T> {
        &self.reservoir
    }

    /// Number of data points seen.
    pub fn i(&self) -> usize {
        self.i
    }

    /// Observe new data point.
    pub fn add(&mut self, obj: T) {
        let t = self.k * 4; // TODO: make this a parameter

        if self.i < self.k {
            // initial fill-up
            self.reservoir.push(obj)
        } else if self.i < t {
            // normal reservoir sampling
            let j = self.rng.gen_range::<usize>(0, self.i);
            if j < self.k {
                self.reservoir[j] = obj;
            }
        } else if self.i >= self.skip_until {
            // fast skipping approximation
            let j = self.rng.gen_range::<usize>(0, self.k);
            self.reservoir[j] = obj;

            // calculate next skip
            let p = (self.k as f64) / ((self.i + 1) as f64);
            let u = 1. - self.rng.gen_range::<f64>(0., 1.); // (0.0, 1.0]
            let g = (u.ln() / (1. - p).ln()).floor() as usize;
            self.skip_until = self.i + g;
        }

        self.i += 1;
    }

    /// Checks if reservoir is empty (i.e. no data points where observed)
    pub fn is_empty(&self) -> bool {
        self.i == 0
    }

    /// Clear sampler state. It now behaves like a fresh one (i.e. no data points seen so far).
    pub fn clear(&mut self) {
        self.i = 0;
        self.skip_until = 0;
        self.reservoir.clear();
    }
}

impl<T, R> fmt::Debug for ReservoirSampling<T, R>
where
    R: Rng,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ReservoirSampling {{ k: {} }}", self.k)
    }
}

impl<T, R> Extend<T> for ReservoirSampling<T, R>
where
    R: Rng,
{
    fn extend<S: IntoIterator<Item = T>>(&mut self, iter: S) {
        for elem in iter {
            self.add(elem);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::ReservoirSampling;
    use rand::ChaChaRng;

    #[test]
    fn getter() {
        let rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        assert_eq!(rs.k(), 10);
        assert_eq!(rs.i(), 0);
        assert_eq!(rs.reservoir(), &vec![]);
    }

    #[test]
    fn empty() {
        let rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        assert!(rs.is_empty());
        assert!(rs.reservoir().is_empty());
    }

    #[test]
    fn add_k() {
        let mut rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        for i in 0..10 {
            rs.add(i);
        }
        assert_eq!(rs.i(), 10);
        assert_eq!(rs.reservoir(), &vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
    }

    #[test]
    fn add_parts() {
        let mut rs = ReservoirSampling::<u64, ChaChaRng>::new(100, ChaChaRng::new_unseeded());
        for _ in 0..1500 {
            rs.add(0);
        }
        for _ in 0..7500 {
            rs.add(1);
        }
        for _ in 0..1000 {
            rs.add(0);
        }
        assert!((rs.reservoir().iter().sum::<u64>() as i64 - 75).abs() < 5);
    }

    #[test]
    fn debug() {
        let rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        assert_eq!(format!("{:?}", rs), "ReservoirSampling { k: 10 }");
    }

    #[test]
    fn clear() {
        let mut rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        for i in 0..10 {
            rs.add(i);
        }
        rs.clear();
        for i in 10..20 {
            rs.add(i);
        }
        assert_eq!(rs.i(), 10);
        assert_eq!(
            rs.reservoir(),
            &vec![10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
        );
    }

    #[test]
    fn extend() {
        let mut rs = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        rs.extend(0..10);
        assert_eq!(rs.i(), 10);
        assert_eq!(rs.reservoir(), &vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
    }

    #[test]
    fn clone() {
        let mut rs1 = ReservoirSampling::<u64, ChaChaRng>::new(10, ChaChaRng::new_unseeded());
        for i in 0..10 {
            rs1.add(i);
        }
        let mut rs2 = rs1.clone();
        for _ in 0..1000 {
            rs2.add(99);
        }
        assert_eq!(rs1.i(), 10);
        assert_eq!(rs2.i(), 1010);
        assert_eq!(rs1.reservoir(), &vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
        assert_eq!(
            rs2.reservoir(),
            &vec![99, 99, 99, 99, 99, 99, 99, 99, 99, 99]
        );
    }
}
<|endoftext|>


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

//! A MIR walk gathering a union-crfind of assigned locals, for the purpose of locating the ones
//! escaping into the output.

use rustc::mir::visit::Visitor;
use rustc::mir::*;
use rustc::ty::{self, TyCtxt};

use rustc_data_structures::indexed_vec::Idx;
use rustc_data_structures::unify as ut;

crate struct EscapingLocals {
    unification_table: ut::UnificationTable<ut::InPlace<AssignedLocal>>,
}

impl EscapingLocals {
    crate fn compute(tcx: TyCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) -> Self {
        let mut visitor = GatherAssignedLocalsVisitor::new(tcx, mir);
        visitor.visit_mir(mir);

        EscapingLocals {
            unification_table: visitor.unification_table,
        }
    }

    /// True if `local` is known to escape into static
    /// memory.
    crate fn escapes_into_return(&mut self, local: Local) -> bool {
        let return_place = AssignedLocal::from(RETURN_PLACE);
        let other_place = AssignedLocal::from(local);
        self.unification_table.unioned(return_place, other_place)
    }
}

/// The MIR visitor gathering the union-find of the locals used in
/// assignments.
struct GatherAssignedLocalsVisitor<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
    unification_table: ut::UnificationTable<ut::InPlace<AssignedLocal>>,
    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
    mir: &'cx Mir<'tcx>,
}

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
struct AssignedLocal(u32);

impl ut::UnifyKey for AssignedLocal {
    type Value = ();

    fn index(&self) -> u32 {
        self.0
    }

    fn from_index(i: u32) -> AssignedLocal {
        AssignedLocal(i)
    }

    fn tag() -> &'static str {
        "AssignedLocal"
    }
}

impl From<Local> for AssignedLocal {
    fn from(item: Local) -> Self {
        // newtype_indexes use usize but are u32s.
        assert!(item.index() < ::std::u32::MAX as usize);
        AssignedLocal(item.index() as u32)
    }
}

impl GatherAssignedLocalsVisitor<'cx, 'gcx, 'tcx> {
    fn new(tcx: TyCtxt<'cx, 'gcx, 'tcx>, mir: &'cx Mir<'tcx>) -> Self {
        Self {
            unification_table: ut::UnificationTable::new(),
            tcx,
            mir,
        }
    }

    fn union_locals_if_needed(&mut self, lvalue: Option<Local>, rvalue: Option<Local>) {
        if let Some(lvalue) = lvalue {
            if let Some(rvalue) = rvalue {
                if lvalue != rvalue {
                    debug!("EscapingLocals: union {:?} and {:?}", lvalue, rvalue);
                    self.unification_table
                        .union(AssignedLocal::from(lvalue), AssignedLocal::from(rvalue));
                }
            }
        }
    }
}

// Returns the potential `Local` associated to this `Place` or `PlaceProjection`
fn find_local_in_place(place: &Place) -> Option<Local> {
    match place {
        Place::Local(local) => Some(*local),

        // If you do e.g. `x = a.f` then only *part* of the type of
        // `a` escapes into `x` (the part contained in `f`); if `a`'s
        // type has regions that don't appear in `f`, those might not
        // escape.
        Place::Projection(..) => None,

        Place::Static { .. } | Place::Promoted { .. } => None,
    }
}

// Returns the potential `Local` in this `Operand`.
fn find_local_in_operand(op: &Operand) -> Option<Local> {
    // Conservatively check a subset of `Operand`s we know our
    // benchmarks track, for example `html5ever`.
    match op {
        Operand::Copy(place) | Operand::Move(place) => find_local_in_place(place),
        Operand::Constant(_) => None,
    }
}

impl Visitor<'tcx> for GatherAssignedLocalsVisitor<'_, '_, 'tcx> {
    fn visit_mir(&mut self, mir: &Mir<'tcx>) {
        // We need as many union-find keys as there are locals
        for _ in 0..mir.local_decls.len() {
            self.unification_table.new_key(());
        }

        self.super_mir(mir);
    }

    fn visit_assign(
        &mut self,
        block: BasicBlock,
        place: &Place<'tcx>,
        rvalue: &Rvalue<'tcx>,
        location: Location,
    ) {
        let local = find_local_in_place(place);

        // Conservatively check a subset of `Rvalue`s we know our
        // benchmarks track, for example `html5ever`.
        match rvalue {
            Rvalue::Use(op) => self.union_locals_if_needed(local, find_local_in_operand(op)),
            Rvalue::Ref(_, _, place) => {
                // Special case: if you have `X = &*Y` where `Y` is a
                // reference, then the outlives relationships should
                // ensure that all regions in `Y` are constrained by
                // regions in `X`.
                if let Place::Projection(proj) = place {
                    if let ProjectionElem::Deref = proj.elem {
                        if let ty::TyRef(..) = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx).sty
                        {
                            self.union_locals_if_needed(local, find_local_in_place(&proj.base));
                        }
                    }
                }

                self.union_locals_if_needed(local, find_local_in_place(place))
            }

            Rvalue::Cast(kind, op, _) => match kind {
                CastKind::Unsize => self.union_locals_if_needed(local, find_local_in_operand(op)),
                _ => (),
            },

            Rvalue::Aggregate(_, ops) => {
                for rvalue in ops.iter().map(find_local_in_operand) {
                    self.union_locals_if_needed(local, rvalue);
                }
            }

            _ => (),
        };

        self.super_assign(block, place, rvalue, location);
    }
}
<commit_msg>add a comment explaining the idea<commit_after>// Copyright 2016 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.

//! Identify those variables whose entire value will eventually be
//! returned from the fn via the RETURN_PLACE. As an optimization, we
//! can skip computing liveness results for those variables. The idea
//! is that the return type of the fn only ever contains free
//! regions. Therefore, the types of those variables are going to
//! ultimately be contrained to outlive those free regions -- since
//! free regions are always live for the entire body, this implies
//! that the liveness results are not important for those regions.
//! This is most important in the "fns" that we create to represent static
//! values, since those are often really quite large, and all regions in them
//! will ultimately be constrained to be `'static`. Two examples:
//!
//! ```
//! fn foo() -> &'static [u32] { &[] }
//! static FOO: &[u32] = &[];
//! ```
//!
//! In both these cases, the return value will only have static lifetime.
//!
//! NB: The simple logic here relies on the fact that outlives
//! relations in our analysis don't have locations. Otherwise, we
//! would have to restrict ourselves to values that are
//! *unconditionally* returned (which would still cover the "big
//! static value" case).
//!
//! The way that this code works is to use union-find -- we iterate
//! over the MIR and union together two variables X and Y if all
//! regions in the value of Y are going to be stored into X -- that
//! is, if `typeof(X): 'a` requires that `typeof(Y): 'a`. This means
//! that e.g. we can union together `x` and `y` if we have something
//! like `x = (y, 22)`, but not something like `x = y.f` (since there
//! may be regions in the type of `y` that do not appear in the field
//! `f`).

use rustc::mir::visit::Visitor;
use rustc::mir::*;
use rustc::ty::{self, TyCtxt};

use rustc_data_structures::indexed_vec::Idx;
use rustc_data_structures::unify as ut;

crate struct EscapingLocals {
    unification_table: ut::UnificationTable<ut::InPlace<AssignedLocal>>,
}

impl EscapingLocals {
    crate fn compute(tcx: TyCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) -> Self {
        let mut visitor = GatherAssignedLocalsVisitor::new(tcx, mir);
        visitor.visit_mir(mir);

        EscapingLocals {
            unification_table: visitor.unification_table,
        }
    }

    /// True if `local` is known to escape into static
    /// memory.
    crate fn escapes_into_return(&mut self, local: Local) -> bool {
        let return_place = AssignedLocal::from(RETURN_PLACE);
        let other_place = AssignedLocal::from(local);
        self.unification_table.unioned(return_place, other_place)
    }
}

/// The MIR visitor gathering the union-find of the locals used in
/// assignments.
struct GatherAssignedLocalsVisitor<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
    unification_table: ut::UnificationTable<ut::InPlace<AssignedLocal>>,
    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
    mir: &'cx Mir<'tcx>,
}

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
struct AssignedLocal(u32);

impl ut::UnifyKey for AssignedLocal {
    type Value = ();

    fn index(&self) -> u32 {
        self.0
    }

    fn from_index(i: u32) -> AssignedLocal {
        AssignedLocal(i)
    }

    fn tag() -> &'static str {
        "AssignedLocal"
    }
}

impl From<Local> for AssignedLocal {
    fn from(item: Local) -> Self {
        // newtype_indexes use usize but are u32s.
        assert!(item.index() < ::std::u32::MAX as usize);
        AssignedLocal(item.index() as u32)
    }
}

impl GatherAssignedLocalsVisitor<'cx, 'gcx, 'tcx> {
    fn new(tcx: TyCtxt<'cx, 'gcx, 'tcx>, mir: &'cx Mir<'tcx>) -> Self {
        Self {
            unification_table: ut::UnificationTable::new(),
            tcx,
            mir,
        }
    }

    fn union_locals_if_needed(&mut self, lvalue: Option<Local>, rvalue: Option<Local>) {
        if let Some(lvalue) = lvalue {
            if let Some(rvalue) = rvalue {
                if lvalue != rvalue {
                    debug!("EscapingLocals: union {:?} and {:?}", lvalue, rvalue);
                    self.unification_table
                        .union(AssignedLocal::from(lvalue), AssignedLocal::from(rvalue));
                }
            }
        }
    }
}

// Returns the potential `Local` associated to this `Place` or `PlaceProjection`
fn find_local_in_place(place: &Place) -> Option<Local> {
    match place {
        Place::Local(local) => Some(*local),

        // If you do e.g. `x = a.f` then only *part* of the type of
        // `a` escapes into `x` (the part contained in `f`); if `a`'s
        // type has regions that don't appear in `f`, those might not
        // escape.
        Place::Projection(..) => None,

        Place::Static { .. } | Place::Promoted { .. } => None,
    }
}

// Returns the potential `Local` in this `Operand`.
fn find_local_in_operand(op: &Operand) -> Option<Local> {
    // Conservatively check a subset of `Operand`s we know our
    // benchmarks track, for example `html5ever`.
    match op {
        Operand::Copy(place) | Operand::Move(place) => find_local_in_place(place),
        Operand::Constant(_) => None,
    }
}

impl Visitor<'tcx> for GatherAssignedLocalsVisitor<'_, '_, 'tcx> {
    fn visit_mir(&mut self, mir: &Mir<'tcx>) {
        // We need as many union-find keys as there are locals
        for _ in 0..mir.local_decls.len() {
            self.unification_table.new_key(());
        }

        self.super_mir(mir);
    }

    fn visit_assign(
        &mut self,
        block: BasicBlock,
        place: &Place<'tcx>,
        rvalue: &Rvalue<'tcx>,
        location: Location,
    ) {
        let local = find_local_in_place(place);

        // Conservatively check a subset of `Rvalue`s we know our
        // benchmarks track, for example `html5ever`.
        match rvalue {
            Rvalue::Use(op) => self.union_locals_if_needed(local, find_local_in_operand(op)),
            Rvalue::Ref(_, _, place) => {
                // Special case: if you have `X = &*Y` where `Y` is a
                // reference, then the outlives relationships should
                // ensure that all regions in `Y` are constrained by
                // regions in `X`.
                if let Place::Projection(proj) = place {
                    if let ProjectionElem::Deref = proj.elem {
                        if let ty::TyRef(..) = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx).sty
                        {
                            self.union_locals_if_needed(local, find_local_in_place(&proj.base));
                        }
                    }
                }

                self.union_locals_if_needed(local, find_local_in_place(place))
            }

            Rvalue::Cast(kind, op, _) => match kind {
                CastKind::Unsize => self.union_locals_if_needed(local, find_local_in_operand(op)),
                _ => (),
            },

            Rvalue::Aggregate(_, ops) => {
                for rvalue in ops.iter().map(find_local_in_operand) {
                    self.union_locals_if_needed(local, rvalue);
                }
            }

            _ => (),
        };

        self.super_assign(block, place, rvalue, location);
    }
}
<|endoftext|>


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

use nom::{IResult, ErrorKind};
use nom::{is_hex_digit, multispace, is_digit};

use num_bigint::BigUint;
use core::str::FromStr;
use std::str;

use script::{Program, ParseError};

fn prefix_word(word: &[u8]) -> Vec<u8> {
    let mut vec = Vec::new();
    vec.push(word.len() as u8 | 128u8);
    vec.extend_from_slice(word);
    vec
}

#[inline]
fn hex_digit(v: u8) -> u8 {
    match v {
        0x61u8...0x66u8 => v - 32 - 0x41 + 10,
        0x41u8...0x46u8 => v - 0x41 + 10,
        _ => v - 48,
    }
}

macro_rules! write_size {
    ($vec : expr, $size : expr) => {
      match $size {
        0...120 => $vec.push($size as u8),
        121...255 => {
            $vec.push(121u8);
            $vec.push($size as u8);
        }
        256...65535 => {
            $vec.push(122u8);
            $vec.push(($size >> 8) as u8);
            $vec.push($size as u8);
        }
        65536...4294967296 => {
            $vec.push(123u8);
            $vec.push(($size >> 24) as u8);
            $vec.push(($size >> 16) as u8);
            $vec.push(($size >> 8) as u8);
            $vec.push($size as u8);
        }
        _ => unreachable!()
      }
    };
}

fn bin(bin: &[u8]) -> Vec<u8> {
    let mut bin_ = Vec::new();
    for i in 0..bin.len() - 1 {
        if i % 2 != 0 {
            continue;
        }
        bin_.push((hex_digit(bin[i]) << 4) | hex_digit(bin[i + 1]));
    }
    let mut vec = Vec::new();
    let size = bin_.len();
    write_size!(vec, size);
    vec.extend_from_slice(bin_.as_slice());
    vec
}

fn string_to_vec(s: &[u8]) -> Vec<u8> {
    let mut bin = Vec::new();
    let size = s.len();
    write_size!(bin, size);
    bin.extend_from_slice(s);
    bin
}

fn sized_vec(s: Vec<u8>) -> Vec<u8> {
    let mut vec = Vec::new();
    let size = s.len();
    write_size!(vec, size);
    vec.extend_from_slice(s.as_slice());
    vec

}

fn is_word_char(s: u8) -> bool {
    (s >= b'a' && s <= b'z') || (s >= b'A' && s <= b'Z') || (s >= b'0' && s <= b'9') ||
    s == b'_' || s == b':' || s == b'-' || s == b'=' ||
    s == b'!' || s == b'#' || s == b'$' || s == b'%' || s == b'@' || s == b'?' ||
    s == b'/'
}

fn flatten_program(p: Vec<Vec<u8>>) -> Vec<u8> {
    let mut vec = Vec::new();
    for mut item in p {
        vec.append(&mut item);
    }
    vec
}

fn delim_or_end(i: &[u8]) -> IResult<&[u8], ()> {
    if i.len() == 0 || (i.len() >= 1 && (i[0] == b' ' || i[0] == b']')) {
        return IResult::Done(&i[0..], ())
    } else {
        IResult::Error(ErrorKind::Custom(0))
    }
}

fn eof(i: &[u8]) -> IResult<&[u8], Vec<u8>> {
    if i.len() == 0 {
        return IResult::Done(&i[0..], Vec::new())
    } else {
        IResult::Error(ErrorKind::Custom(1))
    }
}

fn is_multispace(s: u8) -> bool {
    s == b'\n' || s == b'\r' || s == b'\t' || s == b' '
}

named!(uint<Vec<u8>>, do_parse!(
                     biguint: take_while1!(is_digit)      >>
                              delim_or_end                >>
                              (sized_vec(BigUint::from_str(str::from_utf8(biguint).unwrap())
                                         .unwrap().to_bytes_be()))));
named!(word<Vec<u8>>, do_parse!(
                        word: take_while1!(is_word_char)  >>
                              (prefix_word(word))));
named!(wordref<Vec<u8>>, do_parse!(tag!(b"'") >> w: word >> (sized_vec(w))));
named!(binary<Vec<u8>>, do_parse!(
                              tag!(b"0x")                 >>
                         hex: take_while1!(is_hex_digit)  >>
                              (bin(hex))
));
named!(string<Vec<u8>>,  alt!(do_parse!(tag!(b"\"\"") >> (vec![0])) |
                         do_parse!(
                         str: delimited!(char!('"'), is_not!("\""), char!('"')) >>
                              (string_to_vec(str)))));
named!(code<Vec<u8>>, do_parse!(
                         prog: delimited!(char!('['), ws!(program), char!(']')) >>
                               (sized_vec(prog))));
named!(item<Vec<u8>>, alt!(binary | string | uint | code | wordref | word));
named!(program<Vec<u8>>, alt!(do_parse!(
                               take_while!(is_multispace)                        >>
                            v: eof                                          >>
                               (v))
                              | do_parse!(
                               take_while!(is_multispace)                        >>
                         item: separated_list!(multispace, item)            >>
                               take_while!(is_multispace)                        >>
                               (flatten_program(item)))));
named!(pub programs<Vec<Vec<u8>>>, do_parse!(
                         item: separated_list!(tag!(b"."), program)  >>
                               (item)));

/// Parses human-readable PumpkinScript
///
/// The format is simple, it is a sequence of space-separated tokens,
/// with binaries represented as:
///
/// * `0x<hexadecimal>` (hexadecimal form)
/// * `"STRING"` (string form, no quoted characters support yet)
/// * `integer` (integer form, will convert to a big endian big integer)
/// * `'word` (word in a binary form)
///
/// The rest of the instructions considered to be words.
///
/// One additional piece of syntax is code included within square
/// brackets: `[DUP]`. This means that the parser will take the code inside,
/// compile it to the binary form and add as a data push. This is useful for
/// words like EVAL
///
/// # Example
///
/// ```norun
/// parse("0xABCD DUP DROP DROP")
/// ```
///
/// It's especially useful for testing but there is a chance that there will be
/// a "suboptimal" protocol that allows to converse with PumpkinDB over telnet
pub fn parse(script: &str) -> Result<Program, ParseError> {
    match program(script.as_bytes()) {
        IResult::Done(rest, x) => {
            if rest.len() == 0 {
                Ok(x)
            } else {
                Err(ParseError::Superfluous(Vec::from(rest)))
            }
        },
        IResult::Incomplete(_) => Err(ParseError::Incomplete),
        IResult::Error(ErrorKind::Custom(code)) => Err(ParseError::Err(code)),
        _ => Err(ParseError::UnknownErr),
    }
}

#[cfg(test)]
mod tests {
    use script::textparser::{parse, programs};
    use num_bigint::BigUint;
    use core::str::FromStr;

    #[test]
    fn test_empty() {
        let script = parse("").unwrap();
        assert_eq!(script, vec![]);
        let script = parse("  ").unwrap();
        assert_eq!(script, vec![]);
    }

    #[test]
    fn multiline() {
        let script_multiline = parse("\nHELP [\n\
        DROP] \n\
        1").unwrap();
        let script = parse("HELP [DROP] 1").unwrap();
        assert_eq!(script, script_multiline);
    }

    #[test]
    fn superfluous() {
        assert!(parse("HELP [DROP]]").is_err());
    }

    #[test]
    fn test_wordref() {
        let script = parse("'HELLO").unwrap();
        assert_eq!(script, vec![0x06, 0x85, b'H', b'E', b'L', b'L', b'O']);
    }

    #[test]
    fn test_one() {
        let script = parse("0xAABB").unwrap();
        assert_eq!(script, vec![2, 0xaa,0xbb]);
        let script = parse("HELLO").unwrap();
        assert_eq!(script, vec![0x85, b'H', b'E', b'L', b'L', b'O']);
    }

    #[test]
    fn test_uint() {
        let script = parse("1234567890").unwrap();
        let mut bytes = BigUint::from_str("1234567890").unwrap().to_bytes_be();
        let mut sized = Vec::new();
        sized.push(4);
        sized.append(&mut bytes);
        assert_eq!(script, sized);
    }

    #[test]
    fn test_many_uint() {
        let script = parse("1 2 3").unwrap();

        let mut vec = Vec::new();

        let mut bytes = BigUint::from_str("1").unwrap().to_bytes_be();
        vec.push(1);
        vec.append(&mut bytes);

        let mut bytes = BigUint::from_str("2").unwrap().to_bytes_be();
        vec.push(1);
        vec.append(&mut bytes);

        let mut bytes = BigUint::from_str("3").unwrap().to_bytes_be();
        vec.push(1);
        vec.append(&mut bytes);

        assert_eq!(script, vec);
    }

    #[test]
    fn test_uint_at_the_end_of_code() {
        let script = parse("[1]").unwrap();
        assert_eq!(script, parse("[0x01]").unwrap());
    }

    #[test]
    fn test_number_prefixed_word() {
        let script = parse("2DUP").unwrap();
        assert_eq!(script, b"\x842DUP");
    }

    #[test]
    fn test_extra_spaces() {
        let script = parse(" 0xAABB  \"Hi\" ").unwrap();
        assert_eq!(script, vec![2, 0xaa,0xbb, 2, b'H', b'i']);
    }

    #[test]
    fn test() {
        let script = parse("0xAABB DUP 0xFF00CC \"Hello\"").unwrap();

        assert_eq!(script, vec![0x02, 0xAA, 0xBB, 0x83, b'D', b'U', b'P',
                                0x03, 0xFF, 0x00, 0xCC, 0x05, b'H', b'e', b'l', b'l', b'o']);
    }

    #[test]
    fn test_empty_string() {
        let script = parse("\"\"").unwrap();

        assert_eq!(script, vec![0]);
    }

    #[test]
    fn test_code() {
        let script = parse("[DUP]").unwrap();
        let script_spaced = parse("[ DUP ]").unwrap();
        assert_eq!(script, vec![4, 0x83, b'D', b'U', b'P']);
        assert_eq!(script_spaced, vec![4, 0x83, b'D', b'U', b'P']);
    }

    #[test]
    fn test_programs() {
        let str = "SOMETHING : BURP DURP.\nBURP : DURP";
        let (_, mut progs) = programs(str.as_bytes()).unwrap();
        assert_eq!(Vec::from(progs.pop().unwrap()), parse("BURP : DURP").unwrap());
        assert_eq!(Vec::from(progs.pop().unwrap()), parse("SOMETHING : BURP DURP").unwrap());
    }

}
<commit_msg>Problem: PumpkinScript has no comments<commit_after>// Copyright (c) 2017, All Contributors (see CONTRIBUTORS file)
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use nom::{IResult, ErrorKind};
use nom::{is_hex_digit, multispace, is_digit};

use num_bigint::BigUint;
use core::str::FromStr;
use std::str;

use script::{Program, ParseError};

fn prefix_word(word: &[u8]) -> Vec<u8> {
    let mut vec = Vec::new();
    vec.push(word.len() as u8 | 128u8);
    vec.extend_from_slice(word);
    vec
}

#[inline]
fn hex_digit(v: u8) -> u8 {
    match v {
        0x61u8...0x66u8 => v - 32 - 0x41 + 10,
        0x41u8...0x46u8 => v - 0x41 + 10,
        _ => v - 48,
    }
}

macro_rules! write_size {
    ($vec : expr, $size : expr) => {
      match $size {
        0...120 => $vec.push($size as u8),
        121...255 => {
            $vec.push(121u8);
            $vec.push($size as u8);
        }
        256...65535 => {
            $vec.push(122u8);
            $vec.push(($size >> 8) as u8);
            $vec.push($size as u8);
        }
        65536...4294967296 => {
            $vec.push(123u8);
            $vec.push(($size >> 24) as u8);
            $vec.push(($size >> 16) as u8);
            $vec.push(($size >> 8) as u8);
            $vec.push($size as u8);
        }
        _ => unreachable!()
      }
    };
}

fn bin(bin: &[u8]) -> Vec<u8> {
    let mut bin_ = Vec::new();
    for i in 0..bin.len() - 1 {
        if i % 2 != 0 {
            continue;
        }
        bin_.push((hex_digit(bin[i]) << 4) | hex_digit(bin[i + 1]));
    }
    let mut vec = Vec::new();
    let size = bin_.len();
    write_size!(vec, size);
    vec.extend_from_slice(bin_.as_slice());
    vec
}

fn string_to_vec(s: &[u8]) -> Vec<u8> {
    let mut bin = Vec::new();
    let size = s.len();
    write_size!(bin, size);
    bin.extend_from_slice(s);
    bin
}

fn sized_vec(s: Vec<u8>) -> Vec<u8> {
    let mut vec = Vec::new();
    let size = s.len();
    write_size!(vec, size);
    vec.extend_from_slice(s.as_slice());
    vec

}

fn is_word_char(s: u8) -> bool {
    (s >= b'a' && s <= b'z') || (s >= b'A' && s <= b'Z') || (s >= b'0' && s <= b'9') ||
    s == b'_' || s == b':' || s == b'-' || s == b'=' ||
    s == b'!' || s == b'#' || s == b'$' || s == b'%' || s == b'@' || s == b'?' ||
    s == b'/'
}

fn flatten_program(p: Vec<Vec<u8>>) -> Vec<u8> {
    let mut vec = Vec::new();
    for mut item in p {
        vec.append(&mut item);
    }
    vec
}

fn delim_or_end(i: &[u8]) -> IResult<&[u8], ()> {
    if i.len() == 0 || (i.len() >= 1 && (i[0] == b' ' || i[0] == b']')) {
        return IResult::Done(&i[0..], ())
    } else {
        IResult::Error(ErrorKind::Custom(0))
    }
}

fn eof(i: &[u8]) -> IResult<&[u8], Vec<u8>> {
    if i.len() == 0 {
        return IResult::Done(&i[0..], Vec::new())
    } else {
        IResult::Error(ErrorKind::Custom(1))
    }
}

fn is_multispace(s: u8) -> bool {
    s == b'\n' || s == b'\r' || s == b'\t' || s == b' '
}

named!(uint<Vec<u8>>, do_parse!(
                     biguint: take_while1!(is_digit)      >>
                              delim_or_end                >>
                              (sized_vec(BigUint::from_str(str::from_utf8(biguint).unwrap())
                                         .unwrap().to_bytes_be()))));
named!(word<Vec<u8>>, do_parse!(
                        word: take_while1!(is_word_char)  >>
                              (prefix_word(word))));
named!(wordref<Vec<u8>>, do_parse!(tag!(b"'") >> w: word >> (sized_vec(w))));
named!(binary<Vec<u8>>, do_parse!(
                              tag!(b"0x")                 >>
                         hex: take_while1!(is_hex_digit)  >>
                              (bin(hex))
));
named!(string<Vec<u8>>,  alt!(do_parse!(tag!(b"\"\"") >> (vec![0])) |
                         do_parse!(
                         str: delimited!(char!('"'), is_not!("\""), char!('"')) >>
                              (string_to_vec(str)))));
named!(code<Vec<u8>>, do_parse!(
                         prog: delimited!(char!('['), ws!(program), char!(']')) >>
                               (sized_vec(prog))));
named!(comment<Vec<u8>>, do_parse!(delimited!(char!('('), is_not!(")"), char!(')')) >> (vec![])));
named!(item<Vec<u8>>, alt!(comment | binary | string | uint | code | wordref | word));
named!(program<Vec<u8>>, alt!(do_parse!(
                               take_while!(is_multispace)                        >>
                            v: eof                                          >>
                               (v))
                              | do_parse!(
                               take_while!(is_multispace)                        >>
                         item: separated_list!(multispace, item)            >>
                               take_while!(is_multispace)                        >>
                               (flatten_program(item)))));
named!(pub programs<Vec<Vec<u8>>>, do_parse!(
                         item: separated_list!(tag!(b"."), program)  >>
                               (item)));

/// Parses human-readable PumpkinScript
///
/// The format is simple, it is a sequence of space-separated tokens,
/// with binaries represented as:
///
/// * `0x<hexadecimal>` (hexadecimal form)
/// * `"STRING"` (string form, no quoted characters support yet)
/// * `integer` (integer form, will convert to a big endian big integer)
/// * `'word` (word in a binary form)
///
/// The rest of the instructions considered to be words.
///
/// One additional piece of syntax is code included within square
/// brackets: `[DUP]`. This means that the parser will take the code inside,
/// compile it to the binary form and add as a data push. This is useful for
/// words like EVAL
///
/// # Example
///
/// ```norun
/// parse("0xABCD DUP DROP DROP")
/// ```
///
/// It's especially useful for testing but there is a chance that there will be
/// a "suboptimal" protocol that allows to converse with PumpkinDB over telnet
pub fn parse(script: &str) -> Result<Program, ParseError> {
    match program(script.as_bytes()) {
        IResult::Done(rest, x) => {
            if rest.len() == 0 {
                Ok(x)
            } else {
                Err(ParseError::Superfluous(Vec::from(rest)))
            }
        },
        IResult::Incomplete(_) => Err(ParseError::Incomplete),
        IResult::Error(ErrorKind::Custom(code)) => Err(ParseError::Err(code)),
        _ => Err(ParseError::UnknownErr),
    }
}

#[cfg(test)]
mod tests {
    use script::textparser::{parse, programs};
    use num_bigint::BigUint;
    use core::str::FromStr;

    #[test]
    fn test_empty() {
        let script = parse("").unwrap();
        assert_eq!(script, vec![]);
        let script = parse("  ").unwrap();
        assert_eq!(script, vec![]);
    }

    #[test]
    fn multiline() {
        let script_multiline = parse("\nHELP [\n\
        DROP] \n\
        1").unwrap();
        let script = parse("HELP [DROP] 1").unwrap();
        assert_eq!(script, script_multiline);
    }

    #[test]
    fn test_comment() {
        let script = parse("1 (hello) 2").unwrap();
        assert_eq!(script, parse("1 2").unwrap());
    }

    #[test]
    fn test_multiline_comment() {
        let script = parse("1 (hel\nlo) 2").unwrap();
        assert_eq!(script, parse("1 2").unwrap());
    }

    #[test]
    fn superfluous() {
        assert!(parse("HELP [DROP]]").is_err());
    }

    #[test]
    fn test_wordref() {
        let script = parse("'HELLO").unwrap();
        assert_eq!(script, vec![0x06, 0x85, b'H', b'E', b'L', b'L', b'O']);
    }

    #[test]
    fn test_one() {
        let script = parse("0xAABB").unwrap();
        assert_eq!(script, vec![2, 0xaa,0xbb]);
        let script = parse("HELLO").unwrap();
        assert_eq!(script, vec![0x85, b'H', b'E', b'L', b'L', b'O']);
    }

    #[test]
    fn test_uint() {
        let script = parse("1234567890").unwrap();
        let mut bytes = BigUint::from_str("1234567890").unwrap().to_bytes_be();
        let mut sized = Vec::new();
        sized.push(4);
        sized.append(&mut bytes);
        assert_eq!(script, sized);
    }

    #[test]
    fn test_many_uint() {
        let script = parse("1 2 3").unwrap();

        let mut vec = Vec::new();

        let mut bytes = BigUint::from_str("1").unwrap().to_bytes_be();
        vec.push(1);
        vec.append(&mut bytes);

        let mut bytes = BigUint::from_str("2").unwrap().to_bytes_be();
        vec.push(1);
        vec.append(&mut bytes);

        let mut bytes = BigUint::from_str("3").unwrap().to_bytes_be();
        vec.push(1);
        vec.append(&mut bytes);

        assert_eq!(script, vec);
    }

    #[test]
    fn test_uint_at_the_end_of_code() {
        let script = parse("[1]").unwrap();
        assert_eq!(script, parse("[0x01]").unwrap());
    }

    #[test]
    fn test_number_prefixed_word() {
        let script = parse("2DUP").unwrap();
        assert_eq!(script, b"\x842DUP");
    }

    #[test]
    fn test_extra_spaces() {
        let script = parse(" 0xAABB  \"Hi\" ").unwrap();
        assert_eq!(script, vec![2, 0xaa,0xbb, 2, b'H', b'i']);
    }

    #[test]
    fn test() {
        let script = parse("0xAABB DUP 0xFF00CC \"Hello\"").unwrap();

        assert_eq!(script, vec![0x02, 0xAA, 0xBB, 0x83, b'D', b'U', b'P',
                                0x03, 0xFF, 0x00, 0xCC, 0x05, b'H', b'e', b'l', b'l', b'o']);
    }

    #[test]
    fn test_empty_string() {
        let script = parse("\"\"").unwrap();

        assert_eq!(script, vec![0]);
    }

    #[test]
    fn test_code() {
        let script = parse("[DUP]").unwrap();
        let script_spaced = parse("[ DUP ]").unwrap();
        assert_eq!(script, vec![4, 0x83, b'D', b'U', b'P']);
        assert_eq!(script_spaced, vec![4, 0x83, b'D', b'U', b'P']);
    }

    #[test]
    fn test_programs() {
        let str = "SOMETHING : BURP DURP.\nBURP : DURP";
        let (_, mut progs) = programs(str.as_bytes()).unwrap();
        assert_eq!(Vec::from(progs.pop().unwrap()), parse("BURP : DURP").unwrap());
        assert_eq!(Vec::from(progs.pop().unwrap()), parse("SOMETHING : BURP DURP").unwrap());
    }

}
<|endoftext|>


<commit_before>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate cc;
extern crate cmake;
extern crate pkg_config;

use std::path::Path;
use std::{env, fs, io};
use std::env::VarError;

use cmake::Config;
use cc::Build;
use pkg_config::Config as PkgConfig;

const GRPC_VERSION: &'static str = "1.6.1";

fn link_grpc(cc: &mut Build, library: &str) {
    match PkgConfig::new()
        .atleast_version(GRPC_VERSION)
        .probe(library)
    {
        Ok(lib) => for inc_path in lib.include_paths {
            cc.include(inc_path);
        },
        Err(e) => panic!("can't find library {} via pkg-config: {:?}", library, e),
    }
}

fn prepare_grpc() {
    let mut modules = vec![
        "grpc",
        "grpc/third_party/zlib",
        "grpc/third_party/cares/cares",
    ];

    if cfg!(feature = "secure") {
        modules.push("grpc/third_party/boringssl");
    }

    for module in modules {
        if is_directory_empty(module).unwrap_or(true) {
            panic!(
                "Can't find module {}. You need to run `git submodule \
                 update --init --recursive` first to build the project.",
                module
            );
        }
    }
}

fn is_directory_empty<P: AsRef<Path>>(p: P) -> Result<bool, io::Error> {
    let mut entries = fs::read_dir(p)?;
    Ok(entries.next().is_none())
}

fn build_grpc(cc: &mut Build, library: &str) {
    prepare_grpc();

    let dst = {
        let mut config = Config::new("grpc");
        if cfg!(target_os = "macos") {
            config.cxxflag("-stdlib=libc++");
        }
        if env::var("CARGO_CFG_TARGET_ENV").unwrap_or("".to_owned()) == "musl" {
            config.define("CMAKE_CXX_COMPILER", "g++");
        }
        config.build_target(library).uses_cxx11().build()
    };

    let mut zlib = "z";
    let build_dir = format!("{}/build", dst.display());
    let third_party = vec![
        "cares/cares/lib",
        "zlib",
        "boringssl/ssl",
        "boringssl/crypto",
    ];
    if cfg!(target_os = "windows") {
        let profile = match &*env::var("PROFILE").unwrap_or("debug".to_owned()) {
            "bench" | "release" => {
                zlib = "zlibstatic";
                "Release"
            }
            _ => {
                zlib = "zlibstaticd";
                "Debug"
            }
        };
        println!("cargo:rustc-link-search=native={}/{}", build_dir, profile);
        for path in third_party {
            println!(
                "cargo:rustc-link-search=native={}/third_party/{}/{}",
                build_dir, path, profile
            );
        }
    } else {
        println!("cargo:rustc-link-search=native={}", build_dir);
        for path in third_party {
            println!(
                "cargo:rustc-link-search=native={}/third_party/{}",
                build_dir, path,
            );
        }
    }

    println!("cargo:rustc-link-lib=static={}", zlib);
    println!("cargo:rustc-link-lib=static=cares");
    println!("cargo:rustc-link-lib=static=gpr");
    println!("cargo:rustc-link-lib=static={}", library);

    if cfg!(feature = "secure") {
        println!("cargo:rustc-link-lib=static=ssl");
        println!("cargo:rustc-link-lib=static=crypto");
    }

    cc.include("grpc/include");
}

fn get_env(name: &str) -> Option<String> {
    println!("cargo:rerun-if-env-changed={}", name);
    match env::var(name) {
        Ok(s) => Some(s),
        Err(VarError::NotPresent) => None,
        Err(VarError::NotUnicode(s)) => {
            panic!("unrecognize env var of {}: {:?}", name, s.to_string_lossy());
        }
    }
}

fn main() {
    let mut cc = Build::new();

    println!("cargo:rerun-if-changed=grpc_wrap.c");
    println!("cargo:rerun-if-changed=grpc");

    let library = if cfg!(feature = "secure") {
        cc.define("GRPC_SYS_SECURE", None);
        "grpc"
    } else {
        "grpc_unsecure"
    };

    if get_env("GRPCIO_SYS_USE_PKG_CONFIG").map_or(false, |s| s == "1") {
        link_grpc(&mut cc, library);
    } else {
        build_grpc(&mut cc, library);
    }

    cc.file("grpc_wrap.c");

    if cfg!(target_os = "windows") {
        // At lease win7
        cc.define("_WIN32_WINNT", Some("0x0700"));
    }

    cc.warnings_into_errors(true).compile("libgrpc_wrap.a");
}
<commit_msg>build: use fake go when secure feature is disabled (#201)<commit_after>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate cc;
extern crate cmake;
extern crate pkg_config;

use std::path::Path;
use std::{env, fs, io};
use std::env::VarError;

use cmake::Config;
use cc::Build;
use pkg_config::Config as PkgConfig;

const GRPC_VERSION: &'static str = "1.6.1";

fn link_grpc(cc: &mut Build, library: &str) {
    match PkgConfig::new()
        .atleast_version(GRPC_VERSION)
        .probe(library)
    {
        Ok(lib) => for inc_path in lib.include_paths {
            cc.include(inc_path);
        },
        Err(e) => panic!("can't find library {} via pkg-config: {:?}", library, e),
    }
}

fn prepare_grpc() {
    let mut modules = vec![
        "grpc",
        "grpc/third_party/zlib",
        "grpc/third_party/cares/cares",
    ];

    if cfg!(feature = "secure") {
        modules.push("grpc/third_party/boringssl");
    }

    for module in modules {
        if is_directory_empty(module).unwrap_or(true) {
            panic!(
                "Can't find module {}. You need to run `git submodule \
                 update --init --recursive` first to build the project.",
                module
            );
        }
    }
}

fn is_directory_empty<P: AsRef<Path>>(p: P) -> Result<bool, io::Error> {
    let mut entries = fs::read_dir(p)?;
    Ok(entries.next().is_none())
}

fn build_grpc(cc: &mut Build, library: &str) {
    prepare_grpc();

    let dst = {
        let mut config = Config::new("grpc");
        if !cfg!(feature = "secure") {
            // boringssl's configuration is still included, but targets
            // will never be built, hence specify a fake go to get rid of
            // the unnecessary dependency.
            config.define("GO_EXECUTABLE", "fake-go-nonexist");
        }
        if cfg!(target_os = "macos") {
            config.cxxflag("-stdlib=libc++");
        }
        if env::var("CARGO_CFG_TARGET_ENV").unwrap_or("".to_owned()) == "musl" {
            config.define("CMAKE_CXX_COMPILER", "g++");
        }
        config.build_target(library).uses_cxx11().build()
    };

    let mut zlib = "z";
    let build_dir = format!("{}/build", dst.display());
    let third_party = vec![
        "cares/cares/lib",
        "zlib",
        "boringssl/ssl",
        "boringssl/crypto",
    ];
    if cfg!(target_os = "windows") {
        let profile = match &*env::var("PROFILE").unwrap_or("debug".to_owned()) {
            "bench" | "release" => {
                zlib = "zlibstatic";
                "Release"
            }
            _ => {
                zlib = "zlibstaticd";
                "Debug"
            }
        };
        println!("cargo:rustc-link-search=native={}/{}", build_dir, profile);
        for path in third_party {
            println!(
                "cargo:rustc-link-search=native={}/third_party/{}/{}",
                build_dir, path, profile
            );
        }
    } else {
        println!("cargo:rustc-link-search=native={}", build_dir);
        for path in third_party {
            println!(
                "cargo:rustc-link-search=native={}/third_party/{}",
                build_dir, path,
            );
        }
    }

    println!("cargo:rustc-link-lib=static={}", zlib);
    println!("cargo:rustc-link-lib=static=cares");
    println!("cargo:rustc-link-lib=static=gpr");
    println!("cargo:rustc-link-lib=static={}", library);

    if cfg!(feature = "secure") {
        println!("cargo:rustc-link-lib=static=ssl");
        println!("cargo:rustc-link-lib=static=crypto");
    }

    cc.include("grpc/include");
}

fn get_env(name: &str) -> Option<String> {
    println!("cargo:rerun-if-env-changed={}", name);
    match env::var(name) {
        Ok(s) => Some(s),
        Err(VarError::NotPresent) => None,
        Err(VarError::NotUnicode(s)) => {
            panic!("unrecognize env var of {}: {:?}", name, s.to_string_lossy());
        }
    }
}

fn main() {
    let mut cc = Build::new();

    println!("cargo:rerun-if-changed=grpc_wrap.c");
    println!("cargo:rerun-if-changed=grpc");

    let library = if cfg!(feature = "secure") {
        cc.define("GRPC_SYS_SECURE", None);
        "grpc"
    } else {
        "grpc_unsecure"
    };

    if get_env("GRPCIO_SYS_USE_PKG_CONFIG").map_or(false, |s| s == "1") {
        link_grpc(&mut cc, library);
    } else {
        build_grpc(&mut cc, library);
    }

    cc.file("grpc_wrap.c");

    if cfg!(target_os = "windows") {
        // At lease win7
        cc.define("_WIN32_WINNT", Some("0x0700"));
    }

    cc.warnings_into_errors(true).compile("libgrpc_wrap.a");
}
<|endoftext|>


<commit_before>import libc::types::common::c99::int32_t;
import libc::{c_uint, c_int};
import font::font;
import glyph::{glyph, glyph_pos};
import ptr::{null, addr_of, offset};

import unsafe::reinterpret_cast;
import harfbuzz::{HB_MEMORY_MODE_READONLY,
                  HB_DIRECTION_LTR};
import harfbuzz::{hb_blob_t, hb_face_t, hb_font_t, hb_buffer_t};
import harfbuzz::bindgen::{hb_blob_create, hb_blob_destroy,
                           hb_face_create, hb_face_destroy,
                           hb_font_create, hb_font_destroy,
                           hb_buffer_create, hb_buffer_destroy,
                           hb_buffer_add_utf8, hb_shape,
                           hb_buffer_get_glyph_infos,
                           hb_buffer_get_glyph_positions,
                           hb_font_set_ppem, hb_font_set_scale,
                           hb_buffer_set_direction};

#[doc = "
Calculate the layout metrics associated with a some given text
when rendered in a specific font.
"]
fn shape_text(_font: &font, text: str) -> [glyph] {
    let mut glyphs = [];
    let mut cur_x = 0u;
    for text.each_char {
        |ch|
        // TODO: Use HarfBuzz!
        let hb_pos = {
            x_advance: 10 as int32_t,
            y_advance: 0 as int32_t,
            x_offset: cur_x as int32_t,
            y_offset: 0 as int32_t,
            var: 0
        };

        vec::push(glyphs, glyph(ch as uint, glyph_pos(hb_pos)));
        cur_x += 10u;
    };

    ret glyphs;
}

fn shape_text2(font: &font, text: str) -> [glyph] unsafe {
    #debug("shaping text '%s'", text);

    let face_blob = vec::as_buf(*(*font).buf()) { |buf|
        hb_blob_create(reinterpret_cast(buf),
                       (*(*font).buf()).len() as c_uint,
                       HB_MEMORY_MODE_READONLY,
                       null(),
                       null())
    };

    let face = hb_face_create(face_blob, 0 as c_uint);
    let font = hb_font_create(face);

    hb_font_set_ppem(font, 10 as c_uint, 10 as c_uint);
    hb_font_set_scale(font, 10 as c_int, 10 as c_int);

    let buffer = hb_buffer_create();

    hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);

    str::as_c_str(text) { |ctext|
        hb_buffer_add_utf8(buffer, ctext,
                           text.len() as c_int,
                           0 as c_uint,
                           text.len() as c_int);
    }

    hb_shape(font, buffer, null(), 0 as c_uint);

    let info_len = 0 as c_uint;
    let info_ = hb_buffer_get_glyph_infos(buffer, addr_of(info_len));
    assert info_.is_not_null();
    let pos_len = 0 as c_uint;
    let pos = hb_buffer_get_glyph_positions(buffer, addr_of(pos_len));
    assert pos.is_not_null();

    assert info_len == pos_len;

    for uint::range(0u, info_len as uint) { |i|
        let info_ = offset(info_, i);
        let pos = offset(pos, i);
        #debug("glyph %?: codep %?, cluster %?,\
                x_adv %?, y_adv %?, x_off %?, y_of %?",
               i, (*info_).codepoint, (*info_).cluster,
               (*pos).x_advance, (*pos).y_advance,
               (*pos).x_offset, (*pos).y_offset);
    }

    hb_buffer_destroy(buffer);
    hb_font_destroy(font);
    hb_face_destroy(face);
    hb_blob_destroy(face_blob);

    ret [];
}

#[test]
fn test_shape_basic() {
    let font = font::create();
    shape_text2(&font, "firecracker");
}
<commit_msg>More work on text shaping<commit_after>import libc::types::common::c99::int32_t;
import libc::{c_uint, c_int, c_void};
import font::font;
import glyph::{glyph, glyph_pos};
import ptr::{null, addr_of, offset};

import unsafe::reinterpret_cast;
import harfbuzz::{HB_MEMORY_MODE_READONLY,
                  HB_DIRECTION_LTR};
import harfbuzz::{hb_blob_t, hb_face_t, hb_font_t, hb_buffer_t,
                  hb_codepoint_t, hb_bool_t};
import harfbuzz::bindgen::{hb_blob_create, hb_blob_destroy,
                           hb_face_create, hb_face_destroy,
                           hb_font_create, hb_font_destroy,
                           hb_buffer_create, hb_buffer_destroy,
                           hb_buffer_add_utf8, hb_shape,
                           hb_buffer_get_glyph_infos,
                           hb_buffer_get_glyph_positions,
                           hb_font_set_ppem, hb_font_set_scale,
                           hb_buffer_set_direction,
                           hb_font_funcs_create, hb_font_funcs_destroy,
                           hb_font_set_funcs,
                           hb_font_funcs_set_glyph_h_advance_func,
                           hb_font_funcs_set_glyph_func,
                           hb_font_funcs_set_glyph_h_kerning_func};

#[doc = "
Calculate the layout metrics associated with a some given text
when rendered in a specific font.
"]
fn shape_text(_font: &font, text: str) -> [glyph] {
    let mut glyphs = [];
    let mut cur_x = 0u;
    for text.each_char {
        |ch|
        // TODO: Use HarfBuzz!
        let hb_pos = {
            x_advance: 10 as int32_t,
            y_advance: 0 as int32_t,
            x_offset: cur_x as int32_t,
            y_offset: 0 as int32_t,
            var: 0
        };

        vec::push(glyphs, glyph(ch as uint, glyph_pos(hb_pos)));
        cur_x += 10u;
    };

    ret glyphs;
}

fn shape_text2(font: &font, text: str) -> [glyph] unsafe {
    #debug("shaping text '%s'", text);

    let face_blob = vec::as_buf(*(*font).buf()) { |buf|
        hb_blob_create(reinterpret_cast(buf),
                       (*(*font).buf()).len() as c_uint,
                       HB_MEMORY_MODE_READONLY,
                       null(),
                       null())
    };

    let face = hb_face_create(face_blob, 0 as c_uint);
    let font = hb_font_create(face);

    hb_font_set_ppem(font, 10 as c_uint, 10 as c_uint);
    hb_font_set_scale(font, 10 as c_int, 10 as c_int);

    let funcs = hb_font_funcs_create();
    hb_font_funcs_set_glyph_func(funcs, glyph_func, null(), null());
    hb_font_set_funcs(font, funcs, addr_of(*font), null());

    let buffer = hb_buffer_create();

    hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);

    str::as_c_str(text) { |ctext|
        hb_buffer_add_utf8(buffer, ctext,
                           text.len() as c_int,
                           0 as c_uint,
                           text.len() as c_int);
    }

    hb_shape(font, buffer, null(), 0 as c_uint);

    let info_len = 0 as c_uint;
    let info_ = hb_buffer_get_glyph_infos(buffer, addr_of(info_len));
    assert info_.is_not_null();
    let pos_len = 0 as c_uint;
    let pos = hb_buffer_get_glyph_positions(buffer, addr_of(pos_len));
    assert pos.is_not_null();

    assert info_len == pos_len;

    for uint::range(0u, info_len as uint) { |i|
        let info_ = offset(info_, i);
        let pos = offset(pos, i);
        #debug("glyph %?: codep %?, cluster %?,\
                x_adv %?, y_adv %?, x_off %?, y_of %?",
               i, (*info_).codepoint, (*info_).cluster,
               (*pos).x_advance, (*pos).y_advance,
               (*pos).x_offset, (*pos).y_offset);
    }

    hb_buffer_destroy(buffer);
    hb_font_funcs_destroy(funcs);
    hb_font_destroy(font);
    hb_face_destroy(face);
    hb_blob_destroy(face_blob);

    ret [];
}

crust fn glyph_func(_font: *hb_font_t,
                    _font_data: *c_void,
                    _unicode: hb_codepoint_t,
                    _variant_selector: hb_codepoint_t,
                    glyph: *mut hb_codepoint_t,
                    _user_data: *c_void) -> hb_bool_t unsafe {

    *glyph = 40 as hb_codepoint_t;
    ret true as hb_bool_t;
}

#[test]
fn test_shape_basic() {
    let font = font::create();
    shape_text2(&font, "firecracker");
}
<|endoftext|>


<commit_before>use futures::{Async, Future};
use std::net::SocketAddr;
use service::Service;
use proto::{self, pipeline};
use tokio::reactor::Handle;
use tokio::net::TcpStream;
use futures::stream;
use serde;

use super::sexp_proto::sexp_proto_new;
use super::errors::Error;
use void::Void;

use std::fmt;

pub struct Client<T, R> {
    inner: proto::Client<T, R, stream::Empty<Void, Error>, Error>,
}

impl<T: Send + 'static, R: Send + 'static> Service for Client<T, R> {
    type Request = T;
    type Response = R;
    type Error = Error;
    type Future = Box<Future<Item = Self::Response, Error = Error> + Send>;

    fn poll_ready(&self) -> Async<()> {
        Async::Ready(())
    }
    fn call(&self, req: T) -> Self::Future {
        self.inner.call(proto::Message::WithoutBody(req))
    }
}

impl<T, R> fmt::Debug for Client<T, R> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_tuple("Client").finish()
    }
}

pub fn connect<T, R>(handle: Handle, addr: &SocketAddr) -> Client<T, R>
    where T: Send + 'static + serde::ser::Serialize,
          R: Send + 'static + serde::de::Deserialize
{
    let addr = addr.clone();
    let h = handle.clone();

    let builder = move || TcpStream::connect(&addr, &h).map(|s| sexp_proto_new(s));

    let client = pipeline::connect(builder, &handle);
    Client { inner: client }
}
<commit_msg>Factor out client tcp-related bits.<commit_after>use futures::{Async, IntoFuture, Future};
use std::net::SocketAddr;
use service::Service;
use proto::{self, pipeline};
use proto::pipeline::Frame;
use tokio::reactor::Handle;
use tokio::io::FramedIo;
use tokio::net::TcpStream;
use futures::stream;
use serde;

use super::sexp_proto::sexp_proto_new;
use super::errors::Error;
use void::Void;

use std::fmt;
use std::io;

pub struct Client<Req, Res> {
    inner: proto::Client<Req, Res, stream::Empty<Void, Error>, Error>,
}

impl<Req: Send + 'static, Res: Send + 'static> Service for Client<Req, Res> {
    type Request = Req;
    type Response = Res;
    type Error = Error;
    type Future = Box<Future<Item = Self::Response, Error = Error> + Send>;

    fn poll_ready(&self) -> Async<()> {
        self.inner.poll_ready()
    }
    fn call(&self, req: Req) -> Self::Future {
        self.inner.call(proto::Message::WithoutBody(req))
    }
}

impl<Req, Res> fmt::Debug for Client<Req, Res> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_tuple("Client").finish()
    }
}

pub fn connect<Req, Res>(handle: Handle, addr: &SocketAddr) -> Client<Req, Res>
    where Req: Send + 'static + serde::ser::Serialize,
          Res: Send + 'static + serde::de::Deserialize
{
    let addr = addr.clone();
    let h = handle.clone();

    let builder = move || TcpStream::connect(&addr, &h).map(|s| sexp_proto_new(s));
    connect_with(builder, handle)
}

pub fn connect_with<B, F, T, Req, Res>(builder: B, handle: Handle) -> Client<Req, Res>
    where B: Fn() -> F,
          F: IntoFuture<Item = T, Error = io::Error>,
          F::Future: Send + 'static,
          T: FramedIo<In = Frame<Req, Void, Error>, Out = Frame<Res, Void, Error>> + Send + 'static,
          Req: Send + 'static,
          Res: Send + 'static
{
    let client = pipeline::connect(builder, &handle);
    Client { inner: client }
}
<|endoftext|>


<commit_before>// Copyright 2017 click2stream, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::net::{IpAddr, SocketAddr};

use net::raw::ether::MacAddr;

pub const SVC_TYPE_CONTROL_PROTOCOL: u16 = 0x0000;
pub const SVC_TYPE_RTSP:             u16 = 0x0001;
pub const SVC_TYPE_LOCKED_RTSP:      u16 = 0x0002;
pub const SVC_TYPE_UNKNOWN_RTSP:     u16 = 0x0003;
pub const SVC_TYPE_UNSUPPORTED_RTSP: u16 = 0x0004;
pub const SVC_TYPE_HTTP:             u16 = 0x0005;
pub const SVC_TYPE_MJPEG:            u16 = 0x0006;
pub const SVC_TYPE_LOCKED_MJPEG:     u16 = 0x0007;
pub const SVC_TYPE_TCP:              u16 = 0xffff;

/// Service type.
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub enum ServiceType {
    /// Control Protocol service.
    ControlProtocol,
    /// Remote RTSP service.
    RTSP,
    /// Remote RTSP service requiring authentication.
    LockedRTSP,
    /// Remote RTSP service without any known path.
    UnknownRTSP,
    /// Remote RTSP service without any supported stream.
    UnsupportedRTSP,
    /// Remote HTTP service.
    HTTP,
    /// Remote MJPEG service.
    MJPEG,
    /// Remote MJPEG service requiring authentication.
    LockedMJPEG,
    /// General purpose TCP service.
    TCP,
}

impl ServiceType {
    /// Get code of the service type.
    pub fn code(&self) -> u16 {
        match self {
            &ServiceType::ControlProtocol => SVC_TYPE_CONTROL_PROTOCOL,
            &ServiceType::RTSP            => SVC_TYPE_RTSP,
            &ServiceType::LockedRTSP      => SVC_TYPE_LOCKED_RTSP,
            &ServiceType::UnknownRTSP     => SVC_TYPE_UNKNOWN_RTSP,
            &ServiceType::UnsupportedRTSP => SVC_TYPE_UNSUPPORTED_RTSP,
            &ServiceType::HTTP            => SVC_TYPE_HTTP,
            &ServiceType::MJPEG           => SVC_TYPE_MJPEG,
            &ServiceType::LockedMJPEG     => SVC_TYPE_LOCKED_MJPEG,
            &ServiceType::TCP             => SVC_TYPE_TCP,
        }
    }
}

/// Arrow service identifier.
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct ServiceIdentifier {
    svc_type: ServiceType,
    mac:      Option<MacAddr>,
    port:     Option<u16>,
    path:     Option<String>,
}

impl ServiceIdentifier {
    /// Check if this is the Control Protocol service  identifier.
    pub fn is_control(&self) -> bool {
        self.svc_type == ServiceType::ControlProtocol
    }
}

/// Arrow service.
#[derive(Clone, Eq, PartialEq)]
pub struct Service {
    svc_type: ServiceType,
    mac:      Option<MacAddr>,
    address:  Option<SocketAddr>,
    path:     Option<String>,
}

impl Service {
    /// Create a new Control Protocol service.
    pub fn control() -> Service {
        Service {
            svc_type: ServiceType::ControlProtocol,
            mac:      None,
            address:  None,
            path:     None,
        }
    }

    /// Create a new RTSP service.
    pub fn rtsp(mac: MacAddr, address: SocketAddr, path: String) -> Service {
        Service {
            svc_type: ServiceType::RTSP,
            mac:      Some(mac),
            address:  Some(address),
            path:     Some(path),
        }
    }

    /// Create a new Locked RTSP service.
    pub fn locked_rtsp(mac: MacAddr, address: SocketAddr, path: Option<String>) -> Service {
        Service {
            svc_type: ServiceType::LockedRTSP,
            mac:      Some(mac),
            address:  Some(address),
            path:     path,
        }
    }

    /// Create a new Unknown RTSP service.
    pub fn unknown_rtsp(mac: MacAddr, address: SocketAddr) -> Service {
        Service {
            svc_type: ServiceType::UnknownRTSP,
            mac:      Some(mac),
            address:  Some(address),
            path:     None,
        }
    }

    /// Create a new Unsupported RTSP service.
    pub fn unsupported_rtsp(mac: MacAddr, address: SocketAddr, path: String) -> Service {
        Service {
            svc_type: ServiceType::RTSP,
            mac:      Some(mac),
            address:  Some(address),
            path:     Some(path),
        }
    }

    /// Create a new HTTP service.
    pub fn http(mac: MacAddr, address: SocketAddr) -> Service {
        Service {
            svc_type: ServiceType::HTTP,
            mac:      Some(mac),
            address:  Some(address),
            path:     None,
        }
    }

    /// Create a new MJPEG service.
    pub fn mjpeg(mac: MacAddr, address: SocketAddr, path: String) -> Service {
        Service {
            svc_type: ServiceType::MJPEG,
            mac:      Some(mac),
            address:  Some(address),
            path:     Some(path),
        }
    }

    /// Create a new Locked MJPEG service.
    pub fn locked_mjpeg(mac: MacAddr, address: SocketAddr, path: Option<String>) -> Service {
        Service {
            svc_type: ServiceType::LockedMJPEG,
            mac:      Some(mac),
            address:  Some(address),
            path:     path,
        }
    }

    /// Create a new TCP service.
    pub fn tcp(mac: MacAddr, address: SocketAddr) -> Service {
        Service {
            svc_type: ServiceType::TCP,
            mac:      Some(mac),
            address:  Some(address),
            path:     None,
        }
    }

    /// Check if this is the Control Protocol service.
    pub fn is_control(&self) -> bool {
        self.svc_type == ServiceType::ControlProtocol
    }

    /// Get service type.
    pub fn service_type(&self) -> ServiceType {
        self.svc_type
    }

    /// Get service MAC address.
    pub fn mac(&self) -> Option<MacAddr> {
        self.mac
    }

    /// Get service IP address and port.
    pub fn address(&self) -> Option<SocketAddr> {
        self.address
    }

    /// Get service IP address.
    pub fn ip_address(&self) -> Option<IpAddr> {
        self.address.map(|addr| addr.ip())
    }

    /// Get service port.
    pub fn port(&self) -> Option<u16> {
        self.address.map(|addr| addr.port())
    }

    /// Get service path.
    pub fn path(&self) -> Option<&str> {
        self.path.as_ref()
            .map(|v| v as &str)
    }

    /// Convert service to service identifier.
    pub fn to_service_identifier(&self) -> ServiceIdentifier {
        ServiceIdentifier {
            svc_type: self.service_type(),
            mac:      self.mac(),
            port:     self.port(),
            path:     self.path.clone(),
        }
    }
}
<commit_msg>Fix the unsupported_rtsp service constructor<commit_after>// Copyright 2017 click2stream, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::net::{IpAddr, SocketAddr};

use net::raw::ether::MacAddr;

pub const SVC_TYPE_CONTROL_PROTOCOL: u16 = 0x0000;
pub const SVC_TYPE_RTSP:             u16 = 0x0001;
pub const SVC_TYPE_LOCKED_RTSP:      u16 = 0x0002;
pub const SVC_TYPE_UNKNOWN_RTSP:     u16 = 0x0003;
pub const SVC_TYPE_UNSUPPORTED_RTSP: u16 = 0x0004;
pub const SVC_TYPE_HTTP:             u16 = 0x0005;
pub const SVC_TYPE_MJPEG:            u16 = 0x0006;
pub const SVC_TYPE_LOCKED_MJPEG:     u16 = 0x0007;
pub const SVC_TYPE_TCP:              u16 = 0xffff;

/// Service type.
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub enum ServiceType {
    /// Control Protocol service.
    ControlProtocol,
    /// Remote RTSP service.
    RTSP,
    /// Remote RTSP service requiring authentication.
    LockedRTSP,
    /// Remote RTSP service without any known path.
    UnknownRTSP,
    /// Remote RTSP service without any supported stream.
    UnsupportedRTSP,
    /// Remote HTTP service.
    HTTP,
    /// Remote MJPEG service.
    MJPEG,
    /// Remote MJPEG service requiring authentication.
    LockedMJPEG,
    /// General purpose TCP service.
    TCP,
}

impl ServiceType {
    /// Get code of the service type.
    pub fn code(&self) -> u16 {
        match self {
            &ServiceType::ControlProtocol => SVC_TYPE_CONTROL_PROTOCOL,
            &ServiceType::RTSP            => SVC_TYPE_RTSP,
            &ServiceType::LockedRTSP      => SVC_TYPE_LOCKED_RTSP,
            &ServiceType::UnknownRTSP     => SVC_TYPE_UNKNOWN_RTSP,
            &ServiceType::UnsupportedRTSP => SVC_TYPE_UNSUPPORTED_RTSP,
            &ServiceType::HTTP            => SVC_TYPE_HTTP,
            &ServiceType::MJPEG           => SVC_TYPE_MJPEG,
            &ServiceType::LockedMJPEG     => SVC_TYPE_LOCKED_MJPEG,
            &ServiceType::TCP             => SVC_TYPE_TCP,
        }
    }
}

/// Arrow service identifier.
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct ServiceIdentifier {
    svc_type: ServiceType,
    mac:      Option<MacAddr>,
    port:     Option<u16>,
    path:     Option<String>,
}

impl ServiceIdentifier {
    /// Check if this is the Control Protocol service  identifier.
    pub fn is_control(&self) -> bool {
        self.svc_type == ServiceType::ControlProtocol
    }
}

/// Arrow service.
#[derive(Clone, Eq, PartialEq)]
pub struct Service {
    svc_type: ServiceType,
    mac:      Option<MacAddr>,
    address:  Option<SocketAddr>,
    path:     Option<String>,
}

impl Service {
    /// Create a new Control Protocol service.
    pub fn control() -> Service {
        Service {
            svc_type: ServiceType::ControlProtocol,
            mac:      None,
            address:  None,
            path:     None,
        }
    }

    /// Create a new RTSP service.
    pub fn rtsp(mac: MacAddr, address: SocketAddr, path: String) -> Service {
        Service {
            svc_type: ServiceType::RTSP,
            mac:      Some(mac),
            address:  Some(address),
            path:     Some(path),
        }
    }

    /// Create a new Locked RTSP service.
    pub fn locked_rtsp(mac: MacAddr, address: SocketAddr, path: Option<String>) -> Service {
        Service {
            svc_type: ServiceType::LockedRTSP,
            mac:      Some(mac),
            address:  Some(address),
            path:     path,
        }
    }

    /// Create a new Unknown RTSP service.
    pub fn unknown_rtsp(mac: MacAddr, address: SocketAddr) -> Service {
        Service {
            svc_type: ServiceType::UnknownRTSP,
            mac:      Some(mac),
            address:  Some(address),
            path:     None,
        }
    }

    /// Create a new Unsupported RTSP service.
    pub fn unsupported_rtsp(mac: MacAddr, address: SocketAddr, path: String) -> Service {
        Service {
            svc_type: ServiceType::UnsupportedRTSP,
            mac:      Some(mac),
            address:  Some(address),
            path:     Some(path),
        }
    }

    /// Create a new HTTP service.
    pub fn http(mac: MacAddr, address: SocketAddr) -> Service {
        Service {
            svc_type: ServiceType::HTTP,
            mac:      Some(mac),
            address:  Some(address),
            path:     None,
        }
    }

    /// Create a new MJPEG service.
    pub fn mjpeg(mac: MacAddr, address: SocketAddr, path: String) -> Service {
        Service {
            svc_type: ServiceType::MJPEG,
            mac:      Some(mac),
            address:  Some(address),
            path:     Some(path),
        }
    }

    /// Create a new Locked MJPEG service.
    pub fn locked_mjpeg(mac: MacAddr, address: SocketAddr, path: Option<String>) -> Service {
        Service {
            svc_type: ServiceType::LockedMJPEG,
            mac:      Some(mac),
            address:  Some(address),
            path:     path,
        }
    }

    /// Create a new TCP service.
    pub fn tcp(mac: MacAddr, address: SocketAddr) -> Service {
        Service {
            svc_type: ServiceType::TCP,
            mac:      Some(mac),
            address:  Some(address),
            path:     None,
        }
    }

    /// Check if this is the Control Protocol service.
    pub fn is_control(&self) -> bool {
        self.svc_type == ServiceType::ControlProtocol
    }

    /// Get service type.
    pub fn service_type(&self) -> ServiceType {
        self.svc_type
    }

    /// Get service MAC address.
    pub fn mac(&self) -> Option<MacAddr> {
        self.mac
    }

    /// Get service IP address and port.
    pub fn address(&self) -> Option<SocketAddr> {
        self.address
    }

    /// Get service IP address.
    pub fn ip_address(&self) -> Option<IpAddr> {
        self.address.map(|addr| addr.ip())
    }

    /// Get service port.
    pub fn port(&self) -> Option<u16> {
        self.address.map(|addr| addr.port())
    }

    /// Get service path.
    pub fn path(&self) -> Option<&str> {
        self.path.as_ref()
            .map(|v| v as &str)
    }

    /// Convert service to service identifier.
    pub fn to_service_identifier(&self) -> ServiceIdentifier {
        ServiceIdentifier {
            svc_type: self.service_type(),
            mac:      self.mac(),
            port:     self.port(),
            path:     self.path.clone(),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 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.

extern mod std;

use std::bitv;
use io::{ReaderUtil, WriterUtil};

// Computes a single solution to a given 9x9 sudoku
//
// Call with "-" to read input sudoku from stdin
//
// The expected line-based format is:
//
// 9,9
// <row>,<column>,<color>
// ...
//
// Row and column are 0-based (i.e. <= 8) and color is 1-based (>=1,<=9).
// A color of 0 indicates an empty field.
//
// If called without arguments, sudoku solves a built-in example sudoku
//

export grid_t, read_grid, solve_grid, write_grid;

// internal type of sudoku grids
type grid = ~[~[mut u8]];

// exported type of sudoku grids
enum grid_t { grid_ctor(grid), }

// read a sudoku problem from file f
fn read_grid(f: io::Reader) -> grid_t {
    assert f.read_line() == ~"9,9"; /* assert first line is exactly "9,9" */

    let g = vec::from_fn(10u, {|_i|
        vec::cast_to_mut(vec::from_elem(10u, 0 as u8))
    });
    while !f.eof() {
        let comps = str::split_char(str::trim(f.read_line()), ',');
        if vec::len(comps) >= 3u {
            let row     = uint::from_str(comps[0]).get() as u8;
            let col     = uint::from_str(comps[1]).get() as u8;
            g[row][col] = uint::from_str(comps[2]).get() as u8;
        }
    }
    return grid_ctor(g);
}

// solve sudoku grid
fn solve_grid(g: grid_t) {
    fn next_color(g: grid, row: u8, col: u8, start_color: u8) -> bool {
        if start_color < 10u8 {
            // colors not yet used
            let avail = bitv::Bitv(10u, false);
            for u8::range(start_color, 10u8) |color| {
                avail.set(color as uint, true);
            }

            // drop colors already in use in neighbourhood
            drop_colors(copy g, copy avail, row, col);

            // find first remaining color that is available
            for uint::range(1u, 10u) |i| {
                if avail.get(i) {
                    g[row][col] = i as u8;
                    return true;
                }
            };
        }
        g[row][col] = 0u8;
        return false;
    }

    // find colors available in neighbourhood of (row, col)
    fn drop_colors(g: grid, avail: bitv::Bitv, row: u8, col: u8) {
        fn drop_color(g: grid, colors: bitv::Bitv, row: u8, col: u8) {
            let color = g[row][col];
            if color != 0u8 { colors.set(color as uint, false); }
        }

        let it = |a,b| drop_color(copy g, copy avail, a, b);

        for u8::range(0u8, 9u8) |idx| {
            it(idx, col); /* check same column fields */
            it(row, idx); /* check same row fields */
        }

        // check same block fields
        let row0 = (row / 3u8) * 3u8;
        let col0 = (col / 3u8) * 3u8;
        for u8::range(row0, row0 + 3u8) |alt_row| {
            for u8::range(col0, col0 + 3u8) |alt_col| { it(alt_row, alt_col); }
        }
    }

    let mut work: ~[(u8, u8)] = ~[]; /* queue of uncolored fields */
    for u8::range(0u8, 9u8) |row| {
        for u8::range(0u8, 9u8) |col| {
            let color = (*g)[row][col];
            if color == 0u8 { work += ~[(row, col)]; }
        }
    }

    let mut ptr = 0u;
    let end = vec::len(work);
    while (ptr < end) {
        let (row, col) = work[ptr];
        // is there another color to try?
        if next_color(copy *g, row, col, (*g)[row][col] + (1 as u8)) {
            //  yes: advance work list
            ptr = ptr + 1u;
        } else {
            // no: redo this field aft recoloring pred; unless there is none
            if ptr == 0u { fail ~"No solution found for this sudoku"; }
            ptr = ptr - 1u;
        }
    }
}

fn write_grid(f: io::Writer, g: grid_t) {
    for u8::range(0u8, 9u8) |row| {
        f.write_str(fmt!("%u", (*g)[row][0] as uint));
        for u8::range(1u8, 9u8) |col| {
            f.write_str(fmt!(" %u", (*g)[row][col] as uint));
        }
        f.write_char('\n');
     }
}

fn main() {
    let args = os::args();
    let grid = if vec::len(args) == 1u {
        // FIXME create sudoku inline since nested vec consts dont work yet
        // (#3733)
        let g = vec::from_fn(10u, |_i| {
            vec::cast_to_mut(vec::from_elem(10u, 0 as u8))
        });
        g[0][1] = 4u8;
        g[0][3] = 6u8;
        g[0][7] = 3u8;
        g[0][8] = 2u8;
        g[1][2] = 8u8;
        g[1][4] = 2u8;
        g[2][0] = 7u8;
        g[2][3] = 8u8;
        g[3][3] = 5u8;
        g[4][1] = 5u8;
        g[4][5] = 3u8;
        g[4][6] = 6u8;
        g[5][0] = 6u8;
        g[5][1] = 8u8;
        g[5][7] = 9u8;
        g[6][1] = 9u8;
        g[6][2] = 5u8;
        g[6][5] = 6u8;
        g[6][7] = 7u8;
        g[7][4] = 4u8;
        g[7][7] = 6u8;
        g[8][0] = 4u8;
        g[8][5] = 7u8;
        g[8][6] = 2u8;
        g[8][8] = 3u8;
        grid_ctor(g)
    } else {
        read_grid(io::stdin())
    };
    solve_grid(copy grid);
    write_grid(io::stdout(), grid);
}

<commit_msg>test: De-export sudoku. rs=burningtree<commit_after>// Copyright 2012 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.

extern mod std;

use std::bitv;
use io::{ReaderUtil, WriterUtil};

// Computes a single solution to a given 9x9 sudoku
//
// Call with "-" to read input sudoku from stdin
//
// The expected line-based format is:
//
// 9,9
// <row>,<column>,<color>
// ...
//
// Row and column are 0-based (i.e. <= 8) and color is 1-based (>=1,<=9).
// A color of 0 indicates an empty field.
//
// If called without arguments, sudoku solves a built-in example sudoku
//

// internal type of sudoku grids
type grid = ~[~[mut u8]];

// exported type of sudoku grids
pub enum grid_t { grid_ctor(grid), }

// read a sudoku problem from file f
pub fn read_grid(f: io::Reader) -> grid_t {
    assert f.read_line() == ~"9,9"; /* assert first line is exactly "9,9" */

    let g = vec::from_fn(10u, {|_i|
        vec::cast_to_mut(vec::from_elem(10u, 0 as u8))
    });
    while !f.eof() {
        let comps = str::split_char(str::trim(f.read_line()), ',');
        if vec::len(comps) >= 3u {
            let row     = uint::from_str(comps[0]).get() as u8;
            let col     = uint::from_str(comps[1]).get() as u8;
            g[row][col] = uint::from_str(comps[2]).get() as u8;
        }
    }
    return grid_ctor(g);
}

// solve sudoku grid
pub fn solve_grid(g: grid_t) {
    fn next_color(g: grid, row: u8, col: u8, start_color: u8) -> bool {
        if start_color < 10u8 {
            // colors not yet used
            let avail = bitv::Bitv(10u, false);
            for u8::range(start_color, 10u8) |color| {
                avail.set(color as uint, true);
            }

            // drop colors already in use in neighbourhood
            drop_colors(copy g, copy avail, row, col);

            // find first remaining color that is available
            for uint::range(1u, 10u) |i| {
                if avail.get(i) {
                    g[row][col] = i as u8;
                    return true;
                }
            };
        }
        g[row][col] = 0u8;
        return false;
    }

    // find colors available in neighbourhood of (row, col)
    fn drop_colors(g: grid, avail: bitv::Bitv, row: u8, col: u8) {
        fn drop_color(g: grid, colors: bitv::Bitv, row: u8, col: u8) {
            let color = g[row][col];
            if color != 0u8 { colors.set(color as uint, false); }
        }

        let it = |a,b| drop_color(copy g, copy avail, a, b);

        for u8::range(0u8, 9u8) |idx| {
            it(idx, col); /* check same column fields */
            it(row, idx); /* check same row fields */
        }

        // check same block fields
        let row0 = (row / 3u8) * 3u8;
        let col0 = (col / 3u8) * 3u8;
        for u8::range(row0, row0 + 3u8) |alt_row| {
            for u8::range(col0, col0 + 3u8) |alt_col| { it(alt_row, alt_col); }
        }
    }

    let mut work: ~[(u8, u8)] = ~[]; /* queue of uncolored fields */
    for u8::range(0u8, 9u8) |row| {
        for u8::range(0u8, 9u8) |col| {
            let color = (*g)[row][col];
            if color == 0u8 { work += ~[(row, col)]; }
        }
    }

    let mut ptr = 0u;
    let end = vec::len(work);
    while (ptr < end) {
        let (row, col) = work[ptr];
        // is there another color to try?
        if next_color(copy *g, row, col, (*g)[row][col] + (1 as u8)) {
            //  yes: advance work list
            ptr = ptr + 1u;
        } else {
            // no: redo this field aft recoloring pred; unless there is none
            if ptr == 0u { fail ~"No solution found for this sudoku"; }
            ptr = ptr - 1u;
        }
    }
}

pub fn write_grid(f: io::Writer, g: grid_t) {
    for u8::range(0u8, 9u8) |row| {
        f.write_str(fmt!("%u", (*g)[row][0] as uint));
        for u8::range(1u8, 9u8) |col| {
            f.write_str(fmt!(" %u", (*g)[row][col] as uint));
        }
        f.write_char('\n');
     }
}

fn main() {
    let args = os::args();
    let grid = if vec::len(args) == 1u {
        // FIXME create sudoku inline since nested vec consts dont work yet
        // (#3733)
        let g = vec::from_fn(10u, |_i| {
            vec::cast_to_mut(vec::from_elem(10u, 0 as u8))
        });
        g[0][1] = 4u8;
        g[0][3] = 6u8;
        g[0][7] = 3u8;
        g[0][8] = 2u8;
        g[1][2] = 8u8;
        g[1][4] = 2u8;
        g[2][0] = 7u8;
        g[2][3] = 8u8;
        g[3][3] = 5u8;
        g[4][1] = 5u8;
        g[4][5] = 3u8;
        g[4][6] = 6u8;
        g[5][0] = 6u8;
        g[5][1] = 8u8;
        g[5][7] = 9u8;
        g[6][1] = 9u8;
        g[6][2] = 5u8;
        g[6][5] = 6u8;
        g[6][7] = 7u8;
        g[7][4] = 4u8;
        g[7][7] = 6u8;
        g[8][0] = 4u8;
        g[8][5] = 7u8;
        g[8][6] = 2u8;
        g[8][8] = 3u8;
        grid_ctor(g)
    } else {
        read_grid(io::stdin())
    };
    solve_grid(copy grid);
    write_grid(io::stdout(), grid);
}

<|endoftext|>


<commit_before>use super::Request;
use crate::{
    api_call::ApiCall,
    version::*,
};
use http_types::Request as HTTPRequest;

impl From<Request> for HTTPRequest<String> {
    fn from(r: Request) -> Self {
        let (uri, body) = r.parameters.uri_and_body(r.path);
        let body = body.unwrap_or("").to_owned();
        let mut rb = HTTPRequest::builder();

        rb.header("User-Agent", USER_AGENT)
          .method(r.method)
          .uri(uri.as_ref())
          .body(body)
          .unwrap()
    }
}

impl From<&ApiCall<'_, '_, '_, '_, '_, '_>> for HTTPRequest<String> {
    fn from(i: &ApiCall) -> Self {
        Request::from(i).into()
    }
}

use super::FromRequest;
use crate::Never;

impl FromRequest<Never> for HTTPRequest<String> {
    fn from_request(r: Request, _params: Never) -> Self {
        Self::from(r)
    }
}
<commit_msg>request/http: move to new SetupRequest trait impl<commit_after>use super::Request;
use crate::{
    api_call::ApiCall,
    version::*,
};
use http_types::{
    request::Builder,
    Request as HTTPRequest,
};

impl From<Request> for HTTPRequest<String> {
    fn from(r: Request) -> Self {
        let (uri, body) = r.parameters.uri_and_body(r.path);
        let body = body.unwrap_or("").to_owned();
        let mut rb = HTTPRequest::builder();

        rb.header("User-Agent", USER_AGENT)
          .method(r.method)
          .uri(uri.as_ref())
          .body(body)
          .unwrap()
    }
}

impl From<&ApiCall<'_, '_, '_, '_, '_, '_>> for HTTPRequest<String> {
    fn from(i: &ApiCall) -> Self {
        Request::from(i).into()
    }
}

use super::SetupRequest;
use crate::Never;

impl SetupRequest<'_, Never, HTTPRequest<String>> for Builder {
    fn setup_request(&mut self, r: Request, _params: Never) -> HTTPRequest<String> {
        HTTPRequest::from(r)
    }
}
<|endoftext|>


<commit_before>use ra_syntax::{SourceFileNode, SyntaxKind, SyntaxNode, SyntaxNodeRef, TextRange};

/// A pionter to a syntax node inside a file.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct LocalSyntaxPtr {
    range: TextRange,
    kind: SyntaxKind,
}

impl LocalSyntaxPtr {
    pub fn new(node: SyntaxNodeRef) -> LocalSyntaxPtr {
        LocalSyntaxPtr {
            range: node.range(),
            kind: node.kind(),
        }
    }

    pub fn resolve(self, file: &SourceFileNode) -> SyntaxNode {
        let mut curr = file.syntax();
        loop {
            if curr.range() == self.range && curr.kind() == self.kind {
                return curr.owned();
            }
            curr = curr
                .children()
                .find(|it| self.range.is_subrange(&it.range()))
                .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self))
        }
    }

    pub fn range(self) -> TextRange {
        self.range
    }
}

#[test]
fn test_local_syntax_ptr() {
    use ra_syntax::{ast, AstNode};
    let file = SourceFileNode::parse("struct Foo { f: u32, }");
    let field = file
        .syntax()
        .descendants()
        .find_map(ast::NamedFieldDef::cast)
        .unwrap();
    let ptr = LocalSyntaxPtr::new(field.syntax());
    let field_syntax = ptr.resolve(&file);
    assert_eq!(field.syntax(), field_syntax);
}
<commit_msg>add kind to LocalSyntaxPtr<commit_after>use ra_syntax::{SourceFileNode, SyntaxKind, SyntaxNode, SyntaxNodeRef, TextRange};

/// A pionter to a syntax node inside a file.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct LocalSyntaxPtr {
    range: TextRange,
    kind: SyntaxKind,
}

impl LocalSyntaxPtr {
    pub fn new(node: SyntaxNodeRef) -> LocalSyntaxPtr {
        LocalSyntaxPtr {
            range: node.range(),
            kind: node.kind(),
        }
    }

    pub fn resolve(self, file: &SourceFileNode) -> SyntaxNode {
        let mut curr = file.syntax();
        loop {
            if curr.range() == self.range && curr.kind() == self.kind {
                return curr.owned();
            }
            curr = curr
                .children()
                .find(|it| self.range.is_subrange(&it.range()))
                .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self))
        }
    }

    pub fn range(self) -> TextRange {
        self.range
    }

    pub fn kind(self) -> SyntaxKind {
        self.kind
    }
}

#[test]
fn test_local_syntax_ptr() {
    use ra_syntax::{ast, AstNode};
    let file = SourceFileNode::parse("struct Foo { f: u32, }");
    let field = file
        .syntax()
        .descendants()
        .find_map(ast::NamedFieldDef::cast)
        .unwrap();
    let ptr = LocalSyntaxPtr::new(field.syntax());
    let field_syntax = ptr.resolve(&file);
    assert_eq!(field.syntax(), field_syntax);
}
<|endoftext|>


<commit_before>extern mod http;
use http::client::RequestWriter;
use http::method::Get;
use http::headers::HeaderEnum;
use std::os;
use std::str;
use std::io::Reader;

fn main() {
    format!("{}", Get);
    let args = os::args();
    match args.len() {
        0 => unreachable!(),
        2 => make_and_print_request(args[1]),
        _ => {
            println!("Usage: {} URL", args[0]);
            return;
        },
    };
}

fn make_and_print_request(url: ~str) {
    let request = RequestWriter::new(Get, from_str(url).expect("Invalid URL :-("));

    println("Request");
    println("=======");
    println("");
    println!("URL: {}", request.url.to_str());
    println!("Remote address: {:?}", request.remote_addr);
    println!("Method: {}", request.method);
    println("Headers:");
    for header in request.headers.iter() {
        println!(" - {}: {}", header.header_name(), header.header_value());
    }

    println("");
    println("Response");
    println("========");
    println("");
    let mut response = match request.read_response() {
        Ok(response) => response,
        Err(_request) => fail!("This example can progress no further with no response :-("),
    };
    println!("Status: {}", response.status);
    println("Headers:");
    for header in response.headers.iter() {
        println!(" - {}: {}", header.header_name(), header.header_value());
    }
    println("Body:");
    let body = response.read_to_end();
    println(str::from_utf8_slice(body));
}
<commit_msg>Update for mozilla/rust#10701.<commit_after>extern mod http;
use http::client::RequestWriter;
use http::method::Get;
use http::headers::HeaderEnum;
use std::os;
use std::str;
use std::io::Reader;

fn main() {
    format!("{}", Get);
    let args = os::args();
    match args.len() {
        0 => unreachable!(),
        2 => make_and_print_request(args[1]),
        _ => {
            println!("Usage: {} URL", args[0]);
            return;
        },
    };
}

fn make_and_print_request(url: ~str) {
    let request = RequestWriter::new(Get, from_str(url).expect("Invalid URL :-("));

    println("Request");
    println("=======");
    println("");
    println!("URL: {}", request.url.to_str());
    println!("Remote address: {:?}", request.remote_addr);
    println!("Method: {}", request.method);
    println("Headers:");
    for header in request.headers.iter() {
        println!(" - {}: {}", header.header_name(), header.header_value());
    }

    println("");
    println("Response");
    println("========");
    println("");
    let mut response = match request.read_response() {
        Ok(response) => response,
        Err(_request) => fail!("This example can progress no further with no response :-("),
    };
    println!("Status: {}", response.status);
    println("Headers:");
    for header in response.headers.iter() {
        println!(" - {}: {}", header.header_name(), header.header_value());
    }
    println("Body:");
    let body = response.read_to_end();
    println(str::from_utf8(body));
}
<|endoftext|>