<commit_before>use core::util;
use core::cmp::{ Ord, Eq };
use core::ops::{ Add, Mul };
use core::num::{ Zero, One };
use core::iterator::{ Iterator };

use common::bounded::{ Bounded };

pub trait Monoid {
    fn mempty() -> Self;
    fn mappend(&self, other: &Self) -> Self;
}

pub trait Unwrap<T> {
    fn unwrap(&self) -> T;
}

pub struct Sum<T> { repr: T }
pub fn Sum<T>(val: T) -> Sum<T> { Sum { repr: val } }

impl<T: Zero+Add<T,T>+Copy> Monoid for Sum<T> {
    fn mempty() -> Sum<T> { Sum(Zero::zero()) }
    fn mappend(&self, other: &Sum<T>) -> Sum<T> { Sum(self.repr + other.repr) }
}

impl<T: Copy> Unwrap<T> for Sum<T> {
    fn unwrap(&self) -> T { self.repr }
}

impl<T: Eq> Eq for Sum<T> {
    fn eq(&self, other: &Sum<T>) -> bool { self.repr == other.repr }
    fn ne(&self, other: &Sum<T>) -> bool { self.repr != other.repr }
}

pub struct Prod<T> { repr: T }
pub fn Prod<T>(val: T) -> Prod<T> { Prod { repr: val }}

impl<T: One+Mul<T,T>+Copy> Monoid for Prod<T> {
    fn mempty() -> Prod<T> { Prod(One::one()) }
    fn mappend(&self, other: &Prod<T>) -> Prod<T> { Prod(self.repr * other.repr) }
}

impl<T: Copy> Unwrap<T> for Prod<T> {
    fn unwrap(&self) -> T { self.repr }
}

impl<T: cmp::Eq> Eq for Prod<T> {
    fn eq(&self, other: &Prod<T>) -> bool { self.repr == other.repr }
    fn ne(&self, other: &Prod<T>) -> bool { self.repr != other.repr }
}

pub struct Max<T> { repr: T }
pub fn Max<T>(val: T) -> Max<T> { Max{ repr: val } }

impl<T: Copy+Bounded+Ord> Monoid for Max<T> {
    fn mempty() -> Max<T> { Max(Bounded::min_value()) }
    fn mappend(&self, other: &Max<T>) -> Max<T> {
        if self.repr < other.repr { *other } else { *self }
    }
}

impl<T: Copy> Unwrap<T> for Max<T> {
    fn unwrap(&self) -> T { self.repr }
}

impl<T: Eq> Eq for Max<T> {
    fn eq(&self, other: &Max<T>) -> bool { self.repr == other.repr }
    fn ne(&self, other: &Max<T>) -> bool { self.repr != other.repr }
}

pub struct Min<T> { repr: T }
pub fn Min<T>(val: T) -> Min<T> { Min { repr: val } }

impl<T: Copy+Bounded+Ord> Monoid for Min<T> {
    fn mempty() -> Min<T> { Min(Bounded::max_value()) }
    fn mappend(&self, other: &Min<T>) -> Min<T> {
        if self.repr > other.repr { *other } else { *self }
    }
}

impl<T: Copy> Unwrap<T> for Min<T> {
    fn unwrap(&self) -> T { self.repr }
}

impl<T: Eq> Eq for Min<T> {
    fn eq(&self, other: &Min<T>) -> bool { self.repr == other.repr }
    fn ne(&self, other: &Min<T>) -> bool { self.repr != other.repr }
}

pub fn mconcat<T: Copy+Monoid>(v: &[T]) -> T {
    vec::foldl(Monoid::mempty(), v, |accum, elt| { elt.mappend(&accum) })
}

struct MergeMonoidIterator<V, T, U> {
    iter1: T,
    value1: Option<V>,
    iter2: U,
    value2: Option<V>
}

impl<V, T: Iterator<V>, U: Iterator<V>> MergeMonoidIterator<V, T, U> {
    pub fn new(iter1: T, iter2: U) -> MergeMonoidIterator<V, T, U> {
        MergeMonoidIterator { iter1: iter1, value1: None, iter2: iter2, value2: None }
    }
}

impl<K: TotalOrd, V: Monoid, T: Iterator<(K, V)>, U: Iterator<(K, V)>>
    Iterator<(K, V)> for MergeMonoidIterator<(K, V), T, U> {
    fn next(&mut self) -> Option<(K, V)> {
        fn return_val<V>(opt: &mut Option<V>) -> Option<V> {
            let mut result = None;
            util::swap(opt, &mut result);
            return result;
        }

        // Fill value if empty (if iter ends, set None)
        if self.value1.is_none() { self.value1 = self.iter1.next(); }
        if self.value2.is_none() { self.value2 = self.iter2.next(); }

        // If one value is None, returns anogher value (with setting None)
        if self.value1.is_none() { return return_val(&mut self.value2); }
        if self.value2.is_none() { return return_val(&mut self.value1); }

        // Returns smaller value
        let cmp = self.value1.get_ref().first_ref().cmp(self.value2.get_ref().first_ref());
        match cmp {
            Less    => { return return_val(&mut self.value1); }
            Greater => { return return_val(&mut self.value2); },
            Equal   => {
                let mut r1 = None, r2 = None;
                util::swap(&mut self.value1, &mut r1);
                util::swap(&mut self.value2, &mut r2);
                let ((k, v1), (_, v2)) = (r1.unwrap(), r2.unwrap());
                return Some((k, v1.mappend(&v2)));
            }
        }
    }
}

pub fn merge<T: Copy + Ord, M: Copy + Monoid>(
    vec1: &[(T, M)], vec2: &[(T, M)]
) -> ~[(T, M)] {
    let (l1, l2) = (vec1.len(), vec2.len());

    let mut result = ~[];
    let mut (i1, i2) = (0, 0);
    while i1 < l1 && i2 < l2 {
        let (v1, m1) = vec1[i1];
        let (v2, m2) = vec2[i2];
        if v1 < v2 {
            result.push((v1, m1));
            i1 += 1;
            loop;
        }
        if v2 < v1 {
            result.push((v2, m2));
            i2 += 1;
            loop;
        }
        result.push((v1, m1.mappend(&m2)));
        i1 += 1;
        i2 += 1;
    }

    if i1 < l1 { result += vec1.slice(i1, l1); }
    if i2 < l2 { result += vec2.slice(i2, l2); }
    return result;
}

pub fn mergei<T: Copy+Ord, M: Copy+Monoid>(vecs: &[~[(T, M)]]) -> ~[(T, M)] {
    return match vecs.len() {
      0u => ~[],
      1u => ~[] + vecs[0],
      len  => {
        let pre  = mergei(vecs.slice(0u, len / 2u));
        let post = mergei(vecs.slice(len / 2u, len));
        merge(pre, post)
      }
    }
}

pub fn merge_as<T: Copy+Ord, U: Copy, MT, M: Copy+Monoid+Unwrap<MT>>
    (vec1: &[(T, U)], vec2: &[(T, U)], f: &fn(U) -> M) -> ~[(T, MT)] {
    fn convert<T: Copy, U: Copy, M: Copy>(v: &[(T, U)], f: &fn(U) -> M) -> ~[(T, M)] {
        do v.map |tp| { (tp.first(), f(tp.second())) }
    }
    return merge(convert(vec1, f), convert(vec2, f)).map(|tp| (tp.first(), tp.second().unwrap()));
}

pub fn mergei_as<T: Copy+Ord, U: Copy, MT, M: Copy+Monoid+Unwrap<MT>>(vecs: &[~[(T, U)]], f: &fn(U) -> M) -> ~[(T, MT)] {
    return mergei(
        vecs.map(|v| v.map(|tp| (tp.first(), f(tp.second()))))
    ).map(|tp| (tp.first(), tp.second().unwrap()));
}

#[cfg(test)]
mod tests {
    use super::*;
    use core::iterator::{ IteratorUtil };
    use common::extvec;

    fn to_sum<T, U>(&tp: &(T, U)) -> (T, Sum<U>) {
        let (t, u) = tp;
        return (t, Sum(u));
    }

    fn to_max<T, U>(&tp: &(T, U)) -> (T, Max<U>) {
        let (t, u) = tp;
        return (t, Max(u));
    }

    #[test]
    fn test_merge_monoid_iterator() {
        fn check<M: Monoid + Eq>(v1: &[(int, int)],
                                 v2: &[(int, int)],
                                 f: &fn(&(int, int)) -> (int, M),
                                 result: &[(int, int)]) {
            assert_eq!(
                extvec::from_iter(MergeMonoidIterator::new(v1.iter().transform(f),
                                                           v2.iter().transform(f))),
                result.map(f));
            assert_eq!(
                extvec::from_iter(MergeMonoidIterator::new(v2.iter().transform(f),
                                                           v1.iter().transform(f))),
                result.map(f));
        }

        let v1 = [(1, 1), (3, 1), (4, 1), (6, 1)];
        let v2 = [(1, 2), (2, 1), (4, 1), (7, 2)];

        check(v1, v2, to_sum, [(1, 3), (2, 1), (3, 1), (4, 2), (6, 1), (7, 2)]);
        check(v1, v2, to_max, [(1, 2), (2, 1), (3, 1), (4, 1), (6, 1), (7, 2)]);

        check(v1, [], to_sum, v1);
        check([], [], to_sum, []);
    }

    #[test]
    fn test_merge() {
        let arg1 = [(1, 1), (3, 1), (4, 1), (6, 1)];
        let arg2 = [(1, 2), (2, 1), (4, 1), (7, 2)];

        {
            let result = ~[(1, 3), (2, 1), (3, 1), (4, 2), (6, 1), (7, 2)];
            assert_eq!(merge(arg1.map(to_sum), arg2.map(to_sum)),
                       result.map(to_sum));
            assert_eq!(merge_as(arg1, arg2, Sum), result);
        }

        {
            let result = ~[(1, 2), (2, 1), (3, 1), (4, 1), (6, 1), (7, 2)];
            assert_eq!(merge(arg1.map(to_max), arg2.map(to_max)),
                       result.map(to_max));
            assert_eq!(merge_as(arg1, arg2, Max),
                       result);
        }

        {
            let result = arg1.map(to_sum);
            assert_eq!(merge(result, []), result);
        }

        {
            let result: ~[(int, Sum<int>)] = ~[];
            assert_eq!(merge([], []), result);
        }
    }

    #[test]
    fn test_mergei() {
        {
            let arg = [~[(1, 1), (2, 1)], ~[(1, 2), (3, 1)], ~[(-1, 3)]];
            let result = ~[(-1, 3), (1, 3), (2, 1), (3, 1)];
            assert_eq!(mergei(arg.map(|v| v.map(to_sum))), result.map(to_sum));
            assert_eq!(mergei_as(arg, Sum), result);
        }

        {
            let arg = [~[(1, 1)], ~[(1, 2)], ~[(1, 3)]];
            let result = ~[(1, 6)];
            assert_eq!(mergei(arg.map(|v| v.map(to_sum))), result.map(to_sum));
            assert_eq!(mergei_as(arg, Sum), result);
        }

        {
            let arg = [~[], ~[], ~[]];
            let result: ~[(int, int)] = ~[];
            assert_eq!(mergei(arg.map(|v| v.map(to_sum))),
                       result.map(to_sum));
            assert_eq!(mergei_as(arg, Sum),
                       result);
        }
    }
}

<commit_msg>Add common::monoid::merge_monoid_as<commit_after>use core::util;
use core::cmp::{ Ord, Eq };
use core::ops::{ Add, Mul };
use core::num::{ Zero, One };
use core::iterator::{ Iterator, IteratorUtil, MapIterator };

use common::bounded::{ Bounded };

pub trait Monoid {
    fn mempty() -> Self;
    fn mappend(&self, other: &Self) -> Self;
}

pub trait Unwrap<T> {
    fn unwrap(&self) -> T;
}

pub struct Sum<T> { repr: T }
pub fn Sum<T>(val: T) -> Sum<T> { Sum { repr: val } }

impl<T: Zero+Add<T,T>+Copy> Monoid for Sum<T> {
    fn mempty() -> Sum<T> { Sum(Zero::zero()) }
    fn mappend(&self, other: &Sum<T>) -> Sum<T> { Sum(self.repr + other.repr) }
}

impl<T: Copy> Unwrap<T> for Sum<T> {
    fn unwrap(&self) -> T { self.repr }
}

