<commit_before>use crate::intrinsics;
use crate::iter::{
    DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator, TrustedRandomAccess,
};
use crate::ops::Try;

/// An iterator that yields `None` forever after the underlying iterator
/// yields `None` once.
///
/// This `struct` is created by the [`fuse`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`fuse`]: trait.Iterator.html#method.fuse
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Fuse<I> {
    // NOTE: for `I: FusedIterator`, this is always assumed `Some`!
    iter: Option<I>,
}
impl<I> Fuse<I> {
    pub(in crate::iter) fn new(iter: I) -> Fuse<I> {
        Fuse { iter: Some(iter) }
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<I> FusedIterator for Fuse<I> where I: Iterator {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I> Iterator for Fuse<I>
where
    I: Iterator,
{
    type Item = <I as Iterator>::Item;

    #[inline]
    default fn next(&mut self) -> Option<<I as Iterator>::Item> {
        let next = self.iter.as_mut()?.next();
        if next.is_none() {
            self.iter = None;
        }
        next
    }

    #[inline]
    default fn nth(&mut self, n: usize) -> Option<I::Item> {
        let nth = self.iter.as_mut()?.nth(n);
        if nth.is_none() {
            self.iter = None;
        }
        nth
    }

    #[inline]
    default fn last(self) -> Option<I::Item> {
        self.iter?.last()
    }

    #[inline]
    default fn count(self) -> usize {
        self.iter.map_or(0, I::count)
    }

    #[inline]
    default fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.as_ref().map_or((0, Some(0)), I::size_hint)
    }

    #[inline]
    default fn try_fold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        if let Some(ref mut iter) = self.iter {
            acc = iter.try_fold(acc, fold)?;
            self.iter = None;
        }
        Try::from_ok(acc)
    }

    #[inline]
    default fn fold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        if let Some(iter) = self.iter {
            acc = iter.fold(acc, fold);
        }
        acc
    }

    #[inline]
    default fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        let found = self.iter.as_mut()?.find(predicate);
        if found.is_none() {
            self.iter = None;
        }
        found
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I> DoubleEndedIterator for Fuse<I>
where
    I: DoubleEndedIterator,
{
    #[inline]
    default fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
        let next = self.iter.as_mut()?.next_back();
        if next.is_none() {
            self.iter = None;
        }
        next
    }

    #[inline]
    default fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
        let nth = self.iter.as_mut()?.nth_back(n);
        if nth.is_none() {
            self.iter = None;
        }
        nth
    }

    #[inline]
    default fn try_rfold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        if let Some(ref mut iter) = self.iter {
            acc = iter.try_rfold(acc, fold)?;
            self.iter = None;
        }
        Try::from_ok(acc)
    }

    #[inline]
    default fn rfold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        if let Some(iter) = self.iter {
            acc = iter.rfold(acc, fold);
        }
        acc
    }

    #[inline]
    default fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        let found = self.iter.as_mut()?.rfind(predicate);
        if found.is_none() {
            self.iter = None;
        }
        found
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I> ExactSizeIterator for Fuse<I>
where
    I: ExactSizeIterator,
{
    default fn len(&self) -> usize {
        self.iter.as_ref().map_or(0, I::len)
    }

    default fn is_empty(&self) -> bool {
        self.iter.as_ref().map_or(true, I::is_empty)
    }
}

// NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some`
impl<I: FusedIterator> Fuse<I> {
    #[inline(always)]
    fn as_inner(&self) -> &I {
        match self.iter {
            Some(ref iter) => iter,
            // SAFETY: the specialized iterator never sets `None`
            None => unsafe { intrinsics::unreachable() },
        }
    }

    #[inline(always)]
    fn as_inner_mut(&mut self) -> &mut I {
        match self.iter {
            Some(ref mut iter) => iter,
            // SAFETY: the specialized iterator never sets `None`
            None => unsafe { intrinsics::unreachable() },
        }
    }

    #[inline(always)]
    fn into_inner(self) -> I {
        match self.iter {
            Some(iter) => iter,
            // SAFETY: the specialized iterator never sets `None`
            None => unsafe { intrinsics::unreachable() },
        }
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<I> Iterator for Fuse<I>
where
    I: FusedIterator,
{
    #[inline]
    fn next(&mut self) -> Option<<I as Iterator>::Item> {
        self.as_inner_mut().next()
    }

    #[inline]
    fn nth(&mut self, n: usize) -> Option<I::Item> {
        self.as_inner_mut().nth(n)
    }

    #[inline]
    fn last(self) -> Option<I::Item> {
        self.into_inner().last()
    }

    #[inline]
    fn count(self) -> usize {
        self.into_inner().count()
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.as_inner().size_hint()
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.as_inner_mut().try_fold(init, fold)
    }

    #[inline]
    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        self.into_inner().fold(init, fold)
    }

    #[inline]
    fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        self.as_inner_mut().find(predicate)
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<I> DoubleEndedIterator for Fuse<I>
where
    I: DoubleEndedIterator + FusedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
        self.as_inner_mut().next_back()
    }

    #[inline]
    fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
        self.as_inner_mut().nth_back(n)
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.as_inner_mut().try_rfold(init, fold)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        self.into_inner().rfold(init, fold)
    }

    #[inline]
    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        self.as_inner_mut().rfind(predicate)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I> ExactSizeIterator for Fuse<I>
where
    I: ExactSizeIterator + FusedIterator,
{
    fn len(&self) -> usize {
        self.as_inner().len()
    }

    fn is_empty(&self) -> bool {
        self.as_inner().is_empty()
    }
}

unsafe impl<I> TrustedRandomAccess for Fuse<I>
where
    I: TrustedRandomAccess + FusedIterator,
{
    unsafe fn get_unchecked(&mut self, i: usize) -> I::Item {
        self.as_inner_mut().get_unchecked(i)
    }

    fn may_have_side_effect() -> bool {
        I::may_have_side_effect()
    }
}
<commit_msg>impl TrustedRandomAccess for Fuse without FusedIterator<commit_after>use crate::intrinsics;
use crate::iter::{
    DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator, TrustedRandomAccess,
};
use crate::ops::Try;

/// An iterator that yields `None` forever after the underlying iterator
/// yields `None` once.
///
/// This `struct` is created by the [`fuse`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`fuse`]: trait.Iterator.html#method.fuse
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Fuse<I> {
    // NOTE: for `I: FusedIterator`, this is always assumed `Some`!
    iter: Option<I>,
}
impl<I> Fuse<I> {
    pub(in crate::iter) fn new(iter: I) -> Fuse<I> {
        Fuse { iter: Some(iter) }
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<I> FusedIterator for Fuse<I> where I: Iterator {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I> Iterator for Fuse<I>
where
    I: Iterator,
{
    type Item = <I as Iterator>::Item;

    #[inline]
    default fn next(&mut self) -> Option<<I as Iterator>::Item> {
        let next = self.iter.as_mut()?.next();
        if next.is_none() {
            self.iter = None;
        }
        next
    }

    #[inline]
    default fn nth(&mut self, n: usize) -> Option<I::Item> {
        let nth = self.iter.as_mut()?.nth(n);
        if nth.is_none() {
            self.iter = None;
        }
        nth
    }

    #[inline]
    default fn last(self) -> Option<I::Item> {
        self.iter?.last()
    }

    #[inline]
    default fn count(self) -> usize {
        self.iter.map_or(0, I::count)
    }

    #[inline]
    default fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.as_ref().map_or((0, Some(0)), I::size_hint)
    }

    #[inline]
    default fn try_fold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        if let Some(ref mut iter) = self.iter {
            acc = iter.try_fold(acc, fold)?;
            self.iter = None;
        }
        Try::from_ok(acc)
    }

    #[inline]
    default fn fold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        if let Some(iter) = self.iter {
            acc = iter.fold(acc, fold);
        }
        acc
    }

    #[inline]
    default fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        let found = self.iter.as_mut()?.find(predicate);
        if found.is_none() {
            self.iter = None;
        }
        found
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I> DoubleEndedIterator for Fuse<I>
where
    I: DoubleEndedIterator,
{
    #[inline]
    default fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
        let next = self.iter.as_mut()?.next_back();
        if next.is_none() {
            self.iter = None;
        }
        next
    }

    #[inline]
    default fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
        let nth = self.iter.as_mut()?.nth_back(n);
        if nth.is_none() {
            self.iter = None;
        }
        nth
    }

    #[inline]
    default fn try_rfold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        if let Some(ref mut iter) = self.iter {
            acc = iter.try_rfold(acc, fold)?;
            self.iter = None;
        }
        Try::from_ok(acc)
    }

    #[inline]
    default fn rfold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        if let Some(iter) = self.iter {
            acc = iter.rfold(acc, fold);
        }
        acc
    }

    #[inline]
    default fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        let found = self.iter.as_mut()?.rfind(predicate);
        if found.is_none() {
            self.iter = None;
        }
        found
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I> ExactSizeIterator for Fuse<I>
where
    I: ExactSizeIterator,
{
    default fn len(&self) -> usize {
        self.iter.as_ref().map_or(0, I::len)
    }

    default fn is_empty(&self) -> bool {
        self.iter.as_ref().map_or(true, I::is_empty)
    }
}

// NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some`
impl<I: FusedIterator> Fuse<I> {
    #[inline(always)]
    fn as_inner(&self) -> &I {
        match self.iter {
            Some(ref iter) => iter,
            // SAFETY: the specialized iterator never sets `None`
            None => unsafe { intrinsics::unreachable() },
        }
    }

    #[inline(always)]
    fn as_inner_mut(&mut self) -> &mut I {
        match self.iter {
            Some(ref mut iter) => iter,
            // SAFETY: the specialized iterator never sets `None`
            None => unsafe { intrinsics::unreachable() },
        }
    }

