<commit_before>use std::fmt;
use std::marker::PhantomData;
use std::ops::Range;
use std::usize;

pub trait ReprUsize {
    fn from_usize(usize) -> Self;
    fn into_usize(self) -> usize;
}

impl ReprUsize for bool {
    fn from_usize(i: usize) -> bool {
        match i {
            0 => false,
            1 => true,
            _ => unreachable!(),
        }
    }

    fn into_usize(self) -> usize { self as usize }
}

impl ReprUsize for char {
    fn from_usize(i: usize) -> char { i as u8 as char }
    fn into_usize(self) -> usize { self as u8 as usize }
}

macro_rules! impl_predefined_type {
    ($ty: ty) => {
        impl ReprUsize for $ty {
            fn from_usize(i: usize) -> $ty { i as $ty }
            fn into_usize(self) -> usize { self as usize }
        }
    };
}

impl_predefined_type!(u8);
impl_predefined_type!(u16);
impl_predefined_type!(u32);
impl_predefined_type!(u64);
impl_predefined_type!(usize);
impl_predefined_type!(i8);
impl_predefined_type!(i16);
impl_predefined_type!(i32);
impl_predefined_type!(i64);
impl_predefined_type!(isize);
impl_predefined_type!(f32);
impl_predefined_type!(f64);

#[derive(Clone, Hash)]
pub struct BitsVec<T: ReprUsize> {
    inner: Vec<usize>,
    units: usize,
    bits: usize,
    max_bits: usize,
    leftover: usize,
    _marker: PhantomData<T>,
}

impl<T: ReprUsize> BitsVec<T> {
    pub fn new(bits: usize) -> BitsVec<T> {
        let max = usize::MAX.count_ones() as usize;
        // We can store more bits, but then we might need BigInt to get them out!
        assert!(bits < max, "cannot hold more than {} bits at a time", max - 1);

        BitsVec {
            inner: vec![0],
            units: 0,
            bits: bits,
            max_bits: max,
            leftover: max,
            _marker: PhantomData,
        }
    }

    pub fn push(&mut self, value: T) {
        let mut value = value.into_usize();
        assert!(value >> self.bits == 0,
                "input size is more than allowed size ({} >= {})", value, 2usize.pow(self.bits as u32));

        let mut idx = self.inner.len() - 1;
        let shift;

        if self.leftover < self.bits {
            let left = self.bits - self.leftover;
            self.inner[idx] |= value >> left;
            if self.leftover != 0 {     // special case, in which masking would result in zero!
                value &= (1 << left) - 1;
            }

            self.inner.push(0);
            self.leftover = self.max_bits - left;
            shift = self.max_bits - left;
            idx += 1;
        } else {
            shift = self.leftover - self.bits;
            self.leftover -= self.bits;
        }

        value <<= shift;
        self.inner[idx] |= value;
        self.units += 1;
    }

    pub fn get(&self, i: usize) -> Option<T> {
        if i >= self.units {
            return None
        }

        let idx = i * self.bits / self.max_bits;
        let bits = (i * self.bits) % self.max_bits;
        let diff = self.max_bits - bits;
        let mut val = self.inner[idx];
        if bits != 0 {
            val &= (1 << diff) - 1;
        }

        if diff >= self.bits {
            Some(T::from_usize(val >> (diff - self.bits)))
        } else {
            let shift = self.bits - diff;
            let out = (val << shift) | (self.inner[idx + 1] >> (self.max_bits - shift));
            Some(T::from_usize(out))
        }
    }

    pub fn set(&mut self, i: usize, value: T) {
        let value = value.into_usize();
        assert!(i < self.units, "index out of bounds ({} >= {})", i, self.units);
        assert!(value >> self.bits == 0,
                "input size is more than allowed size ({} >= {})", value, 2usize.pow(self.bits as u32));

        let idx = i * self.bits / self.max_bits;
        let bits = (i * self.bits) % self.max_bits;
        let diff = self.max_bits - bits;
        let mut val = self.inner[idx];

        if diff >= self.bits {
            let shift = diff - self.bits;
            let last = val & ((1 << shift) - 1);
            let mask = if bits == 0 { 0 } else { ((1 << bits) - 1) << diff };   // prevent overflow
            val &= mask;
            val |= value << shift;
            self.inner[idx] = val | last;
        } else {
            let shift = self.bits - diff;
            self.inner[idx] >>= diff;
            self.inner[idx] <<= diff;
            self.inner[idx] |= value >> shift;
            let last = value & ((1 << shift) - 1);
            self.inner[idx + 1] &= (1 << (self.max_bits - shift)) - 1;
            self.inner[idx + 1] |= last << (self.max_bits - shift);
        }
    }

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

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

    pub fn iter(&self) -> Iter<T> {
        Iter { vec: self, range: 0..self.units }
    }

    pub fn into_iter(self) -> IntoIter<T> {
        IntoIter { range: 0..self.units, vec: self }
    }
}

impl<T: ReprUsize + fmt::Debug> fmt::Debug for BitsVec<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_list().entries(self.iter()).finish()
    }
}

pub struct Iter<'a, T: ReprUsize + 'a> {
    vec: &'a BitsVec<T>,
    range: Range<usize>,
}

impl<'a, T: ReprUsize> IntoIterator for &'a BitsVec<T> {
    type Item = T;
    type IntoIter = Iter<'a, T>;

    fn into_iter(self) -> Iter<'a, T> {
        self.iter()
    }
}

impl<'a, T: ReprUsize> Iterator for Iter<'a, T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.range.next().and_then(|i| self.vec.get(i))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.range.size_hint()
    }
}

impl<'a, T: ReprUsize> DoubleEndedIterator for Iter<'a, T> {
    fn next_back(&mut self) -> Option<T> {
        self.range.next_back().and_then(|i| self.vec.get(i))
    }
}

impl<'a, T: ReprUsize> ExactSizeIterator for Iter<'a, T> {}

pub struct IntoIter<T: ReprUsize> {
    vec: BitsVec<T>,
    range: Range<usize>,
}

impl<T: ReprUsize> IntoIterator for BitsVec<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> IntoIter<T> {
        self.into_iter()
    }
}

impl<T: ReprUsize> Iterator for IntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.range.next().and_then(|i| self.vec.get(i))
    }
}

impl<T: ReprUsize> DoubleEndedIterator for IntoIter<T> {
    fn next_back(&mut self) -> Option<T> {
        self.range.next_back().and_then(|i| self.vec.get(i))
    }
}

impl<T: ReprUsize> ExactSizeIterator for IntoIter<T> {}
<commit_msg>Method for extending to a custom length filling the same element<commit_after>use std::cmp;
use std::fmt;
use std::marker::PhantomData;
use std::ops::Range;
use std::usize;

pub trait ReprUsize {
    fn from_usize(usize) -> Self;
    fn into_usize(self) -> usize;
}

impl ReprUsize for bool {
    fn from_usize(i: usize) -> bool {
        match i {
            0 => false,
            1 => true,
            _ => unreachable!(),
        }
    }

    fn into_usize(self) -> usize { self as usize }
}

impl ReprUsize for char {
    fn from_usize(i: usize) -> char { i as u8 as char }
    fn into_usize(self) -> usize { self as u8 as usize }
}

macro_rules! impl_predefined_type {
    ($ty: ty) => {
        impl ReprUsize for $ty {
            fn from_usize(i: usize) -> $ty { i as $ty }
            fn into_usize(self) -> usize { self as usize }
        }
    };
}

impl_predefined_type!(u8);
impl_predefined_type!(u16);
impl_predefined_type!(u32);
impl_predefined_type!(u64);
impl_predefined_type!(usize);
impl_predefined_type!(i8);
impl_predefined_type!(i16);
impl_predefined_type!(i32);
impl_predefined_type!(i64);
impl_predefined_type!(isize);
impl_predefined_type!(f32);
impl_predefined_type!(f64);

#[derive(Clone, Hash)]
pub struct BitsVec<T: ReprUsize> {
    inner: Vec<usize>,
    units: usize,
    bits: usize,
    max_bits: usize,
    leftover: usize,
    _marker: PhantomData<T>,
}

impl<T: ReprUsize> BitsVec<T> {
    pub fn new(bits: usize) -> BitsVec<T> {
        let max = usize::MAX.count_ones() as usize;
        // We can store more bits, but then we might need BigInt to get them out!
        assert!(bits < max, "cannot hold more than {} bits at a time", max - 1);

        BitsVec {
            inner: vec![0],
            units: 0,
            bits: bits,
            max_bits: max,
            leftover: max,
            _marker: PhantomData,
        }
    }

    pub fn with_capacity(bits: usize, capacity: usize) -> BitsVec<T> {
        let mut vec = BitsVec::new(bits);
        vec.reserve(capacity);
        vec
    }

    pub fn push(&mut self, value: T) {
        let mut value = value.into_usize();
        assert!(value >> self.bits == 0,
                "input size is more than allowed size ({} >= {})", value, 2usize.pow(self.bits as u32));

        let mut idx = self.inner.len() - 1;
        let shift;

        if self.leftover < self.bits {
            let left = self.bits - self.leftover;
            self.inner[idx] |= value >> left;
            if self.leftover != 0 {     // special case, in which masking would result in zero!
                value &= (1 << left) - 1;
            }

            self.inner.push(0);
            self.leftover = self.max_bits - left;
            shift = self.max_bits - left;
            idx += 1;
        } else {
            shift = self.leftover - self.bits;
            self.leftover -= self.bits;
        }

        value <<= shift;
        self.inner[idx] |= value;
        self.units += 1;
    }

    pub fn get(&self, i: usize) -> Option<T> {
        if i >= self.units {
            return None
        }

        let idx = i * self.bits / self.max_bits;
        let bits = (i * self.bits) % self.max_bits;
        let diff = self.max_bits - bits;
        let mut val = self.inner[idx];
        if bits != 0 {
            val &= (1 << diff) - 1;
        }

        if diff >= self.bits {
            Some(T::from_usize(val >> (diff - self.bits)))
        } else {
            let shift = self.bits - diff;
            let out = (val << shift) | (self.inner[idx + 1] >> (self.max_bits - shift));
            Some(T::from_usize(out))
        }
    }