impl<T: Eq> Eq for Sum<T> {
    fn eq(&self, other: &Sum<T>) -> bool { self.repr == other.repr }
    fn ne(&self, other: &Sum<T>) -> bool { self.repr != other.repr }
}

pub struct Prod<T> { repr: T }
pub fn Prod<T>(val: T) -> Prod<T> { Prod { repr: val }}

impl<T: One+Mul<T,T>+Copy> Monoid for Prod<T> {
    fn mempty() -> Prod<T> { Prod(One::one()) }
    fn mappend(&self, other: &Prod<T>) -> Prod<T> { Prod(self.repr * other.repr) }
}

impl<T: Copy> Unwrap<T> for Prod<T> {
    fn unwrap(&self) -> T { self.repr }
}

impl<T: cmp::Eq> Eq for Prod<T> {
    fn eq(&self, other: &Prod<T>) -> bool { self.repr == other.repr }
    fn ne(&self, other: &Prod<T>) -> bool { self.repr != other.repr }
}

pub struct Max<T> { repr: T }
pub fn Max<T>(val: T) -> Max<T> { Max{ repr: val } }

impl<T: Copy+Bounded+Ord> Monoid for Max<T> {
    fn mempty() -> Max<T> { Max(Bounded::min_value()) }
    fn mappend(&self, other: &Max<T>) -> Max<T> {
        if self.repr < other.repr { *other } else { *self }
    }
}

impl<T: Copy> Unwrap<T> for Max<T> {
    fn unwrap(&self) -> T { self.repr }
}

impl<T: Eq> Eq for Max<T> {
    fn eq(&self, other: &Max<T>) -> bool { self.repr == other.repr }
    fn ne(&self, other: &Max<T>) -> bool { self.repr != other.repr }
}

pub struct Min<T> { repr: T }
pub fn Min<T>(val: T) -> Min<T> { Min { repr: val } }

impl<T: Copy+Bounded+Ord> Monoid for Min<T> {
    fn mempty() -> Min<T> { Min(Bounded::max_value()) }
    fn mappend(&self, other: &Min<T>) -> Min<T> {
        if self.repr > other.repr { *other } else { *self }
    }
}

impl<T: Copy> Unwrap<T> for Min<T> {
    fn unwrap(&self) -> T { self.repr }
}

impl<T: Eq> Eq for Min<T> {
    fn eq(&self, other: &Min<T>) -> bool { self.repr == other.repr }
    fn ne(&self, other: &Min<T>) -> bool { self.repr != other.repr }
}

pub fn mconcat<T: Copy+Monoid>(v: &[T]) -> T {
    vec::foldl(Monoid::mempty(), v, |accum, elt| { elt.mappend(&accum) })
}

struct MergeMonoidIterator<V, T, U> {
    iter1: T,
    value1: Option<V>,
    iter2: U,
    value2: Option<V>
}

impl<V, T: Iterator<V>, U: Iterator<V>> MergeMonoidIterator<V, T, U> {
    pub fn new(iter1: T, iter2: U) -> MergeMonoidIterator<V, T, U> {
        MergeMonoidIterator { iter1: iter1, value1: None, iter2: iter2, value2: None }
    }
}

impl<K: TotalOrd, V: Monoid, T: Iterator<(K, V)>, U: Iterator<(K, V)>>
    Iterator<(K, V)> for MergeMonoidIterator<(K, V), T, U> {
    fn next(&mut self) -> Option<(K, V)> {
        fn return_val<V>(opt: &mut Option<V>) -> Option<V> {
            let mut result = None;
            util::swap(opt, &mut result);
            return result;
        }

        // Fill value if empty (if iter ends, set None)
        if self.value1.is_none() { self.value1 = self.iter1.next(); }
        if self.value2.is_none() { self.value2 = self.iter2.next(); }

        // If one value is None, returns anogher value (with setting None)
        if self.value1.is_none() { return return_val(&mut self.value2); }
        if self.value2.is_none() { return return_val(&mut self.value1); }

        // Returns smaller value
        let cmp = self.value1.get_ref().first_ref().cmp(self.value2.get_ref().first_ref());
        match cmp {
            Less    => { return return_val(&mut self.value1); }
            Greater => { return return_val(&mut self.value2); },
            Equal   => {
                let mut r1 = None, r2 = None;
                util::swap(&mut self.value1, &mut r1);
                util::swap(&mut self.value2, &mut r2);
                let ((k, v1), (_, v2)) = (r1.unwrap(), r2.unwrap());
                return Some((k, v1.mappend(&v2)));
            }
        }
    }
}

pub fn merge_monoid_as<K: TotalOrd, V, MT, M: Monoid + Unwrap<MT>, T: Iterator<(K, V)>, U: Iterator<(K, V)>, X>
    (it1: T, it2: U, conv: &fn(V) -> M,
     f: &fn(MapIterator<(K, M), (K, MT),
            MergeMonoidIterator<(K, M), MapIterator<(K, V), (K, M), T>,
            MapIterator<(K, V), (K, M), U>>>) -> X
    ) -> X {
    let it1 = it1.transform(|(k, v)| (k, conv(v)));
    let it2 = it2.transform(|(k, v)| (k, conv(v)));
    let it = MergeMonoidIterator::new(it1, it2);
    return f(it.transform(|(k, m)| (k, m.unwrap())));
}

pub fn merge<T: Copy + Ord, M: Copy + Monoid>(
    vec1: &[(T, M)], vec2: &[(T, M)]
) -> ~[(T, M)] {
    let (l1, l2) = (vec1.len(), vec2.len());

    let mut result = ~[];
    let mut (i1, i2) = (0, 0);
    while i1 < l1 && i2 < l2 {
        let (v1, m1) = vec1[i1];
        let (v2, m2) = vec2[i2];
        if v1 < v2 {
            result.push((v1, m1));
            i1 += 1;
            loop;
        }
        if v2 < v1 {
            result.push((v2, m2));
            i2 += 1;
            loop;
        }
        result.push((v1, m1.mappend(&m2)));
        i1 += 1;
        i2 += 1;
    }

    if i1 < l1 { result += vec1.slice(i1, l1); }
    if i2 < l2 { result += vec2.slice(i2, l2); }
    return result;
}

pub fn mergei<T: Copy+Ord, M: Copy+Monoid>(vecs: &[~[(T, M)]]) -> ~[(T, M)] {
    return match vecs.len() {
      0u => ~[],
      1u => ~[] + vecs[0],
      len  => {
        let pre  = mergei(vecs.slice(0u, len / 2u));
        let post = mergei(vecs.slice(len / 2u, len));
        merge(pre, post)
      }
    }
}

pub fn merge_as<T: Copy+Ord, U: Copy, MT, M: Copy+Monoid+Unwrap<MT>>
    (vec1: &[(T, U)], vec2: &[(T, U)], f: &fn(U) -> M) -> ~[(T, MT)] {
    fn convert<T: Copy, U: Copy, M: Copy>(v: &[(T, U)], f: &fn(U) -> M) -> ~[(T, M)] {
        do v.map |tp| { (tp.first(), f(tp.second())) }
    }
    return merge(convert(vec1, f), convert(vec2, f)).map(|tp| (tp.first(), tp.second().unwrap()));
}

pub fn mergei_as<T: Copy+Ord, U: Copy, MT, M: Copy+Monoid+Unwrap<MT>>(vecs: &[~[(T, U)]], f: &fn(U) -> M) -> ~[(T, MT)] {
    return mergei(
        vecs.map(|v| v.map(|tp| (tp.first(), f(tp.second()))))
    ).map(|tp| (tp.first(), tp.second().unwrap()));
}

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

    fn to_sum<T, U>(&tp: &(T, U)) -> (T, Sum<U>) {
        let (t, u) = tp;
        return (t, Sum(u))
    }

    fn to_prod<T, U>(&tp: &(T, U)) -> (T, Prod<U>) {
        let (t, u) = tp;
        return (t, Prod(u));
    }

    fn to_max<T, U>(&tp: &(T, U)) -> (T, Max<U>) {
        let (t, u) = tp;
        return (t, Max(u));
    }

    fn to_min<T, U>(&tp: &(T, U)) -> (T, Min<U>) {
        let (t, u) = tp;
        return (t, Min(u));
    }

    #[test]
    fn test_merge_monoid_iterator() {
        fn check<M: Monoid + Unwrap<int> + Eq>(v1: &[(int, int)],
                                               v2: &[(int, int)],
                                               f: &fn(int) -> M,
                                               result: &[(int, int)]) {
            let conv = |&(x, y): &(int, int)| (x, f(y));
            assert_eq!(
                extvec::from_iter(MergeMonoidIterator::new(v1.iter().transform(conv),
                                                           v2.iter().transform(conv))),
                result.map(conv));
            assert_eq!(
                extvec::from_iter(MergeMonoidIterator::new(v2.iter().transform(conv),
                                                           v1.iter().transform(conv))),
                result.map(conv));

            assert_eq!(merge_monoid_as(v1.iter().transform(|x| *x),
                                       v2.iter().transform(|x| *x),
                                       f, |x| extvec::from_iter(x)),
                       result.to_vec());

            assert_eq!(merge_monoid_as(v2.iter().transform(|x| *x),
                                       v1.iter().transform(|x| *x),
                                       f, |x| extvec::from_iter(x)),
                       result.to_vec());
        }

        let v1 = [(1, 1), (3, 1), (4, 3), (6, 1)];
        let v2 = [(1, 2), (2, 1), (4, 2), (7, 2)];

        check(v1, v2, Sum, [(1, 3), (2, 1), (3, 1), (4, 5), (6, 1), (7, 2)]);
        check(v1, v2, Prod, [(1, 2), (2, 1), (3, 1), (4, 6), (6, 1), (7, 2)]);
        check(v1, v2, Max, [(1, 2), (2, 1), (3, 1), (4, 3), (6, 1), (7, 2)]);
        check(v1, v2, Min, [(1, 1), (2, 1), (3, 1), (4, 2), (6, 1), (7, 2)]);

        check(v1, [], Sum, v1);
        check([], [], Sum, []);
        check(v1, [], Prod, v1);
        check([], [], Prod, []);
        check(v1, [], Max, v1);
        check([], [], Max, []);
        check(v1, [], Min, v1);
        check([], [], Min, []);
    }

    #[test]
    fn test_merge() {
        let arg1 = [(1, 1), (3, 1), (4, 1), (6, 1)];
        let arg2 = [(1, 2), (2, 1), (4, 1), (7, 2)];

        {
            let result = ~[(1, 3), (2, 1), (3, 1), (4, 2), (6, 1), (7, 2)];
            assert_eq!(merge(arg1.map(to_sum), arg2.map(to_sum)),
                       result.map(to_sum));
            assert_eq!(merge_as(arg1, arg2, Sum), result);
        }

        {
            let result = ~[(1, 2), (2, 1), (3, 1), (4, 1), (6, 1), (7, 2)];
            assert_eq!(merge(arg1.map(to_max), arg2.map(to_max)),
                       result.map(to_max));
            assert_eq!(merge_as(arg1, arg2, Max),
                       result);
        }

        {
            let result = arg1.map(to_sum);
            assert_eq!(merge(result, []), result);
        }

        {
            let result: ~[(int, Sum<int>)] = ~[];
            assert_eq!(merge([], []), result);
        }
    }

    #[test]
    fn test_mergei() {
        {
            let arg = [~[(1, 1), (2, 1)], ~[(1, 2), (3, 1)], ~[(-1, 3)]];
            let result = ~[(-1, 3), (1, 3), (2, 1), (3, 1)];
            assert_eq!(mergei(arg.map(|v| v.map(to_sum))), result.map(to_sum));
            assert_eq!(mergei_as(arg, Sum), result);
        }

        {
            let arg = [~[(1, 1)], ~[(1, 2)], ~[(1, 3)]];
            let result = ~[(1, 6)];
            assert_eq!(mergei(arg.map(|v| v.map(to_sum))), result.map(to_sum));
            assert_eq!(mergei_as(arg, Sum), result);
        }

        {
            let arg = [~[], ~[], ~[]];
            let result: ~[(int, int)] = ~[];
            assert_eq!(mergei(arg.map(|v| v.map(to_sum))),
                       result.map(to_sum));
            assert_eq!(mergei_as(arg, Sum),
                       result);
        }
    }
}

<|endoftext|>


<commit_before>//! TLV Support
//!
//! mcuboot images are followed immediately by a list of TLV items that contain integrity
//! information about the image.  Their generation is made a little complicated because the size of
//! the TLV block is in the image header, which is included in the hash.  Since some signatures can
//! vary in size, we just make them the largest size possible.
//!
//! Because of this header, we have to make two passes.  The first pass will compute the size of
//! the TLV, and the second pass will build the data for the TLV.