    #[inline(always)]
    fn into_inner(self) -> I {
        match self.iter {
            Some(iter) => iter,
            // SAFETY: the specialized iterator never sets `None`
            None => unsafe { intrinsics::unreachable() },
        }
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<I> Iterator for Fuse<I>
where
    I: FusedIterator,
{
    #[inline]
    fn next(&mut self) -> Option<<I as Iterator>::Item> {
        self.as_inner_mut().next()
    }

    #[inline]
    fn nth(&mut self, n: usize) -> Option<I::Item> {
        self.as_inner_mut().nth(n)
    }

    #[inline]
    fn last(self) -> Option<I::Item> {
        self.into_inner().last()
    }

    #[inline]
    fn count(self) -> usize {
        self.into_inner().count()
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.as_inner().size_hint()
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.as_inner_mut().try_fold(init, fold)
    }

    #[inline]
    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        self.into_inner().fold(init, fold)
    }

    #[inline]
    fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        self.as_inner_mut().find(predicate)
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<I> DoubleEndedIterator for Fuse<I>
where
    I: DoubleEndedIterator + FusedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
        self.as_inner_mut().next_back()
    }

    #[inline]
    fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
        self.as_inner_mut().nth_back(n)
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.as_inner_mut().try_rfold(init, fold)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        self.into_inner().rfold(init, fold)
    }

    #[inline]
    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        self.as_inner_mut().rfind(predicate)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I> ExactSizeIterator for Fuse<I>
where
    I: ExactSizeIterator + FusedIterator,
{
    fn len(&self) -> usize {
        self.as_inner().len()
    }

    fn is_empty(&self) -> bool {
        self.as_inner().is_empty()
    }
}

unsafe impl<I> TrustedRandomAccess for Fuse<I>
where
    I: TrustedRandomAccess,
{
    unsafe fn get_unchecked(&mut self, i: usize) -> I::Item {
        match self.iter {
            Some(ref mut iter) => iter.get_unchecked(i),
            // SAFETY: the caller asserts there is an item at `i`, so we're not exhausted.
            None => intrinsics::unreachable(),
        }
    }

    fn may_have_side_effect() -> bool {
        I::may_have_side_effect()
    }
}
<|endoftext|>


<commit_before>/// ! A Dominator Tree represented as mappings of Ebbs to their immediate dominator.

use cfg::*;
use ir::entities::Ebb;
use entity_map::EntityMap;

pub struct DominatorTree {
    data: EntityMap<Ebb, Option<Ebb>>,
}

impl DominatorTree {
    pub fn new(cfg: &ControlFlowGraph) -> DominatorTree {
        let mut dt = DominatorTree { data: EntityMap::new() };
        dt.build(cfg);
        dt
    }

    pub fn build(&mut self, cfg: &ControlFlowGraph) {
        let reverse_postorder_map = cfg.reverse_postorder_ebbs();
        let ebbs = reverse_postorder_map.keys().collect::<Vec<Ebb>>();
        let len = reverse_postorder_map.len();

        for (i, ebb) in ebbs.iter().enumerate() {
            if i > 0 {
                self.data.push(None);
            } else {
                self.data.push(Some(ebb.clone()));
            }
        }

        let mut changed = len > 0;

        while changed {
            changed = false;
            for i in 1..len {
                let ebb = ebbs[i];
                let preds = cfg.get_predecessors(ebb);
                let mut new_idom = None;

                for &(p, _) in preds {
                    if new_idom == None {
                        new_idom = Some(p);
                        continue;
                    }
                    if let Some(_) = self.data[p] {
                        new_idom =
                            Some(self.intersect(&reverse_postorder_map, p, new_idom.unwrap()));
                    }
                }
                match self.data[ebb] {
                    None => {
                        self.data[ebb] = new_idom;
                        changed = true;
                    }
                    Some(idom) => {
                        // Old idom != New idom
                        if idom != new_idom.unwrap() {
                            self.data[ebb] = new_idom;
                            changed = true;
                        }
                    }
                }
            }
        }
    }

    fn intersect(&self, ordering: &EntityMap<Ebb, usize>, first: Ebb, second: Ebb) -> Ebb {
        println!("A {} B {}", first, second);
        let mut a = first;
        let mut b = second;
        while a != b {
            while ordering[a] < ordering[b] {
                a = self.data[a].unwrap();
            }
            while ordering[b] < ordering[a] {
                b = self.data[b].unwrap();
            }
        }
        a
    }

    pub fn idom(&self, ebb: Ebb) -> Option<Ebb> {
        self.data[ebb].clone()
    }

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

#[cfg(test)]
mod test {
    use super::*;
    use ir::Function;
    use cfg::ControlFlowGraph;
    use test_utils::make_inst;

    #[test]
    fn empty() {
        let func = Function::new();
        let cfg = ControlFlowGraph::new(&func);
        let dtree = DominatorTree::new(&cfg);
        assert_eq!(dtree.len(), 0);
    }

    #[test]
    fn non_zero_entry_block() {
        let mut func = Function::new();
        let ebb3 = func.dfg.make_ebb();
        let ebb1 = func.dfg.make_ebb();
        let ebb2 = func.dfg.make_ebb();
        let ebb0 = func.dfg.make_ebb();
        func.layout.append_ebb(ebb3);
        func.layout.append_ebb(ebb1);
        func.layout.append_ebb(ebb2);
        func.layout.append_ebb(ebb0);

        let jmp_ebb3_ebb1 = make_inst::jump(&mut func, ebb1);
        let br_ebb1_ebb0 = make_inst::branch(&mut func, ebb0);
        let jmp_ebb1_ebb2 = make_inst::jump(&mut func, ebb2);
        let jmp_ebb2_ebb0 = make_inst::jump(&mut func, ebb0);

        func.layout.append_inst(br_ebb1_ebb0, ebb1);
        func.layout.append_inst(jmp_ebb1_ebb2, ebb1);
        func.layout.append_inst(jmp_ebb2_ebb0, ebb2);
        func.layout.append_inst(jmp_ebb3_ebb1, ebb3);

        let cfg = ControlFlowGraph::new(&func);
        let dt = DominatorTree::new(&cfg);

        assert_eq!(func.layout.entry_block().unwrap(), ebb3);
        assert_eq!(dt.len(), cfg.len());
        assert_eq!(dt.idom(ebb3).unwrap(), ebb3);
        assert_eq!(dt.idom(ebb1).unwrap(), ebb3);
        assert_eq!(dt.idom(ebb2).unwrap(), ebb1);
        assert_eq!(dt.idom(ebb0).unwrap(), ebb1);
    }
}
<commit_msg>Remove println\!<commit_after>/// ! A Dominator Tree represented as mappings of Ebbs to their immediate dominator.

use cfg::*;
use ir::entities::Ebb;
use entity_map::EntityMap;

pub struct DominatorTree {
    data: EntityMap<Ebb, Option<Ebb>>,
}

impl DominatorTree {
    pub fn new(cfg: &ControlFlowGraph) -> DominatorTree {
        let mut dt = DominatorTree { data: EntityMap::new() };
        dt.build(cfg);
        dt
    }

    pub fn build(&mut self, cfg: &ControlFlowGraph) {
        let reverse_postorder_map = cfg.reverse_postorder_ebbs();
        let ebbs = reverse_postorder_map.keys().collect::<Vec<Ebb>>();
        let len = reverse_postorder_map.len();

        for (i, ebb) in ebbs.iter().enumerate() {
            if i > 0 {
                self.data.push(None);
            } else {
                self.data.push(Some(ebb.clone()));
            }
        }

        let mut changed = len > 0;

        while changed {
            changed = false;
            for i in 1..len {
                let ebb = ebbs[i];
                let preds = cfg.get_predecessors(ebb);
                let mut new_idom = None;

                for &(p, _) in preds {
                    if new_idom == None {
                        new_idom = Some(p);
                        continue;
                    }
                    if let Some(_) = self.data[p] {
                        new_idom =
                            Some(self.intersect(&reverse_postorder_map, p, new_idom.unwrap()));
                    }
                }
                match self.data[ebb] {
                    None => {
                        self.data[ebb] = new_idom;
                        changed = true;
                    }
                    Some(idom) => {
                        // Old idom != New idom
                        if idom != new_idom.unwrap() {
                            self.data[ebb] = new_idom;
                            changed = true;
                        }
                    }
                }
            }
        }
    }

    fn intersect(&self, ordering: &EntityMap<Ebb, usize>, first: Ebb, second: Ebb) -> Ebb {
        let mut a = first;
        let mut b = second;
        while a != b {
            while ordering[a] < ordering[b] {
                a = self.data[a].unwrap();
            }
            while ordering[b] < ordering[a] {
                b = self.data[b].unwrap();
            }
        }
        a
    }

    pub fn idom(&self, ebb: Ebb) -> Option<Ebb> {
        self.data[ebb].clone()
    }

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

#[cfg(test)]
mod test {
    use super::*;
    use ir::Function;
    use cfg::ControlFlowGraph;
    use test_utils::make_inst;

    #[test]
    fn empty() {
        let func = Function::new();
        let cfg = ControlFlowGraph::new(&func);
        let dtree = DominatorTree::new(&cfg);
        assert_eq!(dtree.len(), 0);
    }

