<commit_before>use num::Integer;
use euclid::Point2D;
use hex::Dir6;

/// User data for field of view cells.
pub trait FovValue: PartialEq + Clone {
    /// Construct a new FovValue for a position based on the previous one along the line of sight.
    fn advance(&self, offset: Point2D<i32>) -> Option<Self>;

    /// Return whether the given offset contains an isometric wall tile.
    ///
    /// Optional method for showing acute corners of fake isometric rooms in fov.
    fn is_fake_isometric_wall(&self, offset: Point2D<i32>) -> bool {
        let _ = offset;
        false
    }
}

/// Field of view iterator for a hexagonal map.
pub struct HexFov<T> {
    stack: Vec<Arc<T>>,
    /// Extra values generated by special cases.
    side_channel: Vec<(Point2D<i32>, T)>,
}

impl<T: FovValue> HexFov<T> {
    /// Create a new field of view iterator with a seed userdata for the origin position.
    pub fn new(init: T) -> HexFov<T> {
        // We could run f for (0, 0) here, but the traditional way for the FOV to work is to only
        // consider your surroundings, not the origin site itself.
        HexFov {
            stack: vec![Arc::new(PolarPoint::new(0.0, 1),
                                 PolarPoint::new(6.0, 1),
                                 init.clone())],
            // The FOV algorithm will not generate the origin point, so we use
            // the side channel to explicitly add it in the beginning.
            side_channel: vec![(Point2D::new(0, 0), init)],
        }
    }

    /// Add visible horizontal corners to fake-isometric rooms.
    fn make_corners_visible(&mut self, current: &Arc<T>) {
        // We're moving along a vertical line on the hex circle, so there are side
        // points to check.
        if let Some(side_pos) = current.pt.side_point() {
            let next = current.pt.next();
            // If the next cell is within the current span and the current cell is
            // wallform,
            if next.is_below(current.end) &&
               current.prev_value.is_fake_isometric_wall(current.pt.to_v2()) {
                // and if the next cell is visible,
                if let Some(next_value) = current.prev_value.advance(next.to_v2()) {
                    // and if the current and the next cell are in the same value group,
                    // both the next cell and the third corner point cell are
                    // wallforms, and the side point would not be otherwise
                    // visible:
                    if next_value == current.prev_value &&
                       next_value.is_fake_isometric_wall(next.to_v2()) &&
                       current.prev_value.advance(side_pos).is_none() &&
                       current.prev_value.is_fake_isometric_wall(side_pos) {
                        // Add the side point to the side channel.
                        self.side_channel.push((side_pos, current.prev_value.clone()));
                    }
                }
            }
        }
    }
}

impl<T: FovValue> Iterator for HexFov<T> {
    type Item = (Point2D<i32>, T);
    fn next(&mut self) -> Option<(Point2D<i32>, T)> {
        // Empty the side channel before proceeding to the algorithm proper.
        if let Some(ret) = self.side_channel.pop() {
            return Some(ret);
        }

        // Start processing the next arc in the stack.
        if let Some(current) = self.stack.pop() {
            if current.arc_has_split(&mut self.stack) {
                return self.next();
            }

            assert!(current.group_value == current.prev_value.advance(current.pt.to_v2()));

            self.make_corners_visible(&current);

            let pos = current.pt.to_v2();
            let ret = current.group_value.clone();

            current.advance(&mut self.stack);

            if let Some(ret) = ret {
                return Some((pos, ret));
            } else {
                return self.next();
            }
        } else {
            None
        }
    }
}

struct Arc<T> {
    /// Start point of current arc.
    begin: PolarPoint,
    /// Point currently being processed.
    pt: PolarPoint,
    /// End point of current arc.
    end: PolarPoint,
    /// The user value from previous iteration.
    prev_value: T,
    /// The user value for this group.
    group_value: Option<T>,
}

impl<T: FovValue> Arc<T> {
    pub fn new(begin: PolarPoint, end: PolarPoint, prev_value: T) -> Arc<T> {
        let group_value = prev_value.advance(begin.to_v2());
        Arc {
            begin: begin,
            pt: begin,
            end: end,
            prev_value: prev_value,
            group_value: group_value,
        }
    }

    /// Consume the given arc and add its descendent, if any, to the stack.
    pub fn advance(mut self, stack: &mut Vec<Arc<T>>) {
        self.pt = self.pt.next();
        if self.pt.is_below(self.end) {
            stack.push(self);
        } else {
            if let Some(group_value) = self.group_value {
                stack.push(Arc::new(self.begin.further(), self.end.further(), group_value));
            }
        }
    }

    /// If the arc has advanced into a different value group, split it into the given stack.
    ///
    /// Return true if arc was split, false otherwise.
    pub fn arc_has_split(&self, stack: &mut Vec<Arc<T>>) -> bool {
        let next_value = self.prev_value.advance(self.pt.to_v2());
        if next_value != self.group_value {
            // Using the literal instead of the constructor to avoid recomputing next_value.
            stack.push(Arc {
                begin: self.pt,
                pt: self.pt,
                end: self.end,
                prev_value: self.prev_value.clone(),
                group_value: next_value,
            });

            // Extend current arc if it has a group value.
            if let Some(ref group_value) = self.group_value {
                stack.push(Arc::new(self.begin.further(), self.pt.further(), group_value.clone()));
            }

            true
        } else {
            false
        }
    }
}

/// Points on a hex circle expressed in polar coordinates.
#[derive(Copy, Clone, PartialEq)]
struct PolarPoint {
    pos: f32,
    radius: u32,
}

impl PolarPoint {
    pub fn new(pos: f32, radius: u32) -> PolarPoint {
        PolarPoint {
            pos: pos,
            radius: radius,
        }
    }
    /// Index of the discrete hex cell along the circle that corresponds to this point.
    fn winding_index(self) -> i32 { (self.pos + 0.5).floor() as i32 }

    pub fn is_below(self, other: PolarPoint) -> bool { self.winding_index() < other.end_index() }

    fn end_index(self) -> i32 { (self.pos + 0.5).ceil() as i32 }

    pub fn to_v2(self) -> Point2D<i32> {
        if self.radius == 0 {
            return Point2D::new(0, 0);
        }
        let index = self.winding_index();
        let sector = index.mod_floor(&(self.radius as i32 * 6)) / self.radius as i32;
        let offset = index.mod_floor(&(self.radius as i32));

        let rod = Dir6::from_int(sector).to_v2();
        let tangent = Dir6::from_int((sector + 2) % 6).to_v2();

        rod * (self.radius as i32) + tangent * offset
    }

    /// If this point and the next point are adjacent vertically (along the xy
    /// axis), return the point outside of the circle between the two points.
    ///
    /// This is a helper function for the FOV special case where acute corners
    /// of fake isometric rooms are marked visible even though strict hex FOV
    /// logic would keep them unseen.
    pub fn side_point(self) -> Option<Point2D<i32>> {
        let next = self.next();
        let a = self.to_v2();
        let b = next.to_v2();

        if b.x == a.x + 1 && b.y == a.y + 1 {
            // Going down the right rim.
            Some(Point2D::new(a.x + 1, a.y))
        } else if b.x == a.x - 1 && b.y == a.y - 1 {
            // Going up the left rim.
            Some(Point2D::new(a.x - 1, a.y))
        } else {
            None
        }
    }

    /// The point corresponding to this one on the hex circle with radius +1.
    pub fn further(self) -> PolarPoint {
        PolarPoint::new(self.pos * (self.radius + 1) as f32 / self.radius as f32,
                        self.radius + 1)
    }

    /// The point next to this one along the hex circle.
    pub fn next(self) -> PolarPoint { PolarPoint::new((self.pos + 0.5).floor() + 0.5, self.radius) }
}

#[cfg(test)]
mod test {
    use std::collections::HashMap;
    use std::iter::FromIterator;
    use euclid::Point2D;
    use super::{FovValue, HexFov};
    use hex::HexGeom;

    #[derive(PartialEq, Eq, Clone)]
    struct Cell1 {
        range: i32,
    }

    impl FovValue for Cell1 {
        fn advance(&self, offset: Point2D<i32>) -> Option<Self> {
            if offset.hex_dist() < self.range { Some(self.clone()) } else { None }
        }
    }

    #[derive(PartialEq, Eq, Clone)]
    struct Cell2 {
        range: i32,
    }

    impl FovValue for Cell2 {
        fn advance(&self, offset: Point2D<i32>) -> Option<Self> {
            if offset.hex_dist() < self.range { Some(self.clone()) } else { None }
        }

        fn is_fake_isometric_wall(&self, offset: Point2D<i32>) -> bool {
            let _ = offset;
            true
        }
    }

    #[test]
    fn trivial_fov() {
        // Just draw a small circle.
        let field: HashMap<Point2D<i32>, Cell1> = HashMap::from_iter(HexFov::new(Cell1 {
            range: 2,
        }));
        assert!(field.contains_key(&Point2D::new(1, 0)));
        assert!(!field.contains_key(&Point2D::new(1, -1)));

        // Now test out the fake-isometric corners.
        let field: HashMap<Point2D<i32>, Cell2> = HashMap::from_iter(HexFov::new(Cell2 {
            range: 2,
        }));
        assert!(field.contains_key(&Point2D::new(1, 0)));
        assert!(field.contains_key(&Point2D::new(1, -1)));
    }
}
<commit_msg>Long time no fov logic bug fix<commit_after>use num::Integer;
use euclid::Point2D;
use hex::Dir6;

/// User data for field of view cells.
pub trait FovValue: PartialEq + Clone {
    /// Construct a new FovValue for a position based on the previous one along the line of sight.
    fn advance(&self, offset: Point2D<i32>) -> Option<Self>;

    /// Return whether the given offset contains an isometric wall tile.
    ///
    /// Optional method for showing acute corners of fake isometric rooms in fov.
    fn is_fake_isometric_wall(&self, offset: Point2D<i32>) -> bool {
        let _ = offset;
        false
    }
}

/// Field of view iterator for a hexagonal map.
pub struct HexFov<T> {
    stack: Vec<Arc<T>>,
    /// Extra values generated by special cases.
    side_channel: Vec<(Point2D<i32>, T)>,
}

impl<T: FovValue> HexFov<T> {
    /// Create a new field of view iterator with a seed userdata for the origin position.
    pub fn new(init: T) -> HexFov<T> {
        // We could run f for (0, 0) here, but the traditional way for the FOV to work is to only
        // consider your surroundings, not the origin site itself.
        HexFov {
            stack: vec![Arc::new(PolarPoint::new(0.0, 1),
                                 PolarPoint::new(6.0, 1),
                                 init.clone())],
            // The FOV algorithm will not generate the origin point, so we use
            // the side channel to explicitly add it in the beginning.
            side_channel: vec![(Point2D::new(0, 0), init)],
        }
    }

    /// Add visible horizontal corners to fake-isometric rooms.
    fn make_corners_visible(&mut self, current: &Arc<T>) {
        // We're moving along a vertical line on the hex circle, so there are side
        // points to check.
        if let Some(side_pos) = current.pt.side_point() {
            let next = current.pt.next();
            let next_value = current.prev_value.advance(next.to_v2());
            // If the next cell is within the current span and the current cell is
            // wallform, and current and next are in the same value group,
            if next.is_below(current.end) &&
               current.prev_value.is_fake_isometric_wall(current.pt.to_v2()) &&
               next_value == current.prev_value.advance(current.pt.to_v2()) {
                if let Some(next_value) = next_value {
                    // and if both the next cell and the third corner point cell are
                    // wallforms, and the side point would not be otherwise
                    // visible:
                    if next_value.is_fake_isometric_wall(next.to_v2()) &&
                       next_value.advance(side_pos).is_none() &&
                       next_value.is_fake_isometric_wall(side_pos) {
                        // Add the side point to the side channel.
                        self.side_channel.push((side_pos, current.prev_value.clone()));
                    }
                }
            }
        }
    }
}

