<commit_before>//! Tests borrowed from Go and ported to Rust.

extern crate crossbeam;
#[macro_use]
extern crate crossbeam_channel as channel;

mod wrappers;

macro_rules! tests {
    ($channel:path) => {
        use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
        use std::thread;
        use std::time::Duration;

        use $channel as channel;
        use crossbeam;

        fn ms(ms: u64) -> Duration {
            Duration::from_millis(ms)
        }

        // https://github.com/golang/go/blob/master/test/chan/doubleselect.go
        mod doubleselect {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/fifo.go
        mod fifo {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/nonblock.go
        mod nonblock {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/select.go
        mod select {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/select2.go
        mod select2 {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/select3.go
        mod select3 {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/select4.go
        mod select4 {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/select5.go
        mod select5 {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/select6.go
        mod select6 {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/select7.go
        mod select7 {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/sieve1.go
        mod sieve1 {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/sieve2.go
        mod sieve2 {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/zerosize.go
        mod zerosize {
            // TODO
        }

        // https://github.com/golang/go/blob/master/src/runtime/chan_test.go
        mod chan_test {
            use super::*;

            #[test]
            fn chan() {
                const N: usize = 200;

                for cap in 0..N {
                    {
                        let c = channel::bounded::<i32>(cap);
                        let recv1 = AtomicBool::new(false);
                        let recv2 = AtomicBool::new(false);

                        crossbeam::scope(|scope| {
                            scope.spawn(|| {
                                c.1.recv();
                                recv1.store(true, Ordering::SeqCst);
                            });
                            scope.spawn(|| {
                                c.1.recv();
                                recv2.store(true, Ordering::SeqCst);
                            });

                            thread::sleep(ms(1));

                            if recv1.load(Ordering::SeqCst) || recv2.load(Ordering::SeqCst) {
                                panic!();
                            }

                            // Ensure that non-blocking receive does not block.
                            select! {
                                recv(c.1) => panic!(),
                                default => {}
                            }
                            select! {
                                recv(c.1) => panic!(),
                                default => {}
                            }

                            c.0.send(0);
                            c.0.send(0);
                        });
                    }

                    {
                        // Ensure that send to full chan blocks.
                        let c = channel::bounded::<i32>(cap);
                        for i in 0..cap {
                            c.0.send(i as i32);
                        }
                        let sent = AtomicUsize::new(0);

                        crossbeam::scope(|scope| {
                            scope.spawn(|| {
                                c.0.send(0);
                                sent.store(1, Ordering::SeqCst);
                            });

                            thread::sleep(ms(1));

                            if sent.load(Ordering::SeqCst) != 0 {
                                panic!();
                            }

                            // Ensure that non-blocking send does not block.
                            select! {
                                send(c.0, 0) => panic!(),
                                default => {}
                            }
                            c.1.recv();
                        });
                    }

                    {
                        // Ensure that we receive 0 from closed chan.
                        let c = channel::bounded::<i32>(cap);
                        for i in 0..cap {
                            c.0.send(i as i32);
                        }
                        drop(c.0);

                        for i in 0..cap {
                            let v = c.1.recv();
                            assert_eq!(v, Some(i as i32));
                        }

                        assert_eq!(c.1.recv(), None);
                    }

                    {
                        // Ensure that close unblocks receive.
                        let (s, r) = channel::bounded::<i32>(cap);
                        let done = channel::bounded::<bool>(0);

                        crossbeam::scope(|scope| {
                            scope.spawn(|| done.0.send(r.recv() == None));
                            thread::sleep(ms(1));
                            drop(s);

                            assert_eq!(done.1.recv(), Some(true));
                        });
                    }

                    {
                        // Send 100 integers,
                        // ensure that we receive them non-corrupted in FIFO order.
                        let c = channel::bounded::<i32>(cap);
                        crossbeam::scope(|scope| {
                            scope.spawn(|| {
                                for i in 0..100 {
                                    c.0.send(i);
                                }
                            });

                            for i in 0..100 {
                                assert_eq!(c.1.recv(), Some(i));
                            }
                        });

                        // Same, but using recv2.
                        crossbeam::scope(|scope| {
                            scope.spawn(|| {
                                for i in 0..100 {
                                    c.0.send(i);
                                }
                            });

                            for i in 0..100 {
                                assert_eq!(c.1.recv(), Some(i));
                            }
                        });

                        // Send 1000 integers in 4 goroutines,
                        // ensure that we receive what we send.
                        const P: usize = 4;
                        const L: usize = 1000;
                        let done = channel::bounded::<Vec<i32>>(0);
                        crossbeam::scope(|scope| {
                            for _ in 0..P {
                                scope.spawn(|| {
                                    for i in 0..L {
                                        c.0.send(i as i32);
                                    }
                                });
                            }

                            for _ in 0..P {
                                scope.spawn(|| {
                                    let mut recv = vec![0; L];
                                    for _ in 0..L {
                                        let v = c.1.recv().unwrap();
                                        recv[v as usize] += 1;
                                    }
                                    done.0.send(recv);
                                });
                            }

                            let mut recv = vec![0; L];
                            for _ in 0..P {
                                for (i, v) in done.1.recv().unwrap().into_iter().enumerate() {
                                    recv[i] += v;
                                }
                            }

                            assert_eq!(recv.len(), L);
                            for v in recv {
                                assert_eq!(v, P as i32);
                            }
                        });
                    }

                    {
                        // Test len/cap.
                        let c = channel::bounded::<i32>(cap);

                        assert_eq!(c.0.len(), 0);
                        assert_eq!(c.0.capacity(), Some(cap));

                        for i in 0..cap {
                            c.0.send(i as i32);
                        }

                        assert_eq!(c.0.len(), cap);
                        assert_eq!(c.0.capacity(), Some(cap));
                    }
                }
            }

            #[test]
            fn nonblock_recv_race() {
                // TODO
            }

            #[test]
            fn nonblock_select_race() {
                // TODO
            }

            #[test]
            fn nonblock_select_race2() {
                // TODO
            }

            #[test]
            fn self_select() {
                // TODO
            }

            #[test]
            fn select_stress() {
                // TODO
            }

            #[test]
            fn select_fairness() {
                // TODO
            }

            #[test]
            fn chan_send_interface() {
                // TODO
            }

            #[test]
            fn pseudo_random_send() {
                // TODO
            }

            #[test]
            fn multi_consumer() {
                // TODO
            }

            #[test]
            fn shrink_stack_during_blocked_send() {
                // TODO
            }

            #[test]
            fn select_duplicate_channel() {
                // TODO
            }

            #[test]
            fn select_stack_adjust() {
                // TODO
            }
        }

        // https://github.com/golang/go/blob/master/test/closedchan.go
        mod closedchan {
            // TODO
        }

        // https://github.com/golang/go/blob/master/src/runtime/chanbarrier_test.go
        mod chanbarrier_test {
            // TODO
        }

        // https://github.com/golang/go/blob/master/src/runtime/race/testdata/chan_test.go
        mod race_chan_test {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/ken/chan.go
        mod chan {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/ken/chan1.go
        mod chan1 {
            // TODO
        }
    }
}

mod normal {
    tests!(wrappers::normal);
}

mod cloned {
    tests!(wrappers::cloned);
}

mod select {
    tests!(wrappers::select);
}

mod select_spin {
    tests!(wrappers::select_spin);
}

mod select_multi {
    tests!(wrappers::select_multi);
}
<commit_msg>Add more golang tests<commit_after>//! Tests borrowed from Go and ported to Rust.

extern crate crossbeam;
#[macro_use]
extern crate crossbeam_channel as channel;
extern crate parking_lot;

mod wrappers;

macro_rules! tests {
    ($channel:path) => {
        use std::any::Any;
        use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
        use std::thread;
        use std::time::Duration;

        use $channel as channel;
        use crossbeam;
        use parking_lot::Mutex;

        fn ms(ms: u64) -> Duration {
            Duration::from_millis(ms)
        }

        // https://github.com/golang/go/blob/master/test/chan/doubleselect.go
        mod doubleselect {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/fifo.go
        mod fifo {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/nonblock.go
        mod nonblock {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/select.go
        mod select {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/select2.go
        mod select2 {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/select3.go
        mod select3 {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/select4.go
        mod select4 {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/select5.go
        mod select5 {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/select6.go
        mod select6 {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/select7.go
        mod select7 {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/sieve1.go
        mod sieve1 {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/sieve2.go
        mod sieve2 {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/chan/zerosize.go
        mod zerosize {
            // TODO
        }

        // https://github.com/golang/go/blob/master/src/runtime/chan_test.go
        mod chan_test {
            use super::*;

            #[test]
            fn chan() {
                const N: usize = 200;

                for cap in 0..N {
                    {
                        let c = channel::bounded::<i32>(cap);
                        let recv1 = AtomicBool::new(false);
                        let recv2 = AtomicBool::new(false);

                        crossbeam::scope(|scope| {
                            scope.spawn(|| {
                                c.1.recv();
                                recv1.store(true, Ordering::SeqCst);
                            });
                            scope.spawn(|| {
                                c.1.recv();
                                recv2.store(true, Ordering::SeqCst);
                            });

                            thread::sleep(ms(1));

                            if recv1.load(Ordering::SeqCst) || recv2.load(Ordering::SeqCst) {
                                panic!();
                            }

                            // Ensure that non-blocking receive does not block.
                            select! {
                                recv(c.1) => panic!(),
                                default => {}
                            }
                            select! {
                                recv(c.1) => panic!(),
                                default => {}
                            }

                            c.0.send(0);
                            c.0.send(0);
                        });
                    }

                    {
                        // Ensure that send to full chan blocks.
                        let c = channel::bounded::<i32>(cap);
                        for i in 0..cap {
                            c.0.send(i as i32);
                        }
                        let sent = AtomicUsize::new(0);

                        crossbeam::scope(|scope| {
                            scope.spawn(|| {
                                c.0.send(0);
                                sent.store(1, Ordering::SeqCst);
                            });

                            thread::sleep(ms(1));

                            if sent.load(Ordering::SeqCst) != 0 {
                                panic!();
                            }

                            // Ensure that non-blocking send does not block.
                            select! {
                                send(c.0, 0) => panic!(),
                                default => {}
                            }
                            c.1.recv();
                        });
                    }

                    {
                        // Ensure that we receive 0 from closed chan.
                        let c = channel::bounded::<i32>(cap);
                        for i in 0..cap {
                            c.0.send(i as i32);
                        }
                        drop(c.0);

                        for i in 0..cap {
                            let v = c.1.recv();
                            assert_eq!(v, Some(i as i32));
                        }

                        assert_eq!(c.1.recv(), None);
                    }

                    {
                        // Ensure that close unblocks receive.
                        let (s, r) = channel::bounded::<i32>(cap);
                        let done = channel::bounded::<bool>(0);

                        crossbeam::scope(|scope| {
                            scope.spawn(|| done.0.send(r.recv() == None));
                            thread::sleep(ms(1));
                            drop(s);

                            assert_eq!(done.1.recv(), Some(true));
                        });
                    }

                    {
                        // Send 100 integers,
                        // ensure that we receive them non-corrupted in FIFO order.
                        let c = channel::bounded::<i32>(cap);
                        crossbeam::scope(|scope| {
                            scope.spawn(|| {
                                for i in 0..100 {
                                    c.0.send(i);
                                }
                            });

                            for i in 0..100 {
                                assert_eq!(c.1.recv(), Some(i));
                            }
                        });

                        // Same, but using recv2.
                        crossbeam::scope(|scope| {
                            scope.spawn(|| {
                                for i in 0..100 {
                                    c.0.send(i);
                                }
                            });

                            for i in 0..100 {
                                assert_eq!(c.1.recv(), Some(i));
                            }
                        });

                        // Send 1000 integers in 4 goroutines,
                        // ensure that we receive what we send.
                        const P: usize = 4;
                        const L: usize = 1000;
                        let done = channel::bounded::<Vec<i32>>(0);
                        crossbeam::scope(|scope| {
                            for _ in 0..P {
                                scope.spawn(|| {
                                    for i in 0..L {
                                        c.0.send(i as i32);
                                    }
                                });
                            }

                            for _ in 0..P {
                                scope.spawn(|| {
                                    let mut recv = vec![0; L];
                                    for _ in 0..L {
                                        let v = c.1.recv().unwrap();
                                        recv[v as usize] += 1;
                                    }
                                    done.0.send(recv);
                                });
                            }

                            let mut recv = vec![0; L];
                            for _ in 0..P {
                                for (i, v) in done.1.recv().unwrap().into_iter().enumerate() {
                                    recv[i] += v;
                                }
                            }

                            assert_eq!(recv.len(), L);
                            for v in recv {
                                assert_eq!(v, P as i32);
                            }
                        });
                    }

                    {
                        // Test len/cap.
                        let c = channel::bounded::<i32>(cap);

                        assert_eq!(c.0.len(), 0);
                        assert_eq!(c.0.capacity(), Some(cap));

                        for i in 0..cap {
                            c.0.send(i as i32);
                        }

                        assert_eq!(c.0.len(), cap);
                        assert_eq!(c.0.capacity(), Some(cap));
                    }
                }
            }

            #[test]
            fn nonblock_recv_race() {
                const N: usize = 10000;

                for _ in 0..N {
                    let (s, r) = channel::bounded(1);
                    s.send(1);

                    crossbeam::scope(|scope| {
                        scope.spawn(|| {
                            select! {
                                recv(r) => {}
                                default => panic!("chan is not ready"),
                            }
                        });

                        drop(s);
                        r.recv();
                    });
                }
            }

            #[test]
            fn nonblock_select_race() {
                const N: usize = 10000;

                let (done_s, done_r) = channel::bounded::<bool>(1);
                for _ in 0..N {
                    let (s1, r1) = channel::bounded::<i32>(1);
                    let (s2, r2) = channel::bounded::<i32>(1);
                    s1.send(1);

                    crossbeam::scope(|scope| {
                        scope.spawn(|| {
                            select! {
                                recv(r1) => {}
                                recv(r2) => {}
                                default => {
                                    done_s.send(false);
                                    return;
                                }
                            }
                            done_s.send(true);
                        });

                        s2.send(1);
                        select! {
                            recv(r1) => {}
                            default => {}
                        }

                        if !done_r.recv().unwrap() {
                            panic!("no chan is ready");
                        }
                    });
                }
            }

            #[test]
            fn nonblock_select_race2() {
                const N: usize = 1000;

                let (done_s, done_r) = channel::bounded::<bool>(1);
                for _ in 0..N {
                    let (s1, r1) = channel::bounded::<i32>(1);
                    let (s2, r2) = channel::bounded::<i32>(0);
                    s1.send(1);

                    crossbeam::scope(|scope| {
                        scope.spawn(|| {
                            select! {
                                recv(r1) => {}
                                recv(r2) => {}
                                default => {
                                    done_s.send(false);
                                    return;
                                }
                            }
                            done_s.send(true);
                        });

                        drop(s2);
                        select! {
                            recv(r1) => {}
                            default => {}
                        }

                        if !done_r.recv().unwrap() {
                            panic!("no chan is ready");
                        }
                    });
                }
            }

            #[test]
            fn self_select() {
                // Ensure that send/recv on the same chan in select
                // does not crash nor deadlock.
                for &cap in &[0, 10] {
                    let (s, r) = channel::bounded::<i32>(cap);

                    crossbeam::scope(|scope| {
                        for p in 0..2 {
                            let p = p;
                            let (s, r) = (&s, &r);
                            scope.spawn(move || {
                                for i in 0..1000 {
                                    if p == 0 || i % 2 == 0 {
                                        select! {
                                            send(s, p) => {}
                                            recv(r, v) => {
                                                if cap == 0 && v.unwrap() == p {
                                                    panic!("self receive");
                                                }
                                            }
                                        }
                                    } else {
                                        select! {
                                            recv(r, v) => {
                                                if cap == 0 && v.unwrap() == p {
                                                    panic!("self receive");
                                                }
                                            }
                                            send(s, p) => {}
                                        }
                                    }
                                }
                            });
                        }
                    });
                }
            }

            #[test]
            fn select_stress() {
                let c = vec![
                    channel::bounded(0),
                    channel::bounded(0),
                    channel::bounded(2),
                    channel::bounded(3),
                ];

                const N: usize = 10000;

                // There are 4 goroutines that send N values on each of the chans,
                // + 4 goroutines that receive N values on each of the chans,
                // + 1 goroutine that sends N values on each of the chans in a single select,
                // + 1 goroutine that receives N values on each of the chans in a single select.
                // All these sends, receives and selects interact chaotically at runtime,
                // but we are careful that this whole construct does not deadlock.
                crossbeam::scope(|scope| {
                    for k in 0..4 {
                        {
                            let c = c.clone();
                            let k = k;
                            scope.spawn(move || {
                                for _ in 0..N {
                                    c[k].0.send(0);
                                }
                            });
                        }
                        {
                            let c = c.clone();
                            let k = k;
                            scope.spawn(move || {
                                for _ in 0..N {
                                    c[k].1.recv();
                                }
                            });
                        }
                    }

                    {
                        let mut c = c.iter()
                            .map(|(s, r)| (Some(s.clone()), Some(r.clone())))
                            .collect::<Vec<_>>();

                        scope.spawn(move || {
                            let mut n = [0i32; 4];
                            for _ in 0..4 * N {
                                let i;
                                select! {
                                    send(c[3].0.iter().map(|x| &**x), 0) => i = 3,
                                    send(c[2].0.iter().map(|x| &**x), 0) => i = 2,
                                    send(c[0].0.iter().map(|x| &**x), 0) => i = 0,
                                    send(c[1].0.iter().map(|x| &**x), 0) => i = 1,
                                }
                                n[i] += 1;
                                if n[i] == N as i32 {
                                    c[i].0 = None;
                                }
                            }
                        });
                    }

                    {
                        let mut c = c.iter()
                            .map(|(s, r)| (Some(s.clone()), Some(r.clone())))
                            .collect::<Vec<_>>();

                        scope.spawn(move || {
                            let mut n = [0i32; 4];
                            for _ in 0..4 * N {
                                let i;
                                select! {
                                    recv(c[0].1.iter().map(|x| &**x)) => i = 0,
                                    recv(c[1].1.iter().map(|x| &**x)) => i = 1,
                                    recv(c[2].1.iter().map(|x| &**x)) => i = 2,
                                    recv(c[3].1.iter().map(|x| &**x)) => i = 3,
                                }
                                n[i] += 1;
                                if n[i] == N as i32 {
                                    c[i].0 = None;
                                }
                            }
                        });
                    }
                });
            }

            #[test]
            fn select_fairness() {
                const TRIALS: usize = 10000;

                let (s1, r1) = channel::bounded::<u8>(TRIALS + 1);
                let (s2, r2) = channel::bounded::<u8>(TRIALS + 1);

                for _ in 0..TRIALS + 1 {
                    s1.send(1);
                    s2.send(2);
                }

                let (_s3, r3) = channel::bounded::<u8>(TRIALS + 1);
                let (_s4, r4) = channel::bounded::<u8>(TRIALS + 1);
                let (out_s, out_r) = channel::bounded::<u8>(TRIALS + 1);
                let (done_s, done_r) = channel::bounded::<u8>(TRIALS + 1);

                crossbeam::scope(|scope| {
                    scope.spawn(|| {
                        loop {
                            let b = select! {
                                recv(r3, m) => m,
                                recv(r4, m) => m,
                                recv(r1, m) => m,
                                recv(r2, m) => m,
                            }.unwrap();

                            select! {
                                send(out_s, b) => {}
                                recv(done_r) => return
                            }
                        }
                    });

                    let (mut cnt1, mut cnt2) = (0, 0);
                    for _ in 0..TRIALS {
                        match out_r.recv() {
                            Some(1) => cnt1 += 1,
                            Some(2) => cnt2 += 1,
                            b => panic!("unexpected value {:?} on channel", b),
                        }
                    }

                    // If the select in the goroutine is fair,
                    // cnt1 and cnt2 should be about the same value.
                    // With 10,000 trials, the expected margin of error at
                    // a confidence level of five nines is 4.4172 / (2 * Sqrt(10000)).

                    let r = cnt1 as f64 / TRIALS as f64;
                    let e = (r - 0.5).abs();

                    if e > 4.4172 / (2.0 * (TRIALS as f64).sqrt()) {
                        panic!(
                            "unfair select: in {} trials, results were {}, {}",
                            TRIALS,
                            cnt1,
                            cnt2,
                        );
                    }

                    drop(done_s);
                });
            }

            #[test]
            fn chan_send_interface() {
                struct Mt;

                let (s, _r) = channel::bounded::<Box<Any>>(1);
                s.send(Box::new(Mt));

                select! {
                    send(s, Box::new(Mt)) => {}
                    default => {}
                }

                select! {
                    send(s, Box::new(Mt)) => {}
                    send(s, Box::new(Mt)) => {}
                    default => {}
                }
            }

            #[test]
            fn pseudo_random_send() {
                const N: usize = 100;

                for cap in 0..N {
                    let (s, r) = channel::bounded::<i32>(cap);
                    let l = Mutex::new(vec![0i32; N]);

                    crossbeam::scope(|scope| {
                        scope.spawn(|| {
                            let mut l = l.lock();
                            for i in 0..N {
                                thread::yield_now();
                                l[i] = r.recv().unwrap();
                            }
                        });

                        for _ in 0..N {
                            select! {
                                send(s, 1) => {}
                                send(s, 0) => {}
                            }
                        }

                        let l = l.lock();
                        let mut n0 = 0;
                        let mut n1 = 0;
                        for &i in l.iter() {
                            n0 += (i + 1) % 2;
                            n1 += i;
                        }

                        if n0 <= N as i32 / 10 || n1 <= N as i32 / 10 {
                            panic!(
                                "Want pseudorandom, got {} zeros and {} ones (chan cap {})",
                                n0,
                                n1,
                                cap,
                            );
                        }
                    });
                }
            }

            #[test]
            fn multi_consumer() {
                const NWORK: usize = 23;
                const NITER: usize = 271828;

                let pn = [2, 3, 7, 11, 13, 17, 19, 23, 27, 31];

                let (q_s, q_r) = channel::bounded::<i32>(NWORK * 3);
                let (r_s, r_r) = channel::bounded::<i32>(NWORK * 3);

                let expect = AtomicUsize::new(0);

                crossbeam::scope(|scope| {
                    // workers
                    for i in 0..NWORK {
                        let w = i;
                        let q_r = &q_r;
                        let pn = &pn;
                        let r_s = r_s.clone();
                        scope.spawn(move || {
                            for v in &q_r.0 {
                                // mess with the fifo-ish nature of range
                                if pn[w % pn.len()] == v {
                                    thread::yield_now();
                                }
                                r_s.send(v);
                            }
                        });
                    }

                    // feeder & closer
                    scope.spawn(|| {
                        for i in 0..NITER {
                            let v = pn[i % pn.len()];
                            expect.fetch_add(v as usize, Ordering::SeqCst);
                            q_s.send(v);
                        }

                        drop(q_s);
                        drop(r_s);
                    });

                    // consume & check
                    let mut n = 0;
                    let mut s = 0;
                    for v in &r_r.0 {
                        n += 1;
                        s += v;
                    }
                    if n != NITER || s != expect.load(Ordering::SeqCst) as i32 {
                        panic!(
                            "Expected sum {} (got {}) from {} iter (saw {})",
                            expect.load(Ordering::SeqCst),
                            s,
                            NITER,
                            n,
                        );
                    }
                });
            }

            #[test]
            fn select_duplicate_channel() {
                // This test makes sure we can queue a G on
                // the same channel multiple times.
                let (c_s, c_r) = channel::bounded::<i32>(0);
                let (d_s, d_r) = channel::bounded::<i32>(0);
                let (e_s, e_r) = channel::bounded::<i32>(0);

                crossbeam::scope(|scope| {
                    scope.spawn(|| {
                        select! {
                            recv(c_r) => {}
                            recv(c_r) => {}
                            recv(d_r) => {}
                        }
                        e_s.send(9);
                    });
                    thread::sleep(ms(1));

                    scope.spawn(|| {
                        c_r.recv();
                    });
                    thread::sleep(ms(1));

                    d_s.send(7);
                    e_r.recv();
                    c_s.send(8);
                });
            }
        }

        // https://github.com/golang/go/blob/master/test/closedchan.go
        mod closedchan {
            // TODO
        }

        // https://github.com/golang/go/blob/master/src/runtime/chanbarrier_test.go
        mod chanbarrier_test {
            // TODO
        }

        // https://github.com/golang/go/blob/master/src/runtime/race/testdata/chan_test.go
        mod race_chan_test {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/ken/chan.go
        mod chan {
            // TODO
        }

        // https://github.com/golang/go/blob/master/test/ken/chan1.go
        mod chan1 {
            // TODO
        }
    }
}

mod normal {
    tests!(wrappers::normal);
}

mod cloned {
    tests!(wrappers::cloned);
}

mod select {
    tests!(wrappers::select);
}

mod select_spin {
    tests!(wrappers::select_spin);
}

mod select_multi {
    tests!(wrappers::select_multi);
}
<|endoftext|>


<commit_before>//#![feature(trace_macros)]
#![allow(dead_code)]
#![cfg_attr(feature = "cargo-clippy", allow(redundant_closure))]

#[macro_use]
extern crate nom;

use nom::{space, Err, IResult, Needed, le_u64};
use nom::types::CompleteByteSlice;

#[allow(dead_code)]
struct Range {
  start: char,
  end: char,
}

pub fn take_char(input: &[u8]) -> IResult<&[u8], char> {
  if !input.is_empty() {
    Ok((&input[1..], input[0] as char))
  } else {
    Err(Err::Incomplete(Needed::Size(1)))
  }
}

//trace_macros!(true);

#[allow(dead_code)]
named!(range<&[u8], Range>,
    alt!(
        do_parse!(
            start: take_char >>
            tag!("-")        >>
            end: take_char   >>
            (Range {
                start: start,
                end:   end,
            })
        ) |
        map!(
            take_char,
            |c| {
                Range {
                    start: c,
                    end:   c,
                }
            }
        )
    )
);

#[allow(dead_code)]
named!(literal<&[u8], Vec<char> >,
    map!(
        many1!(take_char),
        |cs| {
          cs
        }
    )
);

#[test]
fn issue_58() {
  let _ = range(&b"abcd"[..]);
  let _ = literal(&b"abcd"[..]);
}

//trace_macros!(false);

#[cfg(feature = "std")]
mod parse_int {
  use nom::HexDisplay;
  use nom::{digit, space, IResult};
  use std::str;

  named!(parse_ints<Vec<i32>>, many0!(spaces_or_int));

  fn spaces_or_int(input: &[u8]) -> IResult<&[u8], i32> {
    println!("{}", input.to_hex(8));
    do_parse!(
      input,
      opt!(complete!(space)) >> res: map!(complete!(digit), |x| {
        println!("x: {:?}", x);
        let result = str::from_utf8(x).unwrap();
        println!("Result: {}", result);
        println!("int is empty?: {}", x.is_empty());
        match result.parse() {
          Ok(i) => i,
          Err(e) => panic!("UH OH! NOT A DIGIT! {:?}", e),
        }
      }) >> (res)
    )
  }

  #[test]
  fn issue_142() {
    let subject = parse_ints(&b"12 34 5689a"[..]);
    let expected = Ok((&b"a"[..], vec![12, 34, 5689]));
    assert_eq!(subject, expected);

    let subject = parse_ints(&b"12 34 5689 "[..]);
    let expected = Ok((&b" "[..], vec![12, 34, 5689]));
    assert_eq!(subject, expected)
  }
}

#[test]
fn usize_length_bytes_issue() {
  use nom::be_u16;
  let _: IResult<&[u8], &[u8], u32> = length_bytes!(b"012346", be_u16);
}

/*
 DOES NOT COMPILE
#[test]
fn issue_152() {
  named!(take4, take!(4));
  named!(xyz, tag!("XYZ"));
  named!(abc, tag!("abc"));

  named!(sw,
    switch!(take4,
      b"abcd" => xyz |
      b"efgh" => abc
    )
  );
}
*/

#[test]
fn take_till_issue() {
  named!(nothing, take_till!(call!(|_| true)));

  assert_eq!(nothing(b""), Err(Err::Incomplete(Needed::Size(1))));
  assert_eq!(nothing(b"abc"), Ok((&b"abc"[..], &b""[..])));
}

named!(
  issue_498<Vec<&[u8]>>,
  separated_nonempty_list!(opt!(space), tag!("abcd"))
);

named!(issue_308(&str) -> bool,
    do_parse! (
        tag_s! ("foo") >>
        b: alt_complete! (
            map! (tag_s! ("1"), |_: &str|->bool {true}) |
            value! (false)
        ) >>
        (b) ));

#[cfg(feature = "alloc")]
fn issue_302(input: &[u8]) -> IResult<&[u8], Option<Vec<u64>>> {
  do_parse!(input, entries: cond!(true, count!(le_u64, 3)) >> (entries))
}

#[test]
fn issue_655() {
  use nom::{line_ending, not_line_ending};
  named!(twolines(&str) -> (&str, &str),
    do_parse!(
      l1 : not_line_ending >>
           line_ending >>
      l2 : not_line_ending >>
           line_ending >>
      ((l1, l2))
    )
  );

  assert_eq!(twolines("foo\nbar\n"), Ok(("", ("foo", "bar"))));
  assert_eq!(twolines("féo\nbar\n"), Ok(("", ("féo", "bar"))));
  assert_eq!(twolines("foé\nbar\n"), Ok(("", ("foé", "bar"))));
  assert_eq!(twolines("foé\r\nbar\n"), Ok(("", ("foé", "bar"))));
}

#[cfg(feature = "std")]
named!(issue_666 <CompleteByteSlice, CompleteByteSlice>, dbg_dmp!(tag!("abc")));

#[test]
fn issue_667() {
  use nom::alpha;

  named!(foo <CompleteByteSlice, Vec<CompleteByteSlice>>,
    many0!(
      alt!(alpha | is_a!("_"))
    )
  );
  assert_eq!(
    foo(CompleteByteSlice(b"")),
    Ok((CompleteByteSlice(b""), vec![]))
  );
  assert_eq!(
    foo(CompleteByteSlice(b"loremipsum")),
    Ok((
      CompleteByteSlice(b""),
      vec![CompleteByteSlice(b"loremipsum")]
    ))
  );
  assert_eq!(
    foo(CompleteByteSlice(b"lorem_ipsum")),
    Ok((
      CompleteByteSlice(b""),
      vec![
        CompleteByteSlice(b"lorem"),
        CompleteByteSlice(b"_"),
        CompleteByteSlice(b"ipsum"),
      ]
    ))
  );
  assert_eq!(
    foo(CompleteByteSlice(b"_lorem_ipsum")),
    Ok((
      CompleteByteSlice(b""),
      vec![
        CompleteByteSlice(b"_"),
        CompleteByteSlice(b"lorem"),
        CompleteByteSlice(b"_"),
        CompleteByteSlice(b"ipsum"),
      ]
    ))
  );
  assert_eq!(
    foo(CompleteByteSlice(b"!@#$")),
    Ok((CompleteByteSlice(b"!@#$"), vec![]))
  );
}

#[test]
fn issue_721() {
  assert_eq!(parse_to!("1234", u16), Ok(("", 1234)));
  assert_eq!(parse_to!("foo", String), Ok(("", "foo".to_string())));
}

named!(issue_717<&[u8], Vec<&[u8]> >,
  separated_list!(tag!([0x0]), is_not!([0x0u8]))
);

struct NoPartialEq {
  value: i32
}

named!(issue_724<&str, i32>,
  do_parse!(
    metadata: permutation!(
      map!(tag!("hello"), |_| NoPartialEq { value: 1 }),
      map!(tag!("world"), |_| NoPartialEq { value: 2 })
    ) >>
    (metadata.0.value + metadata.1.value)
  )
);

<commit_msg>fix unit tests<commit_after>//#![feature(trace_macros)]
#![allow(dead_code)]
#![cfg_attr(feature = "cargo-clippy", allow(redundant_closure))]

#[macro_use]
extern crate nom;

use nom::{space, Err, IResult, Needed, le_u64};
use nom::types::CompleteByteSlice;

#[allow(dead_code)]
struct Range {
  start: char,
  end: char,
}

pub fn take_char(input: &[u8]) -> IResult<&[u8], char> {
  if !input.is_empty() {
    Ok((&input[1..], input[0] as char))
  } else {
    Err(Err::Incomplete(Needed::Size(1)))
  }
}

//trace_macros!(true);

#[allow(dead_code)]
named!(range<&[u8], Range>,
    alt!(
        do_parse!(
            start: take_char >>
            tag!("-")        >>
            end: take_char   >>
            (Range {
                start: start,
                end:   end,
            })
        ) |
        map!(
            take_char,
            |c| {
                Range {
                    start: c,
                    end:   c,
                }
            }
        )
    )
);

#[allow(dead_code)]
named!(literal<&[u8], Vec<char> >,
    map!(
        many1!(take_char),
        |cs| {
          cs
        }
    )
);

#[test]
fn issue_58() {
  let _ = range(&b"abcd"[..]);
  let _ = literal(&b"abcd"[..]);
}

//trace_macros!(false);

#[cfg(feature = "std")]
mod parse_int {
  use nom::HexDisplay;
  use nom::{digit, space, IResult};
  use std::str;

  named!(parse_ints<Vec<i32>>, many0!(spaces_or_int));

  fn spaces_or_int(input: &[u8]) -> IResult<&[u8], i32> {
    println!("{}", input.to_hex(8));
    do_parse!(
      input,
      opt!(complete!(space)) >> res: map!(complete!(digit), |x| {
        println!("x: {:?}", x);
        let result = str::from_utf8(x).unwrap();
        println!("Result: {}", result);
        println!("int is empty?: {}", x.is_empty());
        match result.parse() {
          Ok(i) => i,
          Err(e) => panic!("UH OH! NOT A DIGIT! {:?}", e),
        }
      }) >> (res)
    )
  }

  #[test]
  fn issue_142() {
    let subject = parse_ints(&b"12 34 5689a"[..]);
    let expected = Ok((&b"a"[..], vec![12, 34, 5689]));
    assert_eq!(subject, expected);

    let subject = parse_ints(&b"12 34 5689 "[..]);
    let expected = Ok((&b" "[..], vec![12, 34, 5689]));
    assert_eq!(subject, expected)
  }
}

#[test]
fn usize_length_bytes_issue() {
  use nom::be_u16;
  let _: IResult<&[u8], &[u8], u32> = length_bytes!(b"012346", be_u16);
}

/*
 DOES NOT COMPILE
#[test]
fn issue_152() {
  named!(take4, take!(4));
  named!(xyz, tag!("XYZ"));
  named!(abc, tag!("abc"));

  named!(sw,
    switch!(take4,
      b"abcd" => xyz |
      b"efgh" => abc
    )
  );
}
*/

#[test]
fn take_till_issue() {
  named!(nothing, take_till!(call!(|_| true)));

  assert_eq!(nothing(b""), Err(Err::Incomplete(Needed::Size(1))));
  assert_eq!(nothing(b"abc"), Ok((&b"abc"[..], &b""[..])));
}

named!(
  issue_498<Vec<&[u8]>>,
  separated_nonempty_list!(opt!(space), tag!("abcd"))
);

named!(issue_308(&str) -> bool,
    do_parse! (
        tag_s! ("foo") >>
        b: alt_complete! (
            map! (tag_s! ("1"), |_: &str|->bool {true}) |
            value! (false)
        ) >>
        (b) ));

#[cfg(feature = "alloc")]
fn issue_302(input: &[u8]) -> IResult<&[u8], Option<Vec<u64>>> {
  do_parse!(input, entries: cond!(true, count!(le_u64, 3)) >> (entries))
}

#[test]
fn issue_655() {
  use nom::{line_ending, not_line_ending};
  named!(twolines(&str) -> (&str, &str),
    do_parse!(
      l1 : not_line_ending >>
           line_ending >>
      l2 : not_line_ending >>
           line_ending >>
      ((l1, l2))
    )
  );

  assert_eq!(twolines("foo\nbar\n"), Ok(("", ("foo", "bar"))));
  assert_eq!(twolines("féo\nbar\n"), Ok(("", ("féo", "bar"))));
  assert_eq!(twolines("foé\nbar\n"), Ok(("", ("foé", "bar"))));
  assert_eq!(twolines("foé\r\nbar\n"), Ok(("", ("foé", "bar"))));
}

#[cfg(feature = "std")]
named!(issue_666 <CompleteByteSlice, CompleteByteSlice>, dbg_dmp!(tag!("abc")));

#[test]
fn issue_667() {
  use nom::alpha;

  named!(foo <CompleteByteSlice, Vec<CompleteByteSlice>>,
    many0!(
      alt!(alpha | is_a!("_"))
    )
  );
  assert_eq!(
    foo(CompleteByteSlice(b"")),
    Ok((CompleteByteSlice(b""), vec![]))
  );
  assert_eq!(
    foo(CompleteByteSlice(b"loremipsum")),
    Ok((
      CompleteByteSlice(b""),
      vec![CompleteByteSlice(b"loremipsum")]
    ))
  );
  assert_eq!(
    foo(CompleteByteSlice(b"lorem_ipsum")),
    Ok((
      CompleteByteSlice(b""),
      vec![
        CompleteByteSlice(b"lorem"),
        CompleteByteSlice(b"_"),
        CompleteByteSlice(b"ipsum"),
      ]
    ))
  );
  assert_eq!(
    foo(CompleteByteSlice(b"_lorem_ipsum")),
    Ok((
      CompleteByteSlice(b""),
      vec![
        CompleteByteSlice(b"_"),
        CompleteByteSlice(b"lorem"),
        CompleteByteSlice(b"_"),
        CompleteByteSlice(b"ipsum"),
      ]
    ))
  );
  assert_eq!(
    foo(CompleteByteSlice(b"!@#$")),
    Ok((CompleteByteSlice(b"!@#$"), vec![]))
  );
}

#[test]
fn issue_721() {
  assert_eq!(parse_to!("1234", u16), Ok(("", 1234)));
  assert_eq!(parse_to!("foo", String), Ok(("", "foo".to_string())));
}

#[cfg(feature = "std")]
named!(issue_717<&[u8], Vec<&[u8]> >,
  separated_list!(tag!([0x0]), is_not!([0x0u8]))
);

struct NoPartialEq {
  value: i32,
}

named!(issue_724<&str, i32>,
  do_parse!(
    metadata: permutation!(
      map!(tag!("hello"), |_| NoPartialEq { value: 1 }),
      map!(tag!("world"), |_| NoPartialEq { value: 2 })
    ) >>
    (metadata.0.value + metadata.1.value)
  )
);
<|endoftext|>


<commit_before>extern crate rsoundio;

use std::os::raw::c_int;

#[test]
fn test_outstream() {
    println!("test: OutStream");
    let sio = rsoundio::SoundIo::new();
    assert!(sio.connect().is_none());
    // assert!(sio.connect_backend(rsoundio::ffi::SioBackend::Alsa).is_none());
    println!("current backend: {}", sio.current_backend().unwrap());
    sio.flush_events();
    let mut fmt;
    let dev_idx = sio.default_output_device_index().unwrap();
    let dev = sio.get_output_device(dev_idx).unwrap();
    println!("device: {}, ref_count: {}", dev, dev.ref_count());
    let mut stream = dev.create_outstream().unwrap();
    assert!(stream.open().is_none());
    fmt = stream.current_format().unwrap();
    println!("current format: {}", fmt);
    let cb = |out: rsoundio::OutStream, min: i32, max: i32| {
        println!("Closure: {}, {} using format: {}", min, max, fmt);
    };
    let boxed_cb = Box::new(cb);
    stream.register_write_callback(boxed_cb);
    let ucb = | out: rsoundio::OutStream | {
        println!("Underflow!")
    };
    stream.register_underflow_callback(Box::new(ucb));
    let ecb = | out: rsoundio::OutStream, err: rsoundio::ffi::SioError| {
        println!("Error: {}", err)
    };
    stream.register_error_callback(Box::new(ecb));
    assert!(stream.start().is_none());
    loop {
        sio.wait_events();
    }
    assert!(stream.clear_buffer().is_none());
    assert!(stream.pause(true).is_none());
    assert!(stream.pause(false).is_none());
    println!("latency: {}", stream.get_latency().unwrap());
    stream.destroy();
}

unsafe extern "C" fn write_callback(raw_out: *mut rsoundio::ffi::SoundIoOutStream,
                                    min_frame_count: c_int,
                                    max_frame_count: c_int) {
    let out = rsoundio::OutStream::new(raw_out);
    let sr = out.get_sample_rate();
    let layout = out.get_layout();
    let channels = layout.channel_count();
    // osc stuff:
    let mut f = 8_000.0f32;
    // let phi = 2.0 * f * ::std::f32::consts::PI / (sr as f32);
    let mut sample = 0.0f32;

    let mut raw_areas: *mut rsoundio::ffi::SoundIoChannelArea = ::std::ptr::null_mut();
    let mut frames_left = max_frame_count;
    let mut block_size = frames_left;
    while frames_left > 0 {
        if let Some(err) = out.begin_write(&mut raw_areas, &mut block_size) {
            panic!("{}", err);
        }
        if block_size <= 0 {
            break;
        }

        let areas = unsafe { ::std::slice::from_raw_parts_mut(raw_areas, channels as usize) };
        let mut dir = 1.0;
        for idx in 0..block_size {
            if f >= 8_000.0 || f <= 60.0 {
                dir *= -1.0
            };
            f += dir * 1.0;
            let phi = 2.0 * f * ::std::f32::consts::PI / (sr as f32);
            sample = (phi * (idx as f32)).sin();
            assert!(sample.abs() < 1.001);
            for ch_idx in 0..channels {
                let addr = (areas[ch_idx as usize].ptr as usize +
                            areas[ch_idx as usize].step as usize *
                            idx as usize) as *mut f32;
                unsafe { *addr = sample };
            }
        }
        assert!(out.end_write().is_none());
        frames_left -= block_size;
    }
}
<commit_msg>Directly create boxed callback<commit_after>extern crate rsoundio;

use std::os::raw::c_int;

#[test]
fn test_outstream() {
    println!("test: OutStream");
    let sio = rsoundio::SoundIo::new();
    assert!(sio.connect().is_none());
    // assert!(sio.connect_backend(rsoundio::ffi::SioBackend::Alsa).is_none());
    println!("current backend: {}", sio.current_backend().unwrap());
    sio.flush_events();
    let mut fmt;
    let dev_idx = sio.default_output_device_index().unwrap();
    let dev = sio.get_output_device(dev_idx).unwrap();
    println!("device: {}, ref_count: {}", dev, dev.ref_count());
    let mut stream = dev.create_outstream().unwrap();
    assert!(stream.open().is_none());
    fmt = stream.current_format().unwrap();
    println!("current format: {}", fmt);
    let cb = |out: rsoundio::OutStream, min: i32, max: i32| {
        println!("Closure: {}, {} using format: {}", min, max, fmt);
    };
    stream.register_write_callback(Box::new(cb));
    let ucb = | out: rsoundio::OutStream | {
        println!("Underflow!")
    };
    stream.register_underflow_callback(Box::new(ucb));
    let ecb = | out: rsoundio::OutStream, err: rsoundio::ffi::SioError| {
        println!("Error: {}", err)
    };
    stream.register_error_callback(Box::new(ecb));
    assert!(stream.start().is_none());
    loop {
        sio.wait_events();
    }
    assert!(stream.clear_buffer().is_none());
    assert!(stream.pause(true).is_none());
    assert!(stream.pause(false).is_none());
    println!("latency: {}", stream.get_latency().unwrap());
    stream.destroy();
}

unsafe extern "C" fn write_callback(raw_out: *mut rsoundio::ffi::SoundIoOutStream,
                                    min_frame_count: c_int,
                                    max_frame_count: c_int) {
    let out = rsoundio::OutStream::new(raw_out);
    let sr = out.get_sample_rate();
    let layout = out.get_layout();
    let channels = layout.channel_count();
    // osc stuff:
    let mut f = 8_000.0f32;
    // let phi = 2.0 * f * ::std::f32::consts::PI / (sr as f32);
    let mut sample = 0.0f32;

    let mut raw_areas: *mut rsoundio::ffi::SoundIoChannelArea = ::std::ptr::null_mut();
    let mut frames_left = max_frame_count;
    let mut block_size = frames_left;
    while frames_left > 0 {
        if let Some(err) = out.begin_write(&mut raw_areas, &mut block_size) {
            panic!("{}", err);
        }
        if block_size <= 0 {
            break;
        }

        let areas = unsafe { ::std::slice::from_raw_parts_mut(raw_areas, channels as usize) };
        let mut dir = 1.0;
        for idx in 0..block_size {
            if f >= 8_000.0 || f <= 60.0 {
                dir *= -1.0
            };
            f += dir * 1.0;
            let phi = 2.0 * f * ::std::f32::consts::PI / (sr as f32);
            sample = (phi * (idx as f32)).sin();
            assert!(sample.abs() < 1.001);
            for ch_idx in 0..channels {
                let addr = (areas[ch_idx as usize].ptr as usize +
                            areas[ch_idx as usize].step as usize *
                            idx as usize) as *mut f32;
                unsafe { *addr = sample };
            }
        }
        assert!(out.end_write().is_none());
        frames_left -= block_size;
    }
}
<|endoftext|>


<commit_before>use std::sync::Arc;

use rustfft::Length;

use ::Type4;
use mdct::IMDCT;
use common;

/// IMDCT implementation that converts the problem to a DCT Type 4 of the same size.
///
/// It is much easier to express a IMDCT as a DCT Type 4 than it is to express it as a FFT, so converting the IMDCT
/// to a DCT4 before converting it to a FFT results in greatly simplified code
///
/// ~~~
/// // Computes a IMDCT of input size 1234 via a DCT4, using the MP3 window function
/// use rustdct::mdct::{IMDCT, IMDCTViaDCT4, window_fn};
/// use rustdct::DCTplanner;
///
/// let len = 1234;
/// let input:  Vec<f32> = vec![0f32; len];
/// let mut output: Vec<f32> = vec![0f32; len * 2];
///
/// let mut planner = DCTplanner::new();
/// let inner_dct4 = planner.plan_dct4(len);
///
/// let dct = IMDCTViaDCT4::new(inner_dct4, window_fn::mp3);
/// dct.process_imdct(&input, &mut output);
/// ~~~
pub struct IMDCTViaDCT4<T> {
    dct: Arc<Type4<T>>,
    window: Box<[T]>,
}

impl<T: common::DCTnum> IMDCTViaDCT4<T> {
    /// Creates a new IMDCT context that will process inputs of input length `inner_dct.len()`, resulting in outputs of length `inner_dct.len() * 2`
    ///
    /// `window_fn` is a function that takes a `size` and returns a `Vec` containing `size` window values.
    /// See the [`window_fn`](mdct/window_fn/index.html) module for provided window functions.
    pub fn new<F>(inner_dct: Arc<Type4<T>>, window_fn: F) -> Self
    where
        F: FnOnce(usize) -> Vec<T>,
    {
        let len = inner_dct.len();

        assert!(len % 2 == 0, "The IMDCT inner_dct.len() must be even. Got {}", len);

        let window = window_fn(len * 2);
        assert_eq!(window.len(), len * 2, "Window function returned incorrect number of values");

        Self {
            dct: inner_dct,
            window: window.into_boxed_slice(),
        }
    }
}
impl<T: common::DCTnum> IMDCT<T> for IMDCTViaDCT4<T> {
    fn process_imdct_split(&self, input: &[T], output_a: &mut [T], output_b: &mut [T]) {
        common::verify_length(input, output_a, self.len());
        assert_eq!(output_a.len(), output_b.len());

        let mut buffer = vec![T::zero(); self.len() * 2];
        let (mut dct_input, mut dct_output) = buffer.split_at_mut(self.len());
        dct_input.copy_from_slice(input);

        self.dct.process_dct4(&mut dct_input, &mut dct_output);

        let group_size = self.len() / 2;

        //copy the second half of the DCT output into the result
        for ((output, window_val), val) in
            output_a
                .iter_mut()
                .zip(&self.window[..])
                .zip(dct_output[group_size..].iter())
        {
            *output = *output + *val * *window_val;
        }

        //copy the second half of the DCT output again, but this time reversed and negated
        for ((output, window_val), val) in
            output_a
                .iter_mut()
                .zip(&self.window[..])
                .skip(group_size)
                .zip(dct_output[group_size..].iter().rev())
        {
            *output = *output - *val * *window_val;
        }

        //copy the first half of the DCT output into the result, reversde+negated
        for ((output, window_val), val) in
            output_b
                .iter_mut()
                .zip(&self.window[self.len()..])
                .zip( dct_output[..group_size].iter().rev())
        {
            *output = *output - *val * *window_val;
        }

        //copy the first half of the DCT output again, but this time not reversed
        for ((output, window_val), val) in
            output_b
                .iter_mut()
                .zip(&self.window[self.len()..])
                .skip(group_size)
                .zip(dct_output[..group_size].iter())
        {
            *output = *output - *val * *window_val;
        }
    }
}
impl<T> Length for IMDCTViaDCT4<T> {
    fn len(&self) -> usize {
        self.dct.len()
    }
}

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

    use algorithm::Type4Naive;
    use mdct::IMDCTNaive;
    use mdct::window_fn;
    use test_utils::{compare_float_vectors, random_signal};

    /// Verify that our fast implementation of the MDCT and IMDCT gives the same output as the slow version, for many different inputs
    #[test]
    fn test_imdct_via_dct4() {
        for current_window_fn in &[window_fn::one, window_fn::mp3, window_fn::vorbis] {
            for i in 1..11 {
                let input_len = i * 2;
                let output_len = i * 4;

                let input = random_signal(input_len);

                let mut naive_output = vec![0f32; output_len];
                let mut fast_output = vec![0f32; output_len];

                let mut naive_mdct = IMDCTNaive::new(input_len, current_window_fn);

                let inner_dct4 = Arc::new(Type4Naive::new(input_len));
                let mut fast_mdct = IMDCTViaDCT4::new(inner_dct4, current_window_fn);

                naive_mdct.process_imdct(&input, &mut naive_output);
                fast_mdct.process_imdct(&input, &mut fast_output);

                assert!(
                    compare_float_vectors(&naive_output, &fast_output),
                    "i = {}",
                    i
                );

            }
        }
    }
}
<commit_msg>Deleted an obsolete file<commit_after><|endoftext|>


<commit_before>use rustc::lint::*;
use rustc_front::hir;
use rustc_front::intravisit::FnKind;
use syntax::ast;
use syntax::codemap::Span;
use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint,
            DEFAULT_TRAIT_PATH};

/// **What it does:** This lints about type with a `fn new() -> Self` method and no `Default`
/// implementation.
///
/// **Why is this bad?** User might expect to be able to use `Default` is the type can be
/// constructed without arguments.
///
/// **Known problems:** Hopefully none.
///
/// **Example:**
///
/// ```rust,ignore
/// struct Foo;
///
/// impl Foo {
///     fn new() -> Self {
///         Foo
///     }
/// }
/// ```
declare_lint! {
    pub NEW_WITHOUT_DEFAULT,
    Warn,
    "`fn new() -> Self` method without `Default` implementation"
}

#[derive(Copy,Clone)]
pub struct NewWithoutDefault;

impl LintPass for NewWithoutDefault {
    fn get_lints(&self) -> LintArray {
        lint_array!(NEW_WITHOUT_DEFAULT)
    }
}

impl LateLintPass for NewWithoutDefault {
    fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, _: &hir::Block, span: Span, id: ast::NodeId) {
        if in_external_macro(cx, span) {
            return;
        }

        if let FnKind::Method(name, _, _) = kind {
            if decl.inputs.is_empty() && name.as_str() == "new" {
                let self_ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(cx.tcx.map.get_parent(id))).ty;

                if_let_chain!{[
                    self_ty.walk_shallow().next().is_none(), // implements_trait does not work with generics
                    let Some(ret_ty) = return_ty(cx.tcx.node_id_to_type(id)),
                    same_tys(cx, self_ty, ret_ty),
                    let Some(default_trait_id) = get_trait_def_id(cx, &DEFAULT_TRAIT_PATH),
                    !implements_trait(cx, self_ty, default_trait_id, Vec::new())
                ], {
                    span_lint(cx, NEW_WITHOUT_DEFAULT, span,
                              &format!("you should consider adding a `Default` implementation for `{}`", self_ty));
                }}
            }
        }
    }
}
<commit_msg>Fix typo in new_without_default docu<commit_after>use rustc::lint::*;
use rustc_front::hir;
use rustc_front::intravisit::FnKind;
use syntax::ast;
use syntax::codemap::Span;
use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint,
            DEFAULT_TRAIT_PATH};

/// **What it does:** This lints about type with a `fn new() -> Self` method and no `Default`
/// implementation.
///
/// **Why is this bad?** User might expect to be able to use `Default` as the type can be
/// constructed without arguments.
///
/// **Known problems:** Hopefully none.
///
/// **Example:**
///
/// ```rust,ignore
/// struct Foo;
///
/// impl Foo {
///     fn new() -> Self {
///         Foo
///     }
/// }
/// ```
declare_lint! {
    pub NEW_WITHOUT_DEFAULT,
    Warn,
    "`fn new() -> Self` method without `Default` implementation"
}

#[derive(Copy,Clone)]
pub struct NewWithoutDefault;

impl LintPass for NewWithoutDefault {
    fn get_lints(&self) -> LintArray {
        lint_array!(NEW_WITHOUT_DEFAULT)
    }
}

impl LateLintPass for NewWithoutDefault {
    fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, _: &hir::Block, span: Span, id: ast::NodeId) {
        if in_external_macro(cx, span) {
            return;
        }

        if let FnKind::Method(name, _, _) = kind {
            if decl.inputs.is_empty() && name.as_str() == "new" {
                let self_ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(cx.tcx.map.get_parent(id))).ty;

                if_let_chain!{[
                    self_ty.walk_shallow().next().is_none(), // implements_trait does not work with generics
                    let Some(ret_ty) = return_ty(cx.tcx.node_id_to_type(id)),
                    same_tys(cx, self_ty, ret_ty),
                    let Some(default_trait_id) = get_trait_def_id(cx, &DEFAULT_TRAIT_PATH),
                    !implements_trait(cx, self_ty, default_trait_id, Vec::new())
                ], {
                    span_lint(cx, NEW_WITHOUT_DEFAULT, span,
                              &format!("you should consider adding a `Default` implementation for `{}`", self_ty));
                }}
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Module for the pixel data trait and implementations.
//!
//! In order to facilitate typical pixel data manipulation, this crate
//! provides a common interface for retrieving that content as an image
//! or a multi-dimensional array.

use std::fmt;
use dicom_parser::error::{Error, Result};

/** Implemented by DICOM pixel data blocks retrieved from objects.
 *
 * Pixel data elements typically represent 2D images. This trait provides
 * access to Pixel Data (7FE0,0010), Overlay Data (60xx,3000), or Waveform Data (5400,1010)
 * in a similar fashion to a two-dimensional array.
 * `PV` is a type used to represent a pixel.
 */
pub trait PixelData<PV> {
    // TODO this API is a work in progress.

    /// Get the number of rows (height) of the slice.
    fn rows(&self) -> u32;

    /// Get the number of columns (width) of the slice.
    fn columns(&self) -> u32;

    /// Get the number of bits used to represent each pixel.
    fn bits_per_pixel(&self) -> u32;

    /// Retrieve the number of samples (channels) per pixel.
    fn samples_per_pixel(&self) -> u16;

    /// Obtain the pixel value in the given position.
    /// Can return PixelDataOutOfBounds error when the given coordinates
    /// are out of the slice's boundaries.
    fn pixel_at(&self, width: u32, height: u32) -> Result<PV>;

    /// Obtain a mutable reference to the pixel value in the given position.
    /// Can return PixelDataOutOfBounds error when the given coordinates
    /// are out of the slice's boundaries.
    fn pixel_at_mut(&mut self, width: u32, height: u32) -> Result<&mut PV>;
}

/// A DICOM slice that is completely stored in memory.
/// Pixels are stored in row-major order with no padding.
pub struct InMemoryPixelData<P> {
    data: Vec<P>,
    rows: u32,
    cols: u32,
    bpp: u32,
    samples: u16,
}

impl<P: fmt::Debug> fmt::Debug for InMemoryPixelData<P> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "InMemoryPixelData[data={:?}, rows={}, cols={}, bbp={}, samples={}]",
            &self.data, self.rows, self.cols, self.bpp, self.samples
        )
    }
}

impl<P> InMemoryPixelData<P> {
    fn check_bounds(&self, w: u32, h: u32) -> Result<()> {
        if w >= self.cols || h >= self.rows {
            Err(Error::PixelDataOutOfBounds)
        } else {
            Ok(())
        }
    }

    /// Fetch the internal data vector, destroying the slice in the process.
    pub fn into_vector(self) -> Vec<P> {
        self.data
    }
}

impl<P> PixelData<P> for InMemoryPixelData<P>
where
    P: Clone,
{
    fn rows(&self) -> u32 {
        self.rows
    }

    fn columns(&self) -> u32 {
        self.cols
    }

    fn bits_per_pixel(&self) -> u32 {
        self.bpp
    }

    fn samples_per_pixel(&self) -> u16 {
        self.samples
    }

    fn pixel_at(&self, w: u32, h: u32) -> Result<P> {
        self.check_bounds(w, h).map(move |_| {
            let i = (h * self.cols + w) as usize;
            self.data[i].clone()
        })
    }

    fn pixel_at_mut(&mut self, w: u32, h: u32) -> Result<&mut P> {
        self.check_bounds(w, h).map(move |_| {
            let i = (h * self.cols + w) as usize;
            &mut self.data[i]
        })
    }
}
<commit_msg>Refactor PixelData experimental module<commit_after>//! Module for the pixel data trait and implementations.
//!
//! In order to facilitate typical pixel data manipulation, this crate
//! provides a common interface for retrieving that content as an image
//! or a multi-dimensional array.

use std::marker::PhantomData;
use dicom_parser::error::{Error, Result};

/** Implemented by DICOM pixel data blocks retrieved from objects.
 *
 * Pixel data elements typically represent 2D images. This trait provides
 * access to Pixel Data (7FE0,0010), Overlay Data (60xx,3000), or Waveform Data (5400,1010)
 * in a similar fashion to a two-dimensional array.
 */
pub trait PixelData {
    /// The representation of an individual pixel.
    type Pixel;

    /// Get the number of rows (height) of the slice.
    fn rows(&self) -> u32;

    /// Get the number of columns (width) of the slice.
    fn columns(&self) -> u32;

    /// Get the number of bits used to represent each pixel.
    fn bits_per_pixel(&self) -> u32;

    /// Retrieve the number of samples (channels) per pixel.
    fn samples_per_pixel(&self) -> u16;

    /// Obtain the pixel value in the given position.
    /// Can return PixelDataOutOfBounds error when the given coordinates
    /// are out of the slice's boundaries.
    fn pixel_at(&self, width: u32, height: u32) -> Result<Self::Pixel>;
}

pub trait PixelDataMut: PixelData {
    /// Obtain a mutable reference to the pixel value in the given position.
    /// Can return PixelDataOutOfBounds error when the given coordinates
    /// are out of the slice's boundaries.
    fn pixel_at_mut(&mut self, width: u32, height: u32) -> Result<&mut Self::Pixel>;
}

/// A DICOM slice that is completely stored in memory, which may be
/// owned by this  and owned by a local
/// vector. Pixels are stored in row-major order with no padding.
#[derive(Debug, Clone, PartialEq)]
pub struct InMemoryPixelData<C, P> {
    phantom: PhantomData<P>,
    data: C,
    rows: u32,
    cols: u32,
    bpp: u32,
    samples: u16,
}

impl<C, P> InMemoryPixelData<C, P> {
    fn check_bounds(&self, w: u32, h: u32) -> Result<()> {
        if w >= self.cols || h >= self.rows {
            Err(Error::PixelDataOutOfBounds)
        } else {
            Ok(())
        }
    }

    /// Fetch the internal data container, destroying the pixel data structure in the process.
    pub fn into_raw_data(self) -> C {
        self.data
    }

    /// Obtain a reference to the internal data container.
    pub fn raw_data(&self) -> &C {
        &self.data
    }

    /// Obtain a reference to the internal data container.
    pub fn raw_data_mut(&mut self) -> &mut C {
        &mut self.data
    }
}

impl<C, P> PixelData for InMemoryPixelData<C, P>
where
    P: Clone,
    C: std::ops::Deref<Target = [P]>,
{
    type Pixel = P;

    fn rows(&self) -> u32 {
        self.rows
    }

    fn columns(&self) -> u32 {
        self.cols
    }

    fn bits_per_pixel(&self) -> u32 {
        self.bpp
    }

    fn samples_per_pixel(&self) -> u16 {
        self.samples
    }

    fn pixel_at(&self, w: u32, h: u32) -> Result<P> {
        self.check_bounds(w, h).map(move |_| {
            let i = (h * self.cols + w) as usize;
            self.data[i].clone()
        })
    }

}

impl<C, P> PixelDataMut for InMemoryPixelData<C, P>
where
    P: Clone,
    C: std::ops::DerefMut<Target = [P]>,
{
    fn pixel_at_mut(&mut self, w: u32, h: u32) -> Result<&mut P> {
        self.check_bounds(w, h).map(move |_| {
            let i = (h * self.cols + w) as usize;
            &mut self.data[i]
        })
    }
}
<|endoftext|>


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

use std::cmp::Ordering;

use super::symbol_range::*;
use super::countable::*;

///
/// A symbol map maps from one set of symbol ranges to another
///
pub struct SymbolMap<Symbol: PartialOrd+Clone+Countable> {
    // Ranges in this symbol map
    ranges: Vec<SymbolRange<Symbol>>,
}

impl<Symbol: PartialOrd+Clone+Countable> SymbolMap<Symbol> {
    ///
    /// Creates a new symbol map
    ///
    pub fn new() -> SymbolMap<Symbol> {
        SymbolMap { ranges: vec![] }
    }

    ///
    /// Orders two symbols (makes unordered symbols equal)
    ///
    #[inline]
    fn order_symbols(a: &Symbol, b: &Symbol) -> Ordering {
        if let Some(order) = a.partial_cmp(b) {
            order
        } else {
            Ordering::Equal
        }
    }

    ///
    /// Orders two symbol ranges
    ///
    #[inline]
    fn order_ranges(a: &SymbolRange<Symbol>, b: &SymbolRange<Symbol>) -> Ordering {
        let ordering = SymbolMap::order_symbols(&a.lowest, &b.lowest);

        if ordering == Ordering::Equal {
            SymbolMap::order_symbols(&a.highest, &b.highest)
        } else {
            ordering
        }
    }

    ///
    /// Adds a range to those that are known about by this object
    ///
    pub fn add_range(&mut self, range: &SymbolRange<Symbol>) {
        let existing = self.ranges.binary_search_by(|test_range| { SymbolMap::order_ranges(test_range, range) });

        // Insert the range if it is not already in the map
        if let Err(insertion_pos) = existing {
            self.ranges.insert(insertion_pos, range.clone());
        }
    }

    ///
    /// Finds the ranges in this map that overlap the target ranges
    ///
    pub fn find_overlapping_ranges(&self, range: &SymbolRange<Symbol>) -> Vec<&SymbolRange<Symbol>> {
        let mut result = vec![];

        // Find the first range that matches (or the insertion position, which should be the first range wit a lowest value higher than the target range)
        let existing = self.ranges.binary_search_by(|test_range| { SymbolMap::order_ranges(test_range, range) });

        // Start returning values from here
        let mut pos = match existing {
            Ok(found_position) => found_position,
            Err(insert_position) => insert_position
        };

        // Move backwards if the previous position overlaps this one
        if pos > 0 && self.ranges[pos-1].highest >= range.lowest {
            pos -= 1;
        }

        // TODO: can we construct a set of ranges such that one is missed here? Think maybe we can
        while pos < self.ranges.len() && self.ranges[pos].lowest <= range.highest {
            result.push(&self.ranges[pos]);
            pos += 1;
        }

        result
    }

    ///
    /// Creates a non-overlapping range from an overlapping one
    ///
    pub fn to_non_overlapping_map(&self) -> SymbolMap<Symbol> {
        // Stack, popping the lowest ordered ranges first
        let mut to_process = self.ranges.clone();
        to_process.reverse();

        let mut result = vec![];

        while let Some(might_overlap) = to_process.pop() {
            if let Some(overlap_with) = to_process.pop() {
                // Stack has two ranges on top. They might overlap
                if !might_overlap.overlaps(&overlap_with) {
                    // Doesn't overlap: can just push might_overlap and continue
                    result.push(might_overlap);
                    to_process.push(overlap_with);
                } else {
                    // Got an overlap
                    if might_overlap == overlap_with {
                        // Ranges are the same, just discard one
                        to_process.push(overlap_with);
                    } else if might_overlap.lowest == overlap_with.lowest {
                        // Ranges start at the same location. We need to divide them in case more than two ranges are overlapping
                        let (smaller_range, larger_range) = (might_overlap, overlap_with);      // Because of the sort order

                        // Chop out the smaller range from the larger range, then insert into the stack in order
                        let larger_range_without_smaller_range = SymbolRange::new(smaller_range.highest.next(), larger_range.highest.clone());

                        if let Err(insertion_pos) = to_process.binary_search_by(|test_range| { SymbolMap::order_ranges(&larger_range_without_smaller_range, test_range) }) {
                            to_process.insert(insertion_pos, larger_range_without_smaller_range);
                        }

                        to_process.push(smaller_range);
                    } else {
                        // There's a range from the lowest of the first range to the lowest of the second ranges
                        result.push(SymbolRange::new(might_overlap.lowest.clone(), overlap_with.lowest.prev()));

                        // Chop out the bit we just pushed from might_overlap and push back both ranges
                        // Maintain sort order depending on highest (as lowest for both ranges will be equal)
                        if overlap_with.highest > might_overlap.highest {
                            to_process.push(overlap_with.clone());
                            to_process.push(SymbolRange::new(overlap_with.lowest, might_overlap.highest));
                        } else {
                            to_process.push(SymbolRange::new(overlap_with.lowest.clone(), might_overlap.highest));
                            to_process.push(overlap_with);
                        }
                    }
                }
            } else {
                // Last range should never overlap
                result.push(might_overlap);
            }
        }

        // Ranges should already be sorted as we worked from left to right
        SymbolMap { ranges: result }
    }
}

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

    #[test]
    fn can_lookup_overlapping_ranges() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 4));
        map.add_range(&SymbolRange::new(2, 5));
        map.add_range(&SymbolRange::new(3, 6));

        let bottom = map.find_overlapping_ranges(&SymbolRange::new(0, 1));
        let all    = map.find_overlapping_ranges(&SymbolRange::new(1, 3));
        let top    = map.find_overlapping_ranges(&SymbolRange::new(6, 6));

        assert!(bottom == vec![&SymbolRange::new(0, 4)]);
        assert!(all == vec![&SymbolRange::new(0, 4), &SymbolRange::new(2, 5), &SymbolRange::new(3, 6)]);
        assert!(top == vec![&SymbolRange::new(3, 6)]);
    }

    #[test]
    fn can_lookup_mid_range() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 4));
        map.add_range(&SymbolRange::new(5, 10));
        map.add_range(&SymbolRange::new(11, 15));

        let mid = map.find_overlapping_ranges(&SymbolRange::new(1, 3));

        assert!(mid == vec![&SymbolRange::new(0, 4)]);
    }

    #[test]
    fn works_with_duplicate_lower_values() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 2));
        map.add_range(&SymbolRange::new(0, 3));

        let all    = map.find_overlapping_ranges(&SymbolRange::new(0, 1));

        assert!(all == vec![&SymbolRange::new(0, 2), &SymbolRange::new(0, 3)]);
    }

    #[test]
    fn can_get_non_overlapping_map() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 4));
        map.add_range(&SymbolRange::new(2, 5));
        map.add_range(&SymbolRange::new(3, 6));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 6));

        assert!(all == vec![&SymbolRange::new(0, 1), &SymbolRange::new(2, 2), &SymbolRange::new(3, 4), &SymbolRange::new(5, 5), &SymbolRange::new(6, 6)]);
    }

    #[test]
    fn can_get_non_overlapping_map_with_single_symbols() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 5));
        map.add_range(&SymbolRange::new(2, 2));
        map.add_range(&SymbolRange::new(3, 6));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 6));

        assert!(all == vec![&SymbolRange::new(0, 1), &SymbolRange::new(2, 2), &SymbolRange::new(3, 5), &SymbolRange::new(6, 6)]);
    }

    #[test]
    fn generate_correctly_for_single_symbol() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 0));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 10));

        assert!(all == vec![&SymbolRange::new(0, 0)]);
    }

    #[test]
    fn generate_correctly_for_two_single_symbols() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 0));
        map.add_range(&SymbolRange::new(1, 1));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 10));

        assert!(all == vec![&SymbolRange::new(0, 0), &SymbolRange::new(1, 1)]);
    }

    #[test]
    fn generate_correctly_for_non_overlapping_ranges() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 1));
        map.add_range(&SymbolRange::new(2, 4));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 10));

        assert!(all == vec![&SymbolRange::new(0, 1), &SymbolRange::new(2, 4)]);
    }

    #[test]
    fn generate_correctly_for_single_overlap() {
        let mut map = SymbolMap::new();

        // Here the symbol '5' is in both ranges, so we should generate it as a seperate range in the non-overlapping version
        map.add_range(&SymbolRange::new(0, 5));
        map.add_range(&SymbolRange::new(5, 10));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 10));

        assert!(all == vec![&SymbolRange::new(0, 4), &SymbolRange::new(5,5), &SymbolRange::new(6, 10)]);
    }

    #[test]
    fn can_get_non_overlapping_map_with_single_symbols_at_start() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 0));
        map.add_range(&SymbolRange::new(0, 1));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 6));

        assert!(all == vec![&SymbolRange::new(0, 0), &SymbolRange::new(1, 1)]);
    }

    #[test]
    fn can_get_non_overlapping_map_with_single_symbols_at_start_and_gap() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 0));
        map.add_range(&SymbolRange::new(0, 1));
        map.add_range(&SymbolRange::new(3, 6));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 6));

        assert!(all == vec![&SymbolRange::new(0, 0), &SymbolRange::new(1, 1), &SymbolRange::new(3, 6)]);
    }
}
<commit_msg>Test duplicate symbols being added to the symbol range explicitly<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

