<commit_before>#[macro_export(local_inner_macros)]
macro_rules! kaze_sugar {
    ($($contents:tt)*) => {
        kaze_sugar_impl!([], [ $($contents)* ])
    };
}

#[doc(hidden)]
#[macro_export]
// TODO: This formulation can generate a lot of extra mux's with the same or similar conditions, and should be revisited!
macro_rules! kaze_sugar_impl {
    // [selector], [token stream]

    // No selector cases
    ([], [ $name:ident = $value:expr; $($rest:tt)* ]) => {
        $name = $value;
        kaze_sugar_impl!([], [ $($rest)* ]);
    };
    ([], [ if ($sel:expr) { $($inner:tt)* } $($rest:tt)* ]) => {
        kaze_sugar_impl!([ $sel ], [ $($inner)* ]);
        kaze_sugar_impl!([], [ $($rest)* ]);
    };
    ([], []) => {};

    // Selector cases
    ([ $sel:expr ], [ $name:ident = $value:expr; $($rest:tt)* ]) => {
        let prev = $name;
        kaze_sugar_impl!([ $sel ], [ $($rest)* ]);
        $name = $sel.mux($value, prev)
    };
    ([ $prev_sel:expr ], [ if ($sel:expr) { $($inner:tt)* } $($rest:tt)* ]) => {
        kaze_sugar_impl!([ $prev_sel & $sel ], [ $($inner)* ]);
        kaze_sugar_impl!([ $prev_sel ], [ $($rest)* ]);
    };
    ([ $_:expr ], []) => {};
}
<commit_msg>Barebones doc for kaze_sugar<commit_after>/// **UNSTABLE:** Provides a convenient way to write conditional combinational logic.
///
/// # Panics
///
/// Since this macro rewrites the referenced variable assignments using [`mux`], any panic conditions from that method apply to the generated code as well.
///
/// # Examples
///
/// ```
/// use kaze::*;
///
/// let c = Context::new();
///
/// let m = c.module("my_module");
/// let i = m.input("i", 1);
/// let invert = m.input("invert", 1);
/// let mut o = i;
/// kaze_sugar! {
///     if (invert) {
///         o = !o; // Equivalent to `o = invert.mux(!o, o);`
///     }
/// }
/// m.output("o", o);
/// ```
///
/// [`mux`]: ./struct.Signal.html#method.mux
#[macro_export(local_inner_macros)]
macro_rules! kaze_sugar {
    ($($contents:tt)*) => {
        kaze_sugar_impl!([], [ $($contents)* ])
    };
}

#[doc(hidden)]
#[macro_export]
// TODO: This formulation can generate a lot of extra mux's with the same or similar conditions, and should be revisited!
macro_rules! kaze_sugar_impl {
    // [selector], [token stream]

    // No selector cases
    ([], [ $name:ident = $value:expr; $($rest:tt)* ]) => {
        $name = $value;
        kaze_sugar_impl!([], [ $($rest)* ]);
    };
    ([], [ if ($sel:expr) { $($inner:tt)* } $($rest:tt)* ]) => {
        kaze_sugar_impl!([ $sel ], [ $($inner)* ]);
        kaze_sugar_impl!([], [ $($rest)* ]);
    };
    ([], []) => {};

    // Selector cases
    ([ $sel:expr ], [ $name:ident = $value:expr; $($rest:tt)* ]) => {
        let prev = $name;
        kaze_sugar_impl!([ $sel ], [ $($rest)* ]);
        $name = $sel.mux($value, prev)
    };
    ([ $prev_sel:expr ], [ if ($sel:expr) { $($inner:tt)* } $($rest:tt)* ]) => {
        kaze_sugar_impl!([ $prev_sel & $sel ], [ $($inner)* ]);
        kaze_sugar_impl!([ $prev_sel ], [ $($rest)* ]);
    };
    ([ $_:expr ], []) => {};
}
<|endoftext|>


<commit_before>use crate::{
    cluster::Cluster,
    health::{Event, HealthCheck, HealthCheckContext, ValidatorEvent},
};
use std::{collections::HashMap, time::Duration};

pub struct LivenessHealthCheck {
    last_committed: HashMap<String, LastCommitInfo>,
}

const MAX_BEHIND: Duration = Duration::from_secs(15);

#[derive(Default)]
struct LastCommitInfo {
    ve: Option<ValidatorEvent>,
    timestamp: Duration,
}

impl LivenessHealthCheck {
    pub fn new(cluster: &Cluster) -> Self {
        let mut last_committed = HashMap::new();
        for instance in cluster.instances() {
            last_committed.insert(instance.short_hash().clone(), LastCommitInfo::default());
        }
        Self { last_committed }
    }
}

impl HealthCheck for LivenessHealthCheck {
    fn on_event(&mut self, ve: &ValidatorEvent, ctx: &mut HealthCheckContext) {
        match ve.event {
            Event::Commit(..) => {
                if let Some(ref prev) = self.last_committed.get(&ve.validator) {
                    if prev.timestamp > ve.timestamp {
                        return;
                    }
                }
                self.last_committed.insert(
                    ve.validator.clone(),
                    LastCommitInfo {
                        ve: Some(ve.clone()),
                        timestamp: ve.timestamp,
                    },
                );
            }
            Event::ConsensusStarted => {
                ctx.report_failure(ve.validator.clone(), "validator restarted".into());
            }
        }
    }

    fn verify(&mut self, ctx: &mut HealthCheckContext) {
        let min_timestamp = ctx.now - MAX_BEHIND;
        for (validator, lci) in &self.last_committed {
            if lci.timestamp < min_timestamp {
                ctx.report_failure(
                    validator.clone(),
                    format!(
                        "Last commit is {} ms behind: {:?}",
                        (min_timestamp - lci.timestamp).as_millis(),
                        lci.ve,
                    ),
                );
            }
        }
    }

    fn invalidate(&mut self, validator: &str) {
        self.last_committed
            .insert(validator.into(), LastCommitInfo::default());
    }

    fn name(&self) -> &'static str {
        "liveness_check"
    }
}
<commit_msg>[cluster_test] Bump liveness check for 1m<commit_after>use crate::{
    cluster::Cluster,
    health::{Event, HealthCheck, HealthCheckContext, ValidatorEvent},
};
use std::{collections::HashMap, time::Duration};

pub struct LivenessHealthCheck {
    last_committed: HashMap<String, LastCommitInfo>,
}

const MAX_BEHIND: Duration = Duration::from_secs(60);

#[derive(Default)]
struct LastCommitInfo {
    ve: Option<ValidatorEvent>,
    timestamp: Duration,
}

impl LivenessHealthCheck {
    pub fn new(cluster: &Cluster) -> Self {
        let mut last_committed = HashMap::new();
        for instance in cluster.instances() {
            last_committed.insert(instance.short_hash().clone(), LastCommitInfo::default());
        }
        Self { last_committed }
    }
}

impl HealthCheck for LivenessHealthCheck {
    fn on_event(&mut self, ve: &ValidatorEvent, ctx: &mut HealthCheckContext) {
        match ve.event {
            Event::Commit(..) => {
                if let Some(ref prev) = self.last_committed.get(&ve.validator) {
                    if prev.timestamp > ve.timestamp {
                        return;
                    }
                }
                self.last_committed.insert(
                    ve.validator.clone(),
                    LastCommitInfo {
                        ve: Some(ve.clone()),
                        timestamp: ve.timestamp,
                    },
                );
            }
            Event::ConsensusStarted => {
                ctx.report_failure(ve.validator.clone(), "validator restarted".into());
            }
        }
    }

    fn verify(&mut self, ctx: &mut HealthCheckContext) {
        let min_timestamp = ctx.now - MAX_BEHIND;
        for (validator, lci) in &self.last_committed {
            if lci.timestamp < min_timestamp {
                ctx.report_failure(
                    validator.clone(),
                    format!(
                        "Last commit is {} ms behind: {:?}",
                        (min_timestamp - lci.timestamp).as_millis(),
                        lci.ve,
                    ),
                );
            }
        }
    }

    fn invalidate(&mut self, validator: &str) {
        self.last_committed
            .insert(validator.into(), LastCommitInfo::default());
    }

    fn name(&self) -> &'static str {
        "liveness_check"
    }
}
<|endoftext|>


<commit_before>//! Rope slices
//!
//! While we could just have the slicing methods on `Rope`s return `&str`s,
//! this would have some serious drawbacks: to slice a rope as `&str`, we'd have
//! to collect all the `Rope`'s characters into a `String` and then slice that
//! `String`. Creating an intermediate `String` would be slow, would cause
//! unnecessary allocations, and, in the case of `Rope::slice_mut()`, would
//! return a mutable slice of a _new `String`_ –- mutating the slice would _not_
//! mutate the underlying `Rope`.

use std::fmt;
use std::cmp;

use collections::range::RangeArgument;

use super::internals::Node;

/// An immutable borrowed slice of a `Rope`.
///
/// A RopeSlice represents an immutable borrowed slice of some or all the
/// characters in a `Rope`.
#[derive(Debug)]
pub struct RopeSlice<'a> { node: &'a Node
                         , offset: usize
                         , len: usize
                         }

impl<'a> fmt::Display for RopeSlice<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // TODO: don't create an intermediate string?
        write!(f, "{}", self.chars().collect::<String>())
    }
}

/// An mutable borrowed slice of a `Rope`.
///
/// A `RopeSliceMut` represents a mutable borrowed slice of some or all the
/// characters in a `Rope`.
#[derive(Debug)]
pub struct RopeSliceMut<'a> { node: &'a mut Node
                            , offset: usize
                            , len: usize
                            }
impl<'a> RopeSliceMut<'a>  {