impl<T: FovValue> Iterator for HexFov<T> {
    type Item = (Point2D<i32>, T);
    fn next(&mut self) -> Option<(Point2D<i32>, T)> {
        // Empty the side channel before proceeding to the algorithm proper.
        if let Some(ret) = self.side_channel.pop() {
            return Some(ret);
        }

        // Start processing the next arc in the stack.
        if let Some(current) = self.stack.pop() {
            if current.arc_has_split(&mut self.stack) {
                return self.next();
            }

            assert!(current.group_value == current.prev_value.advance(current.pt.to_v2()));

            self.make_corners_visible(&current);

            let pos = current.pt.to_v2();
            let ret = current.group_value.clone();

            current.advance(&mut self.stack);

            if let Some(ret) = ret {
                return Some((pos, ret));
            } else {
                return self.next();
            }
        } else {
            None
        }
    }
}

struct Arc<T> {
    /// Start point of current arc.
    begin: PolarPoint,
    /// Point currently being processed.
    pt: PolarPoint,
    /// End point of current arc.
    end: PolarPoint,
    /// The user value from previous iteration.
    prev_value: T,
    /// The user value for this group.
    group_value: Option<T>,
}

impl<T: FovValue> Arc<T> {
    pub fn new(begin: PolarPoint, end: PolarPoint, prev_value: T) -> Arc<T> {
        let group_value = prev_value.advance(begin.to_v2());
        Arc {
            begin: begin,
            pt: begin,
            end: end,
            prev_value: prev_value,
            group_value: group_value,
        }
    }

    /// Consume the given arc and add its descendent, if any, to the stack.
    pub fn advance(mut self, stack: &mut Vec<Arc<T>>) {
        self.pt = self.pt.next();
        if self.pt.is_below(self.end) {
            stack.push(self);
        } else {
            if let Some(group_value) = self.group_value {
                stack.push(Arc::new(self.begin.further(), self.end.further(), group_value));
            }
        }
    }

    /// If the arc has advanced into a different value group, split it into the given stack.
    ///
    /// Return true if arc was split, false otherwise.
    pub fn arc_has_split(&self, stack: &mut Vec<Arc<T>>) -> bool {
        let next_value = self.prev_value.advance(self.pt.to_v2());
        if next_value != self.group_value {
            // Using the literal instead of the constructor to avoid recomputing next_value.
            stack.push(Arc {
                begin: self.pt,
                pt: self.pt,
                end: self.end,
                prev_value: self.prev_value.clone(),
                group_value: next_value,
            });

            // Extend current arc if it has a group value.
            if let Some(ref group_value) = self.group_value {
                stack.push(Arc::new(self.begin.further(), self.pt.further(), group_value.clone()));
            }

            true
        } else {
            false
        }
    }
}

/// Points on a hex circle expressed in polar coordinates.
#[derive(Copy, Clone, PartialEq)]
struct PolarPoint {
    pos: f32,
    radius: u32,
}

impl PolarPoint {
    pub fn new(pos: f32, radius: u32) -> PolarPoint {
        PolarPoint {
            pos: pos,
            radius: radius,
        }
    }
    /// Index of the discrete hex cell along the circle that corresponds to this point.
    fn winding_index(self) -> i32 { (self.pos + 0.5).floor() as i32 }

    pub fn is_below(self, other: PolarPoint) -> bool { self.winding_index() < other.end_index() }

    fn end_index(self) -> i32 { (self.pos + 0.5).ceil() as i32 }

    pub fn to_v2(self) -> Point2D<i32> {
        if self.radius == 0 {
            return Point2D::new(0, 0);
        }
        let index = self.winding_index();
        let sector = index.mod_floor(&(self.radius as i32 * 6)) / self.radius as i32;
        let offset = index.mod_floor(&(self.radius as i32));

        let rod = Dir6::from_int(sector).to_v2();
        let tangent = Dir6::from_int((sector + 2) % 6).to_v2();

        rod * (self.radius as i32) + tangent * offset
    }

    /// If this point and the next point are adjacent vertically (along the xy
    /// axis), return the point outside of the circle between the two points.
    ///
    /// This is a helper function for the FOV special case where acute corners
    /// of fake isometric rooms are marked visible even though strict hex FOV
    /// logic would keep them unseen.
    pub fn side_point(self) -> Option<Point2D<i32>> {
        let next = self.next();
        let a = self.to_v2();
        let b = next.to_v2();

        if b.x == a.x + 1 && b.y == a.y + 1 {
            // Going down the right rim.
            Some(Point2D::new(a.x + 1, a.y))
        } else if b.x == a.x - 1 && b.y == a.y - 1 {
            // Going up the left rim.
            Some(Point2D::new(a.x - 1, a.y))
        } else {
            None
        }
    }

    /// The point corresponding to this one on the hex circle with radius +1.
    pub fn further(self) -> PolarPoint {
        PolarPoint::new(self.pos * (self.radius + 1) as f32 / self.radius as f32,
                        self.radius + 1)
    }

    /// The point next to this one along the hex circle.
    pub fn next(self) -> PolarPoint { PolarPoint::new((self.pos + 0.5).floor() + 0.5, self.radius) }
}

#[cfg(test)]
mod test {
    use std::collections::HashMap;
    use std::iter::FromIterator;
    use euclid::Point2D;
    use super::{FovValue, HexFov};
    use hex::HexGeom;

    #[derive(PartialEq, Eq, Clone)]
    struct Cell1 {
        range: i32,
    }

    impl FovValue for Cell1 {
        fn advance(&self, offset: Point2D<i32>) -> Option<Self> {
            if offset.hex_dist() < self.range { Some(self.clone()) } else { None }
        }
    }

    #[derive(PartialEq, Eq, Clone)]
    struct Cell2 {
        range: i32,
    }

    impl FovValue for Cell2 {
        fn advance(&self, offset: Point2D<i32>) -> Option<Self> {
            if offset.hex_dist() < self.range { Some(self.clone()) } else { None }
        }

        fn is_fake_isometric_wall(&self, offset: Point2D<i32>) -> bool {
            let _ = offset;
            true
        }
    }

    #[test]
    fn trivial_fov() {
        // Just draw a small circle.
        let field: HashMap<Point2D<i32>, Cell1> = HashMap::from_iter(HexFov::new(Cell1 {
            range: 2,
        }));
        assert!(field.contains_key(&Point2D::new(1, 0)));
        assert!(!field.contains_key(&Point2D::new(1, -1)));

        // Now test out the fake-isometric corners.
        let field: HashMap<Point2D<i32>, Cell2> = HashMap::from_iter(HexFov::new(Cell2 {
            range: 2,
        }));
        assert!(field.contains_key(&Point2D::new(1, 0)));
        assert!(field.contains_key(&Point2D::new(1, -1)));
    }
}
<|endoftext|>


<commit_before>//! A desugared representation of paths like `crate::foo` or `<Type as Trait>::bar`.
mod lower;

use std::{
    fmt::{self, Display},
    iter,
    sync::Arc,
};

use hir_expand::{
    hygiene::Hygiene,
    name::{AsName, Name},
};
use ra_db::CrateId;
use ra_syntax::ast;

use crate::{type_ref::TypeRef, InFile};

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ModPath {
    pub kind: PathKind,
    pub segments: Vec<Name>,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum PathKind {
    Plain,
    /// `self::` is `Super(0)`
    Super(u8),
    Crate,
    /// Absolute path (::foo)
    Abs,
    /// `$crate` from macro expansion
    DollarCrate(CrateId),
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ImportAlias {
    /// Unnamed alias, as in `use Foo as _;`
    Underscore,
    /// Named alias
    Alias(Name),
}

impl ModPath {
    pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> {
        lower::lower_path(path, hygiene).map(|it| it.mod_path)
    }

    pub fn from_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> ModPath {
        let segments = segments.into_iter().collect::<Vec<_>>();
        ModPath { kind, segments }
    }

    pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> ModPath {
        name_ref.as_name().into()
    }

    /// Converts an `tt::Ident` into a single-identifier `Path`.
    pub(crate) fn from_tt_ident(ident: &tt::Ident) -> ModPath {
        ident.as_name().into()
    }

    /// Calls `cb` with all paths, represented by this use item.
    pub(crate) fn expand_use_item(
        item_src: InFile<ast::UseItem>,
        hygiene: &Hygiene,
        mut cb: impl FnMut(ModPath, &ast::UseTree, /* is_glob */ bool, Option<ImportAlias>),
    ) {
        if let Some(tree) = item_src.value.use_tree() {
            lower::lower_use_tree(None, tree, hygiene, &mut cb);
        }
    }

    pub fn is_ident(&self) -> bool {
        self.kind == PathKind::Plain && self.segments.len() == 1
    }

    pub fn is_self(&self) -> bool {
        self.kind == PathKind::Super(0) && self.segments.is_empty()
    }

    /// If this path is a single identifier, like `foo`, return its name.
    pub fn as_ident(&self) -> Option<&Name> {
        if self.kind != PathKind::Plain || self.segments.len() > 1 {
            return None;
        }
        self.segments.first()
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Path {
    /// Type based path like `<T>::foo`.
    /// Note that paths like `<Type as Trait>::foo` are desugard to `Trait::<Self=Type>::foo`.
    type_anchor: Option<Box<TypeRef>>,
    mod_path: ModPath,
    /// Invariant: the same len as self.path.segments
    generic_args: Vec<Option<Arc<GenericArgs>>>,
}

/// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This
/// also includes bindings of associated types, like in `Iterator<Item = Foo>`.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct GenericArgs {
    pub args: Vec<GenericArg>,
    /// This specifies whether the args contain a Self type as the first
    /// element. This is the case for path segments like `<T as Trait>`, where
    /// `T` is actually a type parameter for the path `Trait` specifying the
    /// Self type. Otherwise, when we have a path `Trait<X, Y>`, the Self type
    /// is left out.
    pub has_self_type: bool,
    /// Associated type bindings like in `Iterator<Item = T>`.
    pub bindings: Vec<(Name, TypeRef)>,
}

/// A single generic argument.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum GenericArg {
    Type(TypeRef),
    // or lifetime...
}

impl Path {
    /// Converts an `ast::Path` to `Path`. Works with use trees.
    /// DEPRECATED: It does not handle `$crate` from macro call.
    pub fn from_ast(path: ast::Path) -> Option<Path> {
        lower::lower_path(path, &Hygiene::new_unhygienic())
    }

    /// Converts an `ast::Path` to `Path`. Works with use trees.
    /// It correctly handles `$crate` based path from macro call.
    pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
        lower::lower_path(path, hygiene)
    }

    /// Converts an `ast::NameRef` into a single-identifier `Path`.
    pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path {
        Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] }
    }

    /// Converts a known mod path to `Path`.
    pub(crate) fn from_known_path(
        path: ModPath,
        generic_args: Vec<Option<Arc<GenericArgs>>>,
    ) -> Path {
        Path { type_anchor: None, mod_path: path, generic_args }
    }

    pub fn kind(&self) -> &PathKind {
        &self.mod_path.kind
    }

    pub fn type_anchor(&self) -> Option<&TypeRef> {
        self.type_anchor.as_deref()
    }

    pub fn segments(&self) -> PathSegments<'_> {
        PathSegments {
            segments: self.mod_path.segments.as_slice(),
            generic_args: self.generic_args.as_slice(),
        }
    }

    pub fn mod_path(&self) -> &ModPath {
        &self.mod_path
    }

    pub fn qualifier(&self) -> Option<Path> {
        if self.mod_path.is_ident() {
            return None;
        }
        let res = Path {
            type_anchor: self.type_anchor.clone(),
            mod_path: ModPath {
                kind: self.mod_path.kind.clone(),
                segments: self.mod_path.segments[..self.mod_path.segments.len() - 1].to_vec(),
            },
            generic_args: self.generic_args[..self.generic_args.len() - 1].to_vec(),
        };
        Some(res)
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PathSegment<'a> {
    pub name: &'a Name,
    pub args_and_bindings: Option<&'a GenericArgs>,
}