use std::cmp::Ordering;

use super::symbol_range::*;
use super::countable::*;

///
/// A symbol map maps from one set of symbol ranges to another
///
pub struct SymbolMap<Symbol: PartialOrd+Clone+Countable> {
    // Ranges in this symbol map
    ranges: Vec<SymbolRange<Symbol>>,
}

impl<Symbol: PartialOrd+Clone+Countable> SymbolMap<Symbol> {
    ///
    /// Creates a new symbol map
    ///
    pub fn new() -> SymbolMap<Symbol> {
        SymbolMap { ranges: vec![] }
    }

    ///
    /// Orders two symbols (makes unordered symbols equal)
    ///
    #[inline]
    fn order_symbols(a: &Symbol, b: &Symbol) -> Ordering {
        if let Some(order) = a.partial_cmp(b) {
            order
        } else {
            Ordering::Equal
        }
    }

    ///
    /// Orders two symbol ranges
    ///
    #[inline]
    fn order_ranges(a: &SymbolRange<Symbol>, b: &SymbolRange<Symbol>) -> Ordering {
        let ordering = SymbolMap::order_symbols(&a.lowest, &b.lowest);

        if ordering == Ordering::Equal {
            SymbolMap::order_symbols(&a.highest, &b.highest)
        } else {
            ordering
        }
    }