    pub fn set(&mut self, i: usize, value: T) {
        let value = value.into_usize();
        assert!(i < self.units, "index out of bounds ({} >= {})", i, self.units);
        assert!(value >> self.bits == 0,
                "input size is more than allowed size ({} >= {})", value, 2usize.pow(self.bits as u32));

        let idx = i * self.bits / self.max_bits;
        let bits = (i * self.bits) % self.max_bits;
        let diff = self.max_bits - bits;
        let mut val = self.inner[idx];

        if diff >= self.bits {
            let shift = diff - self.bits;
            let last = val & ((1 << shift) - 1);
            let mask = if bits == 0 { 0 } else { ((1 << bits) - 1) << diff };   // prevent overflow
            val &= mask;
            val |= value << shift;
            self.inner[idx] = val | last;
        } else {
            let shift = self.bits - diff;
            self.inner[idx] >>= diff;
            self.inner[idx] <<= diff;
            self.inner[idx] |= value >> shift;
            let last = value & ((1 << shift) - 1);
            self.inner[idx + 1] &= (1 << (self.max_bits - shift)) - 1;
            self.inner[idx + 1] |= last << (self.max_bits - shift);
        }
    }

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

    pub fn reserve(&mut self, additional: usize) {
        self.inner.reserve(additional * self.bits / self.max_bits + 1);
    }

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

    pub fn iter(&self) -> Iter<T> {
        Iter { vec: self, range: 0..self.units }
    }

    pub fn into_iter(self) -> IntoIter<T> {
        IntoIter { range: 0..self.units, vec: self }
    }
}

impl<T: ReprUsize + Clone> BitsVec<T> {
    pub fn extend_with_element(&mut self, length: usize, value: T) {
        assert!(length > self.len(), "final length should be greater than the initial length");
        // Three phases (somewhat inefficient, using safe code and all, but much better than `push`)
        let mut remain = length - self.len();
        self.reserve(remain);

        // 1. Slow push until we get to a common multiple of (self.bits, self.max_bits)
        while self.leftover > 0 {
            self.push(value.clone());
            remain -= 1;
            if remain == 0 {
                return
            }
        }

        // 2. Do the same to a new BitsVec
        let mut temp = BitsVec::new(self.bits);
        temp.reserve(cmp::min(remain, self.max_bits));
        temp.push(value.clone());
        while temp.leftover > 0 && remain > 0 {
            temp.push(value.clone());
        }

        if remain == 0 {
            self.units += temp.units;
            self.inner.extend(&temp.inner);
            return
        }

        // 3. Extend from the new BitsVec
        while remain >= temp.units {
            self.inner.extend(&temp.inner);
            self.units += temp.units;
            remain -= temp.units;
        }

        for _ in 0..remain {
            self.push(value.clone());
        }
    }
}

impl<T: ReprUsize + fmt::Debug> fmt::Debug for BitsVec<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_list().entries(self.iter()).finish()
    }
}

pub struct Iter<'a, T: ReprUsize + 'a> {
    vec: &'a BitsVec<T>,
    range: Range<usize>,
}

impl<'a, T: ReprUsize> IntoIterator for &'a BitsVec<T> {
    type Item = T;
    type IntoIter = Iter<'a, T>;

    fn into_iter(self) -> Iter<'a, T> {
        self.iter()
    }
}

impl<'a, T: ReprUsize> Iterator for Iter<'a, T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.range.next().and_then(|i| self.vec.get(i))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.range.size_hint()
    }
}

impl<'a, T: ReprUsize> DoubleEndedIterator for Iter<'a, T> {
    fn next_back(&mut self) -> Option<T> {
        self.range.next_back().and_then(|i| self.vec.get(i))
    }
}

impl<'a, T: ReprUsize> ExactSizeIterator for Iter<'a, T> {}

pub struct IntoIter<T: ReprUsize> {
    vec: BitsVec<T>,
    range: Range<usize>,
}

impl<T: ReprUsize> IntoIterator for BitsVec<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> IntoIter<T> {
        self.into_iter()
    }
}

impl<T: ReprUsize> Iterator for IntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.range.next().and_then(|i| self.vec.get(i))
    }
}

impl<T: ReprUsize> DoubleEndedIterator for IntoIter<T> {
    fn next_back(&mut self) -> Option<T> {
        self.range.next_back().and_then(|i| self.vec.get(i))
    }
}

impl<T: ReprUsize> ExactSizeIterator for IntoIter<T> {}
<|endoftext|>


<commit_before>mod ack;
mod blocked;
mod connection_close;
mod goaway;
mod padding;
mod ping;
mod rst_stream;
mod stop_waiting;
mod stream;
mod window_update;

use std::io;

use quic::errors::Error;
use quic::frames;