use ring::digest;

#[derive(EnumFlags, Copy, Clone, Debug)]
#[repr(u32)]
#[allow(non_camel_case_types)]
pub enum Flags {
    PIC = 0x000001,
    SHA256 = 0x000002,
    PKCS15_RSA2048_SHA256 = 0x000004,
    ECDSA224_SHA256 = 0x000008,
    NON_BOOTABLE = 0x000010,
    ECDSA256_SHA256 = 0x000020,
    PKCS1_PSS_RSA2048_SHA256 = 0x000040,
}

#[repr(u8)]
#[derive(Copy, Clone, PartialEq, Eq)]
#[allow(dead_code)] // TODO: For now
pub enum TlvKinds {
    SHA256 = 1,
    RSA2048 = 2,
    ECDSA224 = 3,
    ECDSA256 = 4,
}

pub struct TlvGen {
    flags: Flags,
    kinds: Vec<TlvKinds>,
    size: u16,
    hasher: digest::Context,
}

impl TlvGen {
    /// Construct a new tlv generator that will only contain a hash of the data.
    pub fn new_hash_only() -> TlvGen {
        TlvGen {
            flags: Flags::SHA256,
            kinds: vec![TlvKinds::SHA256],
            size: 4 + 32,
            hasher: digest::Context::new(&digest::SHA256),
        }
    }

    /// Retrieve the header flags for this configuration.  This can be called at any time.
    pub fn get_flags(&self) -> u32 {
        self.flags as u32
    }

    /// Retrieve the size that the TLV will occupy.  This can be called at any time.
    pub fn get_size(&self) -> u16 {
        self.size
    }

    /// Add bytes to the covered hash.
    pub fn add_bytes(&mut self, bytes: &[u8]) {
        self.hasher.update(bytes);
    }

    /// Compute the TLV given the specified block of data.
    pub fn make_tlv(self) -> Vec<u8> {
        let mut result: Vec<u8> = vec![];

        if self.kinds.contains(&TlvKinds::SHA256) {
            let hash = self.hasher.finish();
            let hash = hash.as_ref();

            assert!(hash.len() == 32);
            result.push(TlvKinds::SHA256 as u8);
            result.push(0);
            result.push(32);
            result.push(0);
            result.extend_from_slice(hash);
        }

        result
    }
}
<commit_msg>sim: Capture payload in TLV code<commit_after>//! TLV Support
//!
//! mcuboot images are followed immediately by a list of TLV items that contain integrity
//! information about the image.  Their generation is made a little complicated because the size of
//! the TLV block is in the image header, which is included in the hash.  Since some signatures can
//! vary in size, we just make them the largest size possible.
//!
//! Because of this header, we have to make two passes.  The first pass will compute the size of
//! the TLV, and the second pass will build the data for the TLV.

use ring::digest;

#[derive(EnumFlags, Copy, Clone, Debug)]
#[repr(u32)]
#[allow(non_camel_case_types)]
pub enum Flags {
    PIC = 0x000001,
    SHA256 = 0x000002,
    PKCS15_RSA2048_SHA256 = 0x000004,
    ECDSA224_SHA256 = 0x000008,
    NON_BOOTABLE = 0x000010,
    ECDSA256_SHA256 = 0x000020,
    PKCS1_PSS_RSA2048_SHA256 = 0x000040,
}

#[repr(u8)]
#[derive(Copy, Clone, PartialEq, Eq)]
#[allow(dead_code)] // TODO: For now
pub enum TlvKinds {
    SHA256 = 1,
    RSA2048 = 2,
    ECDSA224 = 3,
    ECDSA256 = 4,
}

pub struct TlvGen {
    flags: Flags,
    kinds: Vec<TlvKinds>,
    size: u16,
    payload: Vec<u8>,
}

impl TlvGen {
    /// Construct a new tlv generator that will only contain a hash of the data.
    pub fn new_hash_only() -> TlvGen {
        TlvGen {
            flags: Flags::SHA256,
            kinds: vec![TlvKinds::SHA256],
            size: 4 + 32,
            payload: vec![],
        }
    }

    /// Retrieve the header flags for this configuration.  This can be called at any time.
    pub fn get_flags(&self) -> u32 {
        self.flags as u32
    }

    /// Retrieve the size that the TLV will occupy.  This can be called at any time.
    pub fn get_size(&self) -> u16 {
        self.size
    }

    /// Add bytes to the covered hash.
    pub fn add_bytes(&mut self, bytes: &[u8]) {
        self.payload.extend_from_slice(bytes);
    }

    /// Compute the TLV given the specified block of data.
    pub fn make_tlv(self) -> Vec<u8> {
        let mut result: Vec<u8> = vec![];

        if self.kinds.contains(&TlvKinds::SHA256) {
            let hash = digest::digest(&digest::SHA256, &self.payload);
            let hash = hash.as_ref();

            assert!(hash.len() == 32);
            result.push(TlvKinds::SHA256 as u8);
            result.push(0);
            result.push(32);
            result.push(0);
            result.extend_from_slice(hash);
        }

        result
    }
}
<|endoftext|>


<commit_before>extern crate csv;
extern crate skeptic;
extern crate serde_json;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate tera;

use std::io::{Write, BufReader, BufWriter};
use std::collections::HashMap;
use std::fs::File;
use std::path::Path;
use std::env;

const DATA_PATH: &'static str = "misc/data.json";
const SUPPORTED_LANG_PATH: &'static str = "misc/supported_languages.csv";
const TEMPLATE_LANG_RS_PATH: &'static str = "templates/lang.rs";
const TRIGRAM_COUNT: usize = 300;

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
struct LangInfo {
    code: String,
    eng_name: String,
    name: String,
    native_speakers: Option<f64>,
}

#[derive(Debug, Clone, PartialEq, Serialize)]
struct Lang {
    info: LangInfo,
    script: String,
    trigrams: Vec<String>,
}

fn main() {
    println!("cargo:rerun-if-changed={}", DATA_PATH);
    println!("cargo:rerun-if-changed={}", SUPPORTED_LANG_PATH);
    println!("cargo:rerun-if-changed={}", TEMPLATE_LANG_RS_PATH);

    generate_source_files();
    skeptic::generate_doc_tests(&["README.md"]);
}

fn generate_source_files() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("lang.rs");
    let mut lang_def = BufWriter::new(File::create(&dest_path).unwrap());

    let (lang_infos, scripts) = load_data();

    render_lang_rs(&mut lang_def, &lang_infos, &scripts);
}

fn load_data() -> (Vec<LangInfo>, HashMap<String, Vec<Lang>>) {
    let data_file = BufReader::new(File::open(DATA_PATH).unwrap());
    let mut lang_reader = csv::ReaderBuilder::new().flexible(true).from_path(SUPPORTED_LANG_PATH).unwrap();

    let mut lang_infos: Vec<LangInfo> = lang_reader.deserialize().map(Result::unwrap).collect();
    lang_infos.sort_by(|left, right| left.code.cmp(&right.code));

    let supported_lang_codes: HashMap<String, LangInfo> = lang_infos.iter()
        .map(|lang| (lang.code.clone(), lang.clone()))
        .collect();

    let lang_data: HashMap<String, HashMap<String, String>> = serde_json::from_reader(data_file).unwrap();

    let mut scripts: HashMap<String, Vec<Lang>> = HashMap::with_capacity(lang_data.len());
    let mut all_langs: Vec<Lang> = Vec::new();
    for (script, langs) in &lang_data {
        for (code, trigrams) in langs {
            let info = match supported_lang_codes.get(&**code) {
                Some(info) => info,
                None => continue,
            };
            let lang = Lang {
                info: (*info).clone(),
                script: script.clone(),
                trigrams: trigrams.split('|').map(Into::into).collect()
            };
            if lang.trigrams.len() != TRIGRAM_COUNT {
                panic!("Language {} has {} trigrams, instead of {}", code, lang.trigrams.len(), TRIGRAM_COUNT);
            }

            all_langs.push(lang.clone());
            scripts.entry(script.clone()).or_insert_with(Vec::new).push(lang);
        }
    }

    (lang_infos, scripts)
}

fn render_lang_rs(buf: &mut BufWriter<File>, lang_infos: &[LangInfo], scripts: &HashMap<String, Vec<Lang>>) {
    let mut tera = tera::Tera::default();
    tera.add_template_file(TEMPLATE_LANG_RS_PATH, Some("lang.rs"));

    let mut ctx = tera::Context::new();
    ctx.insert("lang_infos", lang_infos);
    ctx.insert("scripts", scripts);

    let code = tera.render("lang.rs", &ctx).unwrap();
    writeln!(buf, "{}", code).unwrap();
}
<commit_msg>Unwrap result in build.rs<commit_after>extern crate csv;
extern crate skeptic;
extern crate serde_json;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate tera;

use std::io::{Write, BufReader, BufWriter};
use std::collections::HashMap;
use std::fs::File;
use std::path::Path;
use std::env;

const DATA_PATH: &'static str = "misc/data.json";
const SUPPORTED_LANG_PATH: &'static str = "misc/supported_languages.csv";
const TEMPLATE_LANG_RS_PATH: &'static str = "templates/lang.rs";
const TRIGRAM_COUNT: usize = 300;

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
struct LangInfo {
    code: String,
    eng_name: String,
    name: String,
    native_speakers: Option<f64>,
}

#[derive(Debug, Clone, PartialEq, Serialize)]
struct Lang {
    info: LangInfo,
    script: String,
    trigrams: Vec<String>,
}

fn main() {
    println!("cargo:rerun-if-changed={}", DATA_PATH);
    println!("cargo:rerun-if-changed={}", SUPPORTED_LANG_PATH);
    println!("cargo:rerun-if-changed={}", TEMPLATE_LANG_RS_PATH);

    generate_source_files();
    skeptic::generate_doc_tests(&["README.md"]);
}

fn generate_source_files() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("lang.rs");
    let mut lang_def = BufWriter::new(File::create(&dest_path).unwrap());

    let (lang_infos, scripts) = load_data();

    render_lang_rs(&mut lang_def, &lang_infos, &scripts);
}

fn load_data() -> (Vec<LangInfo>, HashMap<String, Vec<Lang>>) {
    let data_file = BufReader::new(File::open(DATA_PATH).unwrap());
    let mut lang_reader = csv::ReaderBuilder::new().flexible(true).from_path(SUPPORTED_LANG_PATH).unwrap();

    let mut lang_infos: Vec<LangInfo> = lang_reader.deserialize().map(Result::unwrap).collect();
    lang_infos.sort_by(|left, right| left.code.cmp(&right.code));

    let supported_lang_codes: HashMap<String, LangInfo> = lang_infos.iter()
        .map(|lang| (lang.code.clone(), lang.clone()))
        .collect();

    let lang_data: HashMap<String, HashMap<String, String>> = serde_json::from_reader(data_file).unwrap();

    let mut scripts: HashMap<String, Vec<Lang>> = HashMap::with_capacity(lang_data.len());
    let mut all_langs: Vec<Lang> = Vec::new();
    for (script, langs) in &lang_data {
        for (code, trigrams) in langs {
            let info = match supported_lang_codes.get(&**code) {
                Some(info) => info,
                None => continue,
            };
            let lang = Lang {
                info: (*info).clone(),
                script: script.clone(),
                trigrams: trigrams.split('|').map(Into::into).collect()
            };
            if lang.trigrams.len() != TRIGRAM_COUNT {
                panic!("Language {} has {} trigrams, instead of {}", code, lang.trigrams.len(), TRIGRAM_COUNT);
            }

            all_langs.push(lang.clone());
            scripts.entry(script.clone()).or_insert_with(Vec::new).push(lang);
        }
    }

    (lang_infos, scripts)
}

fn render_lang_rs(buf: &mut BufWriter<File>, lang_infos: &[LangInfo], scripts: &HashMap<String, Vec<Lang>>) {
    let mut tera = tera::Tera::default();
    tera.add_template_file(TEMPLATE_LANG_RS_PATH, Some("lang.rs")).unwrap();

    let mut ctx = tera::Context::new();
    ctx.insert("lang_infos", lang_infos);
    ctx.insert("scripts", scripts);

    let code = tera.render("lang.rs", &ctx).unwrap();
    writeln!(buf, "{}", code).unwrap();
}
<|endoftext|>


<commit_before>extern crate phf_codegen;