    ///
    /// Adds a range to those that are known about by this object
    ///
    pub fn add_range(&mut self, range: &SymbolRange<Symbol>) {
        let existing = self.ranges.binary_search_by(|test_range| { SymbolMap::order_ranges(test_range, range) });

        // Insert the range if it is not already in the map
        if let Err(insertion_pos) = existing {
            self.ranges.insert(insertion_pos, range.clone());
        }
    }

    ///
    /// Finds the ranges in this map that overlap the target ranges
    ///
    pub fn find_overlapping_ranges(&self, range: &SymbolRange<Symbol>) -> Vec<&SymbolRange<Symbol>> {
        let mut result = vec![];

        // Find the first range that matches (or the insertion position, which should be the first range wit a lowest value higher than the target range)
        let existing = self.ranges.binary_search_by(|test_range| { SymbolMap::order_ranges(test_range, range) });

        // Start returning values from here
        let mut pos = match existing {
            Ok(found_position) => found_position,
            Err(insert_position) => insert_position
        };

        // Move backwards if the previous position overlaps this one
        if pos > 0 && self.ranges[pos-1].highest >= range.lowest {
            pos -= 1;
        }

        // TODO: can we construct a set of ranges such that one is missed here? Think maybe we can
        while pos < self.ranges.len() && self.ranges[pos].lowest <= range.highest {
            result.push(&self.ranges[pos]);
            pos += 1;
        }

        result
    }