    pub fn new<R>(node: &'a mut Node, range: R) -> Self
    where R: RangeArgument<usize> {
        let len = node.len();

        // if the RangeArgument doesn't have a defined start index,
        // the slice begins at the 0th index.
        let start = *range.start().unwrap_or(&0);
        // similarly, if there's no defined end, then the end index
        // is the last index in the Rope.
        let end = *range.end().unwrap_or(&node.len());

        let slice_len = end - start;

        // find the lowest node that contains both the slice start index and
        // the end index
        let (node, offset) = if start == 0 && end == len {
            // if the slice contains the entire rope, then the spanning node
            // is the root node
            (node, 0)
        } else {
            node.spanning_mut(start, slice_len)
        };

        RopeSliceMut { node: node
                     , offset: offset
                     , len: slice_len }
    }
}

impl<'a> RopeSlice<'a> {
    pub fn new<R>(node: &'a Node, range: R) -> Self
    where R: RangeArgument<usize> {
        let len = node.len();

        // if the RangeArgument doesn't have a defined start index,
        // the slice begins at the 0th index.
        let start = *range.start().unwrap_or(&0);
        // similarly, if there's no defined end, then the end index
        // is the last index in the Rope.
        let end = *range.end().unwrap_or(&node.len());

        let slice_len = end - start;

        // find the lowest node that contains both the slice start index and
        // the end index
        let (node, offset) = if start == 0 && end == len {
            // if the slice contains the entire rope, then the spanning node
            // is the root node
            (node, 0)
        } else {
            node.spanning(start, slice_len)
        };

        RopeSlice { node: node
                  , offset: offset
                  , len: slice_len }
    }

    #[inline]
    fn slice_char_iter<I, T>(&'a self, i: I) -> impl Iterator<Item=T> + 'a
    where I: Iterator<Item=T>
        , I: 'a
        , T: Copy {
            i.skip(self.offset).take(self.len)
    }

    fn slice_strings_iter<I>(&'a self, i: I) -> impl Iterator<Item=&'a str> +'a
    where I: Iterator<Item=&'a str>
        , I: 'a {
        i.scan((self.offset, self.len), |curr, s| {
            match *curr {
                (0, 0) => None
              , (0, ref mut remaining) if *remaining < s.len() => {
                    let r = *remaining;
                    *remaining = 0;
                    Some(&s[..r])
                }
              , (0, ref mut remaining) => {
                    *remaining -= s.len();
                    Some(s)
                }
              , (ref mut offset, _) if *offset > s.len() => {
                    *offset -= s.len();
                    Some("")
                }
              , (ref mut offset, _) => {
                    let c = *offset;
                    *offset -= s.len();
                    Some(&s[c..])
                }
            }
            // if curr_len > 0 {
            //     let c = curr_offset;
            //     let res = if c > 0 {
            //         curr_offset -= s.len();
            //         if c < s.len()  {
            //             &s[c..]
            //         } else {
            //             ""
            //         }
            //     } else {
            //         s
            //     };
            //     Some(res)
            })
         .skip_while(|&s| s == "")
    }

    pub fn chars(&'a self) -> impl Iterator<Item=char> +'a  {
        self.slice_char_iter(self.node.chars())
    }

    pub fn bytes(&'a self) -> impl Iterator<Item=u8> + 'a  {
        self.slice_char_iter(self.node.bytes())
    }

    #[inline]
    pub fn split_whitespace(&'a self) -> impl Iterator<Item=&'a str> {
        self.slice_strings_iter(self.node.split_whitespace())
    }

    #[inline]
    pub fn lines(&'a self) -> impl Iterator<Item=&'a str> {
        self.slice_strings_iter(self.node.lines())
    }

    #[inline]
    pub fn char_indices(&'a self) -> impl Iterator<Item=(usize, char)> + 'a {
        self.chars().enumerate()
    }

    /// Returns true if the bytes in `self` equal the bytes in `other`
    #[inline]
    fn bytes_eq<I>(&self, other: I) -> bool
    where I: Iterator<Item=u8> {
        self.bytes().zip(other).all(|(a, b)| a == b)
    }

    #[inline]
    pub fn len(&self) -> usize { self.len }
}

//-- comparisons ----------------------------------------------------
impl<'a> cmp::Eq for RopeSlice<'a> {}
impl<'a> cmp::PartialEq for RopeSlice<'a> {
    /// A rope equals another rope if all the bytes in both are equal.

    #[inline]
    fn eq(&self, other: &RopeSlice<'a>) -> bool {
        if self.len() == other.len() {
            self.bytes_eq(other.bytes())
        } else {
            false
        }
    }
}

impl<'a> cmp::PartialEq<str> for RopeSlice<'a> {
    /// A rope equals another rope if all the bytes in both are equal.

    #[inline]
    fn eq(&self, other: &str) -> bool {
        if self.len() == other.len() {
            self.bytes_eq(other.bytes())
        } else {
            false
        }
    }
}

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

    #[test]
    fn char_indices() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice(4..8);
        let string_slice = &string[4..8];
        let indices = rope_slice.char_indices().zip(string_slice.char_indices());
        for ((ridx, rch), (sidx, sch)) in indices {
            assert_eq!(rch, sch);
            assert_eq!(ridx, sidx);
        }
    }

    #[test]
    fn to() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice(1..10);
        let string_slice = &string[1..10];
        assert_eq!(&rope_slice, string_slice)
    }

    // #[test]
    // fn between() {
    //     let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
    //     let rope = Rope::from(string);
    //     let rope_slice = rope.slice(1...10usize);
    //     let string_slice = &string[1...10];
    //     assert_eq!(&rope_slice, string_slice)
    // }

    #[test]
    fn until() {
        let string = "aaaaabbbbbbccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice(..10);
        let string_slice = &string[..10];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn from() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice(5..);
        let string_slice = &string[5..];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn full() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice(..);
        let string_slice = &string[..];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn mut_char_indices() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice_mut(4..8);
        let string_slice = &mut string[4..8];
        let indices = rope_slice.char_indices().zip(string_slice.char_indices());
        for ((ridx, rch), (sidx, sch)) in indices {
            assert_eq!(rch, sch);
            assert_eq!(ridx, sidx);
        }
    }

    #[test]
    fn mut_to() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice_mut(1..10);
        let string_slice = &mut string[1..10];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn mut_until() {
        let string = "aaaaabbbbbbccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice_mut(..10);
        let string_slice = &string[..10];
        assert_eq!(&mut rope_slice, string_slice)
    }

    #[test]
    fn mut_from() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice_mut(5..);
        let string_slice = &mut string[5..];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn mut_full() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice_mut(..);
        let string_slice = &mut string[..];
        assert_eq!(&rope_slice, string_slice)
    }
}
<commit_msg>rope: implement iterators for RopeSliceMut<commit_after>//! Rope slices
//!
//! While we could just have the slicing methods on `Rope`s return `&str`s,
//! this would have some serious drawbacks: to slice a rope as `&str`, we'd have
//! to collect all the `Rope`'s characters into a `String` and then slice that
//! `String`. Creating an intermediate `String` would be slow, would cause
//! unnecessary allocations, and, in the case of `Rope::slice_mut()`, would
//! return a mutable slice of a _new `String`_ –- mutating the slice would _not_
//! mutate the underlying `Rope`.
// TODO: implement Borrow<RopeSlice> for Rope?

use std::fmt;
use std::cmp;

use collections::range::RangeArgument;

use super::internals::Node;

/// An immutable borrowed slice of a `Rope`.
///
/// A RopeSlice represents an immutable borrowed slice of some or all the
/// characters in a `Rope`.
#[derive(Debug)]
pub struct RopeSlice<'a> { node: &'a Node
                         , offset: usize
                         , len: usize
                         }

impl<'a> fmt::Display for RopeSlice<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // TODO: don't create an intermediate string?
        write!(f, "{}", self.chars().collect::<String>())
    }
}

/// An mutable borrowed slice of a `Rope`.
///
/// A `RopeSliceMut` represents a mutable borrowed slice of some or all the
/// characters in a `Rope`.
#[derive(Debug)]
pub struct RopeSliceMut<'a> { node: &'a mut Node
                            , offset: usize
                            , len: usize
                            }

impl<'a> RopeSliceMut<'a>  {

    // TODO: share duplicate functionality with non-mutable RopeSlice in a less
    //       ugly way. Maybe an added generic?
    //          - eliza, 12/23/16

    // TODO: add mutable iterators