use std::fs::File;
use std::io::{BufWriter, Write};
use std::path::Path;

fn main() {
    let path = Path::new(env!("OUT_DIR")).join("codegen.rs");
    let mut file = BufWriter::new(File::create(&path).unwrap());

    let mut builder = phf_codegen::Map::new();
    let data = include!("data");
    for i in 0..data.len() {
        let (k, v) = data[i];
        builder.entry(k, &escape_str(v));
    }
    // 拼音库
    write!(&mut file, "static PINYIN_MAP: ::phf::Map<u32, &'static str> = ").unwrap();
    builder.build(&mut file).unwrap();
    write!(&mut file, ";\n").unwrap();

    // 带声调字符
    write!(&mut file, "static PHONETIC_SYMBOL_MAP: ::phf::Map<&'static str, &'static str> = ").unwrap();
    phf_codegen::Map::new()
        .entry("ā", "\"a1\"")
        .entry("á", "\"a2\"")
        .entry("ǎ", "\"a3\"")
        .entry("à", "\"a4\"")
        .entry("ē", "\"e1\"")
        .entry("é", "\"e2\"")
        .entry("ě", "\"e3\"")
        .entry("è", "\"e4\"")
        .entry("ō", "\"o1\"")
        .entry("ó", "\"o2\"")
        .entry("ǒ", "\"o3\"")
        .entry("ò", "\"o4\"")
        .entry("ī", "\"i1\"")
        .entry("í", "\"i2\"")
        .entry("ǐ", "\"i3\"")
        .entry("ì", "\"i4\"")
        .entry("ū", "\"u1\"")
        .entry("ú", "\"u2\"")
        .entry("ǔ", "\"u3\"")
        .entry("ù", "\"u4\"")
        .entry("ü", "\"v0\"")
        .entry("ǘ", "\"v2\"")
        .entry("ǚ", "\"v3\"")
        .entry("ǜ", "\"v4\"")
        .entry("ń", "\"n2\"")
        .entry("ň", "\"n3\"")
        .entry("", "\"m2\"")
        .build(&mut file)
        .unwrap();
    write!(&mut file, ";\n").unwrap();
}

fn escape_str(s: &str) -> String {
    let mut res = String::new();
    res.push('"');
    for ch in s.chars() {
        res.push_str(&format!("\\u{{{:x}}}", ch as u32));
    }
    res.push('"');
    res
}
<commit_msg>Use env::var_os intead of env! in build script<commit_after>extern crate phf_codegen;

use std::env;
use std::fs::File;
use std::io::{BufWriter, Write};
use std::path::Path;

fn main() {
    let path = Path::new(&env::var_os("OUT_DIR").unwrap()).join("codegen.rs");
    let mut file = BufWriter::new(File::create(&path).unwrap());

    let mut builder = phf_codegen::Map::new();
    let data = include!("data");
    for i in 0..data.len() {
        let (k, v) = data[i];
        builder.entry(k, &escape_str(v));
    }
    // 拼音库
    write!(&mut file, "static PINYIN_MAP: ::phf::Map<u32, &'static str> = ").unwrap();
    builder.build(&mut file).unwrap();
    write!(&mut file, ";\n").unwrap();

    // 带声调字符
    write!(&mut file, "static PHONETIC_SYMBOL_MAP: ::phf::Map<&'static str, &'static str> = ").unwrap();
    phf_codegen::Map::new()
        .entry("ā", "\"a1\"")
        .entry("á", "\"a2\"")
        .entry("ǎ", "\"a3\"")
        .entry("à", "\"a4\"")
        .entry("ē", "\"e1\"")
        .entry("é", "\"e2\"")
        .entry("ě", "\"e3\"")
        .entry("è", "\"e4\"")
        .entry("ō", "\"o1\"")
        .entry("ó", "\"o2\"")
        .entry("ǒ", "\"o3\"")
        .entry("ò", "\"o4\"")
        .entry("ī", "\"i1\"")
        .entry("í", "\"i2\"")
        .entry("ǐ", "\"i3\"")
        .entry("ì", "\"i4\"")
        .entry("ū", "\"u1\"")
        .entry("ú", "\"u2\"")
        .entry("ǔ", "\"u3\"")
        .entry("ù", "\"u4\"")
        .entry("ü", "\"v0\"")
        .entry("ǘ", "\"v2\"")
        .entry("ǚ", "\"v3\"")
        .entry("ǜ", "\"v4\"")
        .entry("ń", "\"n2\"")
        .entry("ň", "\"n3\"")
        .entry("", "\"m2\"")
        .build(&mut file)
        .unwrap();
    write!(&mut file, ";\n").unwrap();
}

fn escape_str(s: &str) -> String {
    let mut res = String::new();
    res.push('"');
    for ch in s.chars() {
        res.push_str(&format!("\\u{{{:x}}}", ch as u32));
    }
    res.push('"');
    res
}
<|endoftext|>


<commit_before>extern crate gcc;

fn main() {
    println!("cargo:rustc-link-lib=dylib=gdi32");
    println!("cargo:rustc-link-lib=dylib=comdlg32");
    println!("cargo:rustc-link-lib=dylib=user32");

    gcc::Config::new()
        .file("src/PDCurses/pdcurses/addch.c") //Common PDCurses files
        .file("src/PDCurses/pdcurses/addchstr.c")
        .file("src/PDCurses/pdcurses/addstr.c")
        .file("src/PDCurses/pdcurses/attr.c")
        .file("src/PDCurses/pdcurses/beep.c")
        .file("src/PDCurses/pdcurses/bkgd.c")
        .file("src/PDCurses/pdcurses/border.c")
        .file("src/PDCurses/pdcurses/clear.c")
        .file("src/PDCurses/pdcurses/color.c")
        .file("src/PDCurses/pdcurses/debug.c")
        .file("src/PDCurses/pdcurses/delch.c")
        .file("src/PDCurses/pdcurses/deleteln.c")
        .file("src/PDCurses/pdcurses/deprec.c")
        .file("src/PDCurses/pdcurses/getch.c")
        .file("src/PDCurses/pdcurses/getstr.c")
        .file("src/PDCurses/pdcurses/getyx.c")
        .file("src/PDCurses/pdcurses/inch.c")
        .file("src/PDCurses/pdcurses/inchstr.c")
        .file("src/PDCurses/pdcurses/initscr.c")
        .file("src/PDCurses/pdcurses/inopts.c")
        .file("src/PDCurses/pdcurses/insch.c")
        .file("src/PDCurses/pdcurses/insstr.c")
        .file("src/PDCurses/pdcurses/instr.c")
        .file("src/PDCurses/pdcurses/kernel.c")
        .file("src/PDCurses/pdcurses/keyname.c")
        .file("src/PDCurses/pdcurses/mouse.c")
        .file("src/PDCurses/pdcurses/move.c")
        .file("src/PDCurses/pdcurses/outopts.c")
        .file("src/PDCurses/pdcurses/overlay.c")
        .file("src/PDCurses/pdcurses/pad.c")
        .file("src/PDCurses/pdcurses/panel.c")
        .file("src/PDCurses/pdcurses/printw.c")
        .file("src/PDCurses/pdcurses/refresh.c")
        .file("src/PDCurses/pdcurses/scanw.c")
        .file("src/PDCurses/pdcurses/scr_dump.c")
        .file("src/PDCurses/pdcurses/scroll.c")
        .file("src/PDCurses/pdcurses/slk.c")
        .file("src/PDCurses/pdcurses/termattr.c")
        .file("src/PDCurses/pdcurses/terminfo.c")
        .file("src/PDCurses/pdcurses/touch.c")
        .file("src/PDCurses/pdcurses/util.c")
        .file("src/PDCurses/pdcurses/window.c")
        .file("src/PDCurses/win32a/pdcclip.c") //win32a implementation files
        .file("src/PDCurses/win32a/pdcdisp.c")
        .file("src/PDCurses/win32a/pdcgetsc.c")
        .file("src/PDCurses/win32a/pdckbd.c")
        .file("src/PDCurses/win32a/pdcscrn.c")
        .file("src/PDCurses/win32a/pdcsetsc.c")
        .file("src/PDCurses/win32a/pdcutil.c")
        .include("src/PDCurses")
        .define("PDC_WIDE", Some("Y")) //Build with wide-character (Unicode) support
        .define("PDC_FORCE_UTF8", Some("Y")) //Makes PDCurses ignore the system locale, and treat all narrow-character strings as UTF-8
        .compile("libpdcurses.a");
}
<commit_msg>Use RGB colors instead of BGR. RGB is less surprising than BGR.<commit_after>extern crate gcc;

fn main() {
    println!("cargo:rustc-link-lib=dylib=gdi32");
    println!("cargo:rustc-link-lib=dylib=comdlg32");
    println!("cargo:rustc-link-lib=dylib=user32");

    gcc::Config::new()
        .file("src/PDCurses/pdcurses/addch.c") //Common PDCurses files
        .file("src/PDCurses/pdcurses/addchstr.c")
        .file("src/PDCurses/pdcurses/addstr.c")
        .file("src/PDCurses/pdcurses/attr.c")
        .file("src/PDCurses/pdcurses/beep.c")
        .file("src/PDCurses/pdcurses/bkgd.c")
        .file("src/PDCurses/pdcurses/border.c")
        .file("src/PDCurses/pdcurses/clear.c")
        .file("src/PDCurses/pdcurses/color.c")
        .file("src/PDCurses/pdcurses/debug.c")
        .file("src/PDCurses/pdcurses/delch.c")
        .file("src/PDCurses/pdcurses/deleteln.c")
        .file("src/PDCurses/pdcurses/deprec.c")
        .file("src/PDCurses/pdcurses/getch.c")
        .file("src/PDCurses/pdcurses/getstr.c")
        .file("src/PDCurses/pdcurses/getyx.c")
        .file("src/PDCurses/pdcurses/inch.c")
        .file("src/PDCurses/pdcurses/inchstr.c")
        .file("src/PDCurses/pdcurses/initscr.c")
        .file("src/PDCurses/pdcurses/inopts.c")
        .file("src/PDCurses/pdcurses/insch.c")
        .file("src/PDCurses/pdcurses/insstr.c")
        .file("src/PDCurses/pdcurses/instr.c")
        .file("src/PDCurses/pdcurses/kernel.c")
        .file("src/PDCurses/pdcurses/keyname.c")
        .file("src/PDCurses/pdcurses/mouse.c")
        .file("src/PDCurses/pdcurses/move.c")
        .file("src/PDCurses/pdcurses/outopts.c")
        .file("src/PDCurses/pdcurses/overlay.c")
        .file("src/PDCurses/pdcurses/pad.c")
        .file("src/PDCurses/pdcurses/panel.c")
        .file("src/PDCurses/pdcurses/printw.c")
        .file("src/PDCurses/pdcurses/refresh.c")
        .file("src/PDCurses/pdcurses/scanw.c")
        .file("src/PDCurses/pdcurses/scr_dump.c")
        .file("src/PDCurses/pdcurses/scroll.c")
        .file("src/PDCurses/pdcurses/slk.c")
        .file("src/PDCurses/pdcurses/termattr.c")
        .file("src/PDCurses/pdcurses/terminfo.c")
        .file("src/PDCurses/pdcurses/touch.c")
        .file("src/PDCurses/pdcurses/util.c")
        .file("src/PDCurses/pdcurses/window.c")
        .file("src/PDCurses/win32a/pdcclip.c") //win32a implementation files
        .file("src/PDCurses/win32a/pdcdisp.c")
        .file("src/PDCurses/win32a/pdcgetsc.c")
        .file("src/PDCurses/win32a/pdckbd.c")
        .file("src/PDCurses/win32a/pdcscrn.c")
        .file("src/PDCurses/win32a/pdcsetsc.c")
        .file("src/PDCurses/win32a/pdcutil.c")
        .include("src/PDCurses")
        .define("PDC_WIDE", Some("Y")) // Build with wide-character (Unicode) support
        .define("PDC_FORCE_UTF8", Some("Y")) // Makes PDCurses ignore the system locale, and treat all narrow-character strings as UTF-8
        .define("PDC_RGB", Some("Y")) // Use RGB colors, it's what most people expect them to be
        .compile("libpdcurses.a");
}
<|endoftext|>


<commit_before>extern crate rustc_version;
extern crate xdg;

use std::path::Path;
use std::process::Command;

static AFL_SRC_PATH: &str = "AFLplusplus";

#[path = "src/common.rs"]
mod common;