pub struct PathSegments<'a> {
    segments: &'a [Name],
    generic_args: &'a [Option<Arc<GenericArgs>>],
}

impl<'a> PathSegments<'a> {
    pub const EMPTY: PathSegments<'static> = PathSegments { segments: &[], generic_args: &[] };
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
    pub fn len(&self) -> usize {
        self.segments.len()
    }
    pub fn first(&self) -> Option<PathSegment<'a>> {
        self.get(0)
    }
    pub fn last(&self) -> Option<PathSegment<'a>> {
        self.get(self.len().checked_sub(1)?)
    }
    pub fn get(&self, idx: usize) -> Option<PathSegment<'a>> {
        assert_eq!(self.segments.len(), self.generic_args.len());
        let res = PathSegment {
            name: self.segments.get(idx)?,
            args_and_bindings: self.generic_args.get(idx).unwrap().as_ref().map(|it| &**it),
        };
        Some(res)
    }
    pub fn skip(&self, len: usize) -> PathSegments<'a> {
        assert_eq!(self.segments.len(), self.generic_args.len());
        PathSegments { segments: &self.segments[len..], generic_args: &self.generic_args[len..] }
    }
    pub fn take(&self, len: usize) -> PathSegments<'a> {
        assert_eq!(self.segments.len(), self.generic_args.len());
        PathSegments { segments: &self.segments[..len], generic_args: &self.generic_args[..len] }
    }
    pub fn iter(&self) -> impl Iterator<Item = PathSegment<'a>> {
        self.segments.iter().zip(self.generic_args.iter()).map(|(name, args)| PathSegment {
            name,
            args_and_bindings: args.as_ref().map(|it| &**it),
        })
    }
}

impl GenericArgs {
    pub(crate) fn from_ast(node: ast::TypeArgList) -> Option<GenericArgs> {
        lower::lower_generic_args(node)
    }

    pub(crate) fn empty() -> GenericArgs {
        GenericArgs { args: Vec::new(), has_self_type: false, bindings: Vec::new() }
    }
}

impl From<Name> for Path {
    fn from(name: Name) -> Path {
        Path {
            type_anchor: None,
            mod_path: ModPath::from_segments(PathKind::Plain, iter::once(name)),
            generic_args: vec![None],
        }
    }
}

impl From<Name> for ModPath {
    fn from(name: Name) -> ModPath {
        ModPath::from_segments(PathKind::Plain, iter::once(name))
    }
}

impl Display for ModPath {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut first_segment = true;
        let mut add_segment = |s| {
            if !first_segment {
                f.write_str("::")?;
            }
            first_segment = false;
            f.write_str(s)?;
            Ok(())
        };
        match self.kind {
            PathKind::Plain => {}
            PathKind::Super(n) => {
                if n == 0 {
                    add_segment("self")?;
                }
                for _ in 0..n {
                    add_segment("super")?;
                }
            }
            PathKind::Crate => add_segment("crate")?,
            PathKind::Abs => add_segment("")?,
            PathKind::DollarCrate(_) => add_segment("$crate")?,
        }
        for segment in &self.segments {
            if !first_segment {
                f.write_str("::")?;
            }
            first_segment = false;
            write!(f, "{}", segment)?;
        }
        Ok(())
    }
}

pub use hir_expand::name as __name;

#[macro_export]
macro_rules! __known_path {
    (std::iter::IntoIterator) => {};
    (std::result::Result) => {};
    (std::ops::Range) => {};
    (std::ops::RangeFrom) => {};
    (std::ops::RangeFull) => {};
    (std::ops::RangeTo) => {};
    (std::ops::RangeToInclusive) => {};
    (std::ops::RangeInclusive) => {};
    (std::future::Future) => {};
    (std::ops::Try) => {};
    ($path:path) => {
        compile_error!("Please register your known path in the path module")
    };
}

#[macro_export]
macro_rules! __path {
    ($start:ident $(:: $seg:ident)*) => ({
        $crate::__known_path!($start $(:: $seg)*);
        $crate::path::ModPath::from_segments($crate::path::PathKind::Abs, vec![
            $crate::path::__name![$start], $($crate::path::__name![$seg],)*
        ])
    });
}

pub use crate::__path as path;
<commit_msg>ra_hir_def: fix typo<commit_after>//! A desugared representation of paths like `crate::foo` or `<Type as Trait>::bar`.
mod lower;

use std::{
    fmt::{self, Display},
    iter,
    sync::Arc,
};

use hir_expand::{
    hygiene::Hygiene,
    name::{AsName, Name},
};
use ra_db::CrateId;
use ra_syntax::ast;

use crate::{type_ref::TypeRef, InFile};

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ModPath {
    pub kind: PathKind,
    pub segments: Vec<Name>,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum PathKind {
    Plain,
    /// `self::` is `Super(0)`
    Super(u8),
    Crate,
    /// Absolute path (::foo)
    Abs,
    /// `$crate` from macro expansion
    DollarCrate(CrateId),
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ImportAlias {
    /// Unnamed alias, as in `use Foo as _;`
    Underscore,
    /// Named alias
    Alias(Name),
}

impl ModPath {
    pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> {
        lower::lower_path(path, hygiene).map(|it| it.mod_path)
    }

    pub fn from_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> ModPath {
        let segments = segments.into_iter().collect::<Vec<_>>();
        ModPath { kind, segments }
    }

    pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> ModPath {
        name_ref.as_name().into()
    }

    /// Converts an `tt::Ident` into a single-identifier `Path`.
    pub(crate) fn from_tt_ident(ident: &tt::Ident) -> ModPath {
        ident.as_name().into()
    }

    /// Calls `cb` with all paths, represented by this use item.
    pub(crate) fn expand_use_item(
        item_src: InFile<ast::UseItem>,
        hygiene: &Hygiene,
        mut cb: impl FnMut(ModPath, &ast::UseTree, /* is_glob */ bool, Option<ImportAlias>),
    ) {
        if let Some(tree) = item_src.value.use_tree() {
            lower::lower_use_tree(None, tree, hygiene, &mut cb);
        }
    }

    pub fn is_ident(&self) -> bool {
        self.kind == PathKind::Plain && self.segments.len() == 1
    }

    pub fn is_self(&self) -> bool {
        self.kind == PathKind::Super(0) && self.segments.is_empty()
    }

    /// If this path is a single identifier, like `foo`, return its name.
    pub fn as_ident(&self) -> Option<&Name> {
        if self.kind != PathKind::Plain || self.segments.len() > 1 {
            return None;
        }
        self.segments.first()
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Path {
    /// Type based path like `<T>::foo`.
    /// Note that paths like `<Type as Trait>::foo` are desugard to `Trait::<Self=Type>::foo`.
    type_anchor: Option<Box<TypeRef>>,
    mod_path: ModPath,
    /// Invariant: the same len as `self.mod_path.segments`
    generic_args: Vec<Option<Arc<GenericArgs>>>,
}

/// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This
/// also includes bindings of associated types, like in `Iterator<Item = Foo>`.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct GenericArgs {
    pub args: Vec<GenericArg>,
    /// This specifies whether the args contain a Self type as the first
    /// element. This is the case for path segments like `<T as Trait>`, where
    /// `T` is actually a type parameter for the path `Trait` specifying the
    /// Self type. Otherwise, when we have a path `Trait<X, Y>`, the Self type
    /// is left out.
    pub has_self_type: bool,
    /// Associated type bindings like in `Iterator<Item = T>`.
    pub bindings: Vec<(Name, TypeRef)>,
}

/// A single generic argument.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum GenericArg {
    Type(TypeRef),
    // or lifetime...
}

impl Path {
    /// Converts an `ast::Path` to `Path`. Works with use trees.
    /// DEPRECATED: It does not handle `$crate` from macro call.
    pub fn from_ast(path: ast::Path) -> Option<Path> {
        lower::lower_path(path, &Hygiene::new_unhygienic())
    }

    /// Converts an `ast::Path` to `Path`. Works with use trees.
    /// It correctly handles `$crate` based path from macro call.
    pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
        lower::lower_path(path, hygiene)
    }

    /// Converts an `ast::NameRef` into a single-identifier `Path`.
    pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path {
        Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] }
    }

    /// Converts a known mod path to `Path`.
    pub(crate) fn from_known_path(
        path: ModPath,
        generic_args: Vec<Option<Arc<GenericArgs>>>,
    ) -> Path {
        Path { type_anchor: None, mod_path: path, generic_args }
    }

    pub fn kind(&self) -> &PathKind {
        &self.mod_path.kind
    }

    pub fn type_anchor(&self) -> Option<&TypeRef> {
        self.type_anchor.as_deref()
    }

    pub fn segments(&self) -> PathSegments<'_> {
        PathSegments {
            segments: self.mod_path.segments.as_slice(),
            generic_args: self.generic_args.as_slice(),
        }
    }

    pub fn mod_path(&self) -> &ModPath {
        &self.mod_path
    }

    pub fn qualifier(&self) -> Option<Path> {
        if self.mod_path.is_ident() {
            return None;
        }
        let res = Path {
            type_anchor: self.type_anchor.clone(),
            mod_path: ModPath {
                kind: self.mod_path.kind.clone(),
                segments: self.mod_path.segments[..self.mod_path.segments.len() - 1].to_vec(),
            },
            generic_args: self.generic_args[..self.generic_args.len() - 1].to_vec(),
        };
        Some(res)
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PathSegment<'a> {
    pub name: &'a Name,
    pub args_and_bindings: Option<&'a GenericArgs>,
}

pub struct PathSegments<'a> {
    segments: &'a [Name],
    generic_args: &'a [Option<Arc<GenericArgs>>],
}

impl<'a> PathSegments<'a> {
    pub const EMPTY: PathSegments<'static> = PathSegments { segments: &[], generic_args: &[] };
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
    pub fn len(&self) -> usize {
        self.segments.len()
    }
    pub fn first(&self) -> Option<PathSegment<'a>> {
        self.get(0)
    }
    pub fn last(&self) -> Option<PathSegment<'a>> {
        self.get(self.len().checked_sub(1)?)
    }
    pub fn get(&self, idx: usize) -> Option<PathSegment<'a>> {
        assert_eq!(self.segments.len(), self.generic_args.len());
        let res = PathSegment {
            name: self.segments.get(idx)?,
            args_and_bindings: self.generic_args.get(idx).unwrap().as_ref().map(|it| &**it),
        };
        Some(res)
    }
    pub fn skip(&self, len: usize) -> PathSegments<'a> {
        assert_eq!(self.segments.len(), self.generic_args.len());
        PathSegments { segments: &self.segments[len..], generic_args: &self.generic_args[len..] }
    }
    pub fn take(&self, len: usize) -> PathSegments<'a> {
        assert_eq!(self.segments.len(), self.generic_args.len());
        PathSegments { segments: &self.segments[..len], generic_args: &self.generic_args[..len] }
    }
    pub fn iter(&self) -> impl Iterator<Item = PathSegment<'a>> {
        self.segments.iter().zip(self.generic_args.iter()).map(|(name, args)| PathSegment {
            name,
            args_and_bindings: args.as_ref().map(|it| &**it),
        })
    }
}