    #[test]
    fn non_zero_entry_block() {
        let mut func = Function::new();
        let ebb3 = func.dfg.make_ebb();
        let ebb1 = func.dfg.make_ebb();
        let ebb2 = func.dfg.make_ebb();
        let ebb0 = func.dfg.make_ebb();
        func.layout.append_ebb(ebb3);
        func.layout.append_ebb(ebb1);
        func.layout.append_ebb(ebb2);
        func.layout.append_ebb(ebb0);

        let jmp_ebb3_ebb1 = make_inst::jump(&mut func, ebb1);
        let br_ebb1_ebb0 = make_inst::branch(&mut func, ebb0);
        let jmp_ebb1_ebb2 = make_inst::jump(&mut func, ebb2);
        let jmp_ebb2_ebb0 = make_inst::jump(&mut func, ebb0);

        func.layout.append_inst(br_ebb1_ebb0, ebb1);
        func.layout.append_inst(jmp_ebb1_ebb2, ebb1);
        func.layout.append_inst(jmp_ebb2_ebb0, ebb2);
        func.layout.append_inst(jmp_ebb3_ebb1, ebb3);

        let cfg = ControlFlowGraph::new(&func);
        let dt = DominatorTree::new(&cfg);

        assert_eq!(func.layout.entry_block().unwrap(), ebb3);
        assert_eq!(dt.len(), cfg.len());
        assert_eq!(dt.idom(ebb3).unwrap(), ebb3);
        assert_eq!(dt.idom(ebb1).unwrap(), ebb3);
        assert_eq!(dt.idom(ebb2).unwrap(), ebb1);
        assert_eq!(dt.idom(ebb0).unwrap(), ebb1);
    }
}
<|endoftext|>


<commit_before>//! [Bunyan](https://www.npmjs.com/package/bunyan) formatting for `slog-rs`
//!
//! ```
//! #[macro_use]
//! extern crate slog;
//! extern crate slog_json;
//!
//! use slog::*;
//!
//! fn main() {
//!     let root = Logger::new_root(o!("build-id" => "8dfljdf"));
//!     root.set_drain(
//!             drain::stream(
//!                 std::io::stderr(),
//!                 slog_json::new()
//!                 )
//!             );
//! }
//! ```
#![warn(missing_docs)]

#[macro_use]
extern crate slog;
extern crate slog_serde;
extern crate serde_json;

use std::io;

use slog_serde::SerdeSerializer;
use slog::logger::RecordInfo;
use slog::{Level, OwnedKeyValue, BorrowedKeyValue};
use slog::format::Format;
use slog::Level::*;

fn level_to_string(level: Level) -> &'static str {
    match level {
        Critical => "CRIT",
        Error => "ERRO",
        Warning => "WARN",
        Info => "INFO",
        Debug => "DEBG",
        Trace => "TRCE",
    }
}

/// Json formatter
///
/// Each record will be printed as a Json map.
pub struct Json {
    newlines: bool,
    values: Vec<OwnedKeyValue>,
}

impl Json {
    /// Create new `Json` format.
    ///
    /// It comes with some default fields (`ts`, `level`, `msg`)
    /// and uses newlines.
    ///
    /// Use `Json::build()` to build a custom Json formatter from
    /// scratch.
    pub fn new() -> Self {
        Json {
            newlines: true,
            values: o!(
                "ts" => |rinfo : &RecordInfo| {
                    rinfo.ts.to_rfc3339()
                },
                "level" => |rinfo : &RecordInfo| {
                    level_to_string(rinfo.level)
                },
                "msg" => |rinfo : &RecordInfo| {
                    rinfo.msg.clone()
                }
                ).to_vec(),
        }
    }

    /// Build a Json formatter with custom settings
    pub fn build() -> JsonBuilder {
        JsonBuilder::new()
    }

    /// Create new `Json` format that does not add
    /// newlines after each record.
    pub fn new_nonewline() -> Self {
        let mut json = Json::new();
        json.newlines = false;
        json
    }
}

/// Json formatter builder
///
/// Create with `Json::build`.
pub struct JsonBuilder {
    newlines: bool,
    values: Vec<OwnedKeyValue>,
}

impl JsonBuilder {
    fn new() -> Self {
        JsonBuilder {
            newlines: true,
            values: vec![],
        }
    }

    /// Build `Json` format
    ///
    /// This consumes the builder.
    pub fn build(self) -> Json {
        Json {
            values: self.values,
            newlines: self.newlines,
        }
    }

    /// Set writing a newline after ever log record
    pub fn set_newlines(&mut self, enabled: bool) -> &mut Self {
        self.newlines = enabled;
        self
    }

    /// Add custom values to be printed with this formatter
    pub fn add_key_values(&mut self, values: &[OwnedKeyValue]) -> &mut Self {
        self.values.extend_from_slice(values);
        self
    }

    /// Add custom values to be printed with this formatter
    pub fn add_key_value(&mut self, value: OwnedKeyValue) -> &mut Self {
        self.values.push(value);
        self
    }
}

impl Format for Json {
    fn format(&self,
              io : &mut io::Write,
              rinfo: &RecordInfo,
              logger_values: &[OwnedKeyValue],
              record_values: &[BorrowedKeyValue]) {
        let _ = write!(io, "{{");
        let mut serializer = serde_json::Serializer::new(io);
        {
            let mut serializer = &mut SerdeSerializer(&mut serializer);

            for &(ref k, ref v) in self.values.iter() {
                v.serialize(rinfo, k, serializer);
            }
            for &(ref k, ref v) in logger_values.iter() {
                v.serialize(rinfo, k, serializer);
            }

            for &(ref k, ref v) in record_values.iter() {
                v.serialize(rinfo, k, serializer);
            }
        }
        let mut io = serializer.into_inner();
        let _ = write!(io, "}}");
    }
}

/// Short for `Json::new()`
pub fn new() -> Json {
    Json::new()
}

/// Short for `Json::build()`
pub fn build() -> JsonBuilder {
    Json::build()
}
<commit_msg>Fix the JSON formatting bug<commit_after>//! [Bunyan](https://www.npmjs.com/package/bunyan) formatting for `slog-rs`
//!
//! ```
//! #[macro_use]
//! extern crate slog;
//! extern crate slog_json;
//!
//! use slog::*;
//!
//! fn main() {
//!     let root = Logger::new_root(o!("build-id" => "8dfljdf"));
//!     root.set_drain(
//!             drain::stream(
//!                 std::io::stderr(),
//!                 slog_json::new()
//!                 )
//!             );
//! }
//! ```
#![warn(missing_docs)]

#[macro_use]
extern crate slog;
extern crate slog_serde;
extern crate serde_json;

use std::io;

use slog_serde::SerdeSerializer;
use slog::logger::RecordInfo;
use slog::{Level, OwnedKeyValue, BorrowedKeyValue};
use slog::format::Format;
use slog::Level::*;

fn level_to_string(level: Level) -> &'static str {
    match level {
        Critical => "CRIT",
        Error => "ERRO",
        Warning => "WARN",
        Info => "INFO",
        Debug => "DEBG",
        Trace => "TRCE",
    }
}

/// Json formatter
///
/// Each record will be printed as a Json map.
pub struct Json {
    newlines: bool,
    values: Vec<OwnedKeyValue>,
}

impl Json {
    /// Create new `Json` format.
    ///
    /// It comes with some default fields (`ts`, `level`, `msg`)
    /// and uses newlines.
    ///
    /// Use `Json::build()` to build a custom Json formatter from
    /// scratch.
    pub fn new() -> Self {
        Json {
            newlines: true,
            values: o!(
                "ts" => |rinfo : &RecordInfo| {
                    rinfo.ts.to_rfc3339()
                },
                "level" => |rinfo : &RecordInfo| {
                    level_to_string(rinfo.level)
                },
                "msg" => |rinfo : &RecordInfo| {
                    rinfo.msg.clone()
                }
                ).to_vec(),
        }
    }

    /// Build a Json formatter with custom settings
    pub fn build() -> JsonBuilder {
        JsonBuilder::new()
    }

    /// Create new `Json` format that does not add
    /// newlines after each record.
    pub fn new_nonewline() -> Self {
        let mut json = Json::new();
        json.newlines = false;
        json
    }
}

/// Json formatter builder
///
/// Create with `Json::build`.
pub struct JsonBuilder {
    newlines: bool,
    values: Vec<OwnedKeyValue>,
}

impl JsonBuilder {
    fn new() -> Self {
        JsonBuilder {
            newlines: true,
            values: vec![],
        }
    }

    /// Build `Json` format
    ///
    /// This consumes the builder.
    pub fn build(self) -> Json {
        Json {
            values: self.values,
            newlines: self.newlines,
        }
    }

    /// Set writing a newline after ever log record
    pub fn set_newlines(&mut self, enabled: bool) -> &mut Self {
        self.newlines = enabled;
        self
    }

    /// Add custom values to be printed with this formatter
    pub fn add_key_values(&mut self, values: &[OwnedKeyValue]) -> &mut Self {
        self.values.extend_from_slice(values);
        self
    }

    /// Add custom values to be printed with this formatter
    pub fn add_key_value(&mut self, value: OwnedKeyValue) -> &mut Self {
        self.values.push(value);
        self
    }
}

// TODO: Get rid of after
// https://github.com/serde-rs/serde/issues/386
// is implemented
struct SkipFirstByte<W> {
    first : bool,
    io : W,
}

impl<W : io::Write> SkipFirstByte<W> {
    fn new(io : W) -> Self {
        SkipFirstByte {
            first: true,
            io: io,
        }
    }

    fn into_inner(self) -> W {
        self.io
    }
}

impl<W : io::Write> io::Write for SkipFirstByte<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        if self.first && !buf.is_empty(){
            self.first = false;
            try!(self.io.write_all(&buf[1..]));
        } else {
            try!(self.io.write_all(buf))
        }
        Ok(buf.len())
    }

    fn flush(&mut self) -> io::Result<()> {
        self.io.flush()
    }

}

impl Format for Json {
    fn format(&self,
              io : &mut io::Write,
              rinfo: &RecordInfo,
              logger_values: &[OwnedKeyValue],
              record_values: &[BorrowedKeyValue]) {
        let _ = write!(io, "{{");
        let mut serializer = serde_json::Serializer::new(SkipFirstByte::new(io));
        {
            let mut serializer = &mut SerdeSerializer(&mut serializer);

            for &(ref k, ref v) in self.values.iter() {
                v.serialize(rinfo, k, serializer);
            }
            for &(ref k, ref v) in logger_values.iter() {
                v.serialize(rinfo, k, serializer);
            }

            for &(ref k, ref v) in record_values.iter() {
                v.serialize(rinfo, k, serializer);
            }
        }
        let mut io = serializer.into_inner().into_inner();
        let _ = io.write_all("}".as_bytes());
        if self.newlines {
            let _ = io.write_all("\n".as_bytes());
        }
    }
}

/// Short for `Json::new()`
pub fn new() -> Json {
    Json::new()
}

/// Short for `Json::build()`
pub fn build() -> JsonBuilder {
    Json::build()
}
<|endoftext|>


<commit_before>use std::env;
use std::path::Path;

use lazy_static::lazy_static;
use raw_cpuid::{CpuId, ExtendedFeatures, FeatureInfo};

lazy_static! {
    static ref CPU_ID: CpuId = CpuId::new();
    static ref CPU_FEATURES: Option<FeatureInfo> = CPU_ID.get_feature_info();
    static ref CPU_EXTENDED_FEATURES: Option<ExtendedFeatures> = CPU_ID.get_extended_feature_info();
    static ref TARGET_FEATURES: Vec<String> = env::var("CARGO_CFG_TARGET_FEATURE")
        .unwrap()
        .split(",")
        .map(|s| s.to_owned())
        .collect();
    static ref TARGET_ARCH: String = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
    static ref TARGET_ENV: String = env::var("CARGO_CFG_TARGET_ENV").unwrap();
}