fn main() {
    build_afl(&common::afl_dir());
    build_afl_llvm_runtime();
}

fn build_afl(out_dir: &Path) {
    let mut command = Command::new("make");
    command
        .current_dir(AFL_SRC_PATH)
        .args(&["clean", "all", "install"])
        // Rely on LLVM’s built-in execution tracing feature instead of AFL’s
        // LLVM passi instrumentation.
        .env("AFL_TRACE_PC", "1")
        .env("DESTDIR", out_dir)
        .env("PREFIX", "");
    // sets AFL_NO_X86 to compile for ARM arch
    if cfg!(target_arch = "arm") {
        command.env("AFL_NO_X86", "1");
    }
    let status = command.status().expect("could not run 'make'");
    assert!(status.success());
}

fn build_afl_llvm_runtime() {
    let status = Command::new("make")
        .current_dir(Path::new(AFL_SRC_PATH).join("llvm_mode"))
        .arg("../afl-llvm-rt.o")
        .status()
        .expect("could not compile 'afl-llvm-rt.o'");
    assert!(status.success());

    std::fs::copy(
        Path::new(&AFL_SRC_PATH).join("afl-llvm-rt.o"),
        common::object_file_path(),
    )
    .expect("Couldn't copy object file");

    let status = Command::new("ar")
        .arg("r")
        .arg(common::archive_file_path())
        .arg(common::object_file_path())
        .status()
        .expect("could not run 'ar'");
    assert!(status.success());
}
<commit_msg>Hard-code the path to ar as /usr/bin/ar (#171)<commit_after>extern crate rustc_version;
extern crate xdg;

use std::path::Path;
use std::process::Command;

static AFL_SRC_PATH: &str = "AFLplusplus";

// https://github.com/rust-fuzz/afl.rs/issues/148
#[cfg(target_os = "macos")]
static AR_CMD: &str = "/usr/bin/ar";
#[cfg(not(target_os = "macos"))]
static AR_CMD: &str = "ar";

#[path = "src/common.rs"]
mod common;

fn main() {
    build_afl(&common::afl_dir());
    build_afl_llvm_runtime();
}

fn build_afl(out_dir: &Path) {
    let mut command = Command::new("make");
    command
        .current_dir(AFL_SRC_PATH)
        .args(&["clean", "all", "install"])
        // Rely on LLVM’s built-in execution tracing feature instead of AFL’s
        // LLVM passi instrumentation.
        .env("AFL_TRACE_PC", "1")
        .env("DESTDIR", out_dir)
        .env("PREFIX", "");
    // sets AFL_NO_X86 to compile for ARM arch
    if cfg!(target_arch = "arm") {
        command.env("AFL_NO_X86", "1");
    }
    let status = command.status().expect("could not run 'make'");
    assert!(status.success());
}

fn build_afl_llvm_runtime() {
    let status = Command::new("make")
        .current_dir(Path::new(AFL_SRC_PATH).join("llvm_mode"))
        .arg("../afl-llvm-rt.o")
        .status()
        .expect("could not compile 'afl-llvm-rt.o'");
    assert!(status.success());

    std::fs::copy(
        Path::new(&AFL_SRC_PATH).join("afl-llvm-rt.o"),
        common::object_file_path(),
    )
    .expect("Couldn't copy object file");

    let status = Command::new(AR_CMD)
        .arg("r")
        .arg(common::archive_file_path())
        .arg(common::object_file_path())
        .status()
        .expect("could not run 'ar'");
    assert!(status.success());
}
<|endoftext|>


<commit_before>use std::process::Command;
use std::env;

fn main() {
    let out_dir = env::var("CARGO_MANIFEST_DIR").unwrap();

    println!("Generating Query DSL to: {}", out_dir);

    // Use Ruby to generate src/query.rs - should probably be written in Rust
    // itself to avoid an unnecessary dependency
    match Command::new("tools/generate_query_dsl.rb").arg(out_dir).status() {
        Ok(exit_status) => println!("Finished with status: {}", exit_status),
        Err(err)        => panic!("Error: {}", err)
    }
}
<commit_msg>Check status-code of code-generator in build-script, for a more direct error if it fails.<commit_after>use std::process::Command;
use std::env;

fn main() {
    let out_dir = env::var("CARGO_MANIFEST_DIR").unwrap();

    println!("Generating Query DSL to: {}", out_dir);

    // Use Ruby to generate src/query.rs - should probably be written in Rust
    // itself to avoid an unnecessary dependency
    match Command::new("tools/generate_query_dsl.rb").arg(out_dir).status() {
        Ok(exit_status) => {
            println!("Finished with status: {}", exit_status);
            match exit_status.code() {
                Some(code) if code == 0 => (),
                Some(code)              => { panic!("Status code: {}", code); },
                None                    => { panic!("No status code"); }
            };
        },
        Err(err)        => { panic!("Error: {}", err); }
    }
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::mem;

#[cfg(feature = "winit")]
use winit;

use winapi::shared::dxgi1_4;
use winapi::shared::windef::{HWND, RECT};
use winapi::um::winuser::GetClientRect;

use hal::{self, format as f, image as i};
use {native, resource as r, Backend, Instance, PhysicalDevice, QueueFamily};

use std::os::raw::c_void;

impl Instance {
    pub fn create_surface_from_hwnd(&self, hwnd: *mut c_void) -> Surface {
        Surface {
            factory: self.factory,
            wnd_handle: hwnd as *mut _,
        }
    }

    #[cfg(feature = "winit")]
    pub fn create_surface(&self, window: &winit::Window) -> Surface {
        use winit::os::windows::WindowExt;
        self.create_surface_from_hwnd(window.get_hwnd() as *mut _)
    }
}

pub struct Surface {
    pub(crate) factory: native::WeakPtr<dxgi1_4::IDXGIFactory4>,
    pub(crate) wnd_handle: HWND,
}

unsafe impl Send for Surface {}
unsafe impl Sync for Surface {}

impl Surface {
    fn get_extent(&self) -> (u32, u32) {
        unsafe {
            let mut rect: RECT = mem::zeroed();
            if GetClientRect(self.wnd_handle as *mut _, &mut rect as *mut RECT) == 0 {
                panic!("GetClientRect failed");
            }
            (
                (rect.right - rect.left) as u32,
                (rect.bottom - rect.top) as u32,
            )
        }
    }
}

impl hal::Surface<Backend> for Surface {
    fn supports_queue_family(&self, queue_family: &QueueFamily) -> bool {
        match queue_family {
            &QueueFamily::Present => true,
            _ => false,
        }
    }

    fn kind(&self) -> i::Kind {
        let (width, height) = self.get_extent();
        i::Kind::D2(width, height, 1, 1)
    }

    fn compatibility(
        &self,
        _: &PhysicalDevice,
    ) -> (
        hal::SurfaceCapabilities,
        Option<Vec<f::Format>>,
        Vec<hal::PresentMode>,
    ) {
        let (width, height) = self.get_extent();
        let extent = hal::window::Extent2D { width, height };

        let capabilities = hal::SurfaceCapabilities {
            image_count: 2..16, // we currently use a flip effect which supports 2..16 buffers
            current_extent: Some(extent),
            extents: extent..extent,
            max_image_layers: 1,
            usage: i::Usage::COLOR_ATTACHMENT | i::Usage::TRANSFER_SRC,
        };

        // Sticking to FLIP swap effects for the moment.
        // We also expose sRGB buffers but they are handled internally as UNORM.
        // Roughly ordered by popularity..
        let formats = vec![
            f::Format::Bgra8Srgb,
            f::Format::Bgra8Unorm,
            f::Format::Rgba8Srgb,
            f::Format::Rgba8Unorm,
            f::Format::A2b10g10r10Unorm,
            f::Format::Rgba16Float,
        ];

        let present_modes = vec![
            hal::PresentMode::Fifo, //TODO
        ];

        (capabilities, Some(formats), present_modes)
    }
}

pub struct Swapchain {
    pub(crate) inner: native::WeakPtr<dxgi1_4::IDXGISwapChain3>,
    pub(crate) next_frame: usize,
    pub(crate) frame_queue: VecDeque<usize>,
    #[allow(dead_code)]
    pub(crate) rtv_heap: r::DescriptorHeap,
    // need to associate raw image pointers with the swapchain so they can be properly released
    // when the swapchain is destroyed
    pub(crate) resources: Vec<native::Resource>,
}

impl hal::Swapchain<Backend> for Swapchain {
    fn acquire_image(
        &mut self,
        _timout_ns: u64,
        _sync: hal::FrameSync<Backend>,
    ) -> Result<hal::SwapImageIndex, hal::AcquireError> {
        // TODO: sync

        if false {
            // TODO: we need to block this at some point? (running out of backbuffers)
            //let num_images = self.images.len();
            let num_images = 1;
            let index = self.next_frame;
            self.frame_queue.push_back(index);
            self.next_frame = (self.next_frame + 1) % num_images;
        }

        // TODO:
        Ok(unsafe { self.inner.GetCurrentBackBufferIndex() })
    }
}

unsafe impl Send for Swapchain {}
unsafe impl Sync for Swapchain {}
<commit_msg>Allow to use swapchain image as trasnfer destination<commit_after>use std::collections::VecDeque;
use std::mem;

#[cfg(feature = "winit")]
use winit;

use winapi::shared::dxgi1_4;
use winapi::shared::windef::{HWND, RECT};
use winapi::um::winuser::GetClientRect;

use hal::{self, format as f, image as i};
use {native, resource as r, Backend, Instance, PhysicalDevice, QueueFamily};

use std::os::raw::c_void;

impl Instance {
    pub fn create_surface_from_hwnd(&self, hwnd: *mut c_void) -> Surface {
        Surface {
            factory: self.factory,
            wnd_handle: hwnd as *mut _,
        }
    }

    #[cfg(feature = "winit")]
    pub fn create_surface(&self, window: &winit::Window) -> Surface {
        use winit::os::windows::WindowExt;
        self.create_surface_from_hwnd(window.get_hwnd() as *mut _)
    }
}

pub struct Surface {
    pub(crate) factory: native::WeakPtr<dxgi1_4::IDXGIFactory4>,
    pub(crate) wnd_handle: HWND,
}

unsafe impl Send for Surface {}
unsafe impl Sync for Surface {}

impl Surface {
    fn get_extent(&self) -> (u32, u32) {
        unsafe {
            let mut rect: RECT = mem::zeroed();
            if GetClientRect(self.wnd_handle as *mut _, &mut rect as *mut RECT) == 0 {
                panic!("GetClientRect failed");
            }
            (
                (rect.right - rect.left) as u32,
                (rect.bottom - rect.top) as u32,
            )
        }
    }
}

impl hal::Surface<Backend> for Surface {
    fn supports_queue_family(&self, queue_family: &QueueFamily) -> bool {
        match queue_family {
            &QueueFamily::Present => true,
            _ => false,
        }
    }

    fn kind(&self) -> i::Kind {
        let (width, height) = self.get_extent();
        i::Kind::D2(width, height, 1, 1)
    }

    fn compatibility(
        &self,
        _: &PhysicalDevice,
    ) -> (
        hal::SurfaceCapabilities,
        Option<Vec<f::Format>>,
        Vec<hal::PresentMode>,
    ) {
        let (width, height) = self.get_extent();
        let extent = hal::window::Extent2D { width, height };

        let capabilities = hal::SurfaceCapabilities {
            image_count: 2..16, // we currently use a flip effect which supports 2..16 buffers
            current_extent: Some(extent),
            extents: extent..extent,
            max_image_layers: 1,
            usage: i::Usage::COLOR_ATTACHMENT | i::Usage::TRANSFER_SRC | i::Usage::TRANSFER_DST,
        };

        // Sticking to FLIP swap effects for the moment.
        // We also expose sRGB buffers but they are handled internally as UNORM.
        // Roughly ordered by popularity..
        let formats = vec![
            f::Format::Bgra8Srgb,
            f::Format::Bgra8Unorm,
            f::Format::Rgba8Srgb,
            f::Format::Rgba8Unorm,
            f::Format::A2b10g10r10Unorm,
            f::Format::Rgba16Float,
        ];

        let present_modes = vec![
            hal::PresentMode::Fifo, //TODO
        ];

        (capabilities, Some(formats), present_modes)
    }
}

pub struct Swapchain {
    pub(crate) inner: native::WeakPtr<dxgi1_4::IDXGISwapChain3>,
    pub(crate) next_frame: usize,
    pub(crate) frame_queue: VecDeque<usize>,
    #[allow(dead_code)]
    pub(crate) rtv_heap: r::DescriptorHeap,
    // need to associate raw image pointers with the swapchain so they can be properly released
    // when the swapchain is destroyed
    pub(crate) resources: Vec<native::Resource>,
}

impl hal::Swapchain<Backend> for Swapchain {
    fn acquire_image(
        &mut self,
        _timout_ns: u64,
        _sync: hal::FrameSync<Backend>,
    ) -> Result<hal::SwapImageIndex, hal::AcquireError> {
        // TODO: sync

        if false {
            // TODO: we need to block this at some point? (running out of backbuffers)
            //let num_images = self.images.len();
            let num_images = 1;
            let index = self.next_frame;
            self.frame_queue.push_back(index);
            self.next_frame = (self.next_frame + 1) % num_images;
        }

        // TODO:
        Ok(unsafe { self.inner.GetCurrentBackBufferIndex() })
    }
}

unsafe impl Send for Swapchain {}
unsafe impl Sync for Swapchain {}
<|endoftext|>


<commit_before>use hir::ModuleDef;
use ide_db::helpers::{import_assets::NameToImport, mod_path_to_ast};
use ide_db::items_locator;
use itertools::Itertools;
use syntax::{
    ast::{self, make, AstNode, NameOwner},
    SyntaxKind::{IDENT, WHITESPACE},
};

use crate::{
    assist_context::{AssistBuilder, AssistContext, Assists},
    utils::{
        add_trait_assoc_items_to_impl, filter_assoc_items, generate_trait_impl_text,
        render_snippet, Cursor, DefaultMethods,
    },
    AssistId, AssistKind,
};

// Assist: replace_derive_with_manual_impl
//
// Converts a `derive` impl into a manual one.
//
// ```
// # trait Debug { fn fmt(&self, f: &mut Formatter) -> Result<()>; }
// #[derive(Deb$0ug, Display)]
// struct S;
// ```
// ->
// ```
// # trait Debug { fn fmt(&self, f: &mut Formatter) -> Result<()>; }
// #[derive(Display)]
// struct S;
//
// impl Debug for S {
//     fn fmt(&self, f: &mut Formatter) -> Result<()> {
//         ${0:todo!()}
//     }
// }
// ```
pub(crate) fn replace_derive_with_manual_impl(
    acc: &mut Assists,
    ctx: &AssistContext,
) -> Option<()> {
    let attr = ctx.find_node_at_offset::<ast::Attr>()?;
    let (name, args) = attr.as_simple_call()?;
    if name != "derive" {
        return None;
    }

    if !args.syntax().text_range().contains(ctx.offset()) {
        cov_mark::hit!(outside_of_attr_args);
        return None;
    }

    let trait_token = args.syntax().token_at_offset(ctx.offset()).find(|t| t.kind() == IDENT)?;
    let trait_name = trait_token.text();

    let adt = attr.syntax().parent().and_then(ast::Adt::cast)?;

    let current_module = ctx.sema.scope(adt.syntax()).module()?;
    let current_crate = current_module.krate();

    let found_traits = items_locator::items_with_name(
        &ctx.sema,
        current_crate,
        NameToImport::Exact(trait_name.to_string()),
        items_locator::AssocItemSearch::Exclude,
        Some(items_locator::DEFAULT_QUERY_SEARCH_LIMIT),
    )
    .filter_map(|item| match ModuleDef::from(item.as_module_def_id()?) {
        ModuleDef::Trait(trait_) => Some(trait_),
        _ => None,
    })
    .flat_map(|trait_| {
        current_module
            .find_use_path(ctx.sema.db, hir::ModuleDef::Trait(trait_))
            .as_ref()
            .map(mod_path_to_ast)
            .zip(Some(trait_))
    });

    let mut no_traits_found = true;
    for (trait_path, trait_) in found_traits.inspect(|_| no_traits_found = false) {
        add_assist(acc, ctx, &attr, &args, &trait_path, Some(trait_), &adt)?;
    }
    if no_traits_found {
        let trait_path = make::path_unqualified(make::path_segment(make::name_ref(trait_name)));
        add_assist(acc, ctx, &attr, &args, &trait_path, None, &adt)?;
    }
    Some(())
}

fn add_assist(
    acc: &mut Assists,
    ctx: &AssistContext,
    attr: &ast::Attr,
    input: &ast::TokenTree,
    trait_path: &ast::Path,
    trait_: Option<hir::Trait>,
    adt: &ast::Adt,
) -> Option<()> {
    let target = attr.syntax().text_range();
    let annotated_name = adt.name()?;
    let label = format!("Convert to manual `impl {} for {}`", trait_path, annotated_name);
    let trait_name = trait_path.segment().and_then(|seg| seg.name_ref())?;

    acc.add(
        AssistId("replace_derive_with_manual_impl", AssistKind::Refactor),
        label,
        target,
        |builder| {
            let insert_pos = adt.syntax().text_range().end();
            let impl_def_with_items =
                impl_def_from_trait(&ctx.sema, &annotated_name, trait_, trait_path);
            update_attribute(builder, &input, &trait_name, &attr);
            let trait_path = format!("{}", trait_path);
            match (ctx.config.snippet_cap, impl_def_with_items) {
                (None, _) => {
                    builder.insert(insert_pos, generate_trait_impl_text(adt, &trait_path, ""))
                }
                (Some(cap), None) => builder.insert_snippet(
                    cap,
                    insert_pos,
                    generate_trait_impl_text(adt, &trait_path, "    $0"),
                ),
                (Some(cap), Some((impl_def, first_assoc_item))) => {
                    let mut cursor = Cursor::Before(first_assoc_item.syntax());
                    let placeholder;
                    if let ast::AssocItem::Fn(ref func) = first_assoc_item {
                        if let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast)
                        {
                            if m.syntax().text() == "todo!()" {
                                placeholder = m;
                                cursor = Cursor::Replace(placeholder.syntax());
                            }
                        }
                    }

                    builder.insert_snippet(
                        cap,
                        insert_pos,
                        format!("\n\n{}", render_snippet(cap, impl_def.syntax(), cursor)),
                    )
                }
            };
        },
    )
}

fn impl_def_from_trait(
    sema: &hir::Semantics<ide_db::RootDatabase>,
    annotated_name: &ast::Name,
    trait_: Option<hir::Trait>,
    trait_path: &ast::Path,
) -> Option<(ast::Impl, ast::AssocItem)> {
    let trait_ = trait_?;
    let target_scope = sema.scope(annotated_name.syntax());
    let trait_items = filter_assoc_items(sema.db, &trait_.items(sema.db), DefaultMethods::No);
    if trait_items.is_empty() {
        return None;
    }
    let impl_def = make::impl_trait(
        trait_path.clone(),
        make::path_unqualified(make::path_segment(make::name_ref(&annotated_name.text()))),
    );
    let (impl_def, first_assoc_item) =
        add_trait_assoc_items_to_impl(sema, trait_items, trait_, impl_def, target_scope);
    Some((impl_def, first_assoc_item))
}

fn update_attribute(
    builder: &mut AssistBuilder,
    input: &ast::TokenTree,
    trait_name: &ast::NameRef,
    attr: &ast::Attr,
) {
    let trait_name = trait_name.text();
    let new_attr_input = input
        .syntax()
        .descendants_with_tokens()
        .filter(|t| t.kind() == IDENT)
        .filter_map(|t| t.into_token().map(|t| t.text().to_string()))
        .filter(|t| t != &trait_name)
        .collect::<Vec<_>>();
    let has_more_derives = !new_attr_input.is_empty();

    if has_more_derives {
        let new_attr_input = format!("({})", new_attr_input.iter().format(", "));
        builder.replace(input.syntax().text_range(), new_attr_input);
    } else {
        let attr_range = attr.syntax().text_range();
        builder.delete(attr_range);

        if let Some(line_break_range) = attr
            .syntax()
            .next_sibling_or_token()
            .filter(|t| t.kind() == WHITESPACE)
            .map(|t| t.text_range())
        {
            builder.delete(line_break_range);
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn add_custom_impl_debug() {
        check_assist(
            replace_derive_with_manual_impl,
            "
mod fmt {
    pub struct Error;
    pub type Result = Result<(), Error>;
    pub struct Formatter<'a>;
    pub trait Debug {
        fn fmt(&self, f: &mut Formatter<'_>) -> Result;
    }
}

#[derive(Debu$0g)]
struct Foo {
    bar: String,
}
",
            "
mod fmt {
    pub struct Error;
    pub type Result = Result<(), Error>;
    pub struct Formatter<'a>;
    pub trait Debug {
        fn fmt(&self, f: &mut Formatter<'_>) -> Result;
    }
}

struct Foo {
    bar: String,
}

impl fmt::Debug for Foo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        ${0:todo!()}
    }
}
",
        )
    }
    #[test]
    fn add_custom_impl_all() {
        check_assist(
            replace_derive_with_manual_impl,
            "
mod foo {
    pub trait Bar {
        type Qux;
        const Baz: usize = 42;
        const Fez: usize;
        fn foo();
        fn bar() {}
    }
}

#[derive($0Bar)]
struct Foo {
    bar: String,
}
",
            "
mod foo {
    pub trait Bar {
        type Qux;
        const Baz: usize = 42;
        const Fez: usize;
        fn foo();
        fn bar() {}
    }
}

struct Foo {
    bar: String,
}

impl foo::Bar for Foo {
    $0type Qux;

    const Baz: usize = 42;

    const Fez: usize;

    fn foo() {
        todo!()
    }
}
",
        )
    }
    #[test]
    fn add_custom_impl_for_unique_input() {
        check_assist(
            replace_derive_with_manual_impl,
            "
#[derive(Debu$0g)]
struct Foo {
    bar: String,
}
            ",
            "
struct Foo {
    bar: String,
}

impl Debug for Foo {
    $0
}
            ",
        )
    }

    #[test]
    fn add_custom_impl_for_with_visibility_modifier() {
        check_assist(
            replace_derive_with_manual_impl,
            "
#[derive(Debug$0)]
pub struct Foo {
    bar: String,
}
            ",
            "
pub struct Foo {
    bar: String,
}

impl Debug for Foo {
    $0
}
            ",
        )
    }

    #[test]
    fn add_custom_impl_when_multiple_inputs() {
        check_assist(
            replace_derive_with_manual_impl,
            "
#[derive(Display, Debug$0, Serialize)]
struct Foo {}
            ",
            "
#[derive(Display, Serialize)]
struct Foo {}

impl Debug for Foo {
    $0
}
            ",
        )
    }

    #[test]
    fn test_ignore_derive_macro_without_input() {
        check_assist_not_applicable(
            replace_derive_with_manual_impl,
            "
#[derive($0)]
struct Foo {}
            ",
        )
    }

    #[test]
    fn test_ignore_if_cursor_on_param() {
        check_assist_not_applicable(
            replace_derive_with_manual_impl,
            "
#[derive$0(Debug)]
struct Foo {}
            ",
        );

        check_assist_not_applicable(
            replace_derive_with_manual_impl,
            "
#[derive(Debug)$0]
struct Foo {}
            ",
        )
    }

    #[test]
    fn test_ignore_if_not_derive() {
        check_assist_not_applicable(
            replace_derive_with_manual_impl,
            "
#[allow(non_camel_$0case_types)]
struct Foo {}
            ",
        )
    }

    #[test]
    fn works_at_start_of_file() {
        cov_mark::check!(outside_of_attr_args);
        check_assist_not_applicable(
            replace_derive_with_manual_impl,
            r#"
$0#[derive(Debug)]
struct S;
            "#,
        );
    }
}
<commit_msg>Follow testing style guide<commit_after>use hir::ModuleDef;
use ide_db::helpers::{import_assets::NameToImport, mod_path_to_ast};
use ide_db::items_locator;
use itertools::Itertools;
use syntax::{
    ast::{self, make, AstNode, NameOwner},
    SyntaxKind::{IDENT, WHITESPACE},
};

use crate::{
    assist_context::{AssistBuilder, AssistContext, Assists},
    utils::{
        add_trait_assoc_items_to_impl, filter_assoc_items, generate_trait_impl_text,
        render_snippet, Cursor, DefaultMethods,
    },
    AssistId, AssistKind,
};

// Assist: replace_derive_with_manual_impl
//
// Converts a `derive` impl into a manual one.
//
// ```
// # trait Debug { fn fmt(&self, f: &mut Formatter) -> Result<()>; }
// #[derive(Deb$0ug, Display)]
// struct S;
// ```
// ->
// ```
// # trait Debug { fn fmt(&self, f: &mut Formatter) -> Result<()>; }
// #[derive(Display)]
// struct S;
//
// impl Debug for S {
//     fn fmt(&self, f: &mut Formatter) -> Result<()> {
//         ${0:todo!()}
//     }
// }
// ```
pub(crate) fn replace_derive_with_manual_impl(
    acc: &mut Assists,
    ctx: &AssistContext,
) -> Option<()> {
    let attr = ctx.find_node_at_offset::<ast::Attr>()?;
    let (name, args) = attr.as_simple_call()?;
    if name != "derive" {
        return None;
    }

    if !args.syntax().text_range().contains(ctx.offset()) {
        cov_mark::hit!(outside_of_attr_args);
        return None;
    }

    let trait_token = args.syntax().token_at_offset(ctx.offset()).find(|t| t.kind() == IDENT)?;
    let trait_name = trait_token.text();

    let adt = attr.syntax().parent().and_then(ast::Adt::cast)?;

    let current_module = ctx.sema.scope(adt.syntax()).module()?;
    let current_crate = current_module.krate();

    let found_traits = items_locator::items_with_name(
        &ctx.sema,
        current_crate,
        NameToImport::Exact(trait_name.to_string()),
        items_locator::AssocItemSearch::Exclude,
        Some(items_locator::DEFAULT_QUERY_SEARCH_LIMIT),
    )
    .filter_map(|item| match ModuleDef::from(item.as_module_def_id()?) {
        ModuleDef::Trait(trait_) => Some(trait_),
        _ => None,
    })
    .flat_map(|trait_| {
        current_module
            .find_use_path(ctx.sema.db, hir::ModuleDef::Trait(trait_))
            .as_ref()
            .map(mod_path_to_ast)
            .zip(Some(trait_))
    });

    let mut no_traits_found = true;
    for (trait_path, trait_) in found_traits.inspect(|_| no_traits_found = false) {
        add_assist(acc, ctx, &attr, &args, &trait_path, Some(trait_), &adt)?;
    }
    if no_traits_found {
        let trait_path = make::path_unqualified(make::path_segment(make::name_ref(trait_name)));
        add_assist(acc, ctx, &attr, &args, &trait_path, None, &adt)?;
    }
    Some(())
}

fn add_assist(
    acc: &mut Assists,
    ctx: &AssistContext,
    attr: &ast::Attr,
    input: &ast::TokenTree,
    trait_path: &ast::Path,
    trait_: Option<hir::Trait>,
    adt: &ast::Adt,
) -> Option<()> {
    let target = attr.syntax().text_range();
    let annotated_name = adt.name()?;
    let label = format!("Convert to manual `impl {} for {}`", trait_path, annotated_name);
    let trait_name = trait_path.segment().and_then(|seg| seg.name_ref())?;

    acc.add(
        AssistId("replace_derive_with_manual_impl", AssistKind::Refactor),
        label,
        target,
        |builder| {
            let insert_pos = adt.syntax().text_range().end();
            let impl_def_with_items =
                impl_def_from_trait(&ctx.sema, &annotated_name, trait_, trait_path);
            update_attribute(builder, &input, &trait_name, &attr);
            let trait_path = format!("{}", trait_path);
            match (ctx.config.snippet_cap, impl_def_with_items) {
                (None, _) => {
                    builder.insert(insert_pos, generate_trait_impl_text(adt, &trait_path, ""))
                }
                (Some(cap), None) => builder.insert_snippet(
                    cap,
                    insert_pos,
                    generate_trait_impl_text(adt, &trait_path, "    $0"),
                ),
                (Some(cap), Some((impl_def, first_assoc_item))) => {
                    let mut cursor = Cursor::Before(first_assoc_item.syntax());
                    let placeholder;
                    if let ast::AssocItem::Fn(ref func) = first_assoc_item {
                        if let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast)
                        {
                            if m.syntax().text() == "todo!()" {
                                placeholder = m;
                                cursor = Cursor::Replace(placeholder.syntax());
                            }
                        }
                    }

                    builder.insert_snippet(
                        cap,
                        insert_pos,
                        format!("\n\n{}", render_snippet(cap, impl_def.syntax(), cursor)),
                    )
                }
            };
        },
    )
}

fn impl_def_from_trait(
    sema: &hir::Semantics<ide_db::RootDatabase>,
    annotated_name: &ast::Name,
    trait_: Option<hir::Trait>,
    trait_path: &ast::Path,
) -> Option<(ast::Impl, ast::AssocItem)> {
    let trait_ = trait_?;
    let target_scope = sema.scope(annotated_name.syntax());
    let trait_items = filter_assoc_items(sema.db, &trait_.items(sema.db), DefaultMethods::No);
    if trait_items.is_empty() {
        return None;
    }
    let impl_def = make::impl_trait(
        trait_path.clone(),
        make::path_unqualified(make::path_segment(make::name_ref(&annotated_name.text()))),
    );
    let (impl_def, first_assoc_item) =
        add_trait_assoc_items_to_impl(sema, trait_items, trait_, impl_def, target_scope);
    Some((impl_def, first_assoc_item))
}

fn update_attribute(
    builder: &mut AssistBuilder,
    input: &ast::TokenTree,
    trait_name: &ast::NameRef,
    attr: &ast::Attr,
) {
    let trait_name = trait_name.text();
    let new_attr_input = input
        .syntax()
        .descendants_with_tokens()
        .filter(|t| t.kind() == IDENT)
        .filter_map(|t| t.into_token().map(|t| t.text().to_string()))
        .filter(|t| t != &trait_name)
        .collect::<Vec<_>>();
    let has_more_derives = !new_attr_input.is_empty();

    if has_more_derives {
        let new_attr_input = format!("({})", new_attr_input.iter().format(", "));
        builder.replace(input.syntax().text_range(), new_attr_input);
    } else {
        let attr_range = attr.syntax().text_range();
        builder.delete(attr_range);

        if let Some(line_break_range) = attr
            .syntax()
            .next_sibling_or_token()
            .filter(|t| t.kind() == WHITESPACE)
            .map(|t| t.text_range())
        {
            builder.delete(line_break_range);
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn add_custom_impl_debug() {
        check_assist(
            replace_derive_with_manual_impl,
            r#"
mod fmt {
    pub struct Error;
    pub type Result = Result<(), Error>;
    pub struct Formatter<'a>;
    pub trait Debug {
        fn fmt(&self, f: &mut Formatter<'_>) -> Result;
    }
}

#[derive(Debu$0g)]
struct Foo {
    bar: String,
}
"#,
            r#"
mod fmt {
    pub struct Error;
    pub type Result = Result<(), Error>;
    pub struct Formatter<'a>;
    pub trait Debug {
        fn fmt(&self, f: &mut Formatter<'_>) -> Result;
    }
}

struct Foo {
    bar: String,
}

impl fmt::Debug for Foo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        ${0:todo!()}
    }
}
"#,
        )
    }
    #[test]
    fn add_custom_impl_all() {
        check_assist(
            replace_derive_with_manual_impl,
            r#"
mod foo {
    pub trait Bar {
        type Qux;
        const Baz: usize = 42;
        const Fez: usize;
        fn foo();
        fn bar() {}
    }
}

#[derive($0Bar)]
struct Foo {
    bar: String,
}
"#,
            r#"
mod foo {
    pub trait Bar {
        type Qux;
        const Baz: usize = 42;
        const Fez: usize;
        fn foo();
        fn bar() {}
    }
}

struct Foo {
    bar: String,
}

impl foo::Bar for Foo {
    $0type Qux;

    const Baz: usize = 42;

    const Fez: usize;

    fn foo() {
        todo!()
    }
}
"#,
        )
    }
    #[test]
    fn add_custom_impl_for_unique_input() {
        check_assist(
            replace_derive_with_manual_impl,
            r#"
#[derive(Debu$0g)]
struct Foo {
    bar: String,
}
            "#,
            r#"
struct Foo {
    bar: String,
}

impl Debug for Foo {
    $0
}
            "#,
        )
    }

    #[test]
    fn add_custom_impl_for_with_visibility_modifier() {
        check_assist(
            replace_derive_with_manual_impl,
            r#"
#[derive(Debug$0)]
pub struct Foo {
    bar: String,
}
            "#,
            r#"
pub struct Foo {
    bar: String,
}

impl Debug for Foo {
    $0
}
            "#,
        )
    }

    #[test]
    fn add_custom_impl_when_multiple_inputs() {
        check_assist(
            replace_derive_with_manual_impl,
            r#"
#[derive(Display, Debug$0, Serialize)]
struct Foo {}
            "#,
            r#"
#[derive(Display, Serialize)]
struct Foo {}

impl Debug for Foo {
    $0
}
            "#,
        )
    }

    #[test]
    fn test_ignore_derive_macro_without_input() {
        check_assist_not_applicable(
            replace_derive_with_manual_impl,
            r#"
#[derive($0)]
struct Foo {}
            "#,
        )
    }

    #[test]
    fn test_ignore_if_cursor_on_param() {
        check_assist_not_applicable(
            replace_derive_with_manual_impl,
            r#"
#[derive$0(Debug)]
struct Foo {}
            "#,
        );

        check_assist_not_applicable(
            replace_derive_with_manual_impl,
            r#"
#[derive(Debug)$0]
struct Foo {}
            "#,
        )
    }

    #[test]
    fn test_ignore_if_not_derive() {
        check_assist_not_applicable(
            replace_derive_with_manual_impl,
            r#"
#[allow(non_camel_$0case_types)]
struct Foo {}
            "#,
        )
    }

    #[test]
    fn works_at_start_of_file() {
        cov_mark::check!(outside_of_attr_args);
        check_assist_not_applicable(
            replace_derive_with_manual_impl,
            r#"
$0#[derive(Debug)]
struct S;
            "#,
        );
    }
}
<|endoftext|>


<commit_before>// Unused mut warning is false in this context
#[macro_use]
extern crate slog;
extern crate slog_term;
extern crate slog_stream;

#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate serde;
extern crate futures;
extern crate hyper;
extern crate tokio_core;
extern crate hyper_tls;
extern crate time;
extern crate clap;

mod utils;
mod models;
mod client;
mod app;
mod endpoint;
mod cli;

use app::*;
use models::*;
use client::*;
use cli::*;

use std::io::{self, BufRead};
use std::thread::spawn;
use std::thread;
use futures::{Stream, Sink, Future};
use futures::sync::mpsc;
use futures::sync::mpsc::{Receiver, Sender};
use futures::stream::BoxStream;

fn main() {

    let mut app_domain = AppDomain::new();
    let mut app_cache: AppCache = AppCache::new();
    let mut app_state_machine: AppStateMachine = AppStateMachine::new();

    info!(&app_domain.logger, "Application started");
    app_cache.retrieved_top_stories = get_top_story_ids(&mut app_domain, &mut app_state_machine)
        .ok();
    front_page(&mut app_domain, &mut app_cache, &mut app_state_machine);
    let (mut tx, rx) = mpsc::channel(1);

    let listener = rx.for_each(|res| stdin_listener_sink(res));
    spawn(move || {
        let stdin = io::stdin();
        for line in stdin.lock().lines() {
            tx = tx.send(line).wait().unwrap();
        }
    });

    app_domain.core.run(listener);

    // run_gui_client(&mut app_domain, &mut app_cache, &mut app_state_machine);
}
fn stdin_listener_sink(res:Result<String, io::Error>) -> Result<(),()> {
        match res {
            Ok(_res) => println!("{}", _res),
            Err(_) => println!("{}", "Error"),
        }
        Ok(())
}

fn front_page(app_domain: &mut AppDomain,
              app_cache: &mut AppCache,
              app_state_machine: &mut AppStateMachine) {
    let top_stories = app_cache.retrieved_top_stories.as_ref().unwrap();
    info!(&app_domain.logger,
          format!("Received {} top stories", top_stories.values.len()));
    let mut index = 0;
    for item_id in top_stories.values.iter().take(10) {
        index += 1;
        let s = format!("{}", item_id);
        let item: HnItem = client::get_item_by_id(&s, app_domain, app_state_machine).unwrap();
        print_headline_with_author(&item, &index);
    }
}

<commit_msg>made some vars better named and cloning of sender clearer<commit_after>// Unused mut warning is false in this context
#[macro_use]
extern crate slog;
extern crate slog_term;
extern crate slog_stream;

#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate serde;
extern crate futures;
extern crate hyper;
extern crate tokio_core;
extern crate hyper_tls;
extern crate time;
extern crate clap;

mod utils;
mod models;
mod client;
mod app;
mod endpoint;
mod cli;

use app::*;
use models::*;
use client::*;
use cli::*;

use std::io::{self, BufRead};
use std::thread::spawn;
use std::thread;
use futures::{Stream, Sink, Future};
use futures::sync::mpsc;
use futures::sync::mpsc::{Receiver, Sender};
use futures::stream::BoxStream;

fn main() {

    let mut app_domain = AppDomain::new();
    let mut app_cache: AppCache = AppCache::new();
    let mut app_state_machine: AppStateMachine = AppStateMachine::new();

    info!(&app_domain.logger, "Application started");
    app_cache.retrieved_top_stories = get_top_story_ids(&mut app_domain, &mut app_state_machine)
        .ok();
    front_page(&mut app_domain, &mut app_cache, &mut app_state_machine);
    let (mut sender, receiver) = mpsc::channel(1);

    spawn(move || {
        let stdin = io::stdin();
        for line in stdin.lock().lines() {
            let sender = sender.clone();
            sender.send(line).wait().unwrap();
        }
    });

    let listener = receiver.for_each(|msg| stdin_listener_sink(msg));
    app_domain.core.run(listener);
}

fn stdin_listener_sink(msg:Result<String, io::Error>) -> Result<(),()> {
        // TODO Handle different commands and arguments related to state
        match msg {
            Ok(_msg) => println!("{}", _msg),
            Err(_) => println!("{}", "Error"),
        }
        Ok(())
}

fn front_page(app_domain: &mut AppDomain,
              app_cache: &mut AppCache,
              app_state_machine: &mut AppStateMachine) {
    let top_stories = app_cache.retrieved_top_stories.as_ref().unwrap();
    info!(&app_domain.logger,
          format!("Received {} top stories", top_stories.values.len()));
    let mut index = 0;
    for item_id in top_stories.values.iter().take(10) {
        index += 1;
        let s = format!("{}", item_id);
        let item: HnItem = client::get_item_by_id(&s, app_domain, app_state_machine).unwrap();
        print_headline_with_author(&item, &index);
    }
}

<|endoftext|>


<commit_before>use anyhow::Result;
use bytes::Bytes;
use std::collections::HashMap;
use std::time::Duration;
use tide::Request;

use async_std::sync::{channel, Arc, Receiver, Sender};
use futures::sink::SinkExt;
use futures::stream::StreamExt;
use tungstenite::Message;

use async_std::task;

#[derive(Clone, Copy)]
#[repr(u8)]
enum SystemCommand {
    WakeUp = 1,
    Disconnect = 2,
}

#[derive(Clone, Debug)]
enum ReceiverType {
    System,
    Hypercore,
    Client,
}

#[derive(Clone)]
struct State {
    system_commands: Receiver<Bytes>,
    writers: HashMap<Bytes, Sender<Bytes>>,
    readers: HashMap<Bytes, Receiver<Bytes>>,
}

#[derive(Clone)]
struct WrappedData {
    data: Bytes,
    receiver_type: ReceiverType,
    id: Option<Bytes>,
}

type WrappedBytesClosure = Box<dyn Fn(Bytes) -> WrappedData + Send + Sync>;
// type WrappedWebSocketClosure =
//     Box<dyn Fn(Result<tungstenite::Message, std::io::Error>) -> WrappedData + Send + Sync>;

async fn async_main(initial_state: State) -> Result<()> {
    let mut app = tide::with_state(initial_state);

    app.at("/ws").get(|req: Request<State>| async move {
        tide::websocket::upgrade(req, |_req, handle| async move {
            // https://docs.rs/async-tungstenite/0.10.0/async_tungstenite/struct.WebSocketStream.html
            let (mut ws_writer, mut ws_reader) = handle.into_inner().split();
            let init_msg: Bytes = Bytes::from(ws_reader.next().await.unwrap().unwrap().into_data());
            dbg!(&init_msg);
            let hypercore_writer = _req.state().writers[&*init_msg].clone();
            ws_writer
                .send(Message::Text("reply-to-init".to_string()))
                .await
                .unwrap();
            let (client_sender, client_receiver): (Sender<Bytes>, Receiver<Bytes>) = channel(1000);
            let init_msg: Arc<Bytes> = Arc::new(init_msg.clone());
            task::spawn(async move {
                let receivers = collect_receivers(_req.state(), client_receiver.clone(), init_msg);
                let mut merged = futures::stream::select_all(receivers);
                while let Some(wrapped_value) = merged.next().await {
                    dbg!("got value of type {}", wrapped_value.receiver_type);
                    ws_writer
                        .send(tungstenite::Message::Binary(
                            wrapped_value.data.as_ref().to_vec(),
                        ))
                        .await
                        .unwrap();
                    dbg!("got result");
                }
            });
            loop {
                let incoming_msg = ws_reader.next().await;
                let msg = incoming_msg.unwrap().unwrap();
                client_sender.send(Bytes::from(msg.into_data())).await;
            }
        })
    });

    app.listen("0.0.0.0:8080").await?;
    Ok(())
}

fn collect_receivers(
    state: &State,
    client_receiver: Receiver<Bytes>,
    init_msg: Arc<Bytes>,
) -> Vec<futures::stream::Map<async_std::sync::Receiver<bytes::Bytes>, WrappedBytesClosure>> {
    let reader = state.readers[init_msg.as_ref()].clone();
    vec![
        state
            .system_commands
            .clone()
            .map(Box::new(|data| WrappedData {
                data,
                receiver_type: ReceiverType::System,
                id: None,
            }) as WrappedBytesClosure),
        reader.map(Box::new(move |data| WrappedData {
            data,
            receiver_type: ReceiverType::Hypercore,
            id: Some((*init_msg).clone()),
        }) as WrappedBytesClosure),
        client_receiver.map(Box::new(move |data| WrappedData {
            data,
            receiver_type: ReceiverType::Client,
            id: None,
        }) as WrappedBytesClosure),
    ]
}

fn main() -> Result<()> {
    fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d %H:%M:%S]"),
                record.target(),
                record.level(),
                message
            ))
        })
        .level(log::LevelFilter::Debug)
        .chain(std::io::stdout())
        .apply()?;
    let (ping_sender, system_command_receiver) = channel(1000);
    let (demo_sender, demo_receiver) = channel(1000);
    let initial_state = State {
        system_commands: system_command_receiver,
        writers: [(Bytes::from_static("demo".as_bytes()), demo_sender)]
            .iter()
            .cloned()
            .collect(),
        readers: [(Bytes::from_static("demo".as_bytes()), demo_receiver)]
            .iter()
            .cloned()
            .collect(),
    };

    // TODO: This should be used on SIGINT/SIGTERM
    let disconnect_sender = ping_sender.clone();

    // Need to start a system executor to send the WakeUp command, we send it once per 5 seconds so
    // that the listener will send a WS Ping every 30 to 35 seconds.
    task::spawn(async move {
        loop {
            task::sleep(Duration::from_millis(5000)).await;
            dbg!("Sending WakeUp");
            ping_sender
                .send(Bytes::from_static(&[SystemCommand::WakeUp as u8]))
                .await;
        }
    });

    futures::executor::block_on(async_main(initial_state))?;

    Ok(())
}
<commit_msg>Better variable names<commit_after>use anyhow::Result;
use bytes::Bytes;
use std::collections::HashMap;
use std::time::Duration;
use tide::Request;