impl GenericArgs {
    pub(crate) fn from_ast(node: ast::TypeArgList) -> Option<GenericArgs> {
        lower::lower_generic_args(node)
    }

    pub(crate) fn empty() -> GenericArgs {
        GenericArgs { args: Vec::new(), has_self_type: false, bindings: Vec::new() }
    }
}

impl From<Name> for Path {
    fn from(name: Name) -> Path {
        Path {
            type_anchor: None,
            mod_path: ModPath::from_segments(PathKind::Plain, iter::once(name)),
            generic_args: vec![None],
        }
    }
}

impl From<Name> for ModPath {
    fn from(name: Name) -> ModPath {
        ModPath::from_segments(PathKind::Plain, iter::once(name))
    }
}

impl Display for ModPath {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut first_segment = true;
        let mut add_segment = |s| {
            if !first_segment {
                f.write_str("::")?;
            }
            first_segment = false;
            f.write_str(s)?;
            Ok(())
        };
        match self.kind {
            PathKind::Plain => {}
            PathKind::Super(n) => {
                if n == 0 {
                    add_segment("self")?;
                }
                for _ in 0..n {
                    add_segment("super")?;
                }
            }
            PathKind::Crate => add_segment("crate")?,
            PathKind::Abs => add_segment("")?,
            PathKind::DollarCrate(_) => add_segment("$crate")?,
        }
        for segment in &self.segments {
            if !first_segment {
                f.write_str("::")?;
            }
            first_segment = false;
            write!(f, "{}", segment)?;
        }
        Ok(())
    }
}

pub use hir_expand::name as __name;

#[macro_export]
macro_rules! __known_path {
    (std::iter::IntoIterator) => {};
    (std::result::Result) => {};
    (std::ops::Range) => {};
    (std::ops::RangeFrom) => {};
    (std::ops::RangeFull) => {};
    (std::ops::RangeTo) => {};
    (std::ops::RangeToInclusive) => {};
    (std::ops::RangeInclusive) => {};
    (std::future::Future) => {};
    (std::ops::Try) => {};
    ($path:path) => {
        compile_error!("Please register your known path in the path module")
    };
}

#[macro_export]
macro_rules! __path {
    ($start:ident $(:: $seg:ident)*) => ({
        $crate::__known_path!($start $(:: $seg)*);
        $crate::path::ModPath::from_segments($crate::path::PathKind::Abs, vec![
            $crate::path::__name![$start], $($crate::path::__name![$seg],)*
        ])
    });
}

pub use crate::__path as path;
<|endoftext|>


<commit_before>#![warn(clippy::all, rust_2018_idioms)]

use chrono::prelude::Utc;
use hmac::{Hmac, Mac, NewMac};
use reqwest::{
    blocking::{Body, Client, Response},
    header,
};
use sha1::Sha1;
use std::time::Duration;

pub use reqwest::Error;

#[derive(Clone, Debug)]
pub struct Bucket {
    name: String,
    region: Option<String>,
    access_key: String,
    secret_key: String,
    proto: String,
}

impl Bucket {
    pub fn new(
        name: String,
        region: Option<String>,
        access_key: String,
        secret_key: String,
        proto: &str,
    ) -> Bucket {
        Bucket {
            name,
            region,
            access_key,
            secret_key,
            proto: proto.to_string(),
        }
    }

    pub fn put<R: std::io::Read + Send + 'static>(
        &self,
        client: &Client,
        path: &str,
        content: R,
        content_length: u64,
        content_type: &str,
        extra_headers: header::HeaderMap,
    ) -> Result<Response, Error> {
        let path = path.strip_prefix('/').unwrap_or(path);
        let date = Utc::now().to_rfc2822();
        let auth = self.auth("PUT", &date, path, "", content_type);
        let url = self.url(path);

        client
            .put(&url)
            .header(header::AUTHORIZATION, auth)
            .header(header::CONTENT_TYPE, content_type)
            .header(header::DATE, date)
            .header(header::USER_AGENT, "crates.io (https://crates.io)")
            .headers(extra_headers)
            .body(Body::sized(content, content_length))
            .timeout(Duration::from_secs(60))
            .send()?
            .error_for_status()
            .map_err(Into::into)
    }

    pub fn delete(&self, client: &Client, path: &str) -> Result<Response, Error> {
        let path = path.strip_prefix('/').unwrap_or(path);
        let date = Utc::now().to_rfc2822();
        let auth = self.auth("DELETE", &date, path, "", "");
        let url = self.url(path);

        client
            .delete(&url)
            .header(header::DATE, date)
            .header(header::AUTHORIZATION, auth)
            .send()?
            .error_for_status()
            .map_err(Into::into)
    }

    pub fn host(&self) -> String {
        format!(
            "{}.s3{}.amazonaws.com",
            self.name,
            match self.region {
                Some(ref r) if !r.is_empty() => format!("-{}", r),
                Some(_) => String::new(),
                None => String::new(),
            }
        )
    }

    fn auth(&self, verb: &str, date: &str, path: &str, md5: &str, content_type: &str) -> String {
        let string = format!(
            "{verb}\n{md5}\n{ty}\n{date}\n{headers}/{name}/{path}",
            verb = verb,
            md5 = md5,
            ty = content_type,
            date = date,
            headers = "",
            name = self.name,
            path = path
        );
        let signature = {
            let key = self.secret_key.as_bytes();
            let mut h = Hmac::<Sha1>::new_from_slice(key).expect("HMAC can take key of any size");
            h.update(string.as_bytes());
            let res = h.finalize().into_bytes();
            base64::encode(&res)
        };
        format!("AWS {}:{}", self.access_key, signature)
    }

    fn url(&self, path: &str) -> String {
        format!("{}://{}/{}", self.proto, self.host(), path)
    }
}
<commit_msg>hmac: Fix import<commit_after>#![warn(clippy::all, rust_2018_idioms)]

use chrono::prelude::Utc;
use hmac::{Hmac, Mac};
use reqwest::{
    blocking::{Body, Client, Response},
    header,
};
use sha1::Sha1;
use std::time::Duration;

pub use reqwest::Error;

#[derive(Clone, Debug)]
pub struct Bucket {
    name: String,
    region: Option<String>,
    access_key: String,
    secret_key: String,
    proto: String,
}

impl Bucket {
    pub fn new(
        name: String,
        region: Option<String>,
        access_key: String,
        secret_key: String,
        proto: &str,
    ) -> Bucket {
        Bucket {
            name,
            region,
            access_key,
            secret_key,
            proto: proto.to_string(),
        }
    }

    pub fn put<R: std::io::Read + Send + 'static>(
        &self,
        client: &Client,
        path: &str,
        content: R,
        content_length: u64,
        content_type: &str,
        extra_headers: header::HeaderMap,
    ) -> Result<Response, Error> {
        let path = path.strip_prefix('/').unwrap_or(path);
        let date = Utc::now().to_rfc2822();
        let auth = self.auth("PUT", &date, path, "", content_type);
        let url = self.url(path);

        client
            .put(&url)
            .header(header::AUTHORIZATION, auth)
            .header(header::CONTENT_TYPE, content_type)
            .header(header::DATE, date)
            .header(header::USER_AGENT, "crates.io (https://crates.io)")
            .headers(extra_headers)
            .body(Body::sized(content, content_length))
            .timeout(Duration::from_secs(60))
            .send()?
            .error_for_status()
            .map_err(Into::into)
    }

    pub fn delete(&self, client: &Client, path: &str) -> Result<Response, Error> {
        let path = path.strip_prefix('/').unwrap_or(path);
        let date = Utc::now().to_rfc2822();
        let auth = self.auth("DELETE", &date, path, "", "");
        let url = self.url(path);

        client
            .delete(&url)
            .header(header::DATE, date)
            .header(header::AUTHORIZATION, auth)
            .send()?
            .error_for_status()
            .map_err(Into::into)
    }

    pub fn host(&self) -> String {
        format!(
            "{}.s3{}.amazonaws.com",
            self.name,
            match self.region {
                Some(ref r) if !r.is_empty() => format!("-{}", r),
                Some(_) => String::new(),
                None => String::new(),
            }
        )
    }

    fn auth(&self, verb: &str, date: &str, path: &str, md5: &str, content_type: &str) -> String {
        let string = format!(
            "{verb}\n{md5}\n{ty}\n{date}\n{headers}/{name}/{path}",
            verb = verb,
            md5 = md5,
            ty = content_type,
            date = date,
            headers = "",
            name = self.name,
            path = path
        );
        let signature = {
            let key = self.secret_key.as_bytes();
            let mut h = Hmac::<Sha1>::new_from_slice(key).expect("HMAC can take key of any size");
            h.update(string.as_bytes());
            let res = h.finalize().into_bytes();
            base64::encode(&res)
        };
        format!("AWS {}:{}", self.access_key, signature)
    }

    fn url(&self, path: &str) -> String {
        format!("{}://{}/{}", self.proto, self.host(), path)
    }
}
<|endoftext|>


<commit_before>use nix::sys::select::{FdSet, FD_SETSIZE, select};
use nix::sys::time::TimeVal;
use nix::unistd::{write, pipe};

#[test]
fn test_fdset() {
    let mut fd_set = FdSet::new();

    for i in 0..FD_SETSIZE {
        assert!(!fd_set.contains(i));
    }

    fd_set.insert(7);

    assert!(fd_set.contains(7));

    fd_set.remove(7);

    for i in 0..FD_SETSIZE {
        assert!(!fd_set.contains(i));
    }

    fd_set.insert(1);
    fd_set.insert(FD_SETSIZE / 2);
    fd_set.insert(FD_SETSIZE - 1);

    fd_set.clear();

    for i in 0..FD_SETSIZE {
        assert!(!fd_set.contains(i));
    }
}

#[test]
fn test_select() {
    let (r1, w1) = pipe().unwrap();
    write(w1, b"hi!").unwrap();
    let (r2, _w2) = pipe().unwrap();

    let mut fd_set = FdSet::new();
    fd_set.insert(r1);
    fd_set.insert(r2);

    let mut timeout = TimeVal::seconds(1);
    assert_eq!(1, select(r2 + 1,
                         Some(&mut fd_set),
                         None,
                         None,
                         Some(&mut timeout)).unwrap());
    assert!(fd_set.contains(r1));
    assert!(!fd_set.contains(r2));
}
<commit_msg>Auto merge of #469 - asomers:select, r=posborne<commit_after>use nix::sys::select::{FdSet, FD_SETSIZE, select};
use nix::sys::time::TimeVal;
use nix::unistd::{write, pipe};