fn has_target_feature(feature: &str) -> bool {
    TARGET_FEATURES.iter().any(|name| name == feature)
}

fn has_aesni() -> bool {
    cfg!(feature = "native")
        && CPU_FEATURES
            .as_ref()
            .map_or(false, |features| features.has_aesni())
}

fn has_sse41() -> bool {
    cfg!(feature = "native")
        && CPU_FEATURES
            .as_ref()
            .map_or(false, |features| features.has_sse41())
}

fn has_sse42() -> bool {
    cfg!(feature = "native")
        && CPU_FEATURES
            .as_ref()
            .map_or(false, |features| features.has_sse42())
}

fn has_avx() -> bool {
    cfg!(feature = "native")
        && CPU_FEATURES
            .as_ref()
            .map_or(false, |features| features.has_avx())
}

fn has_avx2() -> bool {
    cfg!(feature = "native")
        && CPU_EXTENDED_FEATURES
            .as_ref()
            .map_or(false, |features| features.has_avx2())
}

fn support_aesni() -> bool {
    cfg!(feature = "aes") || has_target_feature("aes") || has_aesni()
}

#[allow(dead_code)]
fn support_sse41() -> bool {
    cfg!(feature = "sse41") || has_target_feature("sse41") || has_sse41()
}

fn support_sse42() -> bool {
    cfg!(feature = "sse42") || has_target_feature("sse42") || has_sse42()
}

fn support_avx() -> bool {
    cfg!(feature = "avx") || has_target_feature("avx") || has_avx()
}

fn support_avx2() -> bool {
    cfg!(feature = "avx2") || has_target_feature("avx2") || has_avx2()
}

#[cfg(all(not(feature = "gen"), any(target_os = "macos", target_os = "linux")))]
fn generate_binding(_out_file: &Path) {
    cargo_emit::warning!("pregenerated binding file.");
}