#[test]
fn test_encoding() {
    let mut write = io::Cursor::new(Vec::new());

    let frame = frames::Frame::Ack(
        frames::ack::AckFrame {
            largest_acknowledged: 42,
            ack_delay: 32,

            first_ack_block_length: 64,
            extra_ack_blocks: Vec::new(),

            first_timestamp: None,
            extra_timestamps: Vec::new(),
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::Blocked(
        frames::blocked::BlockedFrame { stream_id: 42 }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::ConnectionClose(
        frames::connection_close::ConnectionCloseFrame {
            error_code: 42,
            reason_phrase: None,
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::GoAway(
        frames::goaway::GoAwayFrame {
            error_code: 42,
            last_good_stream_id: 32,
            reason_phrase: None,
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::Padding(
        frames::padding::PaddingFrame {}
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::Ping(
        frames::ping::PingFrame {}
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::RstStream(
        frames::rst_stream::RstStreamFrame {
            error_code: 42,
            stream_id: 32,
            final_offset: 64,
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::StopWaiting(
        frames::stop_waiting::StopWaitingFrame {
            least_acked_delta: 0x00001042DEADCAFE,
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::Stream(
        frames::stream::StreamFrame {
            stream_id: 42,
            offset: 32,
            stream_data: vec![0x68, 0x65, 0x6C, 0x6C, 0x6F],
            fin: false,
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::WindowUpdate(
        frames::window_update::WindowUpdateFrame {
            stream_id: 42,
            byte_offset: 32,
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    assert_eq!(
        write.into_inner(),
        vec![
            // ack frame
            0x4F,
            0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x2A,
            0x00, 0x20,

            0x00, 0x00, 0x00, 0x00, 0x00, 0x40,

            // blocked frame
            0x05,
            0x00, 0x00, 0x00, 0x2A,

            // connection close frame
            0x02,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00,

            // goaway frame
            0x03,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x20,
            0x00, 0x00,

            // padding frame
            0x00,

            // ping frame
            0x07,

            // rst stream frame
            0x01,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x20,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,

            // stop waiting frame
            0x06,
            0x10, 0x42, 0xDE, 0xAD, 0xCA, 0xFE,

            // stream frame
            0xBF,
            0x00, 0x05,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
            0x68, 0x65, 0x6C, 0x6C, 0x6F,

            // window update frame
            0x04,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
        ]
    );
}

#[test]
fn test_decoding() {
    let mut read = io::Cursor::new(
        vec![
            // ack frame
            0x4F,
            0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x2A,
            0x00, 0x20,

            0x00, 0x00, 0x00, 0x00, 0x00, 0x40,

            // blocked frame
            0x05,
            0x00, 0x00, 0x00, 0x2A,

            // connection close frame
            0x02,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00,

            // goaway frame
            0x03,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x20,
            0x00, 0x00,

            // padding frame
            0x00,

            // ping frame
            0x07,

            // rst stream frame
            0x01,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x20,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,

            // stop waiting frame
            0x06,
            0x10, 0x42, 0xDE, 0xAD, 0xCA, 0xFE,

            // stream frame
            0xBF,
            0x00, 0x05,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
            0x68, 0x65, 0x6C, 0x6C, 0x6F,

            // window update frame
            0x04,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
        ]
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::Ack(
            frames::ack::AckFrame {
                largest_acknowledged: 42,
                ack_delay: 32,

                first_ack_block_length: 64,
                extra_ack_blocks: Vec::new(),

                first_timestamp: None,
                extra_timestamps: Vec::new(),
            }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::Blocked(
            frames::blocked::BlockedFrame { stream_id: 42 }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::ConnectionClose(
            frames::connection_close::ConnectionCloseFrame {
                error_code: 42,
                reason_phrase: None,
            }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::GoAway(
            frames::goaway::GoAwayFrame {
                error_code: 42,
                last_good_stream_id: 32,
                reason_phrase: None,
            }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::Padding(
            frames::padding::PaddingFrame {}
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::Ping(
            frames::ping::PingFrame {}
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::RstStream(
            frames::rst_stream::RstStreamFrame {
                error_code: 42,
                stream_id: 32,
                final_offset: 64,
            }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::StopWaiting(
            frames::stop_waiting::StopWaitingFrame {
                least_acked_delta: 0x00001042DEADCAFE,
            }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::Stream(
            frames::stream::StreamFrame {
                stream_id: 42,
                offset: 32,
                stream_data: vec![0x68, 0x65, 0x6C, 0x6C, 0x6F],
                fin: false,
            }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::WindowUpdate(
            frames::window_update::WindowUpdateFrame {
                stream_id: 42,
                byte_offset: 32,
            }
        )
    );

    match frames::Frame::decode(&mut read, 6) {
        Err(Error::Decoding(_)) => {},
        _ => assert!(false, "Error expected"),
    };
}
<commit_msg>Additional test for invalid frame types<commit_after>mod ack;
mod blocked;
mod connection_close;
mod goaway;
mod padding;
mod ping;
mod rst_stream;
mod stop_waiting;
mod stream;
mod window_update;

use std::io;

use quic::errors::Error;
use quic::frames;

#[test]
fn test_encoding() {
    let mut write = io::Cursor::new(Vec::new());

    let frame = frames::Frame::Ack(
        frames::ack::AckFrame {
            largest_acknowledged: 42,
            ack_delay: 32,

            first_ack_block_length: 64,
            extra_ack_blocks: Vec::new(),

            first_timestamp: None,
            extra_timestamps: Vec::new(),
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::Blocked(
        frames::blocked::BlockedFrame { stream_id: 42 }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::ConnectionClose(
        frames::connection_close::ConnectionCloseFrame {
            error_code: 42,
            reason_phrase: None,
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::GoAway(
        frames::goaway::GoAwayFrame {
            error_code: 42,
            last_good_stream_id: 32,
            reason_phrase: None,
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::Padding(
        frames::padding::PaddingFrame {}
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::Ping(
        frames::ping::PingFrame {}
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::RstStream(
        frames::rst_stream::RstStreamFrame {
            error_code: 42,
            stream_id: 32,
            final_offset: 64,
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::StopWaiting(
        frames::stop_waiting::StopWaitingFrame {
            least_acked_delta: 0x00001042DEADCAFE,
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::Stream(
        frames::stream::StreamFrame {
            stream_id: 42,
            offset: 32,
            stream_data: vec![0x68, 0x65, 0x6C, 0x6C, 0x6F],
            fin: false,
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::WindowUpdate(
        frames::window_update::WindowUpdateFrame {
            stream_id: 42,
            byte_offset: 32,
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    assert_eq!(
        write.into_inner(),
        vec![
            // ack frame
            0x4F,
            0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x2A,
            0x00, 0x20,

            0x00, 0x00, 0x00, 0x00, 0x00, 0x40,

            // blocked frame
            0x05,
            0x00, 0x00, 0x00, 0x2A,

            // connection close frame
            0x02,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00,

            // goaway frame
            0x03,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x20,
            0x00, 0x00,

            // padding frame
            0x00,

            // ping frame
            0x07,

            // rst stream frame
            0x01,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x20,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,

            // stop waiting frame
            0x06,
            0x10, 0x42, 0xDE, 0xAD, 0xCA, 0xFE,

            // stream frame
            0xBF,
            0x00, 0x05,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
            0x68, 0x65, 0x6C, 0x6C, 0x6F,

            // window update frame
            0x04,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
        ]
    );
}

#[test]
fn test_decoding() {
    let mut read = io::Cursor::new(
        vec![
            // ack frame
            0x4F,
            0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x2A,
            0x00, 0x20,

            0x00, 0x00, 0x00, 0x00, 0x00, 0x40,

            // blocked frame
            0x05,
            0x00, 0x00, 0x00, 0x2A,

            // connection close frame
            0x02,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00,

            // goaway frame
            0x03,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x20,
            0x00, 0x00,

            // padding frame
            0x00,

            // ping frame
            0x07,

            // rst stream frame
            0x01,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x20,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,

            // stop waiting frame
            0x06,
            0x10, 0x42, 0xDE, 0xAD, 0xCA, 0xFE,

            // stream frame
            0xBF,
            0x00, 0x05,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
            0x68, 0x65, 0x6C, 0x6C, 0x6F,

            // window update frame
            0x04,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
        ]
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::Ack(
            frames::ack::AckFrame {
                largest_acknowledged: 42,
                ack_delay: 32,

                first_ack_block_length: 64,
                extra_ack_blocks: Vec::new(),

                first_timestamp: None,
                extra_timestamps: Vec::new(),
            }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::Blocked(
            frames::blocked::BlockedFrame { stream_id: 42 }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::ConnectionClose(
            frames::connection_close::ConnectionCloseFrame {
                error_code: 42,
                reason_phrase: None,
            }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::GoAway(
            frames::goaway::GoAwayFrame {
                error_code: 42,
                last_good_stream_id: 32,
                reason_phrase: None,
            }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::Padding(
            frames::padding::PaddingFrame {}
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::Ping(
            frames::ping::PingFrame {}
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::RstStream(
            frames::rst_stream::RstStreamFrame {
                error_code: 42,
                stream_id: 32,
                final_offset: 64,
            }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::StopWaiting(
            frames::stop_waiting::StopWaitingFrame {
                least_acked_delta: 0x00001042DEADCAFE,
            }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::Stream(
            frames::stream::StreamFrame {
                stream_id: 42,
                offset: 32,
                stream_data: vec![0x68, 0x65, 0x6C, 0x6C, 0x6F],
                fin: false,
            }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::WindowUpdate(
            frames::window_update::WindowUpdateFrame {
                stream_id: 42,
                byte_offset: 32,
            }
        )
    );

    match frames::Frame::decode(&mut read, 6) {
        Err(Error::Decoding(_)) => {},
        _ => assert!(false, "Error expected"),
    };

    let mut read = io::Cursor::new(
        vec![
            // invalid frame type
            0x20,
        ]
    );
    match frames::Frame::decode(&mut read, 6) {
        Err(Error::Decoding(_)) => {},
        _ => assert!(false, "Error expected"),
    };
}
<|endoftext|>


<commit_before>#![feature(cfg_target_feature)]
extern crate simd;
use simd::f32x4;
#[cfg(target_feature = "avx")]
use simd::x86::avx::f32x8;

#[inline(never)]
pub fn axpy(z: &mut [f32], a: f32, x: &[f32], y: &[f32]) {
    assert_eq!(x.len(), y.len());
    assert_eq!(x.len(), z.len());

    let len = std::cmp::min(std::cmp::min(x.len(), y.len()), z.len());

    let mut i = 0;
    while i < len & !3 {
        let x = f32x4::load(x, i);
        let y = f32x4::load(y, i);
        (f32x4::splat(a) * x + y).store(z, i);
        i += 4
    }
}

#[cfg(target_feature = "avx")]
#[inline(never)]
pub fn axpy8(z: &mut [f32], a: f32, x: &[f32], y: &[f32]) {
    assert_eq!(x.len(), y.len());
    assert_eq!(x.len(), z.len());

    let len = std::cmp::min(std::cmp::min(x.len(), y.len()), z.len());

    let mut i = 0;
    while i < len & !7 {
        let x = f32x8::load(x, i);
        let y = f32x8::load(y, i);
        (f32x8::splat(a) * x + y).store(z, i);
        i += 8
    }
}

#[cfg(not(target_feature = "avx"))]
pub fn axpy8(x: &[f32], y: &[f32]) -> f32 {
    unimplemented!()
}

fn main() {
    let mut z = vec![0.; 4];
    axpy(&mut z, 2., &[1.0, 3.0, 5.0, 7.0], &[2.0, 4.0, 6.0, 8.0]);
    println!("{:?}", z);
    let mut z = vec![0.; 8];
    axpy(&mut z, 3., &[1.0, 3.0, 6.0, 7.0, 10.0, 6.0, 3.0, 2.0],
                       &[2.0, 4.0, 6.0, 8.0, 2.0, 4.0, 6.0, 8.0]);
    println!("{:?}", z);

    if cfg!(target_feature = "avx") {
        let mut z = vec![0.; 4];
        axpy8(&mut z, 2., &[1.0, 3.0, 5.0, 7.0], &[2.0, 4.0, 6.0, 8.0]);
        println!("{:?}", z);
        let mut z = vec![0.; 8];
        axpy8(&mut z, 3., &[1.0, 3.0, 6.0, 7.0, 10.0, 6.0, 3.0, 2.0],
                           &[2.0, 4.0, 6.0, 8.0, 2.0, 4.0, 6.0, 8.0]);
        println!("{:?}", z);
    }
}
<commit_msg>Fix axpy example<commit_after>#![feature(cfg_target_feature)]
extern crate simd;
use simd::f32x4;
#[cfg(target_feature = "avx")]
use simd::x86::avx::f32x8;

#[inline(never)]
pub fn axpy(z: &mut [f32], a: f32, x: &[f32], y: &[f32]) {
    assert_eq!(x.len(), y.len());
    assert_eq!(x.len(), z.len());

    let len = std::cmp::min(std::cmp::min(x.len(), y.len()), z.len());

    let mut i = 0;
    while i < len & !3 {
        let x = f32x4::load(x, i);
        let y = f32x4::load(y, i);
        (f32x4::splat(a) * x + y).store(z, i);
        i += 4
    }
}

#[cfg(target_feature = "avx")]
#[inline(never)]
pub fn axpy8(z: &mut [f32], a: f32, x: &[f32], y: &[f32]) {
    assert_eq!(x.len(), y.len());
    assert_eq!(x.len(), z.len());

    let len = std::cmp::min(std::cmp::min(x.len(), y.len()), z.len());

    let mut i = 0;
    while i < len & !7 {
        let x = f32x8::load(x, i);
        let y = f32x8::load(y, i);
        (f32x8::splat(a) * x + y).store(z, i);
        i += 8
    }
}

#[cfg(not(target_feature = "avx"))]
pub fn axpy8(z: &mut [f32], a: f32, x: &[f32], y: &[f32]) {
    unimplemented!()
}

fn main() {
    let mut z = vec![0.; 4];
    axpy(&mut z, 2., &[1.0, 3.0, 5.0, 7.0], &[2.0, 4.0, 6.0, 8.0]);
    println!("{:?}", z);
    let mut z = vec![0.; 8];
    axpy(&mut z, 3., &[1.0, 3.0, 6.0, 7.0, 10.0, 6.0, 3.0, 2.0],
                       &[2.0, 4.0, 6.0, 8.0, 2.0, 4.0, 6.0, 8.0]);
    println!("{:?}", z);

    if cfg!(target_feature = "avx") {
        let mut z = vec![0.; 4];
        axpy8(&mut z, 2., &[1.0, 3.0, 5.0, 7.0], &[2.0, 4.0, 6.0, 8.0]);
        println!("{:?}", z);
        let mut z = vec![0.; 8];
        axpy8(&mut z, 3., &[1.0, 3.0, 6.0, 7.0, 10.0, 6.0, 3.0, 2.0],
                           &[2.0, 4.0, 6.0, 8.0, 2.0, 4.0, 6.0, 8.0]);
        println!("{:?}", z);
    }
}
<|endoftext|>


<commit_before>//! View bits in memory with turtles
//!
//! This example uses [@myrrlyn]'s [`bitvec`] crate to turn data into strings of
//! bits, and then draws them on the screen.
//!
//! You are encouraged to change both the data used to seed the turtle, and the
//! `bitvec` calls that control how the turtle acts, to see what changes.
//!
//! [@myrrlyn]: //github.com/myrrlyn
//! [`bitvec`]: //crates.io/crates/bitvec

// This imports the things we need from `bitvec`, including the `Bits` trait for
// the `.bits::<_>()` method we use to view memory.
use bitvec::prelude::*;
use turtle::Turtle;

// Modify these constants to change the behavior of the example.

/// This text will be inspected as individual bytes, and drawn on the screen.
/// You can change it to see what different text looks like when viewed as bits.
///
/// The example program will print more information about the parts of the text
/// to the console while the turtle draws, so that you can see how each glyph
/// corresponds to parts of the rendered memory.
static TEXT: &str = "¡Hola, mundo! 🌍🌏🌎";

/// This number will have its bit pattern printed on screen. Rust provides some
/// interesting numbers in its standard library; you can replace this with other
/// numbers to see what they look like. Pi is provided as the default solely
/// because it is well-known, and has an interesting pattern.
const NUMBER: f64 = std::f64::consts::PI;

/// This controls the width of the drawn line for each bit.
const BIT_WIDTH: f64 = 20.0;

/// This controls the vertical spacing between rows of bit lines.
const BIT_HEIGHT: f64 = 10.0;

/// Set the horizontal spacing between successive bits in a row
const BIT_MARGIN: f64 = BIT_WIDTH / 2.0;

/// Compute the total width of a bit plus its spacing
const BIT_BOX: f64 = BIT_WIDTH + BIT_MARGIN;

fn main() {
    // This block sets up the turtle to draw bits more or less centered in the
    // screen. The turtle works by walking horizontally for each bit in a byte,
    // then backtracking and walking vertically to the next byte.
    let mut turtle = Turtle::new();
    // The turtle starts in the center of the screen, but we want to move it
    // around before drawing.
    turtle.pen_up();

    // Compute the boundaries of the part of the screen where the turtle will
    // draw. We expect to be drawing eight bits, with half to the right of
    // center and half to the left.
    let right_edge = BIT_BOX * 8.0 / 2.0;
    // We also expect to be drawing a row for each byte in the text, with an
    // additional separator row for each *character*, half above and half below
    // the center of the screen. This computes how many rows of text we will
    // draw, then moves the turtle appropriately.
    let byte_rows = TEXT.len();
    let char_gaps = TEXT.chars().count();
    let top_edge = BIT_HEIGHT * ((byte_rows + char_gaps) as f64 / 2.0);
    // The turtle starts from the top right of the region,
    turtle.forward(top_edge);
    turtle.right(90.0);
    turtle.forward(right_edge);
    // and walks left
    turtle.left(180.0);

    draw_text(&mut turtle, TEXT);

    // The `draw_number` function reads bits from left to right, so the turtle
    // should also walk from left to right. The `draw_number` function expects
    // that it will be drawing rows sixteen bits long, so it needs to move
    // forward another four bits' worth of space in order to be in the correct
    // spot.
    turtle.forward(8.0 * BIT_BOX / 2.0);
    turtle.forward(16.0 * BIT_BOX / 2.0);
    // Then, it needs to turn around, to walk in the other direction.
    turtle.right(180.0);

    draw_number(&mut turtle, NUMBER);
}

/// Draws the bits of a text span on the screen.
fn draw_text(turtle: &mut Turtle, text: &str) {
    // Rust strings can iterate over their individual characters. This block
    // loops over characters, collecting their start point in the text so that
    // we can grab the encoded bytes of each one.
    let mut row_num = 0;
    for (char_num, (start, codepoint)) in text.char_indices().enumerate() {
        println!("Character {}: {}", char_num, codepoint);
        // Each character has a variable width, so we need to find that.
        let byte_count = codepoint.len_utf8();
        // And then collect the bytes of the string that make up the character.
        // `start` gives us the starting position in the text sequence, and
        // `byte_count` gives us the length in bytes of the character, so we
        // need to select the range beginning at `start`, running for
        // `byte_count`. Another style of writing this that you might see in
        // Rust libraries is `[start ..][.. length]`.
        let row: &[u8] = &text.as_bytes()[start .. start + byte_count];

        // For each byte (`u8`), we use `bitvec` to make a view into its bits.
        // `bitvec` provides the `.bits::<_>()` method on Rust integers for easy
        // access to its view types.
        //
        // The `LittleEndian` means that the view moves from least significant
        // bit to most significant. Since we want to display on screen the most
        // significant bit on the left, and the least on the right, the turtle
        // will have to move from right to left to match.
        //
        // The `LittleEndian` and `BigEndian` types describe different ways to
        // view the same data. You can read more about them in the `bitvec`
        // docs, and at Wikipedia:
        // https://docs.rs/bitvec/0.16.1/bitvec/cursor/index.html
        // https://en.wikipedia.org/wiki/Endianness#Bit_endianness
        for byte in row {
            println!("  Byte {:02}:\n    Value: 0x{:02X}\n    Bits: {:08b}", row_num, byte, byte);

            let bits: &BitSlice<_, _> = byte.bits::<LittleEndian>();

            // Then we draw the byte's bits as a row
            draw_row(turtle, bits);
            //  And go to the next row
            next_row(turtle, 90.0);

            row_num += 1;
        }
        // This puts a dividing line between each *character* in the text.
        // Some characters may have more than one byte, and those bytes will be
        // grouped together.
        delimit(turtle, 8.0 * BIT_BOX - BIT_MARGIN);
    }
}

/// Draws the bits of a number on screen.
fn draw_number(turtle: &mut Turtle, number: f64) {
    // `bitvec` can look at more than just `u8`. Let's try looking at the bits
    // that represent a number!
    //
    // Some numbers, like `f64`, have special rules for their representation in
    // bits. `bitvec` only knows about raw bits, so it does not provide direct
    // support for `f64`. Rust lets us get the bit representation from an `f64`
    // with the method `to_bits(f64) -> u64`, which forgets about the `f64`
    // rules and uses the number's storage as ordinary bits.
    //
    // You can read more about the rules for `f64`'s storage in memory, and
    // behavior in programs, here:
    // https://en.wikipedia.org/wiki/Double-precision_floating-point_format
    let raw_number: u64 = number.to_bits();

    // `bitvec` can also view bits from left to right, with `BigEndian`.
    let bits: &BitSlice<_, _> = raw_number.bits::<BigEndian>();

    // The `&BitSlice` type acts just like `&[bool]`, so it comes with a
    // `.chunks` method which divides it into smaller pieces. `bitvec` can take
    // any number, not just multiples of 8, but 16 is a convenient number to
    // look at. Try changing it to a different number, like 10, to see what
    // happens!
    for (num, row) in bits.chunks(16).enumerate() {
        println!("Row {} bits: {:b}", num, row);
        // Each chunk produced is a smaller `&BitSlice`, just like
        // `&[bool].chunks` produces smaller `&[bool]`s, so we can draw it.
        draw_row(turtle, row);

        next_row(turtle, -90.0);
    }

    // Reader exercise:
    //
    // The IEEE-754 format for `f64` numbers separates them into three parts:
    //
    // 1. The sign marks whether the number is positive or negative: 1 bit
    // 2. The exponent marks how far from zero the number is: 11 bits
    // 3. The fraction describes the number: 52 bits.
    //
    // Using these widths (1 bit, 11 bits, 52 bits), the knowledge that
    // `&BitSlice` is a normal Rust slice, and the API documentation for
    // `std::iter::Iterator`, see if you can display each portion of an `f64`
    // as its own row.
    //
    // Hints:
    //
    // - The variable `bits` is set up to view the entire number, from most
    // significant bit to least.
    // - You can get access to a structure that performs iteration by calling
    //   `bits.iter()`.
    // - You can use the `Iterator::by_ref` method to prevent `Iterator` adapter
    //   functions from destroying the source iterator.
    // - `&BitSlice` is an ordinary Rust slice, so you can use `[start .. end]`
    //   range indexing to get smaller pieces of it.
}

/// Draw a row of bits on the screen.
///
/// This takes a reference to a turtle, which draws, and a reference to a slice
/// of bits, which provides the data to draw.
///
/// Note that this works whether we're going through the bits left to right
/// (`BigEndian`) or right to left (`LittleEndian`), because we assume that the
/// turtle is going to start on the correct side and be facing the correct way
/// for this drawing to work.
fn draw_row<C, T>(turtle: &mut Turtle, row: &BitSlice<C, T>)
where C: Cursor, T: BitStore {
    // `&BitSlice` can iterate over bits. It is just like `&[bool]`, and so it
    // produces `&bool` for each loop.
    for &bit in row {
        // This checks if the bit produced by the row is `1` or `0`, and sets
        // the pen color to black (`1`) or light grey (`0`)
        if bit {
            turtle.set_pen_color("black");
        }
        else {
            turtle.set_pen_color("light grey");
        }

        // For each bit, the loop puts down the pen to draw a line of the bit's
        // color, then picks up the pen to add some horizontal spacing between
        // them.
        turtle.pen_down();
        turtle.forward(BIT_WIDTH);
        turtle.pen_up();
        turtle.forward(BIT_MARGIN);
    }
    //  Rewind the turtle
    for _ in 0 .. row.len() {
        turtle.backward(BIT_BOX);
    }
}

/// Produces a separator line to demark different sections of memory.
fn delimit(turtle: &mut Turtle, width: f64) {
    turtle.set_pen_color("grey");
    turtle.pen_down();
    turtle.forward(width);
    turtle.backward(width);

    next_row(turtle, 90.0);
}

/// Moves the turtle down a row
fn next_row(turtle: &mut Turtle, angle: f64) {
    turtle.pen_up();
    turtle.left(angle);
    turtle.forward(BIT_HEIGHT);
    turtle.right(angle);
}
<commit_msg>Update to bitvec 0.17<commit_after>//! View bits in memory with turtles
//!
//! This example uses [@myrrlyn]'s [`bitvec`] crate to turn data into strings of
//! bits, and then draws them on the screen.
//!
//! You are encouraged to change both the data used to seed the turtle, and the
//! `bitvec` calls that control how the turtle acts, to see what changes.
//!
//! [@myrrlyn]: //github.com/myrrlyn
//! [`bitvec`]: //crates.io/crates/bitvec

// This imports the things we need from `bitvec`, including the `Bits` trait for
// the `.bits::<_>()` method we use to view memory.
use bitvec::prelude::*;
use turtle::Turtle;

// Modify these constants to change the behavior of the example.

/// This text will be inspected as individual bytes, and drawn on the screen.
/// You can change it to see what different text looks like when viewed as bits.
///
/// The example program will print more information about the parts of the text
/// to the console while the turtle draws, so that you can see how each glyph
/// corresponds to parts of the rendered memory.
static TEXT: &str = "¡Hola, mundo! 🌍🌏🌎";

/// This number will have its bit pattern printed on screen. Rust provides some
/// interesting numbers in its standard library; you can replace this with other
/// numbers to see what they look like. Pi is provided as the default solely
/// because it is well-known, and has an interesting pattern.
const NUMBER: f64 = std::f64::consts::PI;

/// This controls the width of the drawn line for each bit.
const BIT_WIDTH: f64 = 20.0;

/// This controls the vertical spacing between rows of bit lines.
const BIT_HEIGHT: f64 = 10.0;

/// Set the horizontal spacing between successive bits in a row
const BIT_MARGIN: f64 = BIT_WIDTH / 2.0;

/// Compute the total width of a bit plus its spacing
const BIT_BOX: f64 = BIT_WIDTH + BIT_MARGIN;

fn main() {
    // This block sets up the turtle to draw bits more or less centered in the
    // screen. The turtle works by walking horizontally for each bit in a byte,
    // then backtracking and walking vertically to the next byte.
    let mut turtle = Turtle::new();
    // The turtle starts in the center of the screen, but we want to move it
    // around before drawing.
    turtle.pen_up();

    // Compute the boundaries of the part of the screen where the turtle will
    // draw. We expect to be drawing eight bits, with half to the right of
    // center and half to the left.
    let right_edge = BIT_BOX * 8.0 / 2.0;
    // We also expect to be drawing a row for each byte in the text, with an
    // additional separator row for each *character*, half above and half below
    // the center of the screen. This computes how many rows of text we will
    // draw, then moves the turtle appropriately.
    let byte_rows = TEXT.len();
    let char_gaps = TEXT.chars().count();
    let top_edge = BIT_HEIGHT * ((byte_rows + char_gaps) as f64 / 2.0);
    // The turtle starts from the top right of the region,
    turtle.forward(top_edge);
    turtle.right(90.0);
    turtle.forward(right_edge);
    // and walks left
    turtle.left(180.0);

    draw_text(&mut turtle, TEXT);

    // The `draw_number` function reads bits from left to right, so the turtle
    // should also walk from left to right. The `draw_number` function expects
    // that it will be drawing rows sixteen bits long, so it needs to move
    // forward another four bits' worth of space in order to be in the correct
    // spot.
    turtle.forward(8.0 * BIT_BOX / 2.0);
    turtle.forward(16.0 * BIT_BOX / 2.0);
    // Then, it needs to turn around, to walk in the other direction.
    turtle.right(180.0);

    draw_number(&mut turtle, NUMBER);
}

/// Draws the bits of a text span on the screen.
fn draw_text(turtle: &mut Turtle, text: &str) {
    // Rust strings can iterate over their individual characters. This block
    // loops over characters, collecting their start point in the text so that
    // we can grab the encoded bytes of each one.
    let mut row_num = 0;
    for (char_num, (start, codepoint)) in text.char_indices().enumerate() {
        println!("Character {}: {}", char_num, codepoint);
        // Each character has a variable width, so we need to find that.
        let byte_count = codepoint.len_utf8();
        // And then collect the bytes of the string that make up the character.
        // `start` gives us the starting position in the text sequence, and
        // `byte_count` gives us the length in bytes of the character, so we
        // need to select the range beginning at `start`, running for
        // `byte_count`. Another style of writing this that you might see in
        // Rust libraries is `[start ..][.. length]`.
        let row: &[u8] = &text.as_bytes()[start .. start + byte_count];

        // For each byte (`u8`), we use `bitvec` to make a view into its bits.
        // `bitvec` provides the `.bits::<_>()` method on Rust integers for easy
        // access to its view types.
        //
        // The `Lsb0` means that the view moves from least significant bit to
        // most significant. Since we want to display on screen the most
        // significant bit on the left, and the least on the right, the turtle
        // will have to move from right to left to match.
        //
        // The `Lsb0` and `Msb0` types describe different ways to view the same
        // data. You can read more about them in the `bitvec` docs, and at
        // Wikipedia:
        // https://docs.rs/bitvec/0.16.1/bitvec/cursor/index.html
        // https://en.wikipedia.org/wiki/Endianness#Bit_endianness
        for byte in row {
            println!("  Byte {:02}:\n    Value: 0x{:02X}\n    Bits: {:08b}", row_num, byte, byte);

            let bits: &BitSlice<_, _> = byte.bits::<Lsb0>();

            // Then we draw the byte's bits as a row
            draw_row(turtle, bits);
            //  And go to the next row
            next_row(turtle, 90.0);

            row_num += 1;
        }
        // This puts a dividing line between each *character* in the text.
        // Some characters may have more than one byte, and those bytes will be
        // grouped together.
        delimit(turtle, 8.0 * BIT_BOX - BIT_MARGIN);
    }
}

/// Draws the bits of a number on screen.
fn draw_number(turtle: &mut Turtle, number: f64) {
    // `bitvec` can look at more than just `u8`. Let's try looking at the bits
    // that represent a number!
    //
    // Some numbers, like `f64`, have special rules for their representation in
    // bits. `bitvec` only knows about raw bits, so it does not provide direct
    // support for `f64`. Rust lets us get the bit representation from an `f64`
    // with the method `to_bits(f64) -> u64`, which forgets about the `f64`
    // rules and uses the number's storage as ordinary bits.
    //
    // You can read more about the rules for `f64`'s storage in memory, and
    // behavior in programs, here:
    // https://en.wikipedia.org/wiki/Double-precision_floating-point_format
    let raw_number: u64 = number.to_bits();

    // `bitvec` can also view bits from left to right, with `Msb0`.
    let bits: &BitSlice<_, _> = raw_number.bits::<Msb0>();

    // The `&BitSlice` type acts just like `&[bool]`, so it comes with a
    // `.chunks` method which divides it into smaller pieces. `bitvec` can take
    // any number, not just multiples of 8, but 16 is a convenient number to
    // look at. Try changing it to a different number, like 10, to see what
    // happens!
    for (num, row) in bits.chunks(16).enumerate() {
        println!("Row {} bits: {:b}", num, row);
        // Each chunk produced is a smaller `&BitSlice`, just like
        // `&[bool].chunks` produces smaller `&[bool]`s, so we can draw it.
        draw_row(turtle, row);

        next_row(turtle, -90.0);
    }

    // Reader exercise:
    //
    // The IEEE-754 format for `f64` numbers separates them into three parts:
    //
    // 1. The sign marks whether the number is positive or negative: 1 bit
    // 2. The exponent marks how far from zero the number is: 11 bits
    // 3. The fraction describes the number: 52 bits.
    //
    // Using these widths (1 bit, 11 bits, 52 bits), the knowledge that
    // `&BitSlice` is a normal Rust slice, and the API documentation for
    // `std::iter::Iterator`, see if you can display each portion of an `f64`
    // as its own row.
    //
    // Hints:
    //
    // - The variable `bits` is set up to view the entire number, from most
    // significant bit to least.
    // - You can get access to a structure that performs iteration by calling
    //   `bits.iter()`.
    // - You can use the `Iterator::by_ref` method to prevent `Iterator` adapter
    //   functions from destroying the source iterator.
    // - `&BitSlice` is an ordinary Rust slice, so you can use `[start .. end]`
    //   range indexing to get smaller pieces of it.
}

/// Draw a row of bits on the screen.
///
/// This takes a reference to a turtle, which draws, and a reference to a slice
/// of bits, which provides the data to draw.
///
/// Note that this works whether we're going through the bits left to right
/// (`Msb0`) or right to left (`Lsb0`), because we assume that the turtle is
/// going to start on the correct side and be facing the correct way for this
/// drawing to work.
fn draw_row<O, T>(turtle: &mut Turtle, row: &BitSlice<O, T>)
where O: BitOrder, T: BitStore {
    // `&BitSlice` can iterate over bits. It is just like `&[bool]`, and so it
    // produces `&bool` for each loop.
    for &bit in row {
        // This checks if the bit produced by the row is `1` or `0`, and sets
        // the pen color to black (`1`) or light grey (`0`)
        if bit {
            turtle.set_pen_color("black");
        }
        else {
            turtle.set_pen_color("light grey");
        }

        // For each bit, the loop puts down the pen to draw a line of the bit's
        // color, then picks up the pen to add some horizontal spacing between
        // them.
        turtle.pen_down();
        turtle.forward(BIT_WIDTH);
        turtle.pen_up();
        turtle.forward(BIT_MARGIN);
    }
    //  Rewind the turtle
    for _ in 0 .. row.len() {
        turtle.backward(BIT_BOX);
    }
}

/// Produces a separator line to demark different sections of memory.
fn delimit(turtle: &mut Turtle, width: f64) {
    turtle.set_pen_color("grey");
    turtle.pen_down();
    turtle.forward(width);
    turtle.backward(width);

    next_row(turtle, 90.0);
}

/// Moves the turtle down a row
fn next_row(turtle: &mut Turtle, angle: f64) {
    turtle.pen_up();
    turtle.left(angle);
    turtle.forward(BIT_HEIGHT);
    turtle.right(angle);
}
<|endoftext|>


<commit_before>
extern crate nest;
use nest::{Window, Event};
use nest::{Rectangle, Circle, ShaderMode};
use nest::{ElementState, VirtualKeyCode};
use nest::support::{self, from_html};
use nest::vertex::color::Vertex;

use std::collections::HashMap;
use std::time::Instant;

fn main() {
    let mut app = Window::new("Hello World", 640, 480);
    let mut keymap: HashMap<VirtualKeyCode, bool> = HashMap::new();
    let pic = app.load_image("examples/city.jpg").unwrap();

    let mut time = 0.0;
    let mut last = Instant::now();

    'main: loop {
        {
            let mut frame = app.next_frame();
            frame.clear();

            let curr = Instant::now();
            let delta = support::as_sec(curr - last);
            last = curr;

            time += delta;

            frame.draw_rect(-0.5, -0.5, 0.5, 0.5, from_html("312"));

            frame.draw_rect(0.0, 0.0, -1.0, -1.0, from_html("#033112"));

            let color = [0.0, 0.0, 1.0, 0.3];
            frame.draw(&[Vertex::new(0.0, 0.0, color), Vertex::new(1.0, 1.0, color), Vertex::new(1.0, 0.0, color)], ShaderMode::Color);

            let color = [0.0, 1.0, 0.0, 0.3];
            frame.draw(&[Vertex::new(0.0, 0.0, color), Vertex::new(0.0, 1.0, color), Vertex::new(1.0, 1.0, color)], ShaderMode::Color);

            frame.draw_shape(&Circle {
                x: 0.25 * time.sin(),
                y: -0.25 * time.cos(),
                rx: 0.75,
                ry: 0.25,
                step_size: 10,
                color: [1.0, 0.0, 0.0, 0.3],
            });

            frame.draw_image(
                &pic,
                Rectangle {
                    x: -1.0,
                    y: 0.0,
                    w: 1.0,
                    h: 1.0,
                },
                Some(Rectangle {
                    x: 0.3,
                    y: 0.0,
                    w: 0.3,
                    h: 1.0,
                }),
            );
            frame.draw_image(
                &pic,
                Rectangle {
                    x: -0.5,
                    y: 0.0,
                    w: 0.5,
                    h: 0.5,
                },
                Default::default(),
            );

            frame.draw_rect(0.0, 0.0, 1.0, 1.0, [0.0, 1.0, 1.0, 0.1]);

            frame.finish();
        }

        for ev in app.poll_events() {
            use Event::*;
            use VirtualKeyCode::*;

            match ev {
                Closed => break 'main,
                KeyboardInput(ElementState::Pressed, Some(key)) => {
                    match key {
                        Space => println!("Space!"),
                        Escape => break 'main,
                        _ => (),
                    };
                    keymap.insert(key, true);
                }
                KeyboardInput(ElementState::Released, Some(key)) => {
                    keymap.insert(key, false);
                }
                _ => (),
            }
        }
    }
}
<commit_msg>Updated examples/demo.rs to illustrate None instead of Default<commit_after>
extern crate nest;
use nest::{Window, Event};
use nest::{Rectangle, Circle, ShaderMode};
use nest::{ElementState, VirtualKeyCode};
use nest::support::{self, from_html};
use nest::vertex::color::Vertex;

use std::collections::HashMap;
use std::time::Instant;

fn main() {
    let mut app = Window::new("Hello World", 640, 480);
    let mut keymap: HashMap<VirtualKeyCode, bool> = HashMap::new();
    let pic = app.load_image("examples/city.jpg").unwrap();

    let mut time = 0.0;
    let mut last = Instant::now();

    'main: loop {
        {
            let mut frame = app.next_frame();
            frame.clear();

            let curr = Instant::now();
            let delta = support::as_sec(curr - last);
            last = curr;

            time += delta;

            frame.draw_rect(-0.5, -0.5, 0.5, 0.5, from_html("312"));

            frame.draw_rect(0.0, 0.0, -1.0, -1.0, from_html("#033112"));

            let color = [0.0, 0.0, 1.0, 0.3];
            frame.draw(&[Vertex::new(0.0, 0.0, color), Vertex::new(1.0, 1.0, color), Vertex::new(1.0, 0.0, color)], ShaderMode::Color);

            let color = [0.0, 1.0, 0.0, 0.3];
            frame.draw(&[Vertex::new(0.0, 0.0, color), Vertex::new(0.0, 1.0, color), Vertex::new(1.0, 1.0, color)], ShaderMode::Color);

            frame.draw_shape(&Circle {
                x: 0.25 * time.sin(),
                y: -0.25 * time.cos(),
                rx: 0.75,
                ry: 0.25,
                step_size: 10,
                color: [1.0, 0.0, 0.0, 0.3],
            });

            frame.draw_image(
                &pic,
                Rectangle {
                    x: -1.0,
                    y: 0.0,
                    w: 1.0,
                    h: 1.0,
                },
                Some(Rectangle {
                    x: 0.3,
                    y: 0.0,
                    w: 0.3,
                    h: 1.0,
                }),
            );
            frame.draw_image(
                &pic,
                Rectangle {
                    x: -0.5,
                    y: 0.0,
                    w: 0.5,
                    h: 0.5,
                },
                None,
            );

            frame.draw_rect(0.0, 0.0, 1.0, 1.0, [0.0, 1.0, 1.0, 0.1]);

            frame.finish();
        }

        for ev in app.poll_events() {
            use Event::*;
            use VirtualKeyCode::*;

            match ev {
                Closed => break 'main,
                KeyboardInput(ElementState::Pressed, Some(key)) => {
                    match key {
                        Space => println!("Space!"),
                        Escape => break 'main,
                        _ => (),
                    };
                    keymap.insert(key, true);
                }
                KeyboardInput(ElementState::Released, Some(key)) => {
                    keymap.insert(key, false);
                }
                _ => (),
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::cmp::min;
use std::fs::File;
use std::io::{self, Seek, SeekFrom, Write};

use fallocate;
use FallocateMode;

/// A trait for writing zeroes to a stream.
pub trait WriteZeroes {
    /// Write `length` bytes of zeroes to the stream, returning how many bytes were written.
    fn write_zeroes(&mut self, length: usize) -> io::Result<usize>;
}

impl WriteZeroes for File {
    fn write_zeroes(&mut self, length: usize) -> io::Result<usize> {
        // Try to use fallocate(FALLOC_FL_ZERO_RANGE) first.
        let offset = self.seek(SeekFrom::Current(0))?;
        match fallocate(self, FallocateMode::ZeroRange, false, offset, length as u64) {
            Ok(()) => {
                // Advance the seek cursor as if we had done a real write().
                self.seek(SeekFrom::Current(length as i64))?;
                return Ok(length);
            }
            Err(_) => {} // fall back to write()
        }

        // fallocate() failed; fall back to writing a buffer of zeroes
        // until we have written up to length.
        let buf_size = min(length, 0x10000);
        let buf = vec![0u8; buf_size];
        let mut nwritten: usize = 0;
        while nwritten < length {
            let remaining = length - nwritten;
            let write_size = min(remaining, buf_size);
            nwritten += self.write(&buf[0..write_size])?;
        }
        Ok(length)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fs::OpenOptions;
    use std::io::{Read, Seek, SeekFrom};
    use std::path::PathBuf;

    use TempDir;

    #[test]
    fn simple_test() {
        let tempdir = TempDir::new("/tmp/write_zeroes_test").unwrap();
        let mut path = PathBuf::from(tempdir.as_path().unwrap());
        path.push("file");
        let mut f = OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(&path)
            .unwrap();
        f.set_len(16384).unwrap();

        // Write buffer of non-zero bytes to offset 1234
        let orig_data = [0x55u8; 5678];
        f.seek(SeekFrom::Start(1234)).unwrap();
        f.write(&orig_data).unwrap();

        // Read back the data plus some overlap on each side
        let mut readback = [0u8; 16384];
        f.seek(SeekFrom::Start(0)).unwrap();
        f.read(&mut readback).unwrap();
        // Bytes before the write should still be 0
        for read in readback[0..1234].iter() {
            assert_eq!(*read, 0);
        }
        // Bytes that were just written should be 0x55
        for read in readback[1234..(1234 + 5678)].iter() {
            assert_eq!(*read, 0x55);
        }
        // Bytes after the written area should still be 0
        for read in readback[(1234 + 5678)..].iter() {
            assert_eq!(*read, 0);
        }

        // Overwrite some of the data with zeroes
        f.seek(SeekFrom::Start(2345)).unwrap();
        f.write_zeroes(4321).expect("write_zeroes failed");
        // Verify seek position after write_zeroes()
        assert_eq!(f.seek(SeekFrom::Current(0)).unwrap(), 2345 + 4321);

        // Read back the data and verify that it is now zero
        f.seek(SeekFrom::Start(0)).unwrap();
        f.read(&mut readback).unwrap();
        // Bytes before the write should still be 0
        for read in readback[0..1234].iter() {
            assert_eq!(*read, 0);
        }
        // Original data should still exist before the write_zeroes region
        for read in readback[1234..2345].iter() {
            assert_eq!(*read, 0x55);
        }
        // The write_zeroes region should now be zero
        for read in readback[2345..(2345 + 4321)].iter() {
            assert_eq!(*read, 0);
        }
        // Original data should still exist after the write_zeroes region
        for read in readback[(2345 + 4321)..(1234 + 5678)].iter() {
            assert_eq!(*read, 0x55);
        }
        // The rest of the file should still be 0
        for read in readback[(1234 + 5678)..].iter() {
            assert_eq!(*read, 0);
        }
    }

    #[test]
    fn large_write_zeroes() {
        let tempdir = TempDir::new("/tmp/write_zeroes_test").unwrap();
        let mut path = PathBuf::from(tempdir.as_path().unwrap());
        path.push("file");
        let mut f = OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(&path)
            .unwrap();
        f.set_len(16384).unwrap();

        // Write buffer of non-zero bytes
        let orig_data = [0x55u8; 0x20000];
        f.seek(SeekFrom::Start(0)).unwrap();
        f.write(&orig_data).unwrap();

        // Overwrite some of the data with zeroes
        f.seek(SeekFrom::Start(0)).unwrap();
        f.write_zeroes(0x10001).expect("write_zeroes failed");
        // Verify seek position after write_zeroes()
        assert_eq!(f.seek(SeekFrom::Current(0)).unwrap(), 0x10001);

        // Read back the data and verify that it is now zero
        let mut readback = [0u8; 0x20000];
        f.seek(SeekFrom::Start(0)).unwrap();
        f.read(&mut readback).unwrap();
        // The write_zeroes region should now be zero
        for read in readback[0..0x10001].iter() {
            assert_eq!(*read, 0);
        }
        // Original data should still exist after the write_zeroes region
        for read in readback[0x10001..0x20000].iter() {
            assert_eq!(*read, 0x55);
        }
    }
}
<commit_msg>sys_util: use PUNCH_HOLE to implement write_zeroes<commit_after>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::cmp::min;
use std::fs::File;
use std::io::{self, Seek, SeekFrom, Write};

use fallocate;
use FallocateMode;

/// A trait for writing zeroes to a stream.
pub trait WriteZeroes {
    /// Write `length` bytes of zeroes to the stream, returning how many bytes were written.
    fn write_zeroes(&mut self, length: usize) -> io::Result<usize>;
}

impl WriteZeroes for File {
    fn write_zeroes(&mut self, length: usize) -> io::Result<usize> {
        // Try to use fallocate(FALLOC_FL_PUNCH_HOLE) first.
        let offset = self.seek(SeekFrom::Current(0))?;
        match fallocate(self, FallocateMode::PunchHole, true, offset, length as u64) {
            Ok(()) => {
                // Advance the seek cursor as if we had done a real write().
                self.seek(SeekFrom::Current(length as i64))?;
                return Ok(length);
            }
            Err(_) => {} // fall back to write()
        }

        // fallocate() failed; fall back to writing a buffer of zeroes
        // until we have written up to length.
        let buf_size = min(length, 0x10000);
        let buf = vec![0u8; buf_size];
        let mut nwritten: usize = 0;
        while nwritten < length {
            let remaining = length - nwritten;
            let write_size = min(remaining, buf_size);
            nwritten += self.write(&buf[0..write_size])?;
        }
        Ok(length)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fs::OpenOptions;
    use std::io::{Read, Seek, SeekFrom};
    use std::path::PathBuf;

    use TempDir;

    #[test]
    fn simple_test() {
        let tempdir = TempDir::new("/tmp/write_zeroes_test").unwrap();
        let mut path = PathBuf::from(tempdir.as_path().unwrap());
        path.push("file");
        let mut f = OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(&path)
            .unwrap();
        f.set_len(16384).unwrap();

        // Write buffer of non-zero bytes to offset 1234
        let orig_data = [0x55u8; 5678];
        f.seek(SeekFrom::Start(1234)).unwrap();
        f.write(&orig_data).unwrap();

        // Read back the data plus some overlap on each side
        let mut readback = [0u8; 16384];
        f.seek(SeekFrom::Start(0)).unwrap();
        f.read(&mut readback).unwrap();
        // Bytes before the write should still be 0
        for read in readback[0..1234].iter() {
            assert_eq!(*read, 0);
        }
        // Bytes that were just written should be 0x55
        for read in readback[1234..(1234 + 5678)].iter() {
            assert_eq!(*read, 0x55);
        }
        // Bytes after the written area should still be 0
        for read in readback[(1234 + 5678)..].iter() {
            assert_eq!(*read, 0);
        }

        // Overwrite some of the data with zeroes
        f.seek(SeekFrom::Start(2345)).unwrap();
        f.write_zeroes(4321).expect("write_zeroes failed");
        // Verify seek position after write_zeroes()
        assert_eq!(f.seek(SeekFrom::Current(0)).unwrap(), 2345 + 4321);

        // Read back the data and verify that it is now zero
        f.seek(SeekFrom::Start(0)).unwrap();
        f.read(&mut readback).unwrap();
        // Bytes before the write should still be 0
        for read in readback[0..1234].iter() {
            assert_eq!(*read, 0);
        }
        // Original data should still exist before the write_zeroes region
        for read in readback[1234..2345].iter() {
            assert_eq!(*read, 0x55);
        }
        // The write_zeroes region should now be zero
        for read in readback[2345..(2345 + 4321)].iter() {
            assert_eq!(*read, 0);
        }
        // Original data should still exist after the write_zeroes region
        for read in readback[(2345 + 4321)..(1234 + 5678)].iter() {
            assert_eq!(*read, 0x55);
        }
        // The rest of the file should still be 0
        for read in readback[(1234 + 5678)..].iter() {
            assert_eq!(*read, 0);
        }
    }

    #[test]
    fn large_write_zeroes() {
        let tempdir = TempDir::new("/tmp/write_zeroes_test").unwrap();
        let mut path = PathBuf::from(tempdir.as_path().unwrap());
        path.push("file");
        let mut f = OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(&path)
            .unwrap();
        f.set_len(16384).unwrap();

        // Write buffer of non-zero bytes
        let orig_data = [0x55u8; 0x20000];
        f.seek(SeekFrom::Start(0)).unwrap();
        f.write(&orig_data).unwrap();

        // Overwrite some of the data with zeroes
        f.seek(SeekFrom::Start(0)).unwrap();
        f.write_zeroes(0x10001).expect("write_zeroes failed");
        // Verify seek position after write_zeroes()
        assert_eq!(f.seek(SeekFrom::Current(0)).unwrap(), 0x10001);

        // Read back the data and verify that it is now zero
        let mut readback = [0u8; 0x20000];
        f.seek(SeekFrom::Start(0)).unwrap();
        f.read(&mut readback).unwrap();
        // The write_zeroes region should now be zero
        for read in readback[0..0x10001].iter() {
            assert_eq!(*read, 0);
        }
        // Original data should still exist after the write_zeroes region
        for read in readback[0x10001..0x20000].iter() {
            assert_eq!(*read, 0x55);
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Simplify<commit_after><|endoftext|>


<commit_before>use bincode;
use serde;
use scoped_pool::Pool;
use std::fmt;
use std::io::{self, BufReader, BufWriter, Write};
use std::net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs};
use std::sync::{Condvar, Mutex};
use std::sync::mpsc::{Sender, TryRecvError, channel};
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;
use std::thread::{self, JoinHandle};
use super::{Packet, Result};

struct ConnectionHandler<'a, S>
    where S: Serve
{
    read_stream: BufReader<TcpStream>,
    write_stream: Mutex<BufWriter<TcpStream>>,
    shutdown: &'a AtomicBool,
    inflight_rpcs: &'a InflightRpcs,
    server: S,
    pool: &'a Pool,
}

impl<'a, S> Drop for ConnectionHandler<'a, S> where S: Serve {
    fn drop(&mut self) {
        trace!("ConnectionHandler: finished serving client.");
        self.inflight_rpcs.decrement_and_notify();
    }
}

impl<'a, S> ConnectionHandler<'a, S> where S: Serve {
    fn handle_conn(&mut self) -> Result<()> {
        let ConnectionHandler {
            ref mut read_stream,
            ref write_stream,
            shutdown,
            inflight_rpcs,
            ref server,
            pool,
        } = *self;
        trace!("ConnectionHandler: serving client...");
        pool.scoped(|scope| {
            loop {
                match bincode::serde::deserialize_from(read_stream, bincode::SizeLimit::Infinite) {
                    Ok(Packet { rpc_id, message, }) => {
                        inflight_rpcs.increment();
                        scope.execute(move || {
                            let reply = server.serve(message);
                            let reply_packet = Packet {
                                rpc_id: rpc_id,
                                message: reply
                            };
                            let mut write_stream = write_stream.lock().unwrap();
                            if let Err(e) =
                                   bincode::serde::serialize_into(&mut *write_stream,
                                                                  &reply_packet,
                                                                  bincode::SizeLimit::Infinite) {
                                warn!("ConnectionHandler: failed to write reply to Client: {:?}",
                                      e);
                            }
                            if let Err(e) = write_stream.flush() {
                                warn!("ConnectionHandler: failed to flush reply to Client: {:?}",
                                      e);
                            }
                            inflight_rpcs.decrement();
                        });
                        if shutdown.load(Ordering::SeqCst) {
                            info!("ConnectionHandler: server shutdown, so closing connection.");
                            break;
                        }
                    }
                    Err(bincode::serde::DeserializeError::IoError(ref err))
                        if Self::timed_out(err.kind()) => {
                        if !shutdown.load(Ordering::SeqCst) {
                            info!("ConnectionHandler: read timed out ({:?}). Server not \
                                   shutdown, so retrying read.",
                                  err);
                            continue;
                        } else {
                            info!("ConnectionHandler: read timed out ({:?}). Server shutdown, so \
                                   closing connection.",
                                  err);
                            break;
                        }
                    }
                    Err(e) => {
                        warn!("ConnectionHandler: closing client connection due to {:?}",
                              e);
                        return Err(e.into());
                    }
                }
            }
            Ok(())
        })
    }

    fn timed_out(error_kind: io::ErrorKind) -> bool {
        match error_kind {
            io::ErrorKind::TimedOut | io::ErrorKind::WouldBlock => true,
            _ => false,
        }
    }
}

struct InflightRpcs {
    count: Mutex<u64>,
    cvar: Condvar,
}

impl InflightRpcs {
    fn new() -> InflightRpcs {
        InflightRpcs {
            count: Mutex::new(0),
            cvar: Condvar::new(),
        }
    }

    fn wait_until_zero(&self) {
        let mut count = self.count.lock().unwrap();
        while *count != 0 {
            count = self.cvar.wait(count).unwrap();
        }
        info!("serve_async: shutdown complete ({} connections alive)",
              *count);
    }

    fn increment(&self) {
        *self.count.lock().unwrap() += 1;
    }

    fn decrement(&self) {
        *self.count.lock().unwrap() -= 1;
    }

    fn decrement_and_notify(&self) {
        *self.count.lock().unwrap() -= 1;
        self.cvar.notify_one();
    }

}

/// Provides methods for blocking until the server completes,
pub struct ServeHandle {
    tx: Sender<()>,
    join_handle: JoinHandle<()>,
    addr: SocketAddr,
}

impl ServeHandle {
    /// Block until the server completes
    pub fn wait(self) {
        self.join_handle.join().unwrap();
    }

    /// Returns the address the server is bound to
    pub fn local_addr(&self) -> &SocketAddr {
        &self.addr
    }

    /// Shutdown the server. Gracefully shuts down the serve thread but currently does not
    /// gracefully close open connections.
    pub fn shutdown(self) {
        info!("ServeHandle: attempting to shut down the server.");
        self.tx.send(()).unwrap();
        if let Ok(_) = TcpStream::connect(self.addr) {
            self.join_handle.join().unwrap();
        } else {
            warn!("ServeHandle: best effort shutdown of serve thread failed");
        }
    }
}

/// Start
pub fn serve_async<A, S>(addr: A,
                         server: S,
                         read_timeout: Option<Duration>)
                         -> io::Result<ServeHandle>
    where A: ToSocketAddrs,
          S: 'static + Serve
{
    let listener = try!(TcpListener::bind(&addr));
    let addr = try!(listener.local_addr());
    info!("serve_async: spinning up server on {:?}", addr);
    let (die_tx, die_rx) = channel();
    let join_handle = thread::spawn(move || {
        let pool = Pool::new(100); // TODO(tjk): make this configurable, and expire idle threads
        let shutdown = AtomicBool::new(false);
        let inflight_rpcs = InflightRpcs::new();
        pool.scoped(|scope| {
            for conn in listener.incoming() {
                match die_rx.try_recv() {
                    Ok(_) => {
                        info!("serve_async: shutdown received. Waiting for open connections to \
                               return...");
                        shutdown.store(true, Ordering::SeqCst);
                        inflight_rpcs.wait_until_zero();
                        break;
                    }
                    Err(TryRecvError::Disconnected) => {
                        info!("serve_async: sender disconnected.");
                        break;
                    }
                    _ => (),
                }
                let conn = match conn {
                    Err(err) => {
                        error!("serve_async: failed to accept connection: {:?}", err);
                        return;
                    }
                    Ok(c) => c,
                };
                if let Err(err) = conn.set_read_timeout(read_timeout) {
                    info!("Server: could not set read timeout: {:?}", err);
                    return;
                }
                inflight_rpcs.increment();
                scope.execute(|| {
                    let mut handler = ConnectionHandler {
                        read_stream: BufReader::new(conn.try_clone().unwrap()),
                        write_stream: Mutex::new(BufWriter::new(conn)),
                        shutdown: &shutdown,
                        inflight_rpcs: &inflight_rpcs,
                        server: &server,
                        pool: &pool,
                    };
                    if let Err(err) = handler.handle_conn() {
                        info!("ConnectionHandler: err in connection handling: {:?}", err);
                    }
                });
            }
        });
    });
    Ok(ServeHandle {
        tx: die_tx,
        join_handle: join_handle,
        addr: addr.clone(),
    })
}

/// A service provided by a server
pub trait Serve: Send + Sync {
    /// The type of request received by the server
    type Request: 'static + fmt::Debug + serde::ser::Serialize + serde::de::Deserialize + Send;
    /// The type of reply sent by the server
    type Reply:  'static + fmt::Debug + serde::ser::Serialize + serde::de::Deserialize;

    /// Return a reply for a given request
    fn serve(&self, request: Self::Request) -> Self::Reply;
}

impl<P, S> Serve for P
    where P: Send + Sync + ::std::ops::Deref<Target=S>,
          S: Serve
{
    type Request = S::Request;
    type Reply = S::Reply;

    fn serve(&self, request: S::Request) -> S::Reply {
        S::serve(self, request)
    }
}
<commit_msg>Server: use a writer thread for each open connection<commit_after>use bincode;
use serde;
use scoped_pool::Pool;
use std::fmt;
use std::io::{self, BufReader, BufWriter, Write};
use std::net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs};
use std::sync::{Condvar, Mutex};
use std::sync::mpsc::{Receiver, Sender, TryRecvError, channel};
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;
use std::thread::{self, JoinHandle};
use super::{Packet, Result};

struct ConnectionHandler<'a, S>
    where S: Serve
{
    read_stream: BufReader<TcpStream>,
    write_stream: BufWriter<TcpStream>,
    shutdown: &'a AtomicBool,
    inflight_rpcs: &'a InflightRpcs,
    server: S,
    pool: &'a Pool,
}

impl<'a, S> Drop for ConnectionHandler<'a, S> where S: Serve {
    fn drop(&mut self) {
        trace!("ConnectionHandler: finished serving client.");
        self.inflight_rpcs.decrement_and_notify();
    }
}

impl<'a, S> ConnectionHandler<'a, S> where S: Serve {
    fn handle_conn(&mut self) -> Result<()> {
        let ConnectionHandler {
            ref mut read_stream,
            ref mut write_stream,
            shutdown,
            ref inflight_rpcs,
            ref server,
            pool,
        } = *self;
        trace!("ConnectionHandler: serving client...");
        pool.scoped(|scope| {
            let (tx, rx) = channel();
            scope.execute(|| Self::write(rx, write_stream, inflight_rpcs));
            loop {
                match bincode::serde::deserialize_from(read_stream, bincode::SizeLimit::Infinite) {
                    Ok(Packet { rpc_id, message, }) => {
                        inflight_rpcs.increment();
                        let tx = tx.clone();
                        scope.execute(move || {
                            let reply = server.serve(message);
                            let reply_packet = Packet {
                                rpc_id: rpc_id,
                                message: reply
                            };
                            tx.send(reply_packet).unwrap();
                        });
                        if shutdown.load(Ordering::SeqCst) {
                            info!("ConnectionHandler: server shutdown, so closing connection.");
                            break;
                        }
                    }
                    Err(bincode::serde::DeserializeError::IoError(ref err))
                        if Self::timed_out(err.kind()) => {
                        if !shutdown.load(Ordering::SeqCst) {
                            info!("ConnectionHandler: read timed out ({:?}). Server not \
                                   shutdown, so retrying read.",
                                  err);
                            continue;
                        } else {
                            info!("ConnectionHandler: read timed out ({:?}). Server shutdown, so \
                                   closing connection.",
                                  err);
                            break;
                        }
                    }
                    Err(e) => {
                        warn!("ConnectionHandler: closing client connection due to {:?}",
                              e);
                        return Err(e.into());
                    }
                }
            }
            Ok(())
        })
    }

    fn timed_out(error_kind: io::ErrorKind) -> bool {
        match error_kind {
            io::ErrorKind::TimedOut | io::ErrorKind::WouldBlock => true,
            _ => false,
        }
    }

    fn write(rx: Receiver<Packet<<S as Serve>::Reply>>,
             stream: &mut BufWriter<TcpStream>,
             inflight_rpcs: &InflightRpcs) {
        loop {
            match rx.recv() {
                Err(e) => {
                    debug!("Write thread: returning due to {:?}", e);
                    return;
                }
                Ok(reply_packet) => {
                    if let Err(e) =
                           bincode::serde::serialize_into(stream,
                                                          &reply_packet,
                                                          bincode::SizeLimit::Infinite) {
                        warn!("Writer: failed to write reply to Client: {:?}",
                              e);
                    }
                    if let Err(e) = stream.flush() {
                        warn!("Writer: failed to flush reply to Client: {:?}",
                              e);
                    }
                    inflight_rpcs.decrement();
                }
            }
        }
    }
}

struct InflightRpcs {
    count: Mutex<u64>,
    cvar: Condvar,
}

impl InflightRpcs {
    fn new() -> InflightRpcs {
        InflightRpcs {
            count: Mutex::new(0),
            cvar: Condvar::new(),
        }
    }

    fn wait_until_zero(&self) {
        let mut count = self.count.lock().unwrap();
        while *count != 0 {
            count = self.cvar.wait(count).unwrap();
        }
        info!("serve_async: shutdown complete ({} connections alive)",
              *count);
    }

    fn increment(&self) {
        *self.count.lock().unwrap() += 1;
    }

    fn decrement(&self) {
        *self.count.lock().unwrap() -= 1;
    }

    fn decrement_and_notify(&self) {
        *self.count.lock().unwrap() -= 1;
        self.cvar.notify_one();
    }

}

/// Provides methods for blocking until the server completes,
pub struct ServeHandle {
    tx: Sender<()>,
    join_handle: JoinHandle<()>,
    addr: SocketAddr,
}

impl ServeHandle {
    /// Block until the server completes
    pub fn wait(self) {
        self.join_handle.join().unwrap();
    }

    /// Returns the address the server is bound to
    pub fn local_addr(&self) -> &SocketAddr {
        &self.addr
    }

    /// Shutdown the server. Gracefully shuts down the serve thread but currently does not
    /// gracefully close open connections.
    pub fn shutdown(self) {
        info!("ServeHandle: attempting to shut down the server.");
        self.tx.send(()).unwrap();
        if let Ok(_) = TcpStream::connect(self.addr) {
            self.join_handle.join().unwrap();
        } else {
            warn!("ServeHandle: best effort shutdown of serve thread failed");
        }
    }
}

/// Start
pub fn serve_async<A, S>(addr: A,
                         server: S,
                         read_timeout: Option<Duration>)
                         -> io::Result<ServeHandle>
    where A: ToSocketAddrs,
          S: 'static + Serve
{
    let listener = try!(TcpListener::bind(&addr));
    let addr = try!(listener.local_addr());
    info!("serve_async: spinning up server on {:?}", addr);
    let (die_tx, die_rx) = channel();
    let join_handle = thread::spawn(move || {
        let pool = Pool::new(100); // TODO(tjk): make this configurable, and expire idle threads
        let shutdown = AtomicBool::new(false);
        let inflight_rpcs = InflightRpcs::new();
        pool.scoped(|scope| {
            for conn in listener.incoming() {
                match die_rx.try_recv() {
                    Ok(_) => {
                        info!("serve_async: shutdown received. Waiting for open connections to \
                               return...");
                        shutdown.store(true, Ordering::SeqCst);
                        inflight_rpcs.wait_until_zero();
                        break;
                    }
                    Err(TryRecvError::Disconnected) => {
                        info!("serve_async: sender disconnected.");
                        break;
                    }
                    _ => (),
                }
                let conn = match conn {
                    Err(err) => {
                        error!("serve_async: failed to accept connection: {:?}", err);
                        return;
                    }
                    Ok(c) => c,
                };
                if let Err(err) = conn.set_read_timeout(read_timeout) {
                    info!("Server: could not set read timeout: {:?}", err);
                    return;
                }
                inflight_rpcs.increment();
                scope.execute(|| {
                    let mut handler = ConnectionHandler {
                        read_stream: BufReader::new(conn.try_clone().unwrap()),
                        write_stream: BufWriter::new(conn),
                        shutdown: &shutdown,
                        inflight_rpcs: &inflight_rpcs,
                        server: &server,
                        pool: &pool,
                    };
                    if let Err(err) = handler.handle_conn() {
                        info!("ConnectionHandler: err in connection handling: {:?}", err);
                    }
                });
            }
        });
    });
    Ok(ServeHandle {
        tx: die_tx,
        join_handle: join_handle,
        addr: addr.clone(),
    })
}

/// A service provided by a server
pub trait Serve: Send + Sync {
    /// The type of request received by the server
    type Request: 'static + fmt::Debug + serde::ser::Serialize + serde::de::Deserialize + Send;
    /// The type of reply sent by the server
    type Reply  : 'static + fmt::Debug + serde::ser::Serialize + serde::de::Deserialize + Send;

    /// Return a reply for a given request
    fn serve(&self, request: Self::Request) -> Self::Reply;
}

impl<P, S> Serve for P
    where P: Send + Sync + ::std::ops::Deref<Target=S>,
          S: Serve
{
    type Request = S::Request;
    type Reply = S::Reply;

    fn serve(&self, request: S::Request) -> S::Reply {
        S::serve(self, request)
    }
}
<|endoftext|>