#[test]
fn test_fdset() {
    let mut fd_set = FdSet::new();

    for i in 0..FD_SETSIZE {
        assert!(!fd_set.contains(i));
    }

    fd_set.insert(7);

    assert!(fd_set.contains(7));

    fd_set.remove(7);

    for i in 0..FD_SETSIZE {
        assert!(!fd_set.contains(i));
    }

    fd_set.insert(1);
    fd_set.insert(FD_SETSIZE / 2);
    fd_set.insert(FD_SETSIZE - 1);

    fd_set.clear();

    for i in 0..FD_SETSIZE {
        assert!(!fd_set.contains(i));
    }
}

#[test]
fn test_select() {
    let (r1, w1) = pipe().unwrap();
    write(w1, b"hi!").unwrap();
    let (r2, _w2) = pipe().unwrap();

    let mut fd_set = FdSet::new();
    fd_set.insert(r1);
    fd_set.insert(r2);

    let mut timeout = TimeVal::seconds(10);
    assert_eq!(1, select(r2 + 1,
                         Some(&mut fd_set),
                         None,
                         None,
                         Some(&mut timeout)).unwrap());
    assert!(fd_set.contains(r1));
    assert!(!fd_set.contains(r2));
}
<|endoftext|>


<commit_before>/*!
* Types used in the PortAudio API
*/

use std::libc::{c_void, c_char, c_double};
use std::{str, ptr};

#[doc(hidden)]
pub type C_PaStream = c_void;

/// The type used to refer to audio devices. Values of this type usually range from 0 to (pa::get_device_count()-1)
pub type PaDeviceIndex = i32;
/// A special PaDeviceIndex value indicating that no device is available, or should be used.
pub static PaNoDevice : PaDeviceIndex = -1;
/// A special PaDeviceIndex value indicating that the device(s) to be used are specified in the host api specific stream info structure.
pub static PaUseHostApiSpecificDeviceSpecification : PaDeviceIndex = -2;

/// The type used to enumerate to host APIs at runtime.
/// Values of this type range from 0 to (pa::get_host_api_count()-1).
pub type PaHostApiIndex = i32;

/// The type used to represent monotonic time in seconds.
pub type PaTime = f64;

/// A type used to specify one or more sample formats.
pub type PaSampleFormat = u64;
pub static PaFloat32 : PaSampleFormat = 0x00000001;
pub static PaInt32 : PaSampleFormat = 0x00000002;
//pub static PaInt24 : PaSampleFormat = 0x00000004;
pub static PaInt16 : PaSampleFormat = 0x00000008;
pub static PaInt8 : PaSampleFormat = 0x00000010;
pub static PaUInt8 : PaSampleFormat = 0x00000020;
pub static PaCustomFormat : PaSampleFormat = 0x00010000;
pub static PaNonInterleaved : PaSampleFormat = 0x80000000;

// pub type PaStream = c_void;

pub type PaStreamFlags = u64;
pub static PaNoFlag : PaStreamFlags = 0;
/// Disable default clipping of out of range samples.
pub static PaClipOff : PaStreamFlags = 0x00000001;
/// Disable default dithering.
pub static PaDitherOff : PaStreamFlags = 0x00000002;
/// Flag requests that where possible a full duplex stream will not discard overflowed input samples without calling the stream callback.
pub static PaNeverDropInput : PaStreamFlags = 0x00000004;
/// Call the stream callback to fill initial output buffers, rather than the default behavior of priming the buffers with zeros (silence)
pub static PaPrimeOutputBuffersUsingStreamCallback : PaStreamFlags = 0x00000008;
/// A mask specifying the platform specific bits.
pub static PaPlatformSpecificFlags : PaStreamFlags = 0xFFFF0000;

#[doc(hidden)]
pub type PaStreamCallbackFlags = u64;
/*
    pub static PaInputUnderflow : PaStreamCallbackFlags = 0x00000001;
    pub static PaInputOverflow : PaStreamCallbackFlags = 0x00000002;
    pub static PaOutputUnderflow : PaStreamCallbackFlags = 0x00000004;
    pub static PaOutputOverflow : PaStreamCallbackFlags = 0x00000008;
    pub static PaPrimingOutput : PaStreamCallbackFlags = 0x00000010;
*/

#[doc(hidden)]
pub type PaCallbackFunction = extern fn(i : f32) -> PaStreamCallbackResult;
#[doc(hidden)]
pub enum PaStreamCallbackResult {
    PaContinue = 0,
    PaComplete = 1,
    PaAbort = 2
}

/// Error codes returned by PortAudio functions.
#[repr(C)]
pub enum PaError {
    /// No Error
    PaNoError = 0,
    /// Portaudio not initialized
    PaNotInitialized = -10000,
    /// Unanticipated error from the host
    PaUnanticipatedHostError,
    /// Invalid channel count
    PaInvalidChannelCount,
    /// Invalid sample rate
    PaInvalidSampleRate,
    /// Invalid Device
    PaInvalidDevice,
    /// Invalid Flag
    PaInvalidFlag,
    /// The Sample format is not supported
    PaSampleFormatNotSupported,
    /// Input device not compatible with output device
    PaBadIODeviceCombination,
    /// Memory insufficient
    PaInsufficientMemory,
    /// The buffer is too big
    PaBufferTooBig,
    /// The buffer is too small
    PaBufferTooSmall,
    /// Invalid callback
    PaNullCallback,
    /// Invalid Stream
    PaBadStreamPtr,
    /// Time out
    PaTimedOut,
    /// Portaudio internal error
    PaInternalError,
    /// Device unavailable
    PaDeviceUnavailable,
    /// Stream info not compatible with the host
    PaIncompatibleHostApiSpecificStreamInfo,
    /// The stream is stopped
    PaStreamIsStopped,
    /// The stream is not stopped
    PaStreamIsNotStopped,
    /// The input stream has overflowed
    PaInputOverflowed,
    /// The output has overflowed
    PaOutputUnderflowed,
    /// The host API is not found by Portaudio
    PaHostApiNotFound,
    /// The host API is invalid
    PaInvalidHostApi,
    /// Portaudio cannot read from the callback stream
    PaCanNotReadFromACallbackStream,
    /// Portaudio cannot wrtie to the callback stream
    PaCanNotWriteToACallbackStream,
    /// Portaudio cannot read from an output only stream
    PaCanNotReadFromAnOutputOnlyStream,
    /// Portaudio cannot write to an input only stream
    PaCanNotWriteToAnInputOnlyStream,
    /// The stream is not compatible with the host API
    PaIncompatibleStreamHostApi,
    /// Invalid buffer
    PaBadBufferPtr
}

/// Unchanging unique identifiers for each supported host API
pub type PaHostApiTypeId = i32;
pub static PaInDevelopment : PaHostApiTypeId = 0;
pub static PaDirectSound : PaHostApiTypeId = 1;
pub static PaMME : PaHostApiTypeId = 2;
pub static PaASIO : PaHostApiTypeId = 3;
pub static PaSoundManager : PaHostApiTypeId = 4;
pub static PaCoreAudio : PaHostApiTypeId = 5;
pub static PaOSS : PaHostApiTypeId = 7;
pub static PaALSA : PaHostApiTypeId = 8;
pub static PaAL : PaHostApiTypeId = 9;
pub static PaBeOS : PaHostApiTypeId = 10;
pub static PaWDMKS : PaHostApiTypeId = 11;
pub static PaJACK : PaHostApiTypeId = 12;
pub static PaWASAPI : PaHostApiTypeId = 13;
pub static PaAudioScienceHPI : PaHostApiTypeId = 14;

/// A structure containing information about a particular host API.
pub struct PaHostApiInfo{
    /// The version of the struct
    struct_version : int,
    /// The type of the current host
    host_type : PaHostApiTypeId,
    /// The name of the host
    name : ~str,
    /// The total count of device in the host
    device_count : int,
    /// The index to the default input device
    default_input_device : PaDeviceIndex,
    /// The index to the default output device
    default_output_device : PaDeviceIndex
}

#[doc(hidden)]
pub struct C_PaHostApiInfo {
    struct_version : i32,
    host_type : i32,
    name : *c_char,
    device_count : i32,
    default_input_device : i32,
    default_output_device : i32
}

#[doc(hidden)]
impl PaHostApiInfo {
    pub fn wrap(c_info : *C_PaHostApiInfo) -> PaHostApiInfo {
        unsafe {
            PaHostApiInfo {
                struct_version : (*c_info).struct_version as int,
                host_type : ((*c_info).host_type),
                name : str::raw::from_c_str((*c_info).name),
                device_count : (*c_info).device_count as int,
                default_input_device : (*c_info).default_input_device,
                default_output_device : (*c_info).default_output_device
            }
        }
    }

    pub fn unwrap(&self) -> C_PaHostApiInfo {
        C_PaHostApiInfo {
            struct_version : self.struct_version as i32,
            host_type : self.host_type as i32,
            name : unsafe { self.name.to_c_str().unwrap() },
            device_count : self.device_count as i32,
            default_input_device : self.default_input_device as i32,
            default_output_device : self.default_output_device as i32
        }
    }
}

/// Structure used to return information about a host error condition.
pub struct PaHostErrorInfo {
    /// The code of the error
    error_code : u32,
    /// The string which explain the error
    error_text : ~str
}

#[doc(hidden)]
pub struct C_PaHostErrorInfo {
    error_code : u32,
    error_text : *c_char
}

#[doc(hidden)]
impl PaHostErrorInfo {
    pub fn wrap(c_error : *C_PaHostErrorInfo) -> PaHostErrorInfo {
        PaHostErrorInfo {
            error_code : unsafe { (*c_error).error_code },
            error_text : unsafe { str::raw::from_c_str((*c_error).error_text) }
        }
    }

    pub fn unwrap(&self) -> C_PaHostErrorInfo {
        C_PaHostErrorInfo {
            error_code : self.error_code,
            error_text : unsafe { self.error_text.to_c_str().unwrap() }
        }
    }
}

/// A structure providing information and capabilities of PortAudio devices. Devices may support input, output or both input and output.
pub struct PaDeviceInfo {
    /// The version of the struct
    struct_version : int,
    /// The name of the devie
    name : ~str,
    /// Host API identifier
    host_api : PaHostApiIndex,
    /// Maximal number of input channels for this device
    max_input_channels : int,
    /// maximal number of output channel for this device
    max_output_channels : int,
    /// The default low latency for input with this device
    default_low_input_latency : PaTime,
    /// The default low latency for output with this device
    default_low_output_latency : PaTime,
    /// The default high latency for input with this device
    default_high_input_latency : PaTime,
    /// The default high latency for output with this device
    default_high_output_latency : PaTime,
    /// The default sample rate for this device
    default_sample_rate : f64
}

#[doc(hidden)]
pub struct C_PaDeviceInfo {
    struct_version : i32,
    name : *c_char,
    host_api : PaHostApiIndex,
    max_input_channels : i32,
    max_output_channels : i32,
    default_low_input_latency : PaTime,
    default_low_output_latency : PaTime,
    default_high_input_latency : PaTime,
    default_high_output_latency : PaTime,
    default_sample_rate : c_double
}

#[doc(hidden)]
impl PaDeviceInfo {
    pub fn wrap(c_info : *C_PaDeviceInfo) -> PaDeviceInfo {
        unsafe {
            PaDeviceInfo {
                struct_version : (*c_info).struct_version as int,
                name : str::raw::from_c_str((*c_info).name),
                host_api : (*c_info).host_api,
                max_input_channels : (*c_info).max_input_channels as int,
                max_output_channels : (*c_info).max_output_channels as int,
                default_low_input_latency : (*c_info).default_low_input_latency,
                default_low_output_latency : (*c_info).default_low_output_latency,
                default_high_input_latency : (*c_info).default_high_input_latency,
                default_high_output_latency : (*c_info).default_high_output_latency,
                default_sample_rate : (*c_info).default_sample_rate
            }
        }
    }