use async_std::sync::{channel, Arc, Receiver, Sender};
use futures::sink::SinkExt;
use futures::stream::StreamExt;
use tungstenite::Message;

use async_std::task;

#[derive(Clone, Copy)]
#[repr(u8)]
enum SystemCommand {
    WakeUp = 1,
    Disconnect = 2,
}

#[derive(Clone, Debug)]
enum ReceiverType {
    System,
    Hypercore,
    Client,
}

#[derive(Clone)]
struct State {
    system_commands: Receiver<Bytes>,
    writers: HashMap<Bytes, Sender<Bytes>>,
    readers: HashMap<Bytes, Receiver<Bytes>>,
}

#[derive(Clone)]
struct WrappedData {
    data: Bytes,
    receiver_type: ReceiverType,
    id: Option<Bytes>,
}

type WrappedBytesClosure = Box<dyn Fn(Bytes) -> WrappedData + Send + Sync>;
// type WrappedWebSocketClosure =
//     Box<dyn Fn(Result<tungstenite::Message, std::io::Error>) -> WrappedData + Send + Sync>;

async fn async_main(initial_state: State) -> Result<()> {
    let mut app = tide::with_state(initial_state);

    app.at("/ws").get(|req: Request<State>| async move {
        tide::websocket::upgrade(req, |_req, handle| async move {
            // https://docs.rs/async-tungstenite/0.10.0/async_tungstenite/struct.WebSocketStream.html
            let (mut ws_writer, mut ws_reader) = handle.into_inner().split();
            let init_msg: Bytes = Bytes::from(ws_reader.next().await.unwrap().unwrap().into_data());
            dbg!(&init_msg);
            let hypercore_writer = _req.state().writers[&*init_msg].clone();
            ws_writer
                .send(Message::Text("reply-to-init".to_string()))
                .await
                .unwrap();
            let (client_sender, client_receiver): (Sender<Bytes>, Receiver<Bytes>) = channel(1000);
            let init_msg: Arc<Bytes> = Arc::new(init_msg.clone());
            task::spawn(async move {
                let receivers = collect_receivers(_req.state(), client_receiver.clone(), init_msg);
                let mut merged_receivers = futures::stream::select_all(receivers);
                while let Some(wrapped_value) = merged_receivers.next().await {
                    dbg!("got value of type {}", wrapped_value.receiver_type);
                    ws_writer
                        .send(tungstenite::Message::Binary(
                            wrapped_value.data.as_ref().to_vec(),
                        ))
                        .await
                        .unwrap();
                    dbg!("got result");
                }
            });
            loop {
                let incoming_msg = ws_reader.next().await;
                let msg = incoming_msg.unwrap().unwrap();
                client_sender.send(Bytes::from(msg.into_data())).await;
            }
        })
    });

    app.listen("0.0.0.0:8080").await?;
    Ok(())
}