#[cfg(any(feature = "gen", not(any(target_os = "macos", target_os = "linux"))))]
fn generate_binding(out_file: &Path) {
    cargo_emit::warning!("generate binding file @ {:?}.", out_file);

    let _ = bindgen::builder()
        .clang_args(&["-x", "c++", "-std=c++11"])
        .clang_args(&[
            "-Dt1ha_EXPORTS",
            "-DXXH_STATIC_LINKING_ONLY",
            "-Isrc/highwayhash",
        ])
        .clang_args(if support_aesni() {
            &[
                "-maes",
                "-DT1HA0_RUNTIME_SELECT=1",
                "-DT1HA0_AESNI_AVAILABLE=1",
            ][..]
        } else {
            &[][..]
        })
        .clang_args(
            vec![
                if cfg!(feature = "native") {
                    Some("-march=native")
                } else {
                    None
                },
                if support_sse41() {
                    Some("-msse4.1")
                } else {
                    None
                },
                if support_sse42() {
                    Some("-msse4.2")
                } else {
                    None
                },
                if support_avx() { Some("-mavx") } else { None },
                if support_avx2() { Some("-mavx2") } else { None },
                if cfg!(feature = "city") {
                    Some("-DCITY_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "farm") {
                    Some("-DFARM_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "highway") {
                    Some("-DHIGHWAY_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "komi") {
                    Some("-DKOMI_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "lookup3") {
                    Some("-DLOOKUP3=1")
                } else {
                    None
                },
                if cfg!(feature = "meow") && matches!(TARGET_ARCH.as_str(), "x86" | "x86_64") {
                    Some("-DMEOW_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "metro") {
                    Some("-DMETRO_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "mum") {
                    Some("-DMUM_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "murmur") {
                    Some("-DMURMUR_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "mx3") {
                    Some("-DMX3_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "nm") {
                    Some("-DNM_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "pengy") {
                    Some("-DPENGY_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "prv") {
                    Some("-DPRV_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "spooky") {
                    Some("-DSPOOKY_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "t1ha") {
                    Some("-DT1_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "wy") {
                    Some("-DWY_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "xx") {
                    Some("-DXX_HASH=1")
                } else {
                    None
                },
            ]
            .into_iter()
            .flatten(),
        )
        .header("src/fasthash.hpp")
        .size_t_is_usize(true)
        .generate_inline_functions(true)
        .disable_name_namespacing()
        .allowlist_function("^CityHash.*")
        .allowlist_function("^farmhash.*")
        .allowlist_function("^HighwayHash.*")
        .allowlist_function("^komi.*")
        .allowlist_function("^lookup3.*")
        .allowlist_function("^metrohash.*")
        .allowlist_function("^mum_hash.*")
        .allowlist_function("^MurmurHash.*")
        .allowlist_function("^mx3hash.*")
        .allowlist_function("^NMHASH.*")
        .allowlist_function("^pengy.*")
        .allowlist_function("^prvhash.*")
        .allowlist_function("^SpookyHasher.*")
        .allowlist_function("^t1ha.*")
        .allowlist_function("^wyhash.*")
        .allowlist_function("^XXH.*")
        .allowlist_function("^Meow.*")
        .blocklist_function("^t1ha_selfcheck__.*")
        .allowlist_var("^Meow.*")
        .allowlist_var("^PRH64S_.*")
        .generate()
        .unwrap()
        .write_to_file(out_file)
        .expect("fail to write bindings");

    cargo_emit::warning!("generate binding file @ {:?}.", out_file);
}

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

    build
        .cpp(true)
        .include("src/highwayhash")
        .flag("-std=c++11")
        .flag_if_supported("-Wno-implicit-fallthrough")
        .flag_if_supported("-Wno-unknown-attributes")
        .flag_if_supported("-Wno-sign-compare")
        .file("src/fasthash.cpp");

    if cfg!(feature = "city") {
        build.flag("-DCITY_HASH=1").file("src/smhasher/City.cpp");
    }

    if cfg!(feature = "farm") {
        build
            .flag("-DFARM_HASH=1")
            .file("src/smhasher/farmhash-c.c");
    }

    if cfg!(feature = "komi") {
        build.flag("-DKOMI_HASH=1");
    }

    if cfg!(feature = "highway") {
        build.flag("-DHIGHWAY_HASH=1");
    }

    if cfg!(feature = "lookup3") {
        build.flag("-DLOOKUP3=1").file("src/smhasher/lookup3.cpp");
    }

    if cfg!(feature = "meow") && matches!(TARGET_ARCH.as_str(), "x86" | "x86_64") {
        build.flag("-DMEOW_HASH=1");
    }

    if cfg!(feature = "mx3") {
        build.flag("-DMX3_HASH=1");
    }

    if cfg!(feature = "nm") {
        build.flag("-DNM_HASH=1");
    }

    if cfg!(feature = "pengy") {
        build
            .flag("-DPENGY_HASH=1")
            .file("src/pengyhash/pengyhash.c");
    }

    if cfg!(feature = "prv") {
        build.flag("-DPRV_HASH=1");
    }

    if cfg!(feature = "t1ha") {
        build.flag("-DT1_HASH=1");
    }

    if cfg!(feature = "metro") {
        build
            .flag("-DMETRO_HASH=1")
            .file("src/smhasher/metrohash/metrohash64.cpp")
            .file("src/smhasher/metrohash/metrohash128.cpp");

        if support_sse42() {
            build
                .file("src/smhasher/metrohash/metrohash64crc.cpp")
                .file("src/smhasher/metrohash/metrohash128crc.cpp");
        }
    }

    if cfg!(feature = "mum") {
        build.flag("-DMUM_HASH=1").file("src/smhasher/mum.cc");
    }

    if cfg!(feature = "murmur") {
        build
            .flag("-DMURMUR_HASH=1")
            .file("src/smhasher/MurmurHash1.cpp")
            .file("src/smhasher/MurmurHash2.cpp")
            .file("src/smhasher/MurmurHash3.cpp");
    }

    if cfg!(feature = "spooky") {
        build
            .flag("-DSPOOKY_HASH=1")
            .file("src/smhasher/Spooky.cpp");
    }

    if cfg!(feature = "wy") {
        build.flag("-DWY_HASH=1");
    }

    if cfg!(feature = "xx") {
        build.flag("-DXX_HASH=1").file("src/xxHash/xxhash.c");
    }

    if cfg!(feature = "native") {
        build.flag("-march=native");
    } else {
        if has_target_feature("aes") {
            build.flag("-maes");
        }
        if has_target_feature("sse41") {
            build.flag("-msse41");
        }
        if has_target_feature("sse42") {
            build.flag("-msse4.2");
        }
        if has_target_feature("avx") {
            build.flag("-mavx");
        }
        if has_target_feature("avx2") {
            build.flag("-mavx2");
        }
    }

    build.static_flag(true).compile("fasthash");
}

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

    build
        .file("src/t1ha/src/t1ha0.c")
        .file("src/t1ha/src/t1ha1.c")
        .file("src/t1ha/src/t1ha2.c");

    // indirect functions are not supported on all targets (e.g. x86_64-unknown-linux-musl)
    if TARGET_ENV.as_str() == "musl" {
        build.define("T1HA_USE_INDIRECT_FUNCTIONS", Some("0"));
    }

    if support_aesni() {
        build
            .define("T1HA0_RUNTIME_SELECT", Some("1"))
            .define("T1HA0_AESNI_AVAILABLE", Some("1"))
            .flag("-maes")
            .file("src/t1ha/src/t1ha0_ia32aes_noavx.c")
            .file("src/t1ha/src/t1ha0_ia32aes_avx.c")
            .file("src/t1ha/src/t1ha0_ia32aes_avx2.c");

        if support_avx() {
            build.flag("-mavx");
        }

        if support_avx2() {
            build.flag("-mavx2");
        }
    }

    build.static_flag(true).compile("t1ha");
}

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

    build
        .cpp(true)
        .flag("-std=c++11")
        .flag_if_supported("-Wno-sign-compare")
        .include("src/highwayhash")
        .file("src/highwayhash/highwayhash/arch_specific.cc")
        .file("src/highwayhash/highwayhash/instruction_sets.cc")
        .file("src/highwayhash/highwayhash/os_specific.cc")
        .file("src/highwayhash/highwayhash/hh_portable.cc")
        .file("src/highwayhash/highwayhash/c_bindings.cc");

    match TARGET_ARCH.as_str() {
        "x86" | "x86_64" => {
            build
                .flag("-msse4.1")
                .flag("-mavx2")
                .file("src/highwayhash/highwayhash/hh_sse41.cc")
                .file("src/highwayhash/highwayhash/hh_avx2.cc");
        }

        "aarch64" => {
            build.file("src/highwayhash/highwayhash/hh_neon.cc");
        }

        "powerpc64" => {
            build
                .flag("-mvsx")
                .file("src/highwayhash/highwayhash/hh_vsx.cc");
        }
        _ => {}
    }

    build.static_flag(true).compile("highwayhash");
}

fn main() {
    if has_aesni() {
        cargo_emit::rustc_cfg!(r#"feature="aes""#);
    }
    if has_sse41() {
        cargo_emit::rustc_cfg!(r#"feature="sse41""#);
    }
    if has_sse42() {
        cargo_emit::rustc_cfg!(r#"feature="sse42""#);
    }
    if has_avx() {
        cargo_emit::rustc_cfg!(r#"feature="avx""#);
    }
    if has_avx2() {
        cargo_emit::rustc_cfg!(r#"feature="avx2""#);
    }

    build_fasthash();
    if cfg!(feature = "t1ha") {
        build_t1();
    }
    if cfg!(feature = "highway") {
        build_highway();
    }

    let out_dir = env::var("OUT_DIR").unwrap();
    let out_file = Path::new(&out_dir).join("fasthash.rs");

    cargo_emit::rerun_if_changed!("src/fasthash.hpp");
    cargo_emit::rerun_if_changed!("src/fasthash.cpp");

    generate_binding(&out_file);
}
<commit_msg>handle empty CARGO_CFG_TARGET_FEATURE<commit_after>use std::env;
use std::path::Path;

use lazy_static::lazy_static;
use raw_cpuid::{CpuId, ExtendedFeatures, FeatureInfo};

lazy_static! {
    static ref CPU_ID: CpuId = CpuId::new();
    static ref CPU_FEATURES: Option<FeatureInfo> = CPU_ID.get_feature_info();
    static ref CPU_EXTENDED_FEATURES: Option<ExtendedFeatures> = CPU_ID.get_extended_feature_info();
    static ref TARGET_FEATURES: Vec<String> = env::var("CARGO_CFG_TARGET_FEATURE")
        .map_or_else(|_| vec![], |s| s.split(",").map(|s| s.to_owned()).collect());
    static ref TARGET_ARCH: String = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
    static ref TARGET_ENV: String = env::var("CARGO_CFG_TARGET_ENV").unwrap();
}

fn has_target_feature(feature: &str) -> bool {
    TARGET_FEATURES.iter().any(|name| name == feature)
}

fn has_aesni() -> bool {
    cfg!(feature = "native")
        && CPU_FEATURES
            .as_ref()
            .map_or(false, |features| features.has_aesni())
}

fn has_sse41() -> bool {
    cfg!(feature = "native")
        && CPU_FEATURES
            .as_ref()
            .map_or(false, |features| features.has_sse41())
}

fn has_sse42() -> bool {
    cfg!(feature = "native")
        && CPU_FEATURES
            .as_ref()
            .map_or(false, |features| features.has_sse42())
}

fn has_avx() -> bool {
    cfg!(feature = "native")
        && CPU_FEATURES
            .as_ref()
            .map_or(false, |features| features.has_avx())
}

fn has_avx2() -> bool {
    cfg!(feature = "native")
        && CPU_EXTENDED_FEATURES
            .as_ref()
            .map_or(false, |features| features.has_avx2())
}

fn support_aesni() -> bool {
    cfg!(feature = "aes") || has_target_feature("aes") || has_aesni()
}

#[allow(dead_code)]
fn support_sse41() -> bool {
    cfg!(feature = "sse41") || has_target_feature("sse41") || has_sse41()
}

fn support_sse42() -> bool {
    cfg!(feature = "sse42") || has_target_feature("sse42") || has_sse42()
}

fn support_avx() -> bool {
    cfg!(feature = "avx") || has_target_feature("avx") || has_avx()
}

fn support_avx2() -> bool {
    cfg!(feature = "avx2") || has_target_feature("avx2") || has_avx2()
}

#[cfg(all(not(feature = "gen"), any(target_os = "macos", target_os = "linux")))]
fn generate_binding(_out_file: &Path) {
    cargo_emit::warning!("pregenerated binding file.");
}

#[cfg(any(feature = "gen", not(any(target_os = "macos", target_os = "linux"))))]
fn generate_binding(out_file: &Path) {
    cargo_emit::warning!("generate binding file @ {:?}.", out_file);

    let _ = bindgen::builder()
        .clang_args(&["-x", "c++", "-std=c++11"])
        .clang_args(&[
            "-Dt1ha_EXPORTS",
            "-DXXH_STATIC_LINKING_ONLY",
            "-Isrc/highwayhash",
        ])
        .clang_args(if support_aesni() {
            &[
                "-maes",
                "-DT1HA0_RUNTIME_SELECT=1",
                "-DT1HA0_AESNI_AVAILABLE=1",
            ][..]
        } else {
            &[][..]
        })
        .clang_args(
            vec![
                if cfg!(feature = "native") {
                    Some("-march=native")
                } else {
                    None
                },
                if support_sse41() {
                    Some("-msse4.1")
                } else {
                    None
                },
                if support_sse42() {
                    Some("-msse4.2")
                } else {
                    None
                },
                if support_avx() { Some("-mavx") } else { None },
                if support_avx2() { Some("-mavx2") } else { None },
                if cfg!(feature = "city") {
                    Some("-DCITY_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "farm") {
                    Some("-DFARM_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "highway") {
                    Some("-DHIGHWAY_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "komi") {
                    Some("-DKOMI_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "lookup3") {
                    Some("-DLOOKUP3=1")
                } else {
                    None
                },
                if cfg!(feature = "meow") && matches!(TARGET_ARCH.as_str(), "x86" | "x86_64") {
                    Some("-DMEOW_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "metro") {
                    Some("-DMETRO_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "mum") {
                    Some("-DMUM_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "murmur") {
                    Some("-DMURMUR_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "mx3") {
                    Some("-DMX3_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "nm") {
                    Some("-DNM_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "pengy") {
                    Some("-DPENGY_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "prv") {
                    Some("-DPRV_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "spooky") {
                    Some("-DSPOOKY_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "t1ha") {
                    Some("-DT1_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "wy") {
                    Some("-DWY_HASH=1")
                } else {
                    None
                },
                if cfg!(feature = "xx") {
                    Some("-DXX_HASH=1")
                } else {
                    None
                },
            ]
            .into_iter()
            .flatten(),
        )
        .header("src/fasthash.hpp")
        .size_t_is_usize(true)
        .generate_inline_functions(true)
        .disable_name_namespacing()
        .allowlist_function("^CityHash.*")
        .allowlist_function("^farmhash.*")
        .allowlist_function("^HighwayHash.*")
        .allowlist_function("^komi.*")
        .allowlist_function("^lookup3.*")
        .allowlist_function("^metrohash.*")
        .allowlist_function("^mum_hash.*")
        .allowlist_function("^MurmurHash.*")
        .allowlist_function("^mx3hash.*")
        .allowlist_function("^NMHASH.*")
        .allowlist_function("^pengy.*")
        .allowlist_function("^prvhash.*")
        .allowlist_function("^SpookyHasher.*")
        .allowlist_function("^t1ha.*")
        .allowlist_function("^wyhash.*")
        .allowlist_function("^XXH.*")
        .allowlist_function("^Meow.*")
        .blocklist_function("^t1ha_selfcheck__.*")
        .allowlist_var("^Meow.*")
        .allowlist_var("^PRH64S_.*")
        .generate()
        .unwrap()
        .write_to_file(out_file)
        .expect("fail to write bindings");

    cargo_emit::warning!("generate binding file @ {:?}.", out_file);
}

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

    build
        .cpp(true)
        .include("src/highwayhash")
        .flag("-std=c++11")
        .flag_if_supported("-Wno-implicit-fallthrough")
        .flag_if_supported("-Wno-unknown-attributes")
        .flag_if_supported("-Wno-sign-compare")
        .file("src/fasthash.cpp");

    if cfg!(feature = "city") {
        build.flag("-DCITY_HASH=1").file("src/smhasher/City.cpp");
    }

    if cfg!(feature = "farm") {
        build
            .flag("-DFARM_HASH=1")
            .file("src/smhasher/farmhash-c.c");
    }

    if cfg!(feature = "komi") {
        build.flag("-DKOMI_HASH=1");
    }

    if cfg!(feature = "highway") {
        build.flag("-DHIGHWAY_HASH=1");
    }

    if cfg!(feature = "lookup3") {
        build.flag("-DLOOKUP3=1").file("src/smhasher/lookup3.cpp");
    }

    if cfg!(feature = "meow") && matches!(TARGET_ARCH.as_str(), "x86" | "x86_64") {
        build.flag("-DMEOW_HASH=1");
    }

    if cfg!(feature = "mx3") {
        build.flag("-DMX3_HASH=1");
    }

    if cfg!(feature = "nm") {
        build.flag("-DNM_HASH=1");
    }

    if cfg!(feature = "pengy") {
        build
            .flag("-DPENGY_HASH=1")
            .file("src/pengyhash/pengyhash.c");
    }

    if cfg!(feature = "prv") {
        build.flag("-DPRV_HASH=1");
    }

    if cfg!(feature = "t1ha") {
        build.flag("-DT1_HASH=1");
    }

    if cfg!(feature = "metro") {
        build
            .flag("-DMETRO_HASH=1")
            .file("src/smhasher/metrohash/metrohash64.cpp")
            .file("src/smhasher/metrohash/metrohash128.cpp");

        if support_sse42() {
            build
                .file("src/smhasher/metrohash/metrohash64crc.cpp")
                .file("src/smhasher/metrohash/metrohash128crc.cpp");
        }
    }

    if cfg!(feature = "mum") {
        build.flag("-DMUM_HASH=1").file("src/smhasher/mum.cc");
    }

    if cfg!(feature = "murmur") {
        build
            .flag("-DMURMUR_HASH=1")
            .file("src/smhasher/MurmurHash1.cpp")
            .file("src/smhasher/MurmurHash2.cpp")
            .file("src/smhasher/MurmurHash3.cpp");
    }

    if cfg!(feature = "spooky") {
        build
            .flag("-DSPOOKY_HASH=1")
            .file("src/smhasher/Spooky.cpp");
    }

    if cfg!(feature = "wy") {
        build.flag("-DWY_HASH=1");
    }

    if cfg!(feature = "xx") {
        build.flag("-DXX_HASH=1").file("src/xxHash/xxhash.c");
    }

    if cfg!(feature = "native") {
        build.flag("-march=native");
    } else {
        if has_target_feature("aes") {
            build.flag("-maes");
        }
        if has_target_feature("sse41") {
            build.flag("-msse41");
        }
        if has_target_feature("sse42") {
            build.flag("-msse4.2");
        }
        if has_target_feature("avx") {
            build.flag("-mavx");
        }
        if has_target_feature("avx2") {
            build.flag("-mavx2");
        }
    }

    build.static_flag(true).compile("fasthash");
}

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

    build
        .file("src/t1ha/src/t1ha0.c")
        .file("src/t1ha/src/t1ha1.c")
        .file("src/t1ha/src/t1ha2.c");

    // indirect functions are not supported on all targets (e.g. x86_64-unknown-linux-musl)
    if TARGET_ENV.as_str() == "musl" {
        build.define("T1HA_USE_INDIRECT_FUNCTIONS", Some("0"));
    }

    if support_aesni() {
        build
            .define("T1HA0_RUNTIME_SELECT", Some("1"))
            .define("T1HA0_AESNI_AVAILABLE", Some("1"))
            .flag("-maes")
            .file("src/t1ha/src/t1ha0_ia32aes_noavx.c")
            .file("src/t1ha/src/t1ha0_ia32aes_avx.c")
            .file("src/t1ha/src/t1ha0_ia32aes_avx2.c");

        if support_avx() {
            build.flag("-mavx");
        }

        if support_avx2() {
            build.flag("-mavx2");
        }
    }

    build.static_flag(true).compile("t1ha");
}

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

    build
        .cpp(true)
        .flag("-std=c++11")
        .flag_if_supported("-Wno-sign-compare")
        .include("src/highwayhash")
        .file("src/highwayhash/highwayhash/arch_specific.cc")
        .file("src/highwayhash/highwayhash/instruction_sets.cc")
        .file("src/highwayhash/highwayhash/os_specific.cc")
        .file("src/highwayhash/highwayhash/hh_portable.cc")
        .file("src/highwayhash/highwayhash/c_bindings.cc");

    match TARGET_ARCH.as_str() {
        "x86" | "x86_64" => {
            build
                .flag("-msse4.1")
                .flag("-mavx2")
                .file("src/highwayhash/highwayhash/hh_sse41.cc")
                .file("src/highwayhash/highwayhash/hh_avx2.cc");
        }

        "aarch64" => {
            build.file("src/highwayhash/highwayhash/hh_neon.cc");
        }

        "powerpc64" => {
            build
                .flag("-mvsx")
                .file("src/highwayhash/highwayhash/hh_vsx.cc");
        }
        _ => {}
    }

    build.static_flag(true).compile("highwayhash");
}

fn main() {
    if has_aesni() {
        cargo_emit::rustc_cfg!(r#"feature="aes""#);
    }
    if has_sse41() {
        cargo_emit::rustc_cfg!(r#"feature="sse41""#);
    }
    if has_sse42() {
        cargo_emit::rustc_cfg!(r#"feature="sse42""#);
    }
    if has_avx() {
        cargo_emit::rustc_cfg!(r#"feature="avx""#);
    }
    if has_avx2() {
        cargo_emit::rustc_cfg!(r#"feature="avx2""#);
    }

    build_fasthash();
    if cfg!(feature = "t1ha") {
        build_t1();
    }
    if cfg!(feature = "highway") {
        build_highway();
    }

    let out_dir = env::var("OUT_DIR").unwrap();
    let out_file = Path::new(&out_dir).join("fasthash.rs");

    cargo_emit::rerun_if_changed!("src/fasthash.hpp");
    cargo_emit::rerun_if_changed!("src/fasthash.cpp");

    generate_binding(&out_file);
}
<|endoftext|>


<commit_before>use geohash::interval::*;
use geohash::Geohash;
use geohash::base32;

//
// constants
//
static MAX_LAT: f64 = 90.0;
static MAX_LON: f64 = 180.0;

pub fn decode(hash:&str) -> Option<Geohash> {
  let mut lat      = Interval{ lo:-MAX_LAT, hi:MAX_LAT };
  let mut lon      = Interval{ lo:-MAX_LON, hi:MAX_LON };
  let contract_lat = |op| { lat.contract(op) };
  let contract_lon = |op| { lon.contract(op) };

  let mut bits : ~[bool] = ~[];
  // TODO: implement an iterator over the packed bits, which would
  // return a stream of bools. should simplify the algorthm when I learn
  // how to do write it :)
  //
  for ch in hash.iter() {
    match base32::decode_vec(ch) {
      None => return None,
      Some(char_bits) => { bits.push_all(char_bits) },
    }
  };

  let ops = bits.map(|&bit| if bit {UpperHalf} else {LowerHalf} );

  for (i, &op) in ops.iter().enumerate() {
    if i.is_even() {
      contract_lon(op)
    } else {
      contract_lat(op)
    }
  }

  Some(Geohash{ lat:lat, lon:lon })
}

#[test]
fn test_decode_good() {
  match Geohash::decode("zz") {
    Some(hash) => {
      assert!( hash.lat.low()  == 84.375 );
      assert!( hash.lat.high() == 90.0 );
      assert!( hash.lon.low()  == 168.75 );
      assert!( hash.lon.high() == 180.0 );
    },
    None => fail!("No geohash returned")
  }

  match Geohash::decode("u4pruydqqvj") {
    Some(hash) => {
      assert!( hash.lat.low()  == 57.649109959602356 );
      assert!( hash.lat.high() == 57.64911130070686 );
      assert!( hash.lon.low()  == 10.407439023256302 );
      assert!( hash.lon.high() == 10.40744036436081 );
    },
    None => fail!("No geohash returned")
  }

  match Geohash::decode("") {
    Some(hash) => {
      assert!( hash.lat.low()  == -MAX_LAT );
      assert!( hash.lat.high() == MAX_LAT );
      assert!( hash.lon.low()  == -MAX_LON );
      assert!( hash.lon.high() == MAX_LON );
    },
    None => fail!("No geohash returned")
  }
}

#[test]
fn test_decode_bad() {
  match Geohash::decode("  ") {
    Some(_) => { fail!("A geohash was returned") },
    None => ()
  }

  match Geohash::decode("zza") {
    Some(_) => { fail!("A geohash was returned") },
    None => ()
  }
}

<commit_msg>Removes closures, because adding them were dumb in the first place<commit_after>use geohash::interval::*;
use geohash::Geohash;
use geohash::base32;

//
// constants
//
static MAX_LAT: f64 = 90.0;
static MAX_LON: f64 = 180.0;

pub fn decode(hash:&str) -> Option<Geohash> {
  let mut lat      = Interval{ lo:-MAX_LAT, hi:MAX_LAT };
  let mut lon      = Interval{ lo:-MAX_LON, hi:MAX_LON };

  let mut bits : ~[bool] = ~[];
  // TODO: implement an iterator over the packed bits, which would
  // return a stream of bools. should simplify the algorthm when I learn
  // how to do write it :)
  //
  for ch in hash.iter() {
    match base32::decode_vec(ch) {
      None => return None,
      Some(char_bits) => { bits.push_all(char_bits) },
    }
  };

  let ops = bits.map(|&bit| if bit {UpperHalf} else {LowerHalf} );

  for (i, &op) in ops.iter().enumerate() {
    let comp = if i.is_even() {&mut lon} else {&mut lat};
    comp.contract(op);
  }

  Some(Geohash{ lat:lat, lon:lon })
}

#[test]
fn test_decode_good() {
  match Geohash::decode("zz") {
    Some(hash) => {
      assert!( hash.lat.low()  == 84.375 );
      assert!( hash.lat.high() == 90.0 );
      assert!( hash.lon.low()  == 168.75 );
      assert!( hash.lon.high() == 180.0 );
    },
    None => fail!("No geohash returned")
  }

  match Geohash::decode("u4pruydqqvj") {
    Some(hash) => {
      assert!( hash.lat.low()  == 57.649109959602356 );
      assert!( hash.lat.high() == 57.64911130070686 );
      assert!( hash.lon.low()  == 10.407439023256302 );
      assert!( hash.lon.high() == 10.40744036436081 );
    },
    None => fail!("No geohash returned")
  }

  match Geohash::decode("") {
    Some(hash) => {
      assert!( hash.lat.low()  == -MAX_LAT );
      assert!( hash.lat.high() == MAX_LAT );
      assert!( hash.lon.low()  == -MAX_LON );
      assert!( hash.lon.high() == MAX_LON );
    },
    None => fail!("No geohash returned")
  }
}

#[test]
fn test_decode_bad() {
  match Geohash::decode("  ") {
    Some(_) => { fail!("A geohash was returned") },
    None => ()
  }

  match Geohash::decode("zza") {
    Some(_) => { fail!("A geohash was returned") },
    None => ()
  }
}

<|endoftext|>


<commit_before>use crate::gen::{Error, Input, Result};
use crate::syntax::namespace::Namespace;
use quote::quote;
use syn::{Attribute, File, Item};

pub(super) fn find_bridge_mod(syntax: File) -> Result<Input> {
    match scan(syntax.items)? {
        Some(input) => Ok(input),
        None => Err(Error::NoBridgeMod),
    }
}

fn scan(items: Vec<Item>) -> Result<Option<Input>> {
    for item in items {
        if let Item::Mod(item) = item {
            for attr in &item.attrs {
                let path = &attr.path;
                if quote!(#path).to_string() == "cxx :: bridge" {
                    let module = match item.content {
                        Some(module) => module.1,
                        None => {
                            return Err(Error::Syn(syn::Error::new_spanned(
                                item,
                                Error::OutOfLineMod,
                            )));
                        }
                    };
                    let namespace = parse_args(attr)?;
                    return Ok(Some(Input { namespace, module }));
                }
            }
            if let Some(module) = item.content {
                if let Some(input) = scan(module.1)? {
                    return Ok(Some(input));
                }
            }
        }
    }
    Ok(None)
}

fn parse_args(attr: &Attribute) -> syn::Result<Namespace> {
    if attr.tokens.is_empty() {
        Ok(Namespace::none())
    } else {
        attr.parse_args()
    }
}
<commit_msg>Less brittle matching of cxx::bridge path<commit_after>use crate::gen::{Error, Input, Result};
use crate::syntax::namespace::Namespace;
use syn::{Attribute, File, Item};

pub(super) fn find_bridge_mod(syntax: File) -> Result<Input> {
    match scan(syntax.items)? {
        Some(input) => Ok(input),
        None => Err(Error::NoBridgeMod),
    }
}

fn scan(items: Vec<Item>) -> Result<Option<Input>> {
    for item in items {
        if let Item::Mod(item) = item {
            for attr in &item.attrs {
                let path = &attr.path.segments;
                if path.len() == 2 && path[0].ident == "cxx" && path[1].ident == "bridge" {
                    let module = match item.content {
                        Some(module) => module.1,
                        None => {
                            return Err(Error::Syn(syn::Error::new_spanned(
                                item,
                                Error::OutOfLineMod,
                            )));
                        }
                    };
                    let namespace = parse_args(attr)?;
                    return Ok(Some(Input { namespace, module }));
                }
            }
            if let Some(module) = item.content {
                if let Some(input) = scan(module.1)? {
                    return Ok(Some(input));
                }
            }
        }
    }
    Ok(None)
}

fn parse_args(attr: &Attribute) -> syn::Result<Namespace> {
    if attr.tokens.is_empty() {
        Ok(Namespace::none())
    } else {
        attr.parse_args()
    }
}
<|endoftext|>


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

use servo_util::namespace;
use dom::attr::Attr;
use dom::bindings::codegen::InheritTypes::{ElementCast, TextCast, CommentCast, NodeCast};
use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, CharacterDataCast};
use dom::bindings::codegen::InheritTypes::ProcessingInstructionCast;
use dom::bindings::js::JSRef;
use dom::characterdata::CharacterData;
use dom::comment::Comment;
use dom::documenttype::DocumentType;
use dom::element::Element;
use dom::node::{Node, NodeIterator};
use dom::node::{DoctypeNodeTypeId, DocumentFragmentNodeTypeId, CommentNodeTypeId};
use dom::node::{DocumentNodeTypeId, ElementNodeTypeId, ProcessingInstructionNodeTypeId};
use dom::node::{TextNodeTypeId, NodeHelpers};
use dom::processinginstruction::ProcessingInstruction;
use dom::text::Text;

pub fn serialize(iterator: &mut NodeIterator) -> ~str {
    let mut html = StrBuf::new();
    let mut open_elements: Vec<~str> = vec!();

    for node in *iterator {
        while open_elements.len() > iterator.depth {
            html.push_str("</");
            html.push_str(open_elements.pop().unwrap().as_slice());
            html.push_str(">");
        }
        match node.type_id() {
            ElementNodeTypeId(..) => {
                let elem: &JSRef<Element> = ElementCast::to_ref(&node).unwrap();
                serialize_elem(elem, &mut open_elements, &mut html)
            }
            CommentNodeTypeId => {
                let comment: &JSRef<Comment> = CommentCast::to_ref(&node).unwrap();
                serialize_comment(comment, &mut html)
            }
            TextNodeTypeId => {
                let text: &JSRef<Text> = TextCast::to_ref(&node).unwrap();
                serialize_text(text, &mut html)
            }
            DoctypeNodeTypeId => {
                let doctype: &JSRef<DocumentType> = DocumentTypeCast::to_ref(&node).unwrap();
                serialize_doctype(doctype, &mut html)
            }
            ProcessingInstructionNodeTypeId => {
                let processing_instruction: &JSRef<ProcessingInstruction> =
                    ProcessingInstructionCast::to_ref(&node).unwrap();
                serialize_processing_instruction(processing_instruction, &mut html)
            }
            DocumentFragmentNodeTypeId => {}
            DocumentNodeTypeId => {
                fail!("It shouldn't be possible to serialize a document node")
            }
        }
    }
    while open_elements.len() > 0 {
        html.push_str("</");
        html.push_str(open_elements.pop().unwrap().as_slice());
        html.push_str(">");
    }
    html.into_owned()
}

fn serialize_comment(comment: &JSRef<Comment>, html: &mut StrBuf) {
    html.push_str("<!--");
    html.push_str(comment.deref().characterdata.data);
    html.push_str("-->");
}

fn serialize_text(text: &JSRef<Text>, html: &mut StrBuf) {
    let text_node: &JSRef<Node> = NodeCast::from_ref(text);
    match text_node.parent_node().map(|node| node.root()) {
        Some(ref parent) if parent.is_element() => {
            let elem: &JSRef<Element> = ElementCast::to_ref(&**parent).unwrap();
            match elem.deref().local_name.as_slice() {
                "style" | "script" | "xmp" | "iframe" |
                "noembed" | "noframes" | "plaintext" |
                "noscript" if elem.deref().namespace == namespace::HTML
                => html.push_str(text.deref().characterdata.data),
                _ => html.push_str(escape(text.deref().characterdata.data, false))
            }
        }
        _ => html.push_str(escape(text.deref().characterdata.data, false))
    }
}

fn serialize_processing_instruction(processing_instruction: &JSRef<ProcessingInstruction>,
                                    html: &mut StrBuf) {
    html.push_str("<?");
    html.push_str(processing_instruction.deref().target);
    html.push_char(' ');
    html.push_str(processing_instruction.deref().characterdata.data);
    html.push_str("?>");
}

fn serialize_doctype(doctype: &JSRef<DocumentType>, html: &mut StrBuf) {
    html.push_str("<!DOCTYPE");
    html.push_str(doctype.deref().name);
    html.push_char('>');
}

fn serialize_elem(elem: &JSRef<Element>, open_elements: &mut Vec<~str>, html: &mut StrBuf) {
    html.push_char('<');
    html.push_str(elem.deref().local_name);
    for attr in elem.deref().attrs.iter() {
        let attr = attr.root();
        serialize_attr(&*attr, html);
    };
    html.push_char('>');

    match elem.deref().local_name.as_slice() {
        "pre" | "listing" | "textarea" if elem.deref().namespace == namespace::HTML => {
            let node: &JSRef<Node> = NodeCast::from_ref(elem);
            match node.first_child().map(|child| child.root()) {
                Some(ref child) if child.is_text() => {
                    let text: &JSRef<CharacterData> = CharacterDataCast::to_ref(&**child).unwrap();
                    if text.deref().data.len() > 0 && text.deref().data[0] == 0x0A as u8 {
                        html.push_char('\x0A');
                    }
                },
                _ => {}
            }
        },
        _ => {}
    }

    if !elem.deref().is_void() {
        open_elements.push(elem.deref().local_name.clone());
    }
}

fn serialize_attr(attr: &JSRef<Attr>, html: &mut StrBuf) {
    html.push_char(' ');
    if attr.deref().namespace == namespace::XML {
        html.push_str("xml:");
        html.push_str(attr.deref().local_name);
    } else if attr.deref().namespace == namespace::XMLNS &&
        attr.deref().local_name.as_slice() == "xmlns" {
        html.push_str("xmlns");
    } else if attr.deref().namespace == namespace::XMLNS {
        html.push_str("xmlns:");
        html.push_str(attr.deref().local_name);
    } else if attr.deref().namespace == namespace::XLink {
        html.push_str("xlink:");
        html.push_str(attr.deref().local_name);
    } else {
        html.push_str(attr.deref().name);
    };
    html.push_str("=\"");
    html.push_str(escape(attr.deref().value, true));
    html.push_char('"');
}

fn escape(string: &str, attr_mode: bool) -> ~str {
    let replaced = string.replace("&", "&").replace("\xA0", " ");
    match attr_mode {
        true => {
            replaced.replace("\"", """)
        },
        false => {
            replaced.replace("<", "<").replace(">", ">")
        }
    }
}
<commit_msg>Rewrite escape() in htmlserializer to push onto a StrBuf.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use servo_util::namespace;
use dom::attr::Attr;
use dom::bindings::codegen::InheritTypes::{ElementCast, TextCast, CommentCast, NodeCast};
use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, CharacterDataCast};
use dom::bindings::codegen::InheritTypes::ProcessingInstructionCast;
use dom::bindings::js::JSRef;
use dom::characterdata::CharacterData;
use dom::comment::Comment;
use dom::documenttype::DocumentType;
use dom::element::Element;
use dom::node::{Node, NodeIterator};
use dom::node::{DoctypeNodeTypeId, DocumentFragmentNodeTypeId, CommentNodeTypeId};
use dom::node::{DocumentNodeTypeId, ElementNodeTypeId, ProcessingInstructionNodeTypeId};
use dom::node::{TextNodeTypeId, NodeHelpers};
use dom::processinginstruction::ProcessingInstruction;
use dom::text::Text;

pub fn serialize(iterator: &mut NodeIterator) -> ~str {
    let mut html = StrBuf::new();
    let mut open_elements: Vec<~str> = vec!();

    for node in *iterator {
        while open_elements.len() > iterator.depth {
            html.push_str("</");
            html.push_str(open_elements.pop().unwrap().as_slice());
            html.push_str(">");
        }
        match node.type_id() {
            ElementNodeTypeId(..) => {
                let elem: &JSRef<Element> = ElementCast::to_ref(&node).unwrap();
                serialize_elem(elem, &mut open_elements, &mut html)
            }
            CommentNodeTypeId => {
                let comment: &JSRef<Comment> = CommentCast::to_ref(&node).unwrap();
                serialize_comment(comment, &mut html)
            }
            TextNodeTypeId => {
                let text: &JSRef<Text> = TextCast::to_ref(&node).unwrap();
                serialize_text(text, &mut html)
            }
            DoctypeNodeTypeId => {
                let doctype: &JSRef<DocumentType> = DocumentTypeCast::to_ref(&node).unwrap();
                serialize_doctype(doctype, &mut html)
            }
            ProcessingInstructionNodeTypeId => {
                let processing_instruction: &JSRef<ProcessingInstruction> =
                    ProcessingInstructionCast::to_ref(&node).unwrap();
                serialize_processing_instruction(processing_instruction, &mut html)
            }
            DocumentFragmentNodeTypeId => {}
            DocumentNodeTypeId => {
                fail!("It shouldn't be possible to serialize a document node")
            }
        }
    }
    while open_elements.len() > 0 {
        html.push_str("</");
        html.push_str(open_elements.pop().unwrap().as_slice());
        html.push_str(">");
    }
    html.into_owned()
}

fn serialize_comment(comment: &JSRef<Comment>, html: &mut StrBuf) {
    html.push_str("<!--");
    html.push_str(comment.deref().characterdata.data);
    html.push_str("-->");
}

fn serialize_text(text: &JSRef<Text>, html: &mut StrBuf) {
    let text_node: &JSRef<Node> = NodeCast::from_ref(text);
    match text_node.parent_node().map(|node| node.root()) {
        Some(ref parent) if parent.is_element() => {
            let elem: &JSRef<Element> = ElementCast::to_ref(&**parent).unwrap();
            match elem.deref().local_name.as_slice() {
                "style" | "script" | "xmp" | "iframe" |
                "noembed" | "noframes" | "plaintext" |
                "noscript" if elem.deref().namespace == namespace::HTML
                => html.push_str(text.deref().characterdata.data),
                _ => escape(text.deref().characterdata.data, false, html)
            }
        }
        _ => escape(text.deref().characterdata.data, false, html)
    }
}

fn serialize_processing_instruction(processing_instruction: &JSRef<ProcessingInstruction>,
                                    html: &mut StrBuf) {
    html.push_str("<?");
    html.push_str(processing_instruction.deref().target);
    html.push_char(' ');
    html.push_str(processing_instruction.deref().characterdata.data);
    html.push_str("?>");
}

fn serialize_doctype(doctype: &JSRef<DocumentType>, html: &mut StrBuf) {
    html.push_str("<!DOCTYPE");
    html.push_str(doctype.deref().name);
    html.push_char('>');
}

fn serialize_elem(elem: &JSRef<Element>, open_elements: &mut Vec<~str>, html: &mut StrBuf) {
    html.push_char('<');
    html.push_str(elem.deref().local_name);
    for attr in elem.deref().attrs.iter() {
        let attr = attr.root();
        serialize_attr(&*attr, html);
    };
    html.push_char('>');

    match elem.deref().local_name.as_slice() {
        "pre" | "listing" | "textarea" if elem.deref().namespace == namespace::HTML => {
            let node: &JSRef<Node> = NodeCast::from_ref(elem);
            match node.first_child().map(|child| child.root()) {
                Some(ref child) if child.is_text() => {
                    let text: &JSRef<CharacterData> = CharacterDataCast::to_ref(&**child).unwrap();
                    if text.deref().data.len() > 0 && text.deref().data[0] == 0x0A as u8 {
                        html.push_char('\x0A');
                    }
                },
                _ => {}
            }
        },
        _ => {}
    }

    if !elem.deref().is_void() {
        open_elements.push(elem.deref().local_name.clone());
    }
}

fn serialize_attr(attr: &JSRef<Attr>, html: &mut StrBuf) {
    html.push_char(' ');
    if attr.deref().namespace == namespace::XML {
        html.push_str("xml:");
        html.push_str(attr.deref().local_name);
    } else if attr.deref().namespace == namespace::XMLNS &&
        attr.deref().local_name.as_slice() == "xmlns" {
        html.push_str("xmlns");
    } else if attr.deref().namespace == namespace::XMLNS {
        html.push_str("xmlns:");
        html.push_str(attr.deref().local_name);
    } else if attr.deref().namespace == namespace::XLink {
        html.push_str("xlink:");
        html.push_str(attr.deref().local_name);
    } else {
        html.push_str(attr.deref().name);
    };
    html.push_str("=\"");
    escape(attr.deref().value, true, html);
    html.push_char('"');
}

fn escape(string: &str, attr_mode: bool, html: &mut StrBuf) {
    for c in string.chars() {
        match c {
            '&' => html.push_str("&"),
            '\xA0' => html.push_str(" "),
            '"' if attr_mode => html.push_str("""),
            '<' if !attr_mode => html.push_str("<"),
            '>' if !attr_mode => html.push_str(">"),
            c => html.push_char(c),
        }
    }
}
<|endoftext|>


<commit_before>
extern crate mmap;
extern crate time;
extern crate timely;
extern crate dataflow_join;

use std::rc::Rc;

use dataflow_join::*;
use dataflow_join::graph::{GraphTrait, GraphMMap, GraphExtenderExt};

use timely::dataflow::*;
use timely::dataflow::operators::*;
use timely::progress::timestamp::RootTimestamp;

fn main () {

    let filename = std::env::args().nth(1).unwrap();
    let inspect = std::env::args().nth(2).unwrap() == "inspect";
    let step_size = std::env::args().nth(3).unwrap().parse::<usize>().unwrap();

    timely::execute_from_args(std::env::args().skip(4), move |root| {

        let index = root.index();
        let peers = root.peers();

        let graph = Rc::new(GraphMMap::<u32>::new(&filename));

        let (mut input, probe) = root.scoped(|builder| {

            let (input, cliques) = builder.new_input::<u32>();

            // pairs
            let cliques = cliques.extend(vec![&graph.extend_using(|&a| a as u64)]);

            // triangles
            let cliques = cliques.flat_map(|(p, es)| es.into_iter().map(move |e| (p, e)))
                                 .extend(vec![&graph.extend_using(|&(a,_)| a as u64),
                                              &graph.extend_using(|&(_,b)| b as u64)]);

            // // quadrangles?
            // let cliques = cliques.flat_map(|(p,es)| es.into_iter().map(move |e| (p, e)))
            //                      .extend(vec![&graph.extend_using(|&((a,_),_)| a as u64),
            //                                   &graph.extend_using(|&((_,b),_)| b as u64),
            //                                   &graph.extend_using(|&((_,_),c)| c as u64)]);

            // // 5 cliques?
            // let cliques = cliques.flat_map(|(p,es)| es.into_iter().map(move |e| (p, e)))
            //                      .extend(vec![&graph.extend_using(|&(((a,_),_),_)| a as u64),
            //                                   &graph.extend_using(|&(((_,b),_),_)| b as u64),
            //                                   &graph.extend_using(|&(((_,_),c),_)| c as u64),
            //                                   &graph.extend_using(|&(((_,_),_),d)| d as u64)]);

            let mut count = 0;
            if inspect {
                cliques.inspect_batch(move |_t, b| {
                    for x in b { count += x.1.len(); }
                    println!("count: {}", count);
                });
            }

            (input, cliques.probe().0)
        });

        let nodes = graph.nodes() - 1;
        let limit = (nodes / step_size) + 1;
        for round in (0..limit) {
            for source in 0..step_size {
                let candidate = source + round * step_size;
                if candidate % peers == index && candidate < nodes {
                    input.send(candidate as u32);
                }
            }

            input.advance_to(round as u64 + 1);
            root.step();
            while probe.lt(&RootTimestamp::new((round - ::std::cmp::min(1, round)) as u64)) {
                root.step();
            }
        }
    })
}
<commit_msg>examples needed fixing too<commit_after>
extern crate mmap;
extern crate time;
extern crate timely;
extern crate dataflow_join;

use std::rc::Rc;

use dataflow_join::*;
use dataflow_join::graph::{GraphTrait, GraphMMap, GraphExtenderExt};

use timely::dataflow::*;
use timely::dataflow::operators::*;
use timely::progress::timestamp::RootTimestamp;

fn main () {

    let filename = std::env::args().nth(1).unwrap();
    let inspect = std::env::args().nth(2).unwrap() == "inspect";
    let step_size = std::env::args().nth(3).unwrap().parse::<usize>().unwrap();

    timely::execute_from_args(std::env::args().skip(4), move |root| {

        let index = root.index();
        let peers = root.peers();

        let graph = Rc::new(GraphMMap::<u32>::new(&filename));

        let (mut input, probe) = root.scoped(|builder| {

            let (input, cliques) = builder.new_input::<u32>();

            // pairs
            let cliques = cliques.extend(vec![&graph.extend_using(|&a| a as u64)]);

            // triangles
            let cliques = cliques.flat_map(|(p, es)| es.into_iter().map(move |e| (p, e)))
                                 .extend(vec![&graph.extend_using(|&(a,_)| a as u64),
                                              &graph.extend_using(|&(_,b)| b as u64)]);

            // // quadrangles?
            // let cliques = cliques.flat_map(|(p,es)| es.into_iter().map(move |e| (p, e)))
            //                      .extend(vec![&graph.extend_using(|&((a,_),_)| a as u64),
            //                                   &graph.extend_using(|&((_,b),_)| b as u64),
            //                                   &graph.extend_using(|&((_,_),c)| c as u64)]);

            // // 5 cliques?
            // let cliques = cliques.flat_map(|(p,es)| es.into_iter().map(move |e| (p, e)))
            //                      .extend(vec![&graph.extend_using(|&(((a,_),_),_)| a as u64),
            //                                   &graph.extend_using(|&(((_,b),_),_)| b as u64),
            //                                   &graph.extend_using(|&(((_,_),c),_)| c as u64),
            //                                   &graph.extend_using(|&(((_,_),_),d)| d as u64)]);

            let mut count = 0;
            if inspect {
                cliques.inspect_batch(move |_t, b| {
                    for x in b { count += x.1.len(); }
                    println!("count: {}", count);
                });
            }

            (input, cliques.probe().0)
        });

        let nodes = graph.nodes() - 1;
        let limit = (nodes / step_size) + 1;
        for round in 0..limit {
            for source in 0..step_size {
                let candidate = source + round * step_size;
                if candidate % peers == index && candidate < nodes {
                    input.send(candidate as u32);
                }
            }

            input.advance_to(round as u64 + 1);
            root.step();
            while probe.lt(&RootTimestamp::new((round - ::std::cmp::min(1, round)) as u64)) {
                root.step();
            }
        }
    }).unwrap();
}
<|endoftext|>