    pub fn unwrap(&self) -> C_PaDeviceInfo {
        C_PaDeviceInfo {
            struct_version : self.struct_version as i32,
            name : unsafe { self.name.to_c_str().unwrap() },
            host_api : self.host_api,
            max_input_channels : self.max_input_channels as i32,
            max_output_channels : self.max_output_channels as i32,
            default_low_input_latency : self.default_low_input_latency,
            default_low_output_latency : self.default_low_output_latency,
            default_high_input_latency : self.default_high_input_latency,
            default_high_output_latency : self.default_high_output_latency,
            default_sample_rate : self.default_sample_rate
        }
    }
}

/// Parameters for one direction (input or output) of a stream.
pub struct PaStreamParameters {
    /// Index of the device
    device : PaDeviceIndex,
    /// The number of channels for this device
    channel_count : i32,
    /// Sample format of the device
    sample_format : PaSampleFormat,
    /// The suggested latency for this device
    suggested_latency : PaTime,
}

#[doc(hidden)]
pub struct C_PaStreamParameters {
    device : PaDeviceIndex,
    channel_count : i32,
    sample_format : PaSampleFormat,
    suggested_latency : PaTime,
    host_api_specific_stream_info : *c_void
}

#[doc(hidden)]
impl PaStreamParameters {
    pub fn wrap(c_parameters : *C_PaStreamParameters) -> PaStreamParameters {
        unsafe {
            PaStreamParameters {
                device : (*c_parameters).device,
                channel_count : (*c_parameters).channel_count,
                sample_format : (*c_parameters).sample_format,
                suggested_latency : (*c_parameters).suggested_latency
            }
        }
    }

    pub fn unwrap(&self) -> C_PaStreamParameters {
        C_PaStreamParameters {
            device : self.device,
            channel_count : self.channel_count as i32,
            sample_format : self.sample_format,
            suggested_latency : self.suggested_latency,
            host_api_specific_stream_info : ptr::null()
        }
    }
}

#[doc(hidden)]
pub struct PaStreamCallbackTimeInfo {
    input_buffer_adc_time : PaTime,
    current_time : PaTime,
    output_buffer_dac_time : PaTime
}

/// A structure containing unchanging information about an open stream.
pub struct PaStreamInfo {
    /// Struct version
    struct_version : i32,
    /// The input latency for this open stream
    input_latency : PaTime,
    /// The output latency for this open stream
    output_latency : PaTime,
    /// The sample rate for this open stream
    sample_rate : f64
}

<commit_msg>update enums and types<commit_after>/*!
* Types used in the PortAudio API
*/

use std::libc::{c_void, c_char, c_double};
use std::{str, ptr, cast};

#[doc(hidden)]
pub type C_PaStream = c_void;

/// The type used to refer to audio devices. Values of this type usually range from 0 to (pa::get_device_count()-1)
pub type PaDeviceIndex = i32;
/// A special PaDeviceIndex value indicating that no device is available, or should be used.
pub static PaNoDevice : PaDeviceIndex = -1;
/// A special PaDeviceIndex value indicating that the device(s) to be used are specified in the host api specific stream info structure.
pub static PaUseHostApiSpecificDeviceSpecification : PaDeviceIndex = -2;

/// The type used to enumerate to host APIs at runtime.
/// Values of this type range from 0 to (pa::get_host_api_count()-1).
pub type PaHostApiIndex = i32;

/// The type used to represent monotonic time in seconds.
pub type PaTime = f64;

#[doc(hidden)]
mod ffi {

    // Sample format
    pub type PaSampleFormat = u64;
    pub static PaFloat32 :          PaSampleFormat = 0x00000001;
    pub static PaInt32 :            PaSampleFormat = 0x00000002;
    // pub static PaInt24 :          PaSampleFormat = 0x00000004;
    pub static PaInt16 :            PaSampleFormat = 0x00000008;
    pub static PaInt8 :             PaSampleFormat = 0x00000010;
    pub static PaUInt8 :            PaSampleFormat = 0x00000020;
    pub static PaCustomFormat :     PaSampleFormat = 0x00010000;
    pub static PaNonInterleaved :   PaSampleFormat = 0x80000000;

    // Stream flags
    pub type PaStreamFlags = u64;
    pub static PaNoFlag :                                   PaStreamFlags = 0;
    pub static PaClipOff :                                  PaStreamFlags = 0x00000001;
    pub static PaDitherOff :                                PaStreamFlags = 0x00000002;
    pub static PaNeverDropInput :                           PaStreamFlags = 0x00000004;
    pub static PaPrimeOutputBuffersUsingStreamCallback :    PaStreamFlags = 0x00000008;
    pub static PaPlatformSpecificFlags :                    PaStreamFlags = 0xFFFF0000;

    /// Unchanging unique identifiers for each supported host API
    pub type PaHostApiTypeId = i32;
    pub static PaInDevelopment : PaHostApiTypeId = 0;
    pub static PaDirectSound : PaHostApiTypeId = 1;
    pub static PaMME : PaHostApiTypeId = 2;
    pub static PaASIO : PaHostApiTypeId = 3;
    pub static PaSoundManager : PaHostApiTypeId = 4;
    pub static PaCoreAudio : PaHostApiTypeId = 5;
    pub static PaOSS : PaHostApiTypeId = 7;
    pub static PaALSA : PaHostApiTypeId = 8;
    pub static PaAL : PaHostApiTypeId = 9;
    pub static PaBeOS : PaHostApiTypeId = 10;
    pub static PaWDMKS : PaHostApiTypeId = 11;
    pub static PaJACK : PaHostApiTypeId = 12;
    pub static PaWASAPI : PaHostApiTypeId = 13;
    pub static PaAudioScienceHPI : PaHostApiTypeId = 14;
}

/// A type used to specify one or more sample formats.
#[repr(u64)]
#[deriving(Clone, Eq, Ord, ToStr)]
pub enum PaSampleFormat {
    /// 32 bits float sample format
    PaFloat32 =         ffi::PaFloat32,
    /// 32 bits int sample format
    PaInt32 =           ffi::PaInt32,
    /// 16 bits int sample format
    PaInt16 =           ffi::PaInt16,
    /// 8 bits int sample format
    PaInt8 =            ffi::PaInt8,
    /// 8 bits unsigned int sample format
    PaUInt8 =           ffi::PaUInt8,
    /// Custom sample format
    PaCustomFormat =    ffi::PaCustomFormat,
    /// Non interleaved sample format
    PaNonInterleaved =  ffi::PaNonInterleaved
}

/// The flags to pass to a stream
#[repr(u64)]
#[deriving(Clone, Eq, Ord, ToStr)]
pub enum PaStreamFlags {
    /// No flags
    PaNoFlag =                                  ffi::PaNoFlag,
    /// Disable default clipping of out of range samples.
    PaClipOff =                                 ffi::PaClipOff,
    /// Disable default dithering.
    PaDitherOff =                               ffi::PaDitherOff,
    /// Flag requests that where possible a full duplex stream will not discard overflowed input samples without calling the stream callback.
    PaNeverDropInput =                          ffi::PaNeverDropInput,
    /// Call the stream callback to fill initial output buffers, rather than the default behavior of priming the buffers with zeros (silence)
    PaPrimeOutputBuffersUsingStreamCallback =   ffi::PaPrimeOutputBuffersUsingStreamCallback,
    /// A mask specifying the platform specific bits.
    PaPlatformSpecificFlags =                   ffi::PaPlatformSpecificFlags
}

#[doc(hidden)]
pub type PaStreamCallbackFlags = u64;
/*
    pub static PaInputUnderflow : PaStreamCallbackFlags = 0x00000001;
    pub static PaInputOverflow : PaStreamCallbackFlags = 0x00000002;
    pub static PaOutputUnderflow : PaStreamCallbackFlags = 0x00000004;
    pub static PaOutputOverflow : PaStreamCallbackFlags = 0x00000008;
    pub static PaPrimingOutput : PaStreamCallbackFlags = 0x00000010;
*/

#[doc(hidden)]
pub type PaCallbackFunction = extern fn(i : f32) -> PaStreamCallbackResult;
#[doc(hidden)]
pub enum PaStreamCallbackResult {
    PaContinue = 0,
    PaComplete = 1,
    PaAbort = 2
}

/// Error codes returned by PortAudio functions.
#[repr(C)]
#[deriving(Clone, Eq, Ord, ToStr)]
pub enum PaError {
    /// No Error
    PaNoError = 0,
    /// Portaudio not initialized
    PaNotInitialized = -10000,
    /// Unanticipated error from the host
    PaUnanticipatedHostError,
    /// Invalid channel count
    PaInvalidChannelCount,
    /// Invalid sample rate
    PaInvalidSampleRate,
    /// Invalid Device
    PaInvalidDevice,
    /// Invalid Flag
    PaInvalidFlag,
    /// The Sample format is not supported
    PaSampleFormatNotSupported,
    /// Input device not compatible with output device
    PaBadIODeviceCombination,
    /// Memory insufficient
    PaInsufficientMemory,
    /// The buffer is too big
    PaBufferTooBig,
    /// The buffer is too small
    PaBufferTooSmall,
    /// Invalid callback
    PaNullCallback,
    /// Invalid Stream
    PaBadStreamPtr,
    /// Time out
    PaTimedOut,
    /// Portaudio internal error
    PaInternalError,
    /// Device unavailable
    PaDeviceUnavailable,
    /// Stream info not compatible with the host
    PaIncompatibleHostApiSpecificStreamInfo,
    /// The stream is stopped
    PaStreamIsStopped,
    /// The stream is not stopped
    PaStreamIsNotStopped,
    /// The input stream has overflowed
    PaInputOverflowed,
    /// The output has overflowed
    PaOutputUnderflowed,
    /// The host API is not found by Portaudio
    PaHostApiNotFound,
    /// The host API is invalid
    PaInvalidHostApi,
    /// Portaudio cannot read from the callback stream
    PaCanNotReadFromACallbackStream,
    /// Portaudio cannot wrtie to the callback stream
    PaCanNotWriteToACallbackStream,
    /// Portaudio cannot read from an output only stream
    PaCanNotReadFromAnOutputOnlyStream,
    /// Portaudio cannot write to an input only stream
    PaCanNotWriteToAnInputOnlyStream,
    /// The stream is not compatible with the host API
    PaIncompatibleStreamHostApi,
    /// Invalid buffer
    PaBadBufferPtr
}

/// Unchanging unique identifiers for each supported host API
#[repr(i32)]
#[deriving(Clone, Eq, Ord, ToStr)]
pub enum PaHostApiTypeId {
    /// In development host
    PaInDevelopment =   ffi::PaInDevelopment,
    /// Direct sound
    PaDirectSound =     ffi::PaDirectSound,
    /// MMe API
    PaMME =             ffi::PaMME,
    /// ASIO API
    PaASIO =            ffi::PaASIO,
    /// Sound manager API
    PaSoundManager =    ffi::PaSoundManager,
    /// Core Audio API
    PaCoreAudio =       ffi::PaCoreAudio,
    /// OSS API
    PaOSS =             ffi::PaOSS,
    /// Alsa API
    PaALSA =            ffi::PaALSA,
    /// AL API
    PaAL =              ffi::PaAL,
    /// BeOS API
    PaBeOS =            ffi::PaBeOS,
    /// WDMKS
    PaWDMKS =           ffi::PaWDMKS,
    /// Jack API
    PaJACK =            ffi::PaJACK,
    /// WASAPI
    PaWASAPI =          ffi::PaWASAPI,
    /// Audio Science HPI
    PaAudioScienceHPI = ffi::PaAudioScienceHPI
}