    pub fn new<R>(node: &'a mut Node, range: R) -> Self
    where R: RangeArgument<usize> {
        let len = node.len();

        // if the RangeArgument doesn't have a defined start index,
        // the slice begins at the 0th index.
        let start = *range.start().unwrap_or(&0);
        // similarly, if there's no defined end, then the end index
        // is the last index in the Rope.
        let end = *range.end().unwrap_or(&node.len());

        let slice_len = end - start;

        // find the lowest node that contains both the slice start index and
        // the end index
        let (node, offset) = if start == 0 && end == len {
            // if the slice contains the entire rope, then the spanning node
            // is the root node
            (node, 0)
        } else {
            node.spanning_mut(start, slice_len)
        };

        RopeSliceMut { node: node
                     , offset: offset
                     , len: slice_len }
    }

    #[inline]
    fn slice_char_iter<I, T>(&'a self, i: I) -> impl Iterator<Item=T> + 'a
    where I: Iterator<Item=T>
        , I: 'a
        , T: Copy {
            i.skip(self.offset).take(self.len)
    }

    fn slice_strings_iter<I>(&'a self, i: I) -> impl Iterator<Item=&'a str> +'a
    where I: Iterator<Item=&'a str>
        , I: 'a {
        i.scan((self.offset, self.len), |curr, s| {
            match *curr {
                (0, 0) => None
              , (0, ref mut remaining) if *remaining < s.len() => {
                    let r = *remaining;
                    *remaining = 0;
                    Some(&s[..r])
                }
              , (0, ref mut remaining) => {
                    *remaining -= s.len();
                    Some(s)
                }
              , (ref mut offset, _) if *offset > s.len() => {
                    *offset -= s.len();
                    Some("")
                }
              , (ref mut offset, _) => {
                    let c = *offset;
                    *offset -= s.len();
                    Some(&s[c..])
                }
            }
            // if curr_len > 0 {
            //     let c = curr_offset;
            //     let res = if c > 0 {
            //         curr_offset -= s.len();
            //         if c < s.len()  {
            //             &s[c..]
            //         } else {
            //             ""
            //         }
            //     } else {
            //         s
            //     };
            //     Some(res)
            })
         .skip_while(|&s| s == "")
    }

    pub fn chars(&'a self) -> impl Iterator<Item=char> +'a  {
        self.slice_char_iter(self.node.chars())
    }

    pub fn bytes(&'a self) -> impl Iterator<Item=u8> + 'a  {
        self.slice_char_iter(self.node.bytes())
    }

    #[inline]
    pub fn split_whitespace(&'a self) -> impl Iterator<Item=&'a str> {
        self.slice_strings_iter(self.node.split_whitespace())
    }

    #[inline]
    pub fn lines(&'a self) -> impl Iterator<Item=&'a str> {
        self.slice_strings_iter(self.node.lines())
    }

    #[inline]
    pub fn char_indices(&'a self) -> impl Iterator<Item=(usize, char)> + 'a {
        self.chars().enumerate()
    }

    /// Returns true if the bytes in `self` equal the bytes in `other`
    #[inline]
    fn bytes_eq<I>(&self, other: I) -> bool
    where I: Iterator<Item=u8> {
        self.bytes().zip(other).all(|(a, b)| a == b)
    }

    #[inline]
    pub fn len(&self) -> usize { self.len }
}

impl<'a> RopeSlice<'a> {
    pub fn new<R>(node: &'a Node, range: R) -> Self
    where R: RangeArgument<usize> {
        let len = node.len();

        // if the RangeArgument doesn't have a defined start index,
        // the slice begins at the 0th index.
        let start = *range.start().unwrap_or(&0);
        // similarly, if there's no defined end, then the end index
        // is the last index in the Rope.
        let end = *range.end().unwrap_or(&node.len());

        let slice_len = end - start;

        // find the lowest node that contains both the slice start index and
        // the end index
        let (node, offset) = if start == 0 && end == len {
            // if the slice contains the entire rope, then the spanning node
            // is the root node
            (node, 0)
        } else {
            node.spanning(start, slice_len)
        };

        RopeSlice { node: node
                  , offset: offset
                  , len: slice_len }
    }

    #[inline]
    fn slice_char_iter<I, T>(&'a self, i: I) -> impl Iterator<Item=T> + 'a
    where I: Iterator<Item=T>
        , I: 'a
        , T: Copy {
            i.skip(self.offset).take(self.len)
    }

    fn slice_strings_iter<I>(&'a self, i: I) -> impl Iterator<Item=&'a str> +'a
    where I: Iterator<Item=&'a str>
        , I: 'a {
        i.scan((self.offset, self.len), |curr, s| {
            match *curr {
                (0, 0) => None
              , (0, ref mut remaining) if *remaining < s.len() => {
                    let r = *remaining;
                    *remaining = 0;
                    Some(&s[..r])
                }
              , (0, ref mut remaining) => {
                    *remaining -= s.len();
                    Some(s)
                }
              , (ref mut offset, _) if *offset > s.len() => {
                    *offset -= s.len();
                    Some("")
                }
              , (ref mut offset, _) => {
                    let c = *offset;
                    *offset -= s.len();
                    Some(&s[c..])
                }
            }
            // if curr_len > 0 {
            //     let c = curr_offset;
            //     let res = if c > 0 {
            //         curr_offset -= s.len();
            //         if c < s.len()  {
            //             &s[c..]
            //         } else {
            //             ""
            //         }
            //     } else {
            //         s
            //     };
            //     Some(res)
            })
         .skip_while(|&s| s == "")
    }

    pub fn chars(&'a self) -> impl Iterator<Item=char> +'a  {
        self.slice_char_iter(self.node.chars())
    }

    pub fn bytes(&'a self) -> impl Iterator<Item=u8> + 'a  {
        self.slice_char_iter(self.node.bytes())
    }

    #[inline]
    pub fn split_whitespace(&'a self) -> impl Iterator<Item=&'a str> {
        self.slice_strings_iter(self.node.split_whitespace())
    }

    #[inline]
    pub fn lines(&'a self) -> impl Iterator<Item=&'a str> {
        self.slice_strings_iter(self.node.lines())
    }

    #[inline]
    pub fn char_indices(&'a self) -> impl Iterator<Item=(usize, char)> + 'a {
        self.chars().enumerate()
    }

    /// Returns true if the bytes in `self` equal the bytes in `other`
    #[inline]
    fn bytes_eq<I>(&self, other: I) -> bool
    where I: Iterator<Item=u8> {
        self.bytes().zip(other).all(|(a, b)| a == b)
    }

    #[inline]
    pub fn len(&self) -> usize { self.len }
}

//-- comparisons ----------------------------------------------------
impl<'a> cmp::Eq for RopeSlice<'a> {}
impl<'a> cmp::PartialEq for RopeSlice<'a> {
    /// A rope equals another rope if all the bytes in both are equal.

    #[inline]
    fn eq(&self, other: &RopeSlice<'a>) -> bool {
        if self.len() == other.len() {
            self.bytes_eq(other.bytes())
        } else {
            false
        }
    }
}

impl<'a> cmp::PartialEq<str> for RopeSlice<'a> {
    /// A rope equals another rope if all the bytes in both are equal.

    #[inline]
    fn eq(&self, other: &str) -> bool {
        if self.len() == other.len() {
            self.bytes_eq(other.bytes())
        } else {
            false
        }
    }
}

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

    #[test]
    fn char_indices() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice(4..8);
        let string_slice = &string[4..8];
        let indices = rope_slice.char_indices().zip(string_slice.char_indices());
        for ((ridx, rch), (sidx, sch)) in indices {
            assert_eq!(rch, sch);
            assert_eq!(ridx, sidx);
        }
    }

    #[test]
    fn to() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice(1..10);
        let string_slice = &string[1..10];
        assert_eq!(&rope_slice, string_slice)
    }

    // #[test]
    // fn between() {
    //     let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
    //     let rope = Rope::from(string);
    //     let rope_slice = rope.slice(1...10usize);
    //     let string_slice = &string[1...10];
    //     assert_eq!(&rope_slice, string_slice)
    // }

    #[test]
    fn until() {
        let string = "aaaaabbbbbbccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice(..10);
        let string_slice = &string[..10];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn from() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice(5..);
        let string_slice = &string[5..];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn full() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice(..);
        let string_slice = &string[..];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn mut_char_indices() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice_mut(4..8);
        let string_slice = &mut string[4..8];
        let indices = rope_slice.char_indices().zip(string_slice.char_indices());
        for ((ridx, rch), (sidx, sch)) in indices {
            assert_eq!(rch, sch);
            assert_eq!(ridx, sidx);
        }
    }

    #[test]
    fn mut_to() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice_mut(1..10);
        let string_slice = &mut string[1..10];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn mut_until() {
        let string = "aaaaabbbbbbccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice_mut(..10);
        let string_slice = &string[..10];
        assert_eq!(&mut rope_slice, string_slice)
    }

    #[test]
    fn mut_from() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice_mut(5..);
        let string_slice = &mut string[5..];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn mut_full() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice_mut(..);
        let string_slice = &mut string[..];
        assert_eq!(&rope_slice, string_slice)
    }
}
<|endoftext|>


<commit_before>use time::{self, Duration};

#[cfg(windows)]
mod win;
#[cfg(windows)]
pub use self::win::get_cpu_time;

#[cfg(unix)]
mod unix;
#[cfg(unix)]
pub use self::unix::get_cpu_time;

#[cfg(not(any(unix, windows)))]
pub fn get_cpu_time() -> Option<u64> {
    None
}

pub fn get_cpu_duration(start: Option<u64>, stop: Option<u64>) -> Option<Duration> {
    start.and_then(|start| stop.and_then(|stop| Some(Duration::nanoseconds((stop - start) as i64))))
}

#[derive(Copy, Clone)]
pub struct CpuMeasure {
    /// number of ns
    pub time_duration: u64,

    /// percentage (0-100) of that as cpu time
    pub cpu_usage_percent: Option<f64>,
}

pub fn measure_cpu(op: impl FnOnce()) -> CpuMeasure {
    let time_start = time::precise_time_ns();
    let cpu_start = get_cpu_time();

    op();

    let cpu_stop = get_cpu_time();
    let time_duration = time::precise_time_ns() - time_start;

    CpuMeasure {
        time_duration,
        cpu_usage_percent: get_cpu_duration(cpu_start, cpu_stop)
            .and_then(|cpu| cpu.num_nanoseconds())
            .and_then(|cpu| Some(100.0 * cpu as f64 / time_duration as f64)),
    }
}

pub fn print_time(m: CpuMeasure) {
    println!("    wallclock: {} ns", m.time_duration);
    if let Some(cpu_usage) = m.cpu_usage_percent {
        println!("    cpu usage: {:3.1}%", cpu_usage);
    } else {
        println!("    cpu usage: N/A");
    }
}
<commit_msg>Reduce Option complexity in demo cpu_time<commit_after>use time::{self, Duration};

#[cfg(windows)]
mod win;
#[cfg(windows)]
pub use self::win::get_cpu_time;

#[cfg(unix)]
mod unix;
#[cfg(unix)]
pub use self::unix::get_cpu_time;

#[cfg(not(any(unix, windows)))]
pub fn get_cpu_time() -> Option<u64> {
    None
}

pub fn get_cpu_duration(start: Option<u64>, stop: Option<u64>) -> Option<Duration> {
    Some(Duration::nanoseconds((stop? - start?) as i64))
}

#[derive(Copy, Clone)]
pub struct CpuMeasure {
    /// number of ns
    pub time_duration: u64,

    /// percentage (0-100) of that as cpu time
    pub cpu_usage_percent: Option<f64>,
}

pub fn measure_cpu(op: impl FnOnce()) -> CpuMeasure {
    let time_start = time::precise_time_ns();
    let cpu_start = get_cpu_time();

    op();

    let cpu_stop = get_cpu_time();
    let time_duration = time::precise_time_ns() - time_start;

    CpuMeasure {
        time_duration,
        cpu_usage_percent: get_cpu_duration(cpu_start, cpu_stop)
            .and_then(|cpu| cpu.num_nanoseconds())
            .map(|cpu| 100.0 * cpu as f64 / time_duration as f64),
    }
}

pub fn print_time(m: CpuMeasure) {
    println!("    wallclock: {} ns", m.time_duration);
    if let Some(cpu_usage) = m.cpu_usage_percent {
        println!("    cpu usage: {:3.1}%", cpu_usage);
    } else {
        println!("    cpu usage: N/A");
    }
}
<|endoftext|>


<commit_before>pub use self::token::Token;
pub use self::token::Category;

pub mod token;
pub mod implementations;

pub struct StateFunction(fn(&mut Lexer) -> Option<StateFunction>);

pub struct Lexer {
    data: String,
    char_count: usize,
    token_start: usize,
    token_position: usize,
    tokens: Vec<Token>,
}

pub fn new(data: &str) -> Lexer {
    Lexer{
      data: data.to_string(),
      char_count: data.chars().count(),
      token_start: 0,
      token_position: 0,
      tokens: vec![]
    }
}

mod tests {
    use super::new;

    #[test]
    fn new_initializes_correctly() {
        let lexer_data = "lexer data";
        let lexer = new(lexer_data);
        assert_eq!(lexer.data, lexer_data);
        assert_eq!(lexer.char_count, 10);
        assert_eq!(lexer.token_start, 0);
        assert_eq!(lexer.token_position, 0);
        assert_eq!(lexer.tokens, vec![]);
    }
}
<commit_msg>Implement advance method for Lexer.<commit_after>pub use self::token::Token;
pub use self::token::Category;

pub mod token;
pub mod implementations;

pub struct StateFunction(fn(&mut Lexer) -> Option<StateFunction>);

pub struct Lexer {
    data: String,
    char_count: usize,
    token_start: usize,
    token_position: usize,
    tokens: Vec<Token>,
}

pub fn new(data: &str) -> Lexer {
    Lexer{
      data: data.to_string(),
      char_count: data.chars().count(),
      token_start: 0,
      token_position: 0,
      tokens: vec![]
    }
}

impl Lexer {
    pub fn advance(&mut self) {
        if self.token_position < self.char_count-1 {
            self.token_position += 1;
        }
    }
}

mod tests {
    use super::new;

    #[test]
    fn new_initializes_correctly_with_unicode_data() {
        let lexer_data = "différent";
        let lexer = new(lexer_data);
        assert_eq!(lexer.data, lexer_data);
        assert_eq!(lexer.char_count, 9);
        assert_eq!(lexer.token_start, 0);
        assert_eq!(lexer.token_position, 0);
        assert_eq!(lexer.tokens, vec![]);
    }

    #[test]
    fn advance_increments_the_cursor_by_one() {
        let lexer_data = "élégant";
        let mut lexer = new(lexer_data);
        lexer.advance();
        assert_eq!(lexer.token_position, 1);
        lexer.advance();
        assert_eq!(lexer.token_position, 2);
    }

    #[test]
    fn advance_stops_when_there_is_no_more_data() {
        let lexer_data = "élégant";
        let mut lexer = new(lexer_data);

        // Try to go beyond the last character.
        for _ in 0..lexer.char_count {
            lexer.advance();
        }

        assert_eq!(lexer.token_position, lexer.char_count-1);
    }
}
<|endoftext|>


<commit_before>#![crate_id = "js"]
#![comment = "Javascript execution"]
#![license = "MIT"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]

#![doc(
	html_favicon_url = "http://tombebbington.github.io/favicon.png",
	html_root_url = "http://tombebbington.github.io/js.rs/"
)]
#![experimental]

#![deny(non_uppercase_statics, missing_doc, unnecessary_parens, unrecognized_lint, unreachable_code, unnecessary_allocation, unnecessary_typecast, unnecessary_allocation, uppercase_variables, non_camel_case_types, unused_must_use)]

//! This crate provides a Javascript execution library with an
//! Interpreter and a Javascript standard library.
extern crate collections;
extern crate syntax = "js_syntax";
extern crate rand;
extern crate serialize;
extern crate time;
extern crate url;
/// The interpreter
pub mod exec;
/// The standard Javascript library
pub mod stdlib {
	/// Javascript values, utility methods and conversion between Javascript values and Rust values
	pub mod value;
	/// The global `Function` object and function value representations
	pub mod function;
	/// The global `Object` object
	pub mod object;
	/// The global `Array` object
	pub mod array;
	/// The global `console` object
	pub mod console;
	/// The global `Math` object
	pub mod math;
	/// The global `JSON` object
	pub mod json;
	/// The global `Number` object with related functions and constants
	pub mod number;
	/// The global `Error` object
	pub mod error;
	/// Contains global methods concerning URIs
	pub mod uri;
	/// The global `String` object
	pub mod string;
}<commit_msg>Include JIT as extern crate<commit_after>#![crate_id = "js"]
#![comment = "Javascript execution"]
#![license = "MIT"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]

#![doc(
	html_favicon_url = "http://tombebbington.github.io/favicon.png",
	html_root_url = "http://tombebbington.github.io/js.rs/"
)]
#![experimental]

#![deny(non_uppercase_statics, missing_doc, unnecessary_parens, unrecognized_lint, unreachable_code, unnecessary_allocation, unnecessary_typecast, unnecessary_allocation, uppercase_variables, non_camel_case_types, unused_must_use)]

//! This crate provides a Javascript execution library with an
//! Interpreter and a Javascript standard library.
extern crate collections;
extern crate syntax = "js_syntax";
extern crate rand;
extern crate serialize;
extern crate time;
extern crate url;
extern crate jit;
/// The interpreter
pub mod exec;
/// The standard Javascript library
pub mod stdlib {
	/// Javascript values, utility methods and conversion between Javascript values and Rust values
	pub mod value;
	/// The global `Function` object and function value representations
	pub mod function;
	/// The global `Object` object
	pub mod object;
	/// The global `Array` object
	pub mod array;
	/// The global `console` object
	pub mod console;
	/// The global `Math` object
	pub mod math;
	/// The global `JSON` object
	pub mod json;
	/// The global `Number` object with related functions and constants
	pub mod number;
	/// The global `Error` object
	pub mod error;
	/// Contains global methods concerning URIs
	pub mod uri;
	/// The global `String` object
	pub mod string;
}<|endoftext|>


<commit_before>use types::*;
use types::flags::*;
use types::generation::*;
use types::parsing::*;

use cookie_factory::GenError;

pub mod metadata {
    use super::*;

    pub const NAME:          &'static str   = "{{protocol.name}}";
    pub const MAJOR_VERSION: ShortShortUInt = {{protocol.major_version}};
    pub const MINOR_VERSION: ShortShortUInt = {{protocol.minor_version}};
    pub const REVISION:      ShortShortUInt = {{protocol.revision}};
    pub const PORT:          LongUInt       = {{protocol.port}};
    pub const COPYRIGHT:     &'static str   = r#"{{copyright}}"#;
}

pub mod constants {
    use super::*;

    {{#each protocol.constants as |constant| ~}}
    pub const {{sanitize_name constant.name}}: {{constant.type}} = {{constant.value}};
    {{/each ~}}
}

pub enum AMQPError {
    Soft(AMQPSoftError),
    Hard(AMQPHardError),
}

impl AMQPError {
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            AMQPError::Soft(ref s) => s.get_id(),
            AMQPError::Hard(ref h) => h.get_id(),
        }
    }

    pub fn from_id(id: ShortUInt) -> Option<AMQPError> {
        AMQPSoftError::from_id(id).map(|e| AMQPError::Soft(e)).or_else(|| AMQPHardError::from_id(id).map(|e| AMQPError::Hard(e)))
    }
}

pub enum AMQPSoftError {
    {{#each protocol.soft_errors as |constant| ~}}
    {{camel constant.name}},
    {{/each ~}}
}

impl AMQPSoftError {
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            {{#each protocol.soft_errors as |constant| ~}}
            AMQPSoftError::{{camel constant.name}} => {{constant.value}},
            {{/each ~}}
        }
    }

    pub fn from_id(id: ShortUInt) -> Option<AMQPSoftError> {
        match id {
            {{#each protocol.soft_errors as |constant| ~}}
            {{constant.value}} => Some(AMQPSoftError::{{camel constant.name}}),
            {{/each ~}}
            _                  => None,
        }
    }
}

pub enum AMQPHardError {
    {{#each protocol.hard_errors as |constant| ~}}
    {{camel constant.name}},
    {{/each ~}}
}

impl AMQPHardError {
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            {{#each protocol.hard_errors as |constant| ~}}
            AMQPHardError::{{camel constant.name}} => {{constant.value}},
            {{/each ~}}
        }
    }

    pub fn from_id(id: ShortUInt) -> Option<AMQPHardError> {
        match id {
            {{#each protocol.hard_errors as |constant| ~}}
            {{constant.value}} => Some(AMQPHardError::{{camel constant.name}}),
            {{/each ~}}
            _                  => None,
        }
    }
}

{{#each protocol.classes as |class| ~}}
use self::{{snake class.name}}::parse_{{snake class.name}};
{{/each ~}}

named!(pub parse_class<AMQPClass>, switch!(parse_id,
    {{#each protocol.classes as |class| ~}}
    {{class.id}} => map!(call!(parse_{{snake class.name}}), AMQPClass::{{camel class.name}}) {{#unless @last ~}}|{{/unless ~}}
    {{/each ~}}
));

pub fn gen_class<'a>(input: (&'a mut [u8], usize), class: &AMQPClass) -> Result<(&'a mut [u8], usize), GenError> {
    match *class {
        {{#each protocol.classes as |class| ~}}
        AMQPClass::{{camel class.name}}(ref {{snake class.name}}) => {{snake class.name}}::gen_{{snake class.name}}(input, {{snake class.name}}),
        {{/each ~}}
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum AMQPClass {
    {{#each protocol.classes as |class| ~}}
    {{camel class.name}}({{snake class.name}}::AMQPMethod),
    {{/each ~}}
}

{{#each protocol.classes as |class|}}
pub mod {{snake class.name}} {
    use super::*;

    named!(pub parse_{{snake class.name}}<{{snake class.name}}::AMQPMethod>, switch!(parse_id,
        {{#each class.methods as |method| ~}}
        {{method.id}} => map!(call!(parse_{{snake method.name}}), AMQPMethod::{{camel method.name}}) {{#unless @last ~}}|{{/unless ~}}
        {{/each ~}}
    ));

    pub fn gen_{{snake class.name}}<'a>(input: (&'a mut [u8], usize), method: &AMQPMethod) -> Result<(&'a mut [u8], usize), GenError> {
        match *method {
            {{#each class.methods as |method| ~}}
            AMQPMethod::{{camel method.name}}(ref {{snake method.name}}) => {
                do_gen!(input,
                    gen_id(&{{class.id}}) >>
                    gen_{{snake method.name}}({{snake method.name}})
                )
            },
            {{/each ~}}
        }
    }

    #[derive(Clone, Debug, PartialEq)]
    pub enum AMQPMethod {
        {{#each class.methods as |method| ~}}
        {{camel method.name}}({{camel method.name}}),
        {{/each ~}}
    }

    {{#each class.methods as |method|}}
    #[derive(Clone, Debug, PartialEq)]
    pub struct {{camel method.name}} {
        {{#each_argument method.arguments as |argument| ~}}
        {{#if argument_is_value ~}}
        pub {{snake argument.name}}: {{argument.type}},
        {{else}}
        {{#each_flag argument as |flag| ~}}
        pub {{snake flag.name}}: Boolean,
        {{/each_flag ~}}
        {{/if ~}}
        {{/each_argument ~}}
    }

    named!(pub parse_{{snake method.name}}<{{camel method.name}}>, do_parse!(
        {{#each_argument method.arguments as |argument| ~}}
        {{#if argument_is_value ~}}
        {{snake argument.name}}: parse_{{snake_type argument.type}} >>
        {{else}}
        /* FIXME: support multiple flags structs? */
        flags: apply!(parse_flags, &vec![
            {{#each_flag argument as |flag| ~}}
            "{{flag.name}}",
            {{/each_flag ~}}
        ]) >>
        {{/if ~}}
        {{/each_argument ~}}
        ({{camel method.name}} {
            {{#each_argument method.arguments as |argument| ~}}
            {{#if argument_is_value ~}}
            {{snake argument.name}}: {{snake argument.name}},
            {{else}}
            {{#each_flag argument as |flag| ~}}
            {{snake flag.name}}: flags.get_flag("{{snake flag.name}}").unwrap_or({{flag.default_value}}),
            {{/each_flag ~}}
            {{/if ~}}
            {{/each_argument ~}}
        })
    ));

    pub fn gen_{{snake method.name}}<'a>(input: (&'a mut [u8], usize), {{#if method.has_arguments ~}}method{{else}}_{{/if ~}}: &{{camel method.name}}) -> Result<(&'a mut [u8],usize), GenError> {
        {{#if method.has_flags ~}}
        /* FIXME: support multiple flags structs? */
        let mut flags = AMQPFlags::new();
        {{#each_argument method.arguments as |argument| ~}}
        {{#unless argument_is_value ~}}
        {{#each_flag argument as |flag| ~}}
        flags.add_flag("{{snake flag.name}}".to_string(), method.{{snake flag.name}});
        {{/each_flag ~}}
        {{/unless ~}}
        {{/each_argument ~}}
        {{/if ~}}
        do_gen!(input,
            gen_id(&{{method.id}})
            {{#each_argument method.arguments as |argument| ~}}
            {{#if argument_is_value ~}}
            >> gen_{{snake_type argument.type}}(&method.{{snake argument.name}})
            {{else}}
            >> gen_flags(&flags)
            {{/if ~}}
            {{/each_argument ~}}
        )
    }
    {{/each ~}}
    {{#if class.has_properties ~}}
    #[derive(Clone,Debug,PartialEq)]
    pub struct AMQPProperties {
        {{#each class.properties as |property| ~}}
        {{snake property.name}}: Option<{{property.type}}>,
        {{/each ~}}
    }

    impl Default for AMQPProperties {
        fn default() -> AMQPProperties {
            AMQPProperties {
                {{#each class.properties as |property| ~}}
                {{snake property.name}}: None,
                {{/each ~}}
            }
        }
    }

    impl AMQPProperties {
        {{#each class.properties as |property| ~}}
        pub fn with_{{snake property.name}}(mut self, value: {{property.type}}) -> AMQPProperties {
            self.{{snake property.name}} = Some(value);
            self
        }
        {{/each ~}}

        pub fn bitmask(&self) -> ShortUInt {
            {{#each class.properties as |property| ~}}
            (if self.{{snake property.name}}.is_some() { 1 << (15 - {{@index}}) } else { 0 }) {{#unless @last ~}} + {{/unless ~}}
            {{/each ~}}
        }
    }

    named!(pub parse_properties<AMQPProperties>, do_parse!(
        flags: parse_short_uint >>
        {{#each class.properties as |property| ~}}
        {{snake property.name}}: cond!(flags & (1 << (15 - {{@index}})) != 0, parse_{{snake_type property.type}}) >>
        {{/each ~}}
        (AMQPProperties {
            {{#each class.properties as |property| ~}}
            {{snake property.name}}: {{snake property.name}},
            {{/each ~}}
        })
    ));

    pub fn gen_properties<'a>(input:(&'a mut [u8],usize), props: &AMQPProperties) -> Result<(&'a mut [u8],usize),GenError> {
        do_gen!(input,
            gen_short_uint(&props.bitmask())
            {{#each class.properties as |property| ~}}
            >> gen_cond!(props.{{snake property.name}}.is_some(), gen_call!(gen_{{snake_type property.type}}, &props.{{snake property.name}}.as_ref().unwrap()))
            {{/each ~}}
        )
    }
    {{/if ~}}
}
{{/each ~}}
<commit_msg>protocol: style fix<commit_after>use types::*;
use types::flags::*;
use types::generation::*;
use types::parsing::*;

use cookie_factory::GenError;

pub mod metadata {
    use super::*;

    pub const NAME:          &'static str   = "{{protocol.name}}";
    pub const MAJOR_VERSION: ShortShortUInt = {{protocol.major_version}};
    pub const MINOR_VERSION: ShortShortUInt = {{protocol.minor_version}};
    pub const REVISION:      ShortShortUInt = {{protocol.revision}};
    pub const PORT:          LongUInt       = {{protocol.port}};
    pub const COPYRIGHT:     &'static str   = r#"{{copyright}}"#;
}

pub mod constants {
    use super::*;

    {{#each protocol.constants as |constant| ~}}
    pub const {{sanitize_name constant.name}}: {{constant.type}} = {{constant.value}};
    {{/each ~}}
}

pub enum AMQPError {
    Soft(AMQPSoftError),
    Hard(AMQPHardError),
}

impl AMQPError {
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            AMQPError::Soft(ref s) => s.get_id(),
            AMQPError::Hard(ref h) => h.get_id(),
        }
    }

    pub fn from_id(id: ShortUInt) -> Option<AMQPError> {
        AMQPSoftError::from_id(id).map(|e| AMQPError::Soft(e)).or_else(|| AMQPHardError::from_id(id).map(|e| AMQPError::Hard(e)))
    }
}

pub enum AMQPSoftError {
    {{#each protocol.soft_errors as |constant| ~}}
    {{camel constant.name}},
    {{/each ~}}
}

impl AMQPSoftError {
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            {{#each protocol.soft_errors as |constant| ~}}
            AMQPSoftError::{{camel constant.name}} => {{constant.value}},
            {{/each ~}}
        }
    }

    pub fn from_id(id: ShortUInt) -> Option<AMQPSoftError> {
        match id {
            {{#each protocol.soft_errors as |constant| ~}}
            {{constant.value}} => Some(AMQPSoftError::{{camel constant.name}}),
            {{/each ~}}
            _                  => None,
        }
    }
}

pub enum AMQPHardError {
    {{#each protocol.hard_errors as |constant| ~}}
    {{camel constant.name}},
    {{/each ~}}
}

impl AMQPHardError {
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            {{#each protocol.hard_errors as |constant| ~}}
            AMQPHardError::{{camel constant.name}} => {{constant.value}},
            {{/each ~}}
        }
    }

    pub fn from_id(id: ShortUInt) -> Option<AMQPHardError> {
        match id {
            {{#each protocol.hard_errors as |constant| ~}}
            {{constant.value}} => Some(AMQPHardError::{{camel constant.name}}),
            {{/each ~}}
            _                  => None,
        }
    }
}

{{#each protocol.classes as |class| ~}}
use self::{{snake class.name}}::parse_{{snake class.name}};
{{/each ~}}

named!(pub parse_class<AMQPClass>, switch!(parse_id,
    {{#each protocol.classes as |class| ~}}
    {{class.id}} => map!(call!(parse_{{snake class.name}}), AMQPClass::{{camel class.name}}) {{#unless @last ~}}|{{/unless ~}}
    {{/each ~}}
));

pub fn gen_class<'a>(input: (&'a mut [u8], usize), class: &AMQPClass) -> Result<(&'a mut [u8], usize), GenError> {
    match *class {
        {{#each protocol.classes as |class| ~}}
        AMQPClass::{{camel class.name}}(ref {{snake class.name}}) => {{snake class.name}}::gen_{{snake class.name}}(input, {{snake class.name}}),
        {{/each ~}}
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum AMQPClass {
    {{#each protocol.classes as |class| ~}}
    {{camel class.name}}({{snake class.name}}::AMQPMethod),
    {{/each ~}}
}

{{#each protocol.classes as |class|}}
pub mod {{snake class.name}} {
    use super::*;

    named!(pub parse_{{snake class.name}}<{{snake class.name}}::AMQPMethod>, switch!(parse_id,
        {{#each class.methods as |method| ~}}
        {{method.id}} => map!(call!(parse_{{snake method.name}}), AMQPMethod::{{camel method.name}}) {{#unless @last ~}}|{{/unless ~}}
        {{/each ~}}
    ));

    pub fn gen_{{snake class.name}}<'a>(input: (&'a mut [u8], usize), method: &AMQPMethod) -> Result<(&'a mut [u8], usize), GenError> {
        match *method {
            {{#each class.methods as |method| ~}}
            AMQPMethod::{{camel method.name}}(ref {{snake method.name}}) => {
                do_gen!(input,
                    gen_id(&{{class.id}}) >>
                    gen_{{snake method.name}}({{snake method.name}})
                )
            },
            {{/each ~}}
        }
    }

    #[derive(Clone, Debug, PartialEq)]
    pub enum AMQPMethod {
        {{#each class.methods as |method| ~}}
        {{camel method.name}}({{camel method.name}}),
        {{/each ~}}
    }

    {{#each class.methods as |method|}}
    #[derive(Clone, Debug, PartialEq)]
    pub struct {{camel method.name}} {
        {{#each_argument method.arguments as |argument| ~}}
        {{#if argument_is_value ~}}
        pub {{snake argument.name}}: {{argument.type}},
        {{else}}
        {{#each_flag argument as |flag| ~}}
        pub {{snake flag.name}}: Boolean,
        {{/each_flag ~}}
        {{/if ~}}
        {{/each_argument ~}}
    }

    named!(pub parse_{{snake method.name}}<{{camel method.name}}>, do_parse!(
        {{#each_argument method.arguments as |argument| ~}}
        {{#if argument_is_value ~}}
        {{snake argument.name}}: parse_{{snake_type argument.type}} >>
        {{else}}
        /* FIXME: support multiple flags structs? */
        flags: apply!(parse_flags, &vec![
            {{#each_flag argument as |flag| ~}}
            "{{flag.name}}",
            {{/each_flag ~}}
        ]) >>
        {{/if ~}}
        {{/each_argument ~}}
        ({{camel method.name}} {
            {{#each_argument method.arguments as |argument| ~}}
            {{#if argument_is_value ~}}
            {{snake argument.name}}: {{snake argument.name}},
            {{else}}
            {{#each_flag argument as |flag| ~}}
            {{snake flag.name}}: flags.get_flag("{{snake flag.name}}").unwrap_or({{flag.default_value}}),
            {{/each_flag ~}}
            {{/if ~}}
            {{/each_argument ~}}
        })
    ));

    pub fn gen_{{snake method.name}}<'a>(input: (&'a mut [u8], usize), {{#if method.has_arguments ~}}method{{else}}_{{/if ~}}: &{{camel method.name}}) -> Result<(&'a mut [u8],usize), GenError> {
        {{#if method.has_flags ~}}
        /* FIXME: support multiple flags structs? */
        let mut flags = AMQPFlags::new();
        {{#each_argument method.arguments as |argument| ~}}
        {{#unless argument_is_value ~}}
        {{#each_flag argument as |flag| ~}}
        flags.add_flag("{{snake flag.name}}".to_string(), method.{{snake flag.name}});
        {{/each_flag ~}}
        {{/unless ~}}
        {{/each_argument ~}}
        {{/if ~}}
        do_gen!(input,
            gen_id(&{{method.id}})
            {{#each_argument method.arguments as |argument| ~}}
            {{#if argument_is_value ~}}
            >> gen_{{snake_type argument.type}}(&method.{{snake argument.name}})
            {{else}}
            >> gen_flags(&flags)
            {{/if ~}}
            {{/each_argument ~}}
        )
    }
    {{/each ~}}
    {{#if class.has_properties ~}}
    #[derive(Clone, Debug, PartialEq)]
    pub struct AMQPProperties {
        {{#each class.properties as |property| ~}}
        {{snake property.name}}: Option<{{property.type}}>,
        {{/each ~}}
    }

    impl Default for AMQPProperties {
        fn default() -> AMQPProperties {
            AMQPProperties {
                {{#each class.properties as |property| ~}}
                {{snake property.name}}: None,
                {{/each ~}}
            }
        }
    }

    impl AMQPProperties {
        {{#each class.properties as |property| ~}}
        pub fn with_{{snake property.name}}(mut self, value: {{property.type}}) -> AMQPProperties {
            self.{{snake property.name}} = Some(value);
            self
        }
        {{/each ~}}

        pub fn bitmask(&self) -> ShortUInt {
            {{#each class.properties as |property| ~}}
            (if self.{{snake property.name}}.is_some() { 1 << (15 - {{@index}}) } else { 0 }) {{#unless @last ~}} + {{/unless ~}}
            {{/each ~}}
        }
    }

    named!(pub parse_properties<AMQPProperties>, do_parse!(
        flags: parse_short_uint >>
        {{#each class.properties as |property| ~}}
        {{snake property.name}}: cond!(flags & (1 << (15 - {{@index}})) != 0, parse_{{snake_type property.type}}) >>
        {{/each ~}}
        (AMQPProperties {
            {{#each class.properties as |property| ~}}
            {{snake property.name}}: {{snake property.name}},
            {{/each ~}}
        })
    ));

    pub fn gen_properties<'a>(input:(&'a mut [u8],usize), props: &AMQPProperties) -> Result<(&'a mut [u8],usize),GenError> {
        do_gen!(input,
            gen_short_uint(&props.bitmask())
            {{#each class.properties as |property| ~}}
            >> gen_cond!(props.{{snake property.name}}.is_some(), gen_call!(gen_{{snake_type property.type}}, &props.{{snake property.name}}.as_ref().unwrap()))
            {{/each ~}}
        )
    }
    {{/if ~}}
}
{{/each ~}}
<|endoftext|>


<commit_before>// Type Names for Debug Info.

use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::{self, subst::SubstsRef, Ty, TyCtxt};

use std::fmt::Write;

// Compute the name of the type as it should be stored in debuginfo. Does not do
// any caching, i.e., calling the function twice with the same type will also do
// the work twice. The `qualified` parameter only affects the first level of the
// type name, further levels (i.e., type parameters) are always fully qualified.
pub fn compute_debuginfo_type_name<'tcx>(
    tcx: TyCtxt<'tcx>,
    t: Ty<'tcx>,
    qualified: bool,
) -> String {
    let mut result = String::with_capacity(64);
    let mut visited = FxHashSet::default();
    push_debuginfo_type_name(tcx, t, qualified, &mut result, &mut visited);
    result
}

// Pushes the name of the type as it should be stored in debuginfo on the
// `output` String. See also compute_debuginfo_type_name().
pub fn push_debuginfo_type_name<'tcx>(
    tcx: TyCtxt<'tcx>,
    t: Ty<'tcx>,
    qualified: bool,
    output: &mut String,
    visited: &mut FxHashSet<Ty<'tcx>>,
) {
    // When targeting MSVC, emit C++ style type names for compatibility with
    // .natvis visualizers (and perhaps other existing native debuggers?)
    let cpp_like_names = tcx.sess.target.is_like_msvc;

    match *t.kind() {
        ty::Bool => output.push_str("bool"),
        ty::Char => output.push_str("char"),
        ty::Str => output.push_str("str"),
        ty::Never => output.push('!'),
        ty::Int(int_ty) => output.push_str(int_ty.name_str()),
        ty::Uint(uint_ty) => output.push_str(uint_ty.name_str()),
        ty::Float(float_ty) => output.push_str(float_ty.name_str()),
        ty::Foreign(def_id) => push_item_name(tcx, def_id, qualified, output),
        ty::Adt(def, substs) => {
            push_item_name(tcx, def.did, qualified, output);
            push_type_params(tcx, substs, output, visited);
        }
        ty::Tuple(component_types) => {
            if cpp_like_names {
                output.push_str("tuple<");
            } else {
                output.push('(');
            }

            for component_type in component_types {
                push_debuginfo_type_name(tcx, component_type.expect_ty(), true, output, visited);
                output.push_str(", ");
            }
            if !component_types.is_empty() {
                output.pop();
                output.pop();
            }

            if cpp_like_names {
                output.push('>');
            } else {
                output.push(')');
            }
        }
        ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => {
            if !cpp_like_names {
                output.push('*');
            }
            match mutbl {
                hir::Mutability::Not => output.push_str("const "),
                hir::Mutability::Mut => output.push_str("mut "),
            }

            push_debuginfo_type_name(tcx, inner_type, true, output, visited);

            if cpp_like_names {
                output.push('*');
            }
        }
        ty::Ref(_, inner_type, mutbl) => {
            if !cpp_like_names {
                output.push('&');
            }
            output.push_str(mutbl.prefix_str());

            push_debuginfo_type_name(tcx, inner_type, true, output, visited);

            if cpp_like_names {
                output.push('*');
            }
        }
        ty::Array(inner_type, len) => {
            output.push('[');
            push_debuginfo_type_name(tcx, inner_type, true, output, visited);
            output.push_str(&format!("; {}", len.eval_usize(tcx, ty::ParamEnv::reveal_all())));
            output.push(']');
        }
        ty::Slice(inner_type) => {
            if cpp_like_names {
                output.push_str("slice<");
            } else {
                output.push('[');
            }

            push_debuginfo_type_name(tcx, inner_type, true, output, visited);

            if cpp_like_names {
                output.push('>');
            } else {
                output.push(']');
            }
        }
        ty::Dynamic(ref trait_data, ..) => {
            if let Some(principal) = trait_data.principal() {
                let principal =
                    tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), principal);
                push_item_name(tcx, principal.def_id, false, output);
                push_type_params(tcx, principal.substs, output, visited);
            } else {
                output.push_str("dyn '_");
            }
        }
        ty::FnDef(..) | ty::FnPtr(_) => {
            // We've encountered a weird 'recursive type'
            // Currently, the only way to generate such a type
            // is by using 'impl trait':
            //
            // fn foo() -> impl Copy { foo }
            //
            // There's not really a sensible name we can generate,
            // since we don't include 'impl trait' types (e.g. ty::Opaque)
            // in the output
            //
            // Since we need to generate *something*, we just
            // use a dummy string that should make it clear
            // that something unusual is going on
            if !visited.insert(t) {
                output.push_str("<recursive_type>");
                return;
            }

            let sig = t.fn_sig(tcx);
            output.push_str(sig.unsafety().prefix_str());

            let abi = sig.abi();
            if abi != rustc_target::spec::abi::Abi::Rust {
                output.push_str("extern \"");
                output.push_str(abi.name());
                output.push_str("\" ");
            }

            output.push_str("fn(");

            let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig);
            if !sig.inputs().is_empty() {
                for &parameter_type in sig.inputs() {
                    push_debuginfo_type_name(tcx, parameter_type, true, output, visited);
                    output.push_str(", ");
                }
                output.pop();
                output.pop();
            }

            if sig.c_variadic {
                if !sig.inputs().is_empty() {
                    output.push_str(", ...");
                } else {
                    output.push_str("...");
                }
            }

            output.push(')');

            if !sig.output().is_unit() {
                output.push_str(" -> ");
                push_debuginfo_type_name(tcx, sig.output(), true, output, visited);
            }

            // We only keep the type in 'visited'
            // for the duration of the body of this method.
            // It's fine for a particular function type
            // to show up multiple times in one overall type
            // (e.g. MyType<fn() -> u8, fn() -> u8>
            //
            // We only care about avoiding recursing
            // directly back to the type we're currently
            // processing
            visited.remove(t);
        }
        ty::Closure(def_id, ..) => {
            output.push_str(&format!(
                "closure-{}",
                tcx.def_key(def_id).disambiguated_data.disambiguator
            ));
        }
        ty::Generator(def_id, ..) => {
            output.push_str(&format!(
                "generator-{}",
                tcx.def_key(def_id).disambiguated_data.disambiguator
            ));
        }
        // Type parameters from polymorphized functions.
        ty::Param(_) => {
            output.push_str(&format!("{:?}", t));
        }
        ty::Error(_)
        | ty::Infer(_)
        | ty::Placeholder(..)
        | ty::Projection(..)
        | ty::Bound(..)
        | ty::Opaque(..)
        | ty::GeneratorWitness(..) => {
            bug!(
                "debuginfo: Trying to create type name for \
                  unexpected type: {:?}",
                t
            );
        }
    }

    fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) {
        if qualified {
            output.push_str(&tcx.crate_name(def_id.krate).as_str());
            for path_element in tcx.def_path(def_id).data {
                write!(output, "::{}", path_element.data).unwrap();
            }
        } else {
            output.push_str(&tcx.item_name(def_id).as_str());
        }
    }

    // Pushes the type parameters in the given `InternalSubsts` to the output string.
    // This ignores region parameters, since they can't reliably be
    // reconstructed for items from non-local crates. For local crates, this
    // would be possible but with inlining and LTO we have to use the least
    // common denominator - otherwise we would run into conflicts.
    fn push_type_params<'tcx>(
        tcx: TyCtxt<'tcx>,
        substs: SubstsRef<'tcx>,
        output: &mut String,
        visited: &mut FxHashSet<Ty<'tcx>>,
    ) {
        if substs.types().next().is_none() {
            return;
        }

        output.push('<');

        for type_parameter in substs.types() {
            push_debuginfo_type_name(tcx, type_parameter, true, output, visited);
            output.push_str(", ");
        }

        output.pop();
        output.pop();

        output.push('>');
    }
}
<commit_msg>Rollup merge of #79184 - nanguye2496:nanguye2496/fix_slice_and_str_type_name, r=varkor<commit_after>// Type Names for Debug Info.

use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::{self, subst::SubstsRef, Ty, TyCtxt};

use std::fmt::Write;

// Compute the name of the type as it should be stored in debuginfo. Does not do
// any caching, i.e., calling the function twice with the same type will also do
// the work twice. The `qualified` parameter only affects the first level of the
// type name, further levels (i.e., type parameters) are always fully qualified.
pub fn compute_debuginfo_type_name<'tcx>(
    tcx: TyCtxt<'tcx>,
    t: Ty<'tcx>,
    qualified: bool,
) -> String {
    let mut result = String::with_capacity(64);
    let mut visited = FxHashSet::default();
    push_debuginfo_type_name(tcx, t, qualified, &mut result, &mut visited);
    result
}

// Pushes the name of the type as it should be stored in debuginfo on the
// `output` String. See also compute_debuginfo_type_name().
pub fn push_debuginfo_type_name<'tcx>(
    tcx: TyCtxt<'tcx>,
    t: Ty<'tcx>,
    qualified: bool,
    output: &mut String,
    visited: &mut FxHashSet<Ty<'tcx>>,
) {
    // When targeting MSVC, emit C++ style type names for compatibility with
    // .natvis visualizers (and perhaps other existing native debuggers?)
    let cpp_like_names = tcx.sess.target.is_like_msvc;

    match *t.kind() {
        ty::Bool => output.push_str("bool"),
        ty::Char => output.push_str("char"),
        ty::Str => output.push_str("str"),
        ty::Never => output.push('!'),
        ty::Int(int_ty) => output.push_str(int_ty.name_str()),
        ty::Uint(uint_ty) => output.push_str(uint_ty.name_str()),
        ty::Float(float_ty) => output.push_str(float_ty.name_str()),
        ty::Foreign(def_id) => push_item_name(tcx, def_id, qualified, output),
        ty::Adt(def, substs) => {
            push_item_name(tcx, def.did, qualified, output);
            push_type_params(tcx, substs, output, visited);
        }
        ty::Tuple(component_types) => {
            if cpp_like_names {
                output.push_str("tuple<");
            } else {
                output.push('(');
            }

            for component_type in component_types {
                push_debuginfo_type_name(tcx, component_type.expect_ty(), true, output, visited);
                output.push_str(", ");
            }
            if !component_types.is_empty() {
                output.pop();
                output.pop();
            }

            if cpp_like_names {
                output.push('>');
            } else {
                output.push(')');
            }
        }
        ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => {
            if !cpp_like_names {
                output.push('*');
            }
            match mutbl {
                hir::Mutability::Not => output.push_str("const "),
                hir::Mutability::Mut => output.push_str("mut "),
            }

            push_debuginfo_type_name(tcx, inner_type, true, output, visited);

            if cpp_like_names {
                output.push('*');
            }
        }
        ty::Ref(_, inner_type, mutbl) => {
            if !cpp_like_names {
                output.push('&');
            }
            output.push_str(mutbl.prefix_str());

            push_debuginfo_type_name(tcx, inner_type, true, output, visited);

            if cpp_like_names {
                // Slices and `&str` are treated like C++ pointers when computing debug
                // info for MSVC debugger. However, adding '*' at the end of these types' names
                // causes the .natvis engine for WinDbg to fail to display their data, so we opt these
                // types out to aid debugging in MSVC.
                match *inner_type.kind() {
                    ty::Slice(_) | ty::Str => {}
                    _ => output.push('*'),
                }
            }
        }
        ty::Array(inner_type, len) => {
            output.push('[');
            push_debuginfo_type_name(tcx, inner_type, true, output, visited);
            output.push_str(&format!("; {}", len.eval_usize(tcx, ty::ParamEnv::reveal_all())));
            output.push(']');
        }
        ty::Slice(inner_type) => {
            if cpp_like_names {
                output.push_str("slice<");
            } else {
                output.push('[');
            }

            push_debuginfo_type_name(tcx, inner_type, true, output, visited);

            if cpp_like_names {
                output.push('>');
            } else {
                output.push(']');
            }
        }
        ty::Dynamic(ref trait_data, ..) => {
            if let Some(principal) = trait_data.principal() {
                let principal =
                    tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), principal);
                push_item_name(tcx, principal.def_id, false, output);
                push_type_params(tcx, principal.substs, output, visited);
            } else {
                output.push_str("dyn '_");
            }
        }
        ty::FnDef(..) | ty::FnPtr(_) => {
            // We've encountered a weird 'recursive type'
            // Currently, the only way to generate such a type
            // is by using 'impl trait':
            //
            // fn foo() -> impl Copy { foo }
            //
            // There's not really a sensible name we can generate,
            // since we don't include 'impl trait' types (e.g. ty::Opaque)
            // in the output
            //
            // Since we need to generate *something*, we just
            // use a dummy string that should make it clear
            // that something unusual is going on
            if !visited.insert(t) {
                output.push_str("<recursive_type>");
                return;
            }

            let sig = t.fn_sig(tcx);
            output.push_str(sig.unsafety().prefix_str());

            let abi = sig.abi();
            if abi != rustc_target::spec::abi::Abi::Rust {
                output.push_str("extern \"");
                output.push_str(abi.name());
                output.push_str("\" ");
            }

            output.push_str("fn(");

            let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig);
            if !sig.inputs().is_empty() {
                for &parameter_type in sig.inputs() {
                    push_debuginfo_type_name(tcx, parameter_type, true, output, visited);
                    output.push_str(", ");
                }
                output.pop();
                output.pop();
            }

            if sig.c_variadic {
                if !sig.inputs().is_empty() {
                    output.push_str(", ...");
                } else {
                    output.push_str("...");
                }
            }

            output.push(')');

            if !sig.output().is_unit() {
                output.push_str(" -> ");
                push_debuginfo_type_name(tcx, sig.output(), true, output, visited);
            }

            // We only keep the type in 'visited'
            // for the duration of the body of this method.
            // It's fine for a particular function type
            // to show up multiple times in one overall type
            // (e.g. MyType<fn() -> u8, fn() -> u8>
            //
            // We only care about avoiding recursing
            // directly back to the type we're currently
            // processing
            visited.remove(t);
        }
        ty::Closure(def_id, ..) => {
            output.push_str(&format!(
                "closure-{}",
                tcx.def_key(def_id).disambiguated_data.disambiguator
            ));
        }
        ty::Generator(def_id, ..) => {
            output.push_str(&format!(
                "generator-{}",
                tcx.def_key(def_id).disambiguated_data.disambiguator
            ));
        }
        // Type parameters from polymorphized functions.
        ty::Param(_) => {
            output.push_str(&format!("{:?}", t));
        }
        ty::Error(_)
        | ty::Infer(_)
        | ty::Placeholder(..)
        | ty::Projection(..)
        | ty::Bound(..)
        | ty::Opaque(..)
        | ty::GeneratorWitness(..) => {
            bug!(
                "debuginfo: Trying to create type name for \
                  unexpected type: {:?}",
                t
            );
        }
    }

    fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) {
        if qualified {
            output.push_str(&tcx.crate_name(def_id.krate).as_str());
            for path_element in tcx.def_path(def_id).data {
                write!(output, "::{}", path_element.data).unwrap();
            }
        } else {
            output.push_str(&tcx.item_name(def_id).as_str());
        }
    }

    // Pushes the type parameters in the given `InternalSubsts` to the output string.
    // This ignores region parameters, since they can't reliably be
    // reconstructed for items from non-local crates. For local crates, this
    // would be possible but with inlining and LTO we have to use the least
    // common denominator - otherwise we would run into conflicts.
    fn push_type_params<'tcx>(
        tcx: TyCtxt<'tcx>,
        substs: SubstsRef<'tcx>,
        output: &mut String,
        visited: &mut FxHashSet<Ty<'tcx>>,
    ) {
        if substs.types().next().is_none() {
            return;
        }

        output.push('<');

        for type_parameter in substs.types() {
            push_debuginfo_type_name(tcx, type_parameter, true, output, visited);
            output.push_str(", ");
        }

        output.pop();
        output.pop();

        output.push('>');
    }
}
<|endoftext|>


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

use std::ffi::OsString;

use common::ui::UI;

use error::Result;

pub fn start(
    ui: &mut UI,
    args: Vec<OsString>,
    export_cmd: &str,
    export_cmd_envvar: &str,
    export_pkg_ident: &str,
    export_pkg_ident_envvar: &str,
) -> Result<()> {
    inner::start(
        ui,
        args,
        export_cmd,
        export_cmd_envvar,
        export_pkg_ident,
        export_pkg_ident_envvar,
    )
}

#[cfg(target_os = "linux")]
mod inner {
    use std::ffi::OsString;
    use std::path::PathBuf;
    use std::str::FromStr;

    use common::ui::UI;
    use hcore::crypto::{init, default_cache_key_path};
    use hcore::env as henv;
    use hcore::fs::find_command;
    use hcore::os::process;
    use hcore::package::PackageIdent;

    use error::{Error, Result};
    use exec;
    use VERSION;

    pub fn start(
        ui: &mut UI,
        args: Vec<OsString>,
        export_cmd: &str,
        export_cmd_envvar: &str,
        export_pkg_ident: &str,
        export_pkg_ident_envvar: &str,
    ) -> Result<()> {
        let command = match henv::var(export_cmd_envvar) {
            Ok(command) => PathBuf::from(command),
            Err(_) => {
                init();
                let ident = match henv::var(export_pkg_ident_envvar) {
                    Ok(ref ident_str) => PackageIdent::from_str(ident_str)?,
                    Err(_) => {
                        let version: Vec<&str> = VERSION.split("/").collect();
                        PackageIdent::from_str(&format!("{}/{}", export_pkg_ident, version[0]))?
                    }
                };
                let cmd = exec::command_from_min_pkg(
                    ui,
                    export_cmd,
                    &ident,
                    &default_cache_key_path(None),
                    0,
                )?;
                PathBuf::from(cmd)
            }
        };
        if let Some(cmd) = find_command(&command) {
            Ok(process::become_command(cmd, args)?)
        } else {
            Err(Error::ExecCommandNotFound(command))
        }
    }
}

#[cfg(not(target_os = "linux"))]
mod inner {
    use std::ffi::OsString;

    use common::ui::UI;

    use error::{Error, Result};

    pub fn start(
        ui: &mut UI,
        args: Vec<OsString>,
        export_cmd: &str,
        export_cmd_envvar: &str,
        export_pkg_ident: &str,
        export_pkg_ident_envvar: &str,
    ) -> Result<()> {
        let cmd = export_cmd.replace("hab", "").replace("-", " ");
        ui.warn(format!(
            "Running 'hab {}' on this operating system is not yet supported. \
            Try running this command again on 64-bit Linux.",
            &cmd
        ))?;
        ui.br()?;
        Err(Error::SubcommandNotSupported(cmd.to_string()))
    }
}
<commit_msg>fix regression breaking docker exporter on windows<commit_after>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ffi::OsString;

use common::ui::UI;

use error::Result;

pub fn start(
    ui: &mut UI,
    args: Vec<OsString>,
    export_cmd: &str,
    export_cmd_envvar: &str,
    export_pkg_ident: &str,
    export_pkg_ident_envvar: &str,
) -> Result<()> {
    inner::start(
        ui,
        args,
        export_cmd,
        export_cmd_envvar,
        export_pkg_ident,
        export_pkg_ident_envvar,
    )
}

#[cfg(not(target_os = "macos"))]
mod inner {
    use std::ffi::OsString;
    use std::path::PathBuf;
    use std::str::FromStr;

    use common::ui::UI;
    use hcore::crypto::{init, default_cache_key_path};
    use hcore::env as henv;
    use hcore::fs::find_command;
    use hcore::os::process;
    use hcore::package::PackageIdent;

    use error::{Error, Result};
    use exec;
    use VERSION;

    pub fn start(
        ui: &mut UI,
        args: Vec<OsString>,
        export_cmd: &str,
        export_cmd_envvar: &str,
        export_pkg_ident: &str,
        export_pkg_ident_envvar: &str,
    ) -> Result<()> {
        let command = match henv::var(export_cmd_envvar) {
            Ok(command) => PathBuf::from(command),
            Err(_) => {
                init();
                let ident = match henv::var(export_pkg_ident_envvar) {
                    Ok(ref ident_str) => PackageIdent::from_str(ident_str)?,
                    Err(_) => {
                        let version: Vec<&str> = VERSION.split("/").collect();
                        PackageIdent::from_str(&format!("{}/{}", export_pkg_ident, version[0]))?
                    }
                };
                let cmd = exec::command_from_min_pkg(
                    ui,
                    export_cmd,
                    &ident,
                    &default_cache_key_path(None),
                    0,
                )?;
                PathBuf::from(cmd)
            }
        };
        if let Some(cmd) = find_command(&command) {
            Ok(process::become_command(cmd, args)?)
        } else {
            Err(Error::ExecCommandNotFound(command))
        }
    }
}

#[cfg(target_os = "macos")]
mod inner {
    use std::ffi::OsString;

    use common::ui::UI;

    use error::{Error, Result};

    pub fn start(
        ui: &mut UI,
        args: Vec<OsString>,
        export_cmd: &str,
        export_cmd_envvar: &str,
        export_pkg_ident: &str,
        export_pkg_ident_envvar: &str,
    ) -> Result<()> {
        let cmd = export_cmd.replace("hab", "").replace("-", " ");
        ui.warn(format!(
            "Running 'hab {}' on this operating system is not yet supported. \
            Try running this command again on 64-bit Linux.",
            &cmd
        ))?;
        ui.br()?;
        Err(Error::SubcommandNotSupported(cmd.to_string()))
    }
}
<|endoftext|>


<commit_before>use crate::types::atom;
use crate::{Decoder, Encoder, Env, Error, NifResult, Term};

macro_rules! impl_number_transcoder {
    ($dec_type:ty, $nif_type:ty, $encode_fun:ident, $decode_fun:ident) => {
        impl Encoder for $dec_type {
            fn encode<'a>(&self, env: Env<'a>) -> Term<'a> {
                #[allow(clippy::cast_lossless)]
                unsafe {
                    Term::new(
                        env,
                        rustler_sys::$encode_fun(env.as_c_arg(), *self as $nif_type),
                    )
                }
            }
        }
        impl<'a> Decoder<'a> for $dec_type {
            fn decode(term: Term) -> NifResult<$dec_type> {
                #![allow(unused_unsafe)]
                let mut res: $nif_type = Default::default();
                if unsafe {
                    rustler_sys::$decode_fun(term.get_env().as_c_arg(), term.as_c_arg(), &mut res)
                } == 0
                {
                    return Err(Error::BadArg);
                }
                Ok(res as $dec_type)
            }
        }
    };
}

// Base number types
impl_number_transcoder!(i32, i32, enif_make_int, enif_get_int);
impl_number_transcoder!(u32, u32, enif_make_uint, enif_get_uint);
impl_number_transcoder!(i64, i64, enif_make_int64, enif_get_int64);
impl_number_transcoder!(u64, u64, enif_make_uint64, enif_get_uint64);
impl_number_transcoder!(f64, f64, enif_make_double, enif_get_double);

// Casted number types
impl_number_transcoder!(i8, i32, enif_make_int, enif_get_int);
impl_number_transcoder!(u8, u32, enif_make_uint, enif_get_uint);
impl_number_transcoder!(i16, i32, enif_make_int, enif_get_int);
impl_number_transcoder!(u16, u32, enif_make_uint, enif_get_uint);
impl_number_transcoder!(usize, u64, enif_make_uint64, enif_get_uint64);
impl_number_transcoder!(isize, i64, enif_make_int64, enif_get_int64);

impl Encoder for bool {
    fn encode<'a>(&self, env: Env<'a>) -> Term<'a> {
        if *self {
            atom::true_().to_term(env)
        } else {
            atom::false_().to_term(env)
        }
    }
}
impl<'a> Decoder<'a> for bool {
    fn decode(term: Term<'a>) -> NifResult<bool> {
        atom::decode_bool(term)
    }
}

impl Encoder for f32 {
    fn encode<'a>(&self, env: Env<'a>) -> Term<'a> {
        #[allow(clippy::cast_lossless)]
        unsafe {
            Term::new(
                env,
                rustler_sys::enif_make_double(env.as_c_arg(), *self as f64),
            )
        }
    }
}
impl<'a> Decoder<'a> for f32 {
    fn decode(term: Term) -> NifResult<f32> {
        #![allow(unused_unsafe)]
        let mut res: f64 = Default::default();
        if unsafe {
            rustler_sys::enif_get_double(term.get_env().as_c_arg(), term.as_c_arg(), &mut res)
        } == 0
        {
            return Err(Error::BadArg);
        }
        let res = res as f32;
        // Values bigger then f32 are coerced as infinity
        if res.is_finite() {
            Ok(res)
        } else {
            Err(Error::BadArg)
        }
    }
}
<commit_msg>Removing unsafe with reusing existing f64 functions<commit_after>use crate::types::atom;
use crate::{Decoder, Encoder, Env, Error, NifResult, Term};

macro_rules! impl_number_transcoder {
    ($dec_type:ty, $nif_type:ty, $encode_fun:ident, $decode_fun:ident) => {
        impl Encoder for $dec_type {
            fn encode<'a>(&self, env: Env<'a>) -> Term<'a> {
                #[allow(clippy::cast_lossless)]
                unsafe {
                    Term::new(
                        env,
                        rustler_sys::$encode_fun(env.as_c_arg(), *self as $nif_type),
                    )
                }
            }
        }
        impl<'a> Decoder<'a> for $dec_type {
            fn decode(term: Term) -> NifResult<$dec_type> {
                #![allow(unused_unsafe)]
                let mut res: $nif_type = Default::default();
                if unsafe {
                    rustler_sys::$decode_fun(term.get_env().as_c_arg(), term.as_c_arg(), &mut res)
                } == 0
                {
                    return Err(Error::BadArg);
                }
                Ok(res as $dec_type)
            }
        }
    };
}

// Base number types
impl_number_transcoder!(i32, i32, enif_make_int, enif_get_int);
impl_number_transcoder!(u32, u32, enif_make_uint, enif_get_uint);
impl_number_transcoder!(i64, i64, enif_make_int64, enif_get_int64);
impl_number_transcoder!(u64, u64, enif_make_uint64, enif_get_uint64);
impl_number_transcoder!(f64, f64, enif_make_double, enif_get_double);

// Casted number types
impl_number_transcoder!(i8, i32, enif_make_int, enif_get_int);
impl_number_transcoder!(u8, u32, enif_make_uint, enif_get_uint);
impl_number_transcoder!(i16, i32, enif_make_int, enif_get_int);
impl_number_transcoder!(u16, u32, enif_make_uint, enif_get_uint);
impl_number_transcoder!(usize, u64, enif_make_uint64, enif_get_uint64);
impl_number_transcoder!(isize, i64, enif_make_int64, enif_get_int64);

impl Encoder for bool {
    fn encode<'a>(&self, env: Env<'a>) -> Term<'a> {
        if *self {
            atom::true_().to_term(env)
        } else {
            atom::false_().to_term(env)
        }
    }
}
impl<'a> Decoder<'a> for bool {
    fn decode(term: Term<'a>) -> NifResult<bool> {
        atom::decode_bool(term)
    }
}

impl Encoder for f32 {
    fn encode<'a>(&self, env: Env<'a>) -> Term<'a> {
        f64::from(*self).encode(env)
    }
}
impl<'a> Decoder<'a> for f32 {
    fn decode(term: Term) -> NifResult<f32> {
        let res: f64 = term.decode()?;
        let res = res as f32;
        // Values bigger than f32 are coerced as infinity
        if res.is_finite() {
            Ok(res)
        } else {
            Err(Error::BadArg)
        }
    }
}
<|endoftext|>


<commit_before>use crate::fbo::{self, ValidatedAttachments};

use crate::context::Context;
use crate::ContextExt;
use crate::Rect;

use crate::QueryExt;
use crate::draw_parameters::TimeElapsedQuery;

use crate::Api;
use crate::version::Version;
use crate::gl;

pub fn clear(context: &Context, framebuffer: Option<&ValidatedAttachments<'_>>,
             rect: Option<&Rect>, color: Option<(f32, f32, f32, f32)>, color_srgb: bool,
             depth: Option<f32>, stencil: Option<i32>)
{
    unsafe {
        let mut ctxt = context.make_current();

        let fbo_id = fbo::FramebuffersContainer::get_framebuffer_for_drawing(&mut ctxt, framebuffer);
        fbo::bind_framebuffer(&mut ctxt, fbo_id, true, false);

        if ctxt.state.enabled_rasterizer_discard {
            ctxt.gl.Disable(gl::RASTERIZER_DISCARD);
            ctxt.state.enabled_rasterizer_discard = false;
        }

        if ctxt.state.color_mask != (1, 1, 1, 1) {
            ctxt.state.color_mask = (1, 1, 1, 1);
            ctxt.gl.ColorMask(1, 1, 1, 1);
        }

        if ctxt.version >= &Version(Api::Gl, 3, 0) || ctxt.extensions.gl_arb_framebuffer_srgb ||
           ctxt.extensions.gl_ext_framebuffer_srgb || ctxt.extensions.gl_ext_srgb_write_control
        {
            if !color_srgb && !ctxt.state.enabled_framebuffer_srgb {
                ctxt.gl.Enable(gl::FRAMEBUFFER_SRGB);
                ctxt.state.enabled_framebuffer_srgb = true;

            } else if color_srgb && ctxt.state.enabled_framebuffer_srgb {
                ctxt.gl.Disable(gl::FRAMEBUFFER_SRGB);
                ctxt.state.enabled_framebuffer_srgb = false;
            }
        }

        TimeElapsedQuery::end_conditional_render(&mut ctxt);

        if let Some(rect) = rect {
            let rect = (rect.left as gl::types::GLint, rect.bottom as gl::types::GLint,
                        rect.width as gl::types::GLsizei, rect.height as gl::types::GLsizei);

            if ctxt.state.scissor != Some(rect) {
                ctxt.gl.Scissor(rect.0, rect.1, rect.2, rect.3);
                ctxt.state.scissor = Some(rect);
            }

            if !ctxt.state.enabled_scissor_test {
                ctxt.gl.Enable(gl::SCISSOR_TEST);
                ctxt.state.enabled_scissor_test = true;
            }

        } else if ctxt.state.enabled_scissor_test {
            ctxt.gl.Disable(gl::SCISSOR_TEST);
            ctxt.state.enabled_scissor_test = false;
        }

        let mut flags = 0;

        if let Some(color) = color {
            let color = (color.0 as gl::types::GLclampf, color.1 as gl::types::GLclampf,
                         color.2 as gl::types::GLclampf, color.3 as gl::types::GLclampf);

            flags |= gl::COLOR_BUFFER_BIT;

            if ctxt.state.clear_color != color {
                ctxt.gl.ClearColor(color.0, color.1, color.2, color.3);
                ctxt.state.clear_color = color;
            }
        }

        if let Some(depth) = depth {
            let depth = depth as gl::types::GLclampf;

            flags |= gl::DEPTH_BUFFER_BIT;

            if ctxt.state.clear_depth != depth {
                if ctxt.version >= &Version(Api::Gl, 1, 0) {
                    ctxt.gl.ClearDepth(depth as gl::types::GLclampd);
                } else if ctxt.version >= &Version(Api::GlEs, 2, 0) {
                    ctxt.gl.ClearDepthf(depth);
                } else {
                    unreachable!();
                }

                ctxt.state.clear_depth = depth;
            }

            if !ctxt.state.depth_mask {
                ctxt.gl.DepthMask(gl::TRUE);
                ctxt.state.depth_mask = true;
            }
        }

        if let Some(stencil) = stencil {
            let stencil = stencil as gl::types::GLint;

            flags |= gl::STENCIL_BUFFER_BIT;

            if ctxt.state.clear_stencil != stencil {
                ctxt.gl.ClearStencil(stencil);
                ctxt.state.clear_stencil = stencil;
            }
        }

        ctxt.gl.Clear(flags);
    }
}
<commit_msg>sRGB clear color logic fix<commit_after>use crate::fbo::{self, ValidatedAttachments};

use crate::context::Context;
use crate::ContextExt;
use crate::Rect;

use crate::QueryExt;
use crate::draw_parameters::TimeElapsedQuery;

use crate::Api;
use crate::version::Version;
use crate::gl;

pub fn clear(context: &Context, framebuffer: Option<&ValidatedAttachments<'_>>,
             rect: Option<&Rect>, color: Option<(f32, f32, f32, f32)>, color_srgb: bool,
             depth: Option<f32>, stencil: Option<i32>)
{
    unsafe {
        let mut ctxt = context.make_current();

        let fbo_id = fbo::FramebuffersContainer::get_framebuffer_for_drawing(&mut ctxt, framebuffer);
        fbo::bind_framebuffer(&mut ctxt, fbo_id, true, false);

        if ctxt.state.enabled_rasterizer_discard {
            ctxt.gl.Disable(gl::RASTERIZER_DISCARD);
            ctxt.state.enabled_rasterizer_discard = false;
        }

        if ctxt.state.color_mask != (1, 1, 1, 1) {
            ctxt.state.color_mask = (1, 1, 1, 1);
            ctxt.gl.ColorMask(1, 1, 1, 1);
        }

        if ctxt.version >= &Version(Api::Gl, 3, 0) || ctxt.extensions.gl_arb_framebuffer_srgb ||
           ctxt.extensions.gl_ext_framebuffer_srgb || ctxt.extensions.gl_ext_srgb_write_control
        {
            if color_srgb && !ctxt.state.enabled_framebuffer_srgb {
                ctxt.gl.Enable(gl::FRAMEBUFFER_SRGB);
                ctxt.state.enabled_framebuffer_srgb = true;

            } else if !color_srgb && ctxt.state.enabled_framebuffer_srgb {
                ctxt.gl.Disable(gl::FRAMEBUFFER_SRGB);
                ctxt.state.enabled_framebuffer_srgb = false;
            }
        }

        TimeElapsedQuery::end_conditional_render(&mut ctxt);

        if let Some(rect) = rect {
            let rect = (rect.left as gl::types::GLint, rect.bottom as gl::types::GLint,
                        rect.width as gl::types::GLsizei, rect.height as gl::types::GLsizei);

            if ctxt.state.scissor != Some(rect) {
                ctxt.gl.Scissor(rect.0, rect.1, rect.2, rect.3);
                ctxt.state.scissor = Some(rect);
            }

            if !ctxt.state.enabled_scissor_test {
                ctxt.gl.Enable(gl::SCISSOR_TEST);
                ctxt.state.enabled_scissor_test = true;
            }

        } else if ctxt.state.enabled_scissor_test {
            ctxt.gl.Disable(gl::SCISSOR_TEST);
            ctxt.state.enabled_scissor_test = false;
        }

        let mut flags = 0;

        if let Some(color) = color {
            let color = (color.0 as gl::types::GLclampf, color.1 as gl::types::GLclampf,
                         color.2 as gl::types::GLclampf, color.3 as gl::types::GLclampf);

            flags |= gl::COLOR_BUFFER_BIT;

            if ctxt.state.clear_color != color {
                ctxt.gl.ClearColor(color.0, color.1, color.2, color.3);
                ctxt.state.clear_color = color;
            }
        }

        if let Some(depth) = depth {
            let depth = depth as gl::types::GLclampf;

            flags |= gl::DEPTH_BUFFER_BIT;

            if ctxt.state.clear_depth != depth {
                if ctxt.version >= &Version(Api::Gl, 1, 0) {
                    ctxt.gl.ClearDepth(depth as gl::types::GLclampd);
                } else if ctxt.version >= &Version(Api::GlEs, 2, 0) {
                    ctxt.gl.ClearDepthf(depth);
                } else {
                    unreachable!();
                }

                ctxt.state.clear_depth = depth;
            }

            if !ctxt.state.depth_mask {
                ctxt.gl.DepthMask(gl::TRUE);
                ctxt.state.depth_mask = true;
            }
        }

        if let Some(stencil) = stencil {
            let stencil = stencil as gl::types::GLint;

            flags |= gl::STENCIL_BUFFER_BIT;

            if ctxt.state.clear_stencil != stencil {
                ctxt.gl.ClearStencil(stencil);
                ctxt.state.clear_stencil = stencil;
            }
        }

        ctxt.gl.Clear(flags);
    }
}
<|endoftext|>