    ///
    /// Creates a non-overlapping range from an overlapping one
    ///
    pub fn to_non_overlapping_map(&self) -> SymbolMap<Symbol> {
        // Stack, popping the lowest ordered ranges first
        let mut to_process = self.ranges.clone();
        to_process.reverse();

        let mut result = vec![];

        while let Some(might_overlap) = to_process.pop() {
            if let Some(overlap_with) = to_process.pop() {
                // Stack has two ranges on top. They might overlap
                if !might_overlap.overlaps(&overlap_with) {
                    // Doesn't overlap: can just push might_overlap and continue
                    result.push(might_overlap);
                    to_process.push(overlap_with);
                } else {
                    // Got an overlap
                    if might_overlap == overlap_with {
                        // Ranges are the same, just discard one
                        to_process.push(overlap_with);
                    } else if might_overlap.lowest == overlap_with.lowest {
                        // Ranges start at the same location. We need to divide them in case more than two ranges are overlapping
                        let (smaller_range, larger_range) = (might_overlap, overlap_with);      // Because of the sort order

                        // Chop out the smaller range from the larger range, then insert into the stack in order
                        let larger_range_without_smaller_range = SymbolRange::new(smaller_range.highest.next(), larger_range.highest.clone());

                        if let Err(insertion_pos) = to_process.binary_search_by(|test_range| { SymbolMap::order_ranges(&larger_range_without_smaller_range, test_range) }) {
                            to_process.insert(insertion_pos, larger_range_without_smaller_range);
                        }

                        to_process.push(smaller_range);
                    } else {
                        // There's a range from the lowest of the first range to the lowest of the second ranges
                        result.push(SymbolRange::new(might_overlap.lowest.clone(), overlap_with.lowest.prev()));

                        // Chop out the bit we just pushed from might_overlap and push back both ranges
                        // Maintain sort order depending on highest (as lowest for both ranges will be equal)
                        if overlap_with.highest > might_overlap.highest {
                            to_process.push(overlap_with.clone());
                            to_process.push(SymbolRange::new(overlap_with.lowest, might_overlap.highest));
                        } else {
                            to_process.push(SymbolRange::new(overlap_with.lowest.clone(), might_overlap.highest));
                            to_process.push(overlap_with);
                        }
                    }
                }
            } else {
                // Last range should never overlap
                result.push(might_overlap);
            }
        }

        // Ranges should already be sorted as we worked from left to right
        SymbolMap { ranges: result }
    }
}

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

    #[test]
    fn can_lookup_overlapping_ranges() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 4));
        map.add_range(&SymbolRange::new(2, 5));
        map.add_range(&SymbolRange::new(3, 6));

        let bottom = map.find_overlapping_ranges(&SymbolRange::new(0, 1));
        let all    = map.find_overlapping_ranges(&SymbolRange::new(1, 3));
        let top    = map.find_overlapping_ranges(&SymbolRange::new(6, 6));

        assert!(bottom == vec![&SymbolRange::new(0, 4)]);
        assert!(all == vec![&SymbolRange::new(0, 4), &SymbolRange::new(2, 5), &SymbolRange::new(3, 6)]);
        assert!(top == vec![&SymbolRange::new(3, 6)]);
    }

    #[test]
    fn can_lookup_mid_range() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 4));
        map.add_range(&SymbolRange::new(5, 10));
        map.add_range(&SymbolRange::new(11, 15));

        let mid = map.find_overlapping_ranges(&SymbolRange::new(1, 3));

        assert!(mid == vec![&SymbolRange::new(0, 4)]);
    }

    #[test]
    fn works_with_duplicate_lower_values() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 2));
        map.add_range(&SymbolRange::new(0, 3));

        let all    = map.find_overlapping_ranges(&SymbolRange::new(0, 1));

        assert!(all == vec![&SymbolRange::new(0, 2), &SymbolRange::new(0, 3)]);
    }

    #[test]
    fn can_get_non_overlapping_map() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 4));
        map.add_range(&SymbolRange::new(2, 5));
        map.add_range(&SymbolRange::new(3, 6));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 6));

        assert!(all == vec![&SymbolRange::new(0, 1), &SymbolRange::new(2, 2), &SymbolRange::new(3, 4), &SymbolRange::new(5, 5), &SymbolRange::new(6, 6)]);
    }

    #[test]
    fn can_get_non_overlapping_map_with_single_symbols() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 5));
        map.add_range(&SymbolRange::new(2, 2));
        map.add_range(&SymbolRange::new(3, 6));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 6));

        assert!(all == vec![&SymbolRange::new(0, 1), &SymbolRange::new(2, 2), &SymbolRange::new(3, 5), &SymbolRange::new(6, 6)]);
    }

    #[test]
    fn can_deal_with_duplicate_symbols() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 5));
        map.add_range(&SymbolRange::new(2, 2));
        map.add_range(&SymbolRange::new(3, 6));

        map.add_range(&SymbolRange::new(0, 5));
        map.add_range(&SymbolRange::new(2, 2));
        map.add_range(&SymbolRange::new(3, 6));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 6));

        assert!(all == vec![&SymbolRange::new(0, 1), &SymbolRange::new(2, 2), &SymbolRange::new(3, 5), &SymbolRange::new(6, 6)]);
    }

    #[test]
    fn generate_correctly_for_single_symbol() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 0));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 10));

        assert!(all == vec![&SymbolRange::new(0, 0)]);
    }

    #[test]
    fn generate_correctly_for_two_single_symbols() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 0));
        map.add_range(&SymbolRange::new(1, 1));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 10));

        assert!(all == vec![&SymbolRange::new(0, 0), &SymbolRange::new(1, 1)]);
    }

    #[test]
    fn generate_correctly_for_non_overlapping_ranges() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 1));
        map.add_range(&SymbolRange::new(2, 4));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 10));

        assert!(all == vec![&SymbolRange::new(0, 1), &SymbolRange::new(2, 4)]);
    }

    #[test]
    fn generate_correctly_for_single_overlap() {
        let mut map = SymbolMap::new();

        // Here the symbol '5' is in both ranges, so we should generate it as a seperate range in the non-overlapping version
        map.add_range(&SymbolRange::new(0, 5));
        map.add_range(&SymbolRange::new(5, 10));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 10));

        assert!(all == vec![&SymbolRange::new(0, 4), &SymbolRange::new(5,5), &SymbolRange::new(6, 10)]);
    }

    #[test]
    fn can_get_non_overlapping_map_with_single_symbols_at_start() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 0));
        map.add_range(&SymbolRange::new(0, 1));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 6));

        assert!(all == vec![&SymbolRange::new(0, 0), &SymbolRange::new(1, 1)]);
    }

    #[test]
    fn can_get_non_overlapping_map_with_single_symbols_at_start_and_gap() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 0));
        map.add_range(&SymbolRange::new(0, 1));
        map.add_range(&SymbolRange::new(3, 6));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 6));

        assert!(all == vec![&SymbolRange::new(0, 0), &SymbolRange::new(1, 1), &SymbolRange::new(3, 6)]);
    }
}
<|endoftext|>