/// A structure containing information about a particular host API.
pub struct PaHostApiInfo{
    /// The version of the struct
    struct_version : int,
    /// The type of the current host
    host_type : PaHostApiTypeId,
    /// The name of the host
    name : ~str,
    /// The total count of device in the host
    device_count : int,
    /// The index to the default input device
    default_input_device : PaDeviceIndex,
    /// The index to the default output device
    default_output_device : PaDeviceIndex
}

#[doc(hidden)]
pub struct C_PaHostApiInfo {
    struct_version : i32,
    host_type : i32,
    name : *c_char,
    device_count : i32,
    default_input_device : i32,
    default_output_device : i32
}

#[doc(hidden)]
impl PaHostApiInfo {
    pub fn wrap(c_info : *C_PaHostApiInfo) -> PaHostApiInfo {
        unsafe {
            PaHostApiInfo {
                struct_version : (*c_info).struct_version as int,
                host_type : cast::transmute(((*c_info).host_type)),
                name : str::raw::from_c_str((*c_info).name),
                device_count : (*c_info).device_count as int,
                default_input_device : (*c_info).default_input_device,
                default_output_device : (*c_info).default_output_device
            }
        }
    }

    pub fn unwrap(&self) -> C_PaHostApiInfo {
        C_PaHostApiInfo {
            struct_version : self.struct_version as i32,
            host_type : self.host_type as i32,
            name : unsafe { self.name.to_c_str().unwrap() },
            device_count : self.device_count as i32,
            default_input_device : self.default_input_device as i32,
            default_output_device : self.default_output_device as i32
        }
    }
}

/// Structure used to return information about a host error condition.
#[deriving(Clone, Eq, Ord, ToStr)]
pub struct PaHostErrorInfo {
    /// The code of the error
    error_code : u32,
    /// The string which explain the error
    error_text : ~str
}

#[doc(hidden)]
pub struct C_PaHostErrorInfo {
    error_code : u32,
    error_text : *c_char
}

#[doc(hidden)]
impl PaHostErrorInfo {
    pub fn wrap(c_error : *C_PaHostErrorInfo) -> PaHostErrorInfo {
        PaHostErrorInfo {
            error_code : unsafe { (*c_error).error_code },
            error_text : unsafe { str::raw::from_c_str((*c_error).error_text) }
        }
    }

    pub fn unwrap(&self) -> C_PaHostErrorInfo {
        C_PaHostErrorInfo {
            error_code : self.error_code,
            error_text : unsafe { self.error_text.to_c_str().unwrap() }
        }
    }
}

/// A structure providing information and capabilities of PortAudio devices. Devices may support input, output or both input and output.
#[deriving(Clone, Eq, Ord, ToStr)]
pub struct PaDeviceInfo {
    /// The version of the struct
    struct_version : int,
    /// The name of the devie
    name : ~str,
    /// Host API identifier
    host_api : PaHostApiIndex,
    /// Maximal number of input channels for this device
    max_input_channels : int,
    /// maximal number of output channel for this device
    max_output_channels : int,
    /// The default low latency for input with this device
    default_low_input_latency : PaTime,
    /// The default low latency for output with this device
    default_low_output_latency : PaTime,
    /// The default high latency for input with this device
    default_high_input_latency : PaTime,
    /// The default high latency for output with this device
    default_high_output_latency : PaTime,
    /// The default sample rate for this device
    default_sample_rate : f64
}

#[doc(hidden)]
pub struct C_PaDeviceInfo {
    struct_version : i32,
    name : *c_char,
    host_api : PaHostApiIndex,
    max_input_channels : i32,
    max_output_channels : i32,
    default_low_input_latency : PaTime,
    default_low_output_latency : PaTime,
    default_high_input_latency : PaTime,
    default_high_output_latency : PaTime,
    default_sample_rate : c_double
}

#[doc(hidden)]
impl PaDeviceInfo {
    pub fn wrap(c_info : *C_PaDeviceInfo) -> PaDeviceInfo {
        unsafe {
            PaDeviceInfo {
                struct_version : (*c_info).struct_version as int,
                name : str::raw::from_c_str((*c_info).name),
                host_api : (*c_info).host_api,
                max_input_channels : (*c_info).max_input_channels as int,
                max_output_channels : (*c_info).max_output_channels as int,
                default_low_input_latency : (*c_info).default_low_input_latency,
                default_low_output_latency : (*c_info).default_low_output_latency,
                default_high_input_latency : (*c_info).default_high_input_latency,
                default_high_output_latency : (*c_info).default_high_output_latency,
                default_sample_rate : (*c_info).default_sample_rate
            }
        }
    }

    pub fn unwrap(&self) -> C_PaDeviceInfo {
        C_PaDeviceInfo {
            struct_version : self.struct_version as i32,
            name : unsafe { self.name.to_c_str().unwrap() },
            host_api : self.host_api,
            max_input_channels : self.max_input_channels as i32,
            max_output_channels : self.max_output_channels as i32,
            default_low_input_latency : self.default_low_input_latency,
            default_low_output_latency : self.default_low_output_latency,
            default_high_input_latency : self.default_high_input_latency,
            default_high_output_latency : self.default_high_output_latency,
            default_sample_rate : self.default_sample_rate
        }
    }
}

/// Parameters for one direction (input or output) of a stream.
#[deriving(Clone, Eq, Ord, ToStr)]
pub struct PaStreamParameters {
    /// Index of the device
    device : PaDeviceIndex,
    /// The number of channels for this device
    channel_count : i32,
    /// Sample format of the device
    sample_format : PaSampleFormat,
    /// The suggested latency for this device
    suggested_latency : PaTime,
}

#[doc(hidden)]
pub struct C_PaStreamParameters {
    device : PaDeviceIndex,
    channel_count : i32,
    sample_format : PaSampleFormat,
    suggested_latency : PaTime,
    host_api_specific_stream_info : *c_void
}

#[doc(hidden)]
impl PaStreamParameters {
    pub fn wrap(c_parameters : *C_PaStreamParameters) -> PaStreamParameters {
        unsafe {
            PaStreamParameters {
                device : (*c_parameters).device,
                channel_count : (*c_parameters).channel_count,
                sample_format : (*c_parameters).sample_format,
                suggested_latency : (*c_parameters).suggested_latency
            }
        }
    }

    pub fn unwrap(&self) -> C_PaStreamParameters {
        C_PaStreamParameters {
            device : self.device,
            channel_count : self.channel_count as i32,
            sample_format : self.sample_format,
            suggested_latency : self.suggested_latency,
            host_api_specific_stream_info : ptr::null()
        }
    }
}

#[doc(hidden)]
pub struct PaStreamCallbackTimeInfo {
    input_buffer_adc_time : PaTime,
    current_time : PaTime,
    output_buffer_dac_time : PaTime
}

/// A structure containing unchanging information about an open stream.
#[deriving(Clone, Eq, Ord, ToStr)]
pub struct PaStreamInfo {
    /// Struct version
    struct_version : i32,
    /// The input latency for this open stream
    input_latency : PaTime,
    /// The output latency for this open stream
    output_latency : PaTime,
    /// The sample rate for this open stream
    sample_rate : f64
}

<|endoftext|>


<commit_before>//! Cretonne code generation library.

#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
#![warn(unused_import_braces)]
#![cfg_attr(feature = "std", warn(unstable_features))]
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
#![cfg_attr(feature="cargo-clippy", allow(
// Rustfmt 0.9.0 is at odds with this lint:
                block_in_if_condition_stmt,
// Produces only a false positive:
                while_let_loop,
// Produces many false positives, but did produce some valid lints, now fixed:
                needless_lifetimes,
// Generated code makes some style transgressions, but readability doesn't suffer much:
                many_single_char_names,
                identity_op,
                needless_borrow,
                cast_lossless,
                unreadable_literal,
                assign_op_pattern,
                empty_line_after_outer_attr,
// Hard to avoid in generated code:
                cyclomatic_complexity,
                too_many_arguments,
// Code generator doesn't have a way to collapse identical arms:
                match_same_arms,
// These are relatively minor style issues, but would be easy to fix:
                new_without_default,
                new_without_default_derive,
                should_implement_trait,
                redundant_field_names,
                useless_let_if_seq,
                len_without_is_empty))]
#![cfg_attr(
    feature = "cargo-clippy",
    warn(
        float_arithmetic, mut_mut, nonminimal_bool, option_map_unwrap_or, option_map_unwrap_or_else,
        print_stdout, unicode_not_nfc, use_self
    )
)]
// Turns on no_std and alloc features if std is not available.
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc))]

#[cfg(not(feature = "std"))]
#[macro_use]
extern crate alloc;
extern crate failure;
#[macro_use]
extern crate failure_derive;
#[cfg(test)]
#[macro_use]
extern crate target_lexicon;
#[cfg(not(test))]
extern crate target_lexicon;

pub use context::Context;
pub use legalizer::legalize_function;
pub use verifier::verify_function;
pub use write::write_function;

/// Version number of the cretonne-codegen crate.
pub const VERSION: &str = env!("CARGO_PKG_VERSION");

#[macro_use]
pub extern crate cretonne_entity as entity;

#[macro_use]
pub mod dbg;

pub mod bforest;
pub mod binemit;
pub mod cfg_printer;
pub mod cursor;
pub mod dominator_tree;
pub mod flowgraph;
pub mod ir;
pub mod isa;
pub mod loop_analysis;
pub mod print_errors;
pub mod result;
pub mod settings;
pub mod timing;
pub mod verifier;

pub use entity::packed_option;

mod abi;
mod bitset;
mod constant_hash;
mod context;
mod dce;
mod divconst_magic_numbers;
mod fx;
mod iterators;
mod legalizer;
mod licm;
mod nan_canonicalization;
mod partition_slice;
mod postopt;
mod predicates;
mod preopt;
mod ref_slice;
mod regalloc;
mod scoped_hash_map;
mod simple_gvn;
mod stack_layout;
mod topo_order;
mod unreachable_code;
mod write;

/// This replaces `std` in builds with `core`.
#[cfg(not(feature = "std"))]
mod std {
    pub use alloc::{boxed, string, vec};
    pub use core::*;
    pub mod collections {
        #[allow(unused_extern_crates)]
        extern crate hashmap_core;

        pub use self::hashmap_core::map as hash_map;
        pub use self::hashmap_core::{HashMap, HashSet};
        pub use alloc::BTreeSet;
    }
}
<commit_msg>Use cfg_attr to tidy up an extern crate declaration.<commit_after>//! Cretonne code generation library.

#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
#![warn(unused_import_braces)]
#![cfg_attr(feature = "std", warn(unstable_features))]
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
#![cfg_attr(feature="cargo-clippy", allow(
// Rustfmt 0.9.0 is at odds with this lint:
                block_in_if_condition_stmt,
// Produces only a false positive:
                while_let_loop,
// Produces many false positives, but did produce some valid lints, now fixed:
                needless_lifetimes,