fn collect_receivers(
    state: &State,
    client_receiver: Receiver<Bytes>,
    init_msg: Arc<Bytes>,
) -> Vec<futures::stream::Map<async_std::sync::Receiver<bytes::Bytes>, WrappedBytesClosure>> {
    let reader = state.readers[init_msg.as_ref()].clone();
    vec![
        state
            .system_commands
            .clone()
            .map(Box::new(|data| WrappedData {
                data,
                receiver_type: ReceiverType::System,
                id: None,
            }) as WrappedBytesClosure),
        reader.map(Box::new(move |data| WrappedData {
            data,
            receiver_type: ReceiverType::Hypercore,
            id: Some((*init_msg).clone()),
        }) as WrappedBytesClosure),
        client_receiver.map(Box::new(move |data| WrappedData {
            data,
            receiver_type: ReceiverType::Client,
            id: None,
        }) as WrappedBytesClosure),
    ]
}

fn main() -> Result<()> {
    fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d %H:%M:%S]"),
                record.target(),
                record.level(),
                message
            ))
        })
        .level(log::LevelFilter::Debug)
        .chain(std::io::stdout())
        .apply()?;
    let (ping_sender, system_command_receiver) = channel(1000);
    let (demo_sender, demo_receiver) = channel(1000);
    let initial_state = State {
        system_commands: system_command_receiver,
        writers: [(Bytes::from_static("demo".as_bytes()), demo_sender)]
            .iter()
            .cloned()
            .collect(),
        readers: [(Bytes::from_static("demo".as_bytes()), demo_receiver)]
            .iter()
            .cloned()
            .collect(),
    };

    // TODO: This should be used on SIGINT/SIGTERM
    let disconnect_sender = ping_sender.clone();

    // Need to start a system executor to send the WakeUp command, we send it once per 5 seconds so
    // that the listener will send a WS Ping every 30 to 35 seconds.
    task::spawn(async move {
        loop {
            task::sleep(Duration::from_millis(5000)).await;
            dbg!("Sending WakeUp");
            ping_sender
                .send(Bytes::from_static(&[SystemCommand::WakeUp as u8]))
                .await;
        }
    });

    futures::executor::block_on(async_main(initial_state))?;

    Ok(())
}
<|endoftext|>


<commit_before><commit_msg>Use `read_blocking`<commit_after><|endoftext|>