// Generated code makes some style transgressions, but readability doesn't suffer much:
                many_single_char_names,
                identity_op,
                needless_borrow,
                cast_lossless,
                unreadable_literal,
                assign_op_pattern,
                empty_line_after_outer_attr,
// Hard to avoid in generated code:
                cyclomatic_complexity,
                too_many_arguments,
// Code generator doesn't have a way to collapse identical arms:
                match_same_arms,
// These are relatively minor style issues, but would be easy to fix:
                new_without_default,
                new_without_default_derive,
                should_implement_trait,
                redundant_field_names,
                useless_let_if_seq,
                len_without_is_empty))]
#![cfg_attr(
    feature = "cargo-clippy",
    warn(
        float_arithmetic, mut_mut, nonminimal_bool, option_map_unwrap_or, option_map_unwrap_or_else,
        print_stdout, unicode_not_nfc, use_self
    )
)]
// Turns on no_std and alloc features if std is not available.
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc))]

#[cfg(not(feature = "std"))]
#[macro_use]
extern crate alloc;
extern crate failure;
#[macro_use]
extern crate failure_derive;
#[cfg_attr(test, macro_use)]
extern crate target_lexicon;

pub use context::Context;
pub use legalizer::legalize_function;
pub use verifier::verify_function;
pub use write::write_function;

/// Version number of the cretonne-codegen crate.
pub const VERSION: &str = env!("CARGO_PKG_VERSION");

#[macro_use]
pub extern crate cretonne_entity as entity;

#[macro_use]
pub mod dbg;

pub mod bforest;
pub mod binemit;
pub mod cfg_printer;
pub mod cursor;
pub mod dominator_tree;
pub mod flowgraph;
pub mod ir;
pub mod isa;
pub mod loop_analysis;
pub mod print_errors;
pub mod result;
pub mod settings;
pub mod timing;
pub mod verifier;

pub use entity::packed_option;

mod abi;
mod bitset;
mod constant_hash;
mod context;
mod dce;
mod divconst_magic_numbers;
mod fx;
mod iterators;
mod legalizer;
mod licm;
mod nan_canonicalization;
mod partition_slice;
mod postopt;
mod predicates;
mod preopt;
mod ref_slice;
mod regalloc;
mod scoped_hash_map;
mod simple_gvn;
mod stack_layout;
mod topo_order;
mod unreachable_code;
mod write;

/// This replaces `std` in builds with `core`.
#[cfg(not(feature = "std"))]
mod std {
    pub use alloc::{boxed, string, vec};
    pub use core::*;
    pub mod collections {
        #[allow(unused_extern_crates)]
        extern crate hashmap_core;

        pub use self::hashmap_core::map as hash_map;
        pub use self::hashmap_core::{HashMap, HashSet};
        pub use alloc::BTreeSet;
    }
}
<|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.

use tipb::expression::Expr;
use super::super::codec::datum::Datum;
use super::{Evaluator, EvalContext, Result, Error};

const ERROR_UNIMPLEMENTED: &'static str = "unimplemented";
pub const TYPE_INT: &'static str = "int";

pub fn invalid_type_error(datum: &Datum, expected_type: &str) -> Result<Datum> {
    Err(Error::Eval(format!("invalid expr type: {:?}, expect: {}", datum, expected_type)))
}

impl Evaluator {
    pub fn abs_int(&mut self, ctx: &EvalContext, expr: &Expr) -> Result<Datum> {
        let child = try!(self.get_one_child(expr));
        let d = try!(self.eval(ctx, child));
        match d {
            Datum::I64(i) => {
                if i >= 0 {
                    Ok(Datum::I64(i))
                } else {
                    Ok(Datum::I64(-i))
                }
            }
            Datum::U64(_) => Ok(d),
            _ => invalid_type_error(&d, TYPE_INT),
        }
    }

    pub fn abs_real(&mut self, _ctx: &EvalContext, _expr: &Expr) -> Result<Datum> {
        // TODO add impl
        Err(Error::Eval(ERROR_UNIMPLEMENTED.to_owned()))
    }

    pub fn ceil_int(&mut self, _ctx: &EvalContext, _expr: &Expr) -> Result<Datum> {
        // TODO add impl
        Err(Error::Eval(ERROR_UNIMPLEMENTED.to_owned()))
    }

    pub fn ceil_real(&mut self, _ctx: &EvalContext, _expr: &Expr) -> Result<Datum> {
        // TODO add impl
        Err(Error::Eval(ERROR_UNIMPLEMENTED.to_owned()))
    }

    pub fn floor_int(&mut self, _ctx: &EvalContext, _expr: &Expr) -> Result<Datum> {
        // TODO add impl
        Err(Error::Eval(ERROR_UNIMPLEMENTED.to_owned()))
    }

    pub fn floor_real(&mut self, _ctx: &EvalContext, _expr: &Expr) -> Result<Datum> {
        // TODO add impl
        Err(Error::Eval(ERROR_UNIMPLEMENTED.to_owned()))
    }
}

#[cfg(test)]
mod test {
    use tipb::expression::{ExprType, ScalarFuncSig};
    use coprocessor::codec::datum::Datum;
    use super::super::Evaluator;
    use super::super::evaluator::test::build_expr_with_sig;

    macro_rules! test_eval {
        ($tag:ident, $cases:expr) => {
            #[test]
            fn $tag() {
                let mut test_cases = $cases;
                let mut evaluator = Evaluator::default();
                for (i, (expr, expected)) in test_cases.drain(..).enumerate() {
                    let res = evaluator.eval(&Default::default(), &expr);
                    assert!(res.is_ok(),
                            "#{} expect eval expr {:?} ok but got {:?}",
                            i,
                            expr,
                            res);
                    let res = res.unwrap();
                    assert_eq!(res,
                               expected,
                               "#{} expect {:?} but got {:?}",
                               i,
                               expected,
                               res);
                }
            }
        };
    }

    test_eval!(test_abs_int,
               vec![(build_expr_with_sig(vec![Datum::I64(-1)],
                                         ExprType::ScalarFunc,
                                         ScalarFuncSig::AbsInt),
                     Datum::I64(1)),
                    (build_expr_with_sig(vec![Datum::I64(1)],
                                         ExprType::ScalarFunc,
                                         ScalarFuncSig::AbsInt),
                     Datum::I64(1)),
                    (build_expr_with_sig(vec![Datum::U64(1)],
                                         ExprType::ScalarFunc,
                                         ScalarFuncSig::AbsInt),
                     Datum::U64(1))]);
}
<commit_msg>coprocessor/xeval: add ceil int function impl (#2060)<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.

use tipb::expression::Expr;
use super::super::codec::datum::Datum;
use super::{Evaluator, EvalContext, Result, Error};

const ERROR_UNIMPLEMENTED: &'static str = "unimplemented";
pub const TYPE_INT: &'static str = "int";
pub const TYPE_FLOAT: &'static str = "float";

pub fn invalid_type_error(datum: &Datum, expected_type: &str) -> Result<Datum> {
    Err(Error::Eval(format!("invalid expr type: {:?}, expect: {}", datum, expected_type)))
}

impl Evaluator {
    pub fn abs_int(&mut self, ctx: &EvalContext, expr: &Expr) -> Result<Datum> {
        let child = try!(self.get_one_child(expr));
        let d = try!(self.eval(ctx, child));
        match d {
            Datum::I64(i) => {
                if i >= 0 {
                    Ok(Datum::I64(i))
                } else {
                    Ok(Datum::I64(-i))
                }
            }
            Datum::U64(_) => Ok(d),
            _ => invalid_type_error(&d, TYPE_INT),
        }
    }

    pub fn abs_real(&mut self, _ctx: &EvalContext, _expr: &Expr) -> Result<Datum> {
        // TODO add impl
        Err(Error::Eval(ERROR_UNIMPLEMENTED.to_owned()))
    }

    pub fn ceil_int(&mut self, ctx: &EvalContext, expr: &Expr) -> Result<Datum> {
        let child = try!(self.get_one_child(expr));
        let d = try!(self.eval(ctx, child));
        match d {
            Datum::F64(i) => {
                let result = i.ceil() as i64;
                Ok(Datum::I64(result))
            }
            Datum::Null => Ok(Datum::Null),
            _ => invalid_type_error(&d, TYPE_FLOAT),
        }
    }

    pub fn ceil_real(&mut self, _ctx: &EvalContext, _expr: &Expr) -> Result<Datum> {
        // TODO add impl
        Err(Error::Eval(ERROR_UNIMPLEMENTED.to_owned()))
    }

    pub fn floor_int(&mut self, _ctx: &EvalContext, _expr: &Expr) -> Result<Datum> {
        // TODO add impl
        Err(Error::Eval(ERROR_UNIMPLEMENTED.to_owned()))
    }

    pub fn floor_real(&mut self, _ctx: &EvalContext, _expr: &Expr) -> Result<Datum> {
        // TODO add impl
        Err(Error::Eval(ERROR_UNIMPLEMENTED.to_owned()))
    }
}

#[cfg(test)]
mod test {
    use tipb::expression::{ExprType, ScalarFuncSig};
    use coprocessor::codec::datum::Datum;
    use super::super::Evaluator;
    use super::super::evaluator::test::build_expr_with_sig;

    macro_rules! test_eval {
        ($tag:ident, $cases:expr) => {
            #[test]
            fn $tag() {
                let mut test_cases = $cases;
                let mut evaluator = Evaluator::default();
                for (i, (expr, expected)) in test_cases.drain(..).enumerate() {
                    let res = evaluator.eval(&Default::default(), &expr);
                    assert!(res.is_ok(),
                            "#{} expect eval expr {:?} ok but got {:?}",
                            i,
                            expr,
                            res);
                    let res = res.unwrap();
                    assert_eq!(res,
                               expected,
                               "#{} expect {:?} but got {:?}",
                               i,
                               expected,
                               res);
                }
            }
        };
    }

    test_eval!(test_abs_int,
               vec![(build_expr_with_sig(vec![Datum::I64(-1)],
                                         ExprType::ScalarFunc,
                                         ScalarFuncSig::AbsInt),
                     Datum::I64(1)),
                    (build_expr_with_sig(vec![Datum::I64(1)],
                                         ExprType::ScalarFunc,
                                         ScalarFuncSig::AbsInt),
                     Datum::I64(1)),
                    (build_expr_with_sig(vec![Datum::U64(1)],
                                         ExprType::ScalarFunc,
                                         ScalarFuncSig::AbsInt),
                     Datum::U64(1))]);

    test_eval!(test_ceil_int,
               vec![(build_expr_with_sig(vec![Datum::F64(-1.23)],
                                         ExprType::ScalarFunc,
                                         ScalarFuncSig::CeilInt),
                     Datum::I64(-1)),
                    (build_expr_with_sig(vec![Datum::F64(1.23)],
                                         ExprType::ScalarFunc,
                                         ScalarFuncSig::CeilInt),
                     Datum::I64(2)),
                    (build_expr_with_sig(vec![Datum::F64(2.0)],
                                         ExprType::ScalarFunc,
                                         ScalarFuncSig::CeilInt),
                     Datum::I64(2)),
                    (build_expr_with_sig(vec![Datum::Null],
                                         ExprType::ScalarFunc,
                                         ScalarFuncSig::CeilInt),
                     Datum::Null)]);
}
<|endoftext|>


<commit_before><commit_msg>revert(usage): Go back to clap2 behavior<commit_after><|endoftext|>


<commit_before><commit_msg>Use steps! for Reset future<commit_after><|endoftext|>