<commit_before>//! Types around a convolution, see also https://en.wikipedia.org/wiki/Convolution.
//!
//! Convolutions in this library can be defined in time or frequency domain. In
//! frequency domain the convolution is automatically transformed into a multiplication
//! which is the analog operation to a convolution in time domain.
use RealNumber;
use num::traits::Zero;
use num::complex::{Complex, Complex32,Complex64};

/// The domain of a convolution.
/// Convolutions in this library can be defined in time or frequency domain. In
/// frequency domain the convolution is automatically transformed into a multiplication
/// which is the analog operation to a convolution in time domain.
#[derive(Copy)]
#[derive(Clone)]
#[derive(PartialEq)]
#[derive(Debug)]
pub enum ConvDomain {
	/// Time domain, the x-axis is in [s]
	Time,
	/// Frequency domain, the x-axis in in [Hz]
    Frequency
}

/// Meta information about the convolution.
pub trait ConvInfo {
    fn domain(&self) -> ConvDomain;
}

/// A convolution function in time domain and real number space
pub trait RealTimeConvFunction<T> : ConvInfo
    where T: RealNumber {
    fn calc(&self, x: T) -> T;
}

/// A convolution function in time domain and complex number space
pub trait ComplexTimeConvFunction<T> : ConvInfo
    where T: RealNumber {
    fn calc(&self, x: T) -> Complex<T>;
}

/// A convolution function in frequency domain and complex number space
pub trait ComplexFrequencyConvFunction<T> : ConvInfo
    where T: RealNumber {
    fn calc(&self, x: T) -> Complex<T>;
}

/// Allows to create a lookup table with linear interpolation between table points.
/// This usually speeds up a convolution and sacrifies accuracy.
pub struct RealTimeLinearTableLookup<T>
    where T: RealNumber {
    table: Vec<T>,
    domain: ConvDomain,
    delta: T,
    offset: T
}

/// Allows to create a lookup table with linear interpolation between table points.
/// This usually speeds up a convolution and sacrifies accuracy.
pub struct ComplexTimeLinearTableLookup<T>
    where T: RealNumber {
    table: Vec<Complex<T>>,
    domain: ConvDomain,
    delta: T,
    offset: T
}

/// Allows to create a lookup table with linear interpolation between table points.
/// This usually speeds up a convolution and sacrifies accuracy.
pub struct ComplexFrequencyLinearTableLookup<T>
    where T: RealNumber {
    table: Vec<Complex<T>>,
    domain: ConvDomain,
    delta: T,
    offset: T
}

macro_rules! add_linear_table_lookup_impl {
    ($($name: ident: $conv_type: ident, $($data_type: ident, $result_type:ident),*);*) => {
        $(
            $(
                impl ConvInfo for $name<$data_type> {
                    fn domain(&self) -> ConvDomain {
                        self.domain
                    }
                }

                impl $conv_type<$data_type> for $name<$data_type> {
                    fn calc(&self, x: $data_type) -> $result_type {
                        let len = self.table.len();
                        let center = len / 2;
                        let center_float = center as $data_type;
                        let x = x / self.delta - self.offset + center_float;
                        let round_float = x.round();
                        let round = round_float as usize;
                        if round >= len {
                            return $result_type::zero();
                        }

                        let round_tolerance = 1e-6;
                        if (x - round_float).abs() < round_tolerance {
                            return self.table[round];
                        }

                        if x > round_float {
                            let other = round + 1;
                            if other >= len {
                                return self.table[round];
                            }
                            let y0 = self.table[round];
                            let x0 = round_float;
                            let y1 = self.table[other];
                            return y0 + (y1 - y0) * (x - x0);
                        } else {
                            if round == 0 {
                                return self.table[round];
                            }
                            let other = round - 1;
                            let y0 = self.table[round];
                            let x0 = round_float;
                            let y1 = self.table[other];
                            return y0 + (y1 - y0) * (x0 - x);
                        }
                    }
                }

                impl $name<$data_type> {
                    pub fn from_raw_parts(table: &[$result_type], domain: ConvDomain, delta: $data_type, offset: $data_type) -> Self {
                        let owned_table = Vec::from(table);
                        $name { table: owned_table, domain: domain, delta: delta, offset: offset }
                    }

                    pub fn from_conv_function(other: &$conv_type<$data_type>, delta: $data_type, offset: $data_type, len: usize) -> Self {
                        let center = (len / 2) as isize;
                        let mut table = vec![$result_type::zero(); len];
                        let mut i = -center;
                        for n in &mut table {
                            *n = other.calc((i as $data_type) * delta);
                            i += 1;
                        }
                        $name { table: table, domain: other.domain(), delta: delta, offset: offset }
                    }
                }
            )*
        )*
    }
}
add_linear_table_lookup_impl!(
    RealTimeLinearTableLookup: RealTimeConvFunction, f32, f32, f64, f64;
    ComplexTimeLinearTableLookup: ComplexTimeConvFunction, f32, Complex32, f64, Complex64;
    ComplexFrequencyLinearTableLookup: ComplexFrequencyConvFunction, f32, Complex32, f64, Complex64);

/// Raised cosine function according to https://en.wikipedia.org/wiki/Raised-cosine_filter
pub struct  RaiseCosineFuncton<T>
    where T: RealNumber {
    rolloff: T
}

impl<T> ConvInfo for RaiseCosineFuncton<T>
    where T: RealNumber {
    fn domain(&self) -> ConvDomain {
        ConvDomain::Time
    }
}

impl<T> RealTimeConvFunction<T> for RaiseCosineFuncton<T>
    where T: RealNumber {
    fn calc(&self, x: T) -> T {
        if x == T::zero() {
            return T::one();
        }

        let one = T::one();
        let two = T::from(2.0).unwrap();
        let pi = two * one.asin();
        let four = two * two;
        if x.abs() == one / (two * self.rolloff) {
            let arg = pi / two / self.rolloff;
            return (arg).sin() / arg * pi / four;
        }

        let pi_x = pi * x;
        let arg = two * self.rolloff * x;
        return pi_x.sin() * (pi_x * self.rolloff).cos() / pi_x / (one - (arg * arg))
    }
}

impl<T> RaiseCosineFuncton<T>
    where T: RealNumber {
    pub fn new(rolloff: T) -> Self {
        RaiseCosineFuncton { rolloff: rolloff }
    }
}

#[cfg(test)]
mod tests {
	use super::*;
    use super::super::RealNumber;
    use std::fmt::Debug;

    fn conv_test<T, C>(conv: C, expected: &[T], step: T, tolerance: T)
        where T: RealNumber + Debug,
              C: RealTimeConvFunction<T> {
        let mut result = vec![T::zero(); expected.len()];
        let mut j = -(expected.len() as isize / 2);
        for i in 0..result.len() {
            result[i] = conv.calc(T::from(j).unwrap() * step);
            j += 1;
        }

        for i in 0..result.len() {
            if (result[i] - expected[i]).abs() > tolerance {
                panic!("assertion failed: {:?} != {:?}", result, expected);
            }
        }
    }

	#[test]
	fn raised_cosine32_test()
	{
        let window = RaiseCosineFuncton::new(0.35);
        let expected =
            [0.0, 0.2171850639713355, 0.4840621929215732, 0.7430526238101408, 0.9312114164253432,
             1.0, 0.9312114164253432, 0.7430526238101408, 0.4840621929215732, 0.2171850639713355];
        conv_test(window, &expected, 0.2, 1e-4);
	}

    #[test]
    fn lookup_table32_test() {
        let window = RaiseCosineFuncton::new(0.35);
        let table = RealTimeLinearTableLookup::<f64>::from_conv_function(&window, 0.2, 0.0, 10);
        let expected =
            [0.0, 0.2171850639713355, 0.4840621929215732, 0.7430526238101408, 0.9312114164253432,
             1.0, 0.9312114164253432, 0.7430526238101408, 0.4840621929215732, 0.2171850639713355];
        conv_test(table, &expected, 0.2, 1e-4);
    }

    #[test]
    fn linear_interpolation_lookup_table32_test() {
        let window = RaiseCosineFuncton::new(0.35);
        let table = RealTimeLinearTableLookup::<f64>::from_conv_function(&window, 0.4, 0.0, 10);
        let expected =
            [0.0, 0.2171850639713355, 0.4840621929215732, 0.7430526238101408, 0.9312114164253432,
             1.0, 0.9312114164253432, 0.7430526238101408, 0.4840621929215732, 0.2171850639713355];
        conv_test(table, &expected, 0.2, 0.1);
    }
}<commit_msg>Removed ConfInfo trait and will likely deal with domains and number spaces completely by using types<commit_after>//! Types around a convolution, see also https://en.wikipedia.org/wiki/Convolution.
//!
//! Convolutions in this library can be defined in time or frequency domain. In
//! frequency domain the convolution is automatically transformed into a multiplication
//! which is the analog operation to a convolution in time domain.
use RealNumber;
use num::traits::Zero;
use num::complex::{Complex, Complex32,Complex64};

/// A convolution function in time domain and real number space
pub trait RealTimeConvFunction<T>
    where T: RealNumber {
    fn calc(&self, x: T) -> T;
}

/// A convolution function in time domain and complex number space
pub trait ComplexTimeConvFunction<T>
    where T: RealNumber {
    fn calc(&self, x: T) -> Complex<T>;
}

/// A convolution function in frequency domain and complex number space
pub trait ComplexFrequencyConvFunction<T>
    where T: RealNumber {
    fn calc(&self, x: T) -> Complex<T>;
}

/// Allows to create a lookup table with linear interpolation between table points.
/// This usually speeds up a convolution and sacrifies accuracy.
pub struct RealTimeLinearTableLookup<T>
    where T: RealNumber {
    table: Vec<T>,
    delta: T,
    offset: T
}

/// Allows to create a lookup table with linear interpolation between table points.
/// This usually speeds up a convolution and sacrifies accuracy.
pub struct ComplexTimeLinearTableLookup<T>
    where T: RealNumber {
    table: Vec<Complex<T>>,
    delta: T,
    offset: T
}

/// Allows to create a lookup table with linear interpolation between table points.
/// This usually speeds up a convolution and sacrifies accuracy.
pub struct ComplexFrequencyLinearTableLookup<T>
    where T: RealNumber {
    table: Vec<Complex<T>>,
    delta: T,
    offset: T
}

macro_rules! add_linear_table_lookup_impl {
    ($($name: ident: $conv_type: ident, $($data_type: ident, $result_type:ident),*);*) => {
        $(
            $(
                impl $conv_type<$data_type> for $name<$data_type> {
                    fn calc(&self, x: $data_type) -> $result_type {
                        let len = self.table.len();
                        let center = len / 2;
                        let center_float = center as $data_type;
                        let x = x / self.delta - self.offset + center_float;
                        let round_float = x.round();
                        let round = round_float as usize;
                        if round >= len {
                            return $result_type::zero();
                        }

                        let round_tolerance = 1e-6;
                        if (x - round_float).abs() < round_tolerance {
                            return self.table[round];
                        }

                        if x > round_float {
                            let other = round + 1;
                            if other >= len {
                                return self.table[round];
                            }
                            let y0 = self.table[round];
                            let x0 = round_float;
                            let y1 = self.table[other];
                            return y0 + (y1 - y0) * (x - x0);
                        } else {
                            if round == 0 {
                                return self.table[round];
                            }
                            let other = round - 1;
                            let y0 = self.table[round];
                            let x0 = round_float;
                            let y1 = self.table[other];
                            return y0 + (y1 - y0) * (x0 - x);
                        }
                    }
                }

                impl $name<$data_type> {
                    pub fn from_raw_parts(table: &[$result_type], delta: $data_type, offset: $data_type) -> Self {
                        let owned_table = Vec::from(table);
                        $name { table: owned_table, delta: delta, offset: offset }
                    }

                    pub fn from_conv_function(other: &$conv_type<$data_type>, delta: $data_type, offset: $data_type, len: usize) -> Self {
                        let center = (len / 2) as isize;
                        let mut table = vec![$result_type::zero(); len];
                        let mut i = -center;
                        for n in &mut table {
                            *n = other.calc((i as $data_type) * delta);
                            i += 1;
                        }
                        $name { table: table, delta: delta, offset: offset }
                    }
                }
            )*
        )*
    }
}
add_linear_table_lookup_impl!(
    RealTimeLinearTableLookup: RealTimeConvFunction, f32, f32, f64, f64;
    ComplexTimeLinearTableLookup: ComplexTimeConvFunction, f32, Complex32, f64, Complex64;
    ComplexFrequencyLinearTableLookup: ComplexFrequencyConvFunction, f32, Complex32, f64, Complex64);

/// Raised cosine function according to https://en.wikipedia.org/wiki/Raised-cosine_filter
pub struct  RaiseCosineFuncton<T>
    where T: RealNumber {
    rolloff: T
}

impl<T> RealTimeConvFunction<T> for RaiseCosineFuncton<T>
    where T: RealNumber {
    fn calc(&self, x: T) -> T {
        if x == T::zero() {
            return T::one();
        }

        let one = T::one();
        let two = T::from(2.0).unwrap();
        let pi = two * one.asin();
        let four = two * two;
        if x.abs() == one / (two * self.rolloff) {
            let arg = pi / two / self.rolloff;
            return (arg).sin() / arg * pi / four;
        }

        let pi_x = pi * x;
        let arg = two * self.rolloff * x;
        return pi_x.sin() * (pi_x * self.rolloff).cos() / pi_x / (one - (arg * arg))
    }
}

impl<T> RaiseCosineFuncton<T>
    where T: RealNumber {
    pub fn new(rolloff: T) -> Self {
        RaiseCosineFuncton { rolloff: rolloff }
    }
}

#[cfg(test)]
mod tests {
	use super::*;
    use super::super::RealNumber;
    use std::fmt::Debug;

    fn conv_test<T, C>(conv: C, expected: &[T], step: T, tolerance: T)
        where T: RealNumber + Debug,
              C: RealTimeConvFunction<T> {
        let mut result = vec![T::zero(); expected.len()];
        let mut j = -(expected.len() as isize / 2);
        for i in 0..result.len() {
            result[i] = conv.calc(T::from(j).unwrap() * step);
            j += 1;
        }

        for i in 0..result.len() {
            if (result[i] - expected[i]).abs() > tolerance {
                panic!("assertion failed: {:?} != {:?}", result, expected);
            }
        }
    }

	#[test]
	fn raised_cosine32_test()
	{
        let window = RaiseCosineFuncton::new(0.35);
        let expected =
            [0.0, 0.2171850639713355, 0.4840621929215732, 0.7430526238101408, 0.9312114164253432,
             1.0, 0.9312114164253432, 0.7430526238101408, 0.4840621929215732, 0.2171850639713355];
        conv_test(window, &expected, 0.2, 1e-4);
	}

    #[test]
    fn lookup_table32_test() {
        let window = RaiseCosineFuncton::new(0.35);
        let table = RealTimeLinearTableLookup::<f64>::from_conv_function(&window, 0.2, 0.0, 10);
        let expected =
            [0.0, 0.2171850639713355, 0.4840621929215732, 0.7430526238101408, 0.9312114164253432,
             1.0, 0.9312114164253432, 0.7430526238101408, 0.4840621929215732, 0.2171850639713355];
        conv_test(table, &expected, 0.2, 1e-4);
    }

    #[test]
    fn linear_interpolation_lookup_table32_test() {
        let window = RaiseCosineFuncton::new(0.35);
        let table = RealTimeLinearTableLookup::<f64>::from_conv_function(&window, 0.4, 0.0, 10);
        let expected =
            [0.0, 0.2171850639713355, 0.4840621929215732, 0.7430526238101408, 0.9312114164253432,
             1.0, 0.9312114164253432, 0.7430526238101408, 0.4840621929215732, 0.2171850639713355];
        conv_test(table, &expected, 0.2, 0.1);
    }
}<|endoftext|>


<commit_before>//! A zero-capacity channel.
//!
//! This kind of channel also known as *rendezvous* channel.

use std::marker::PhantomData;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Instant;

use parking_lot::Mutex;

use internal::channel::RecvNonblocking;
use internal::context;
use internal::select::{CaseId, Select, Token};
use internal::utils::Backoff;
use internal::waker::Waker;

// TODO: anything that calls read/write in any flavor should have an abort guard

/// Result of a receive operation.
pub type ZeroToken = Option<usize>;

/// TODO
struct Packet<T> {
    on_stack: bool,
    ready: AtomicBool,
    msg: Mutex<Option<T>>,
}

/// Inner representation of a zero-capacity channel.
struct Inner {
    /// Senders waiting to pair up with a receive operation.
    senders: Waker,

    /// Receivers waiting to pair up with a send operation.
    receivers: Waker,

    /// Equals `true` when the channel is closed.
    is_closed: bool,
}

/// A zero-capacity channel.
pub struct Channel<T> {
    /// Inner representation of the channel.
    inner: Mutex<Inner>,

    /// Indicates that dropping a `Channel<T>` may drop values of type `T`.
    _marker: PhantomData<T>,
}

impl<T> Channel<T> {
    /// Constructs a new zero-capacity channel.
    pub fn new() -> Self {
        Channel {
            inner: Mutex::new(Inner {
                senders: Waker::new(),
                receivers: Waker::new(),
                is_closed: false,
            }),
            _marker: PhantomData,
        }
    }

    /// Returns a receiver handle to the channel.
    pub fn receiver(&self) -> Receiver<T> {
        Receiver(self)
    }

    /// Returns a sender handle to the channel.
    pub fn sender(&self) -> Sender<T> {
        Sender(self)
    }

    /// Attempts to reserve a slot for sending a message.
    fn start_send(&self, token: &mut Token) -> bool {
        let mut inner = self.inner.lock();

        // If there's someone on the other side, exchange message with it.
        if let Some(case) = inner.receivers.wake_one() {
            token.zero = Some(case.packet);
            true
        } else {
            false
        }
    }

    /// TODO
    pub unsafe fn write(&self, token: &mut Token, msg: T) {
        let packet = token.zero.unwrap() as *const Packet<T>;

        *(*packet).msg.lock() = Some(msg);
        (*packet).ready.store(true, Ordering::Release);
    }

    /// TODO
    fn start_recv(&self, token: &mut Token) -> bool {
        let mut inner = self.inner.lock();

        if let Some(case) = inner.senders.wake_one() {
            token.zero = Some(case.packet);
            true
        } else if inner.is_closed {
            token.zero = None;
            true
        } else {
            false
        }
    }

    /// TODO
    pub unsafe fn read(&self, token: &mut Token) -> Option<T> {
        let packet;

        match token.zero {
            None => return None,
            Some(p) => {
                packet = p as *const Packet<T>;
            }
        }

        if (*packet).on_stack {
            let msg = (*packet).msg.lock().take();
            (*packet).ready.store(true, Ordering::Release);
            msg
        } else {
            let mut backoff = Backoff::new();
            while !(*packet).ready.load(Ordering::Acquire) {
                backoff.step();
            }
            let msg = (*packet).msg.lock().take();
            drop(Box::from_raw(packet as *mut Packet<T>));
            msg
        }
    }

    pub fn send(&self, mut msg: T) {
        let token = &mut Token::default();
        let case_id = CaseId::new(token as *mut Token as usize);

        loop {
            let packet;
            {
                let mut inner = self.inner.lock();
                // If there's someone on the other side, exchange message with it.
                if let Some(case) = inner.receivers.wake_one() {
                    token.zero = Some(case.packet);
                    drop(inner);
                    unsafe { self.write(token, msg); }
                    break;
                }

                context::current_reset();

                packet = Packet {
                    on_stack: true,
                    ready: AtomicBool::new(false),
                    msg: Mutex::new(Some(msg)),
                };
                inner.senders.register_with_packet(case_id, &packet as *const _ as usize);
            }

            context::current_wait_until(None);

            let s = context::current_selected();
            if s == case_id {
                let mut backoff = Backoff::new();
                while !packet.ready.load(Ordering::Acquire) {
                    backoff.step();
                }
                break;
            } else {
                self.inner.lock().senders.unregister(case_id);
                msg = packet.msg.into_inner().unwrap();
            }
        }
    }

    pub fn recv(&self) -> Option<T> {
        let token = &mut Token::default();
        let case_id = CaseId::new(token as *mut Token as usize);

        loop {
            let packet;
            {
                let mut inner = self.inner.lock();

                if let Some(case) = inner.senders.wake_one() {
                    token.zero = Some(case.packet);
                    drop(inner);
                    unsafe {
                        return self.read(token);
                    }
                }

                if inner.is_closed {
                    return None;
                }

                context::current_reset();

                packet = Packet {
                    on_stack: true,
                    ready: AtomicBool::new(false),
                    msg: Mutex::new(None::<T>),
                };
                inner.receivers.register_with_packet(case_id, &packet as *const _ as usize);
            }

            context::current_wait_until(None);

            let s = context::current_selected();
            if s == case_id {
                let mut backoff = Backoff::new();
                while !packet.ready.load(Ordering::Acquire) {
                    backoff.step();
                }
                return Some(packet.msg.into_inner().unwrap());
            } else {
                self.inner.lock().receivers.unregister(case_id);
            }
        }
    }

    pub fn recv_nonblocking(&self) -> RecvNonblocking<T> {
        let token = &mut Token::default();

        let mut inner = self.inner.lock();

        if let Some(case) = inner.senders.wake_one() {
            token.zero = Some(case.packet);
            drop(inner);

            match unsafe { self.read(token) } {
                None => RecvNonblocking::Closed,
                Some(msg) => RecvNonblocking::Message(msg),
            }
        } else if inner.is_closed {
            RecvNonblocking::Closed
        } else {
            RecvNonblocking::Empty
        }
    }

    /// Closes the channel and wakes up all currently blocked operations on it.
    pub fn close(&self) -> bool {
        let mut inner = self.inner.lock();

        if inner.is_closed {
            false
        } else {
            inner.is_closed = true;
            inner.receivers.abort_all();
            true
        }
    }

    /// Returns the current number of messages inside the channel.
    pub fn len(&self) -> usize {
        0
    }

    /// Returns the capacity of the channel.
    pub fn capacity(&self) -> Option<usize> {
        Some(0)
    }

    /// Returns `true` if the channel is empty.
    pub fn is_empty(&self) -> bool {
        true
    }

    /// Returns `true` if the channel is full.
    pub fn is_full(&self) -> bool {
        true
    }
}

/// A receiver handle to a channel.
pub struct Receiver<'a, T: 'a>(&'a Channel<T>);

/// A sender handle to a channel.
pub struct Sender<'a, T: 'a>(&'a Channel<T>);

impl<'a, T> Select for Receiver<'a, T> {
    fn try(&self, token: &mut Token) -> bool {
        self.0.start_recv(token)
    }

    fn retry(&self, token: &mut Token) -> bool {
        // self.0.start_recv(token)

        let case_id = CaseId::new(&token as *const _ as usize);
        let mut inner = self.0.inner.lock();

        if let Some(case) = inner.senders.wake_one() {
            token.zero = Some(case.packet);
            return true;
        } else if inner.is_closed {
            token.zero = None;
            return true;
        }

        context::current_reset();

        let packet = Box::into_raw(Box::new(Packet {
            on_stack: false,
            ready: AtomicBool::new(false),
            msg: Mutex::new(None::<T>),
        }));
        inner.receivers.register_with_packet(case_id, packet as usize);

        drop(inner);

        thread::yield_now();
        context::current_try_abort();

        if context::current_selected() != CaseId::abort() {
            token.zero = Some(context::current_wait_packet());
            true
        } else {
            if let Some(case) = self.0.inner.lock().receivers.unregister(case_id) {
                unsafe {
                    drop(Box::from_raw(case.packet as *mut Packet<T>));
                }
            }
            false
        }
    }

    fn deadline(&self) -> Option<Instant> {
        None
    }

    fn register(&self, _token: &mut Token, case_id: CaseId) -> bool {
        let packet = Box::into_raw(Box::new(Packet {
            on_stack: false,
            ready: AtomicBool::new(false),
            msg: Mutex::new(None::<T>),
        }));

        let mut inner = self.0.inner.lock();
        inner.receivers.register_with_packet(case_id, packet as usize);
        !inner.senders.can_notify() && !inner.is_closed
    }

    fn unregister(&self, case_id: CaseId) {
        if let Some(case) = self.0.inner.lock().receivers.unregister(case_id) {
            unsafe {
                drop(Box::from_raw(case.packet as *mut Packet<T>));
            }
        }
    }

    fn accept(&self, token: &mut Token) -> bool {
        token.zero = Some(context::current_wait_packet());
        true
    }
}

impl<'a, T> Select for Sender<'a, T> {
    fn try(&self, token: &mut Token) -> bool {
        self.0.start_send(token)
    }

    fn retry(&self, token: &mut Token) -> bool {
        // self.0.start_send(token)

        let case_id = CaseId::new(&token as *const _ as usize);
        let mut inner = self.0.inner.lock();

        // If there's someone on the other side, exchange message with it.
        if let Some(case) = inner.receivers.wake_one() {
            token.zero = Some(case.packet);
            return true;
        }

        context::current_reset();

        let packet = Box::into_raw(Box::new(Packet {
            on_stack: false,
            ready: AtomicBool::new(false),
            msg: Mutex::new(None::<T>),
        }));
        inner.senders.register_with_packet(case_id, packet as usize);

        drop(inner);

        thread::yield_now();
        context::current_try_abort();

        if context::current_selected() != CaseId::abort() {
            token.zero = Some(context::current_wait_packet());
            true
        } else {
            if let Some(case) = self.0.inner.lock().senders.unregister(case_id) {
                unsafe {
                    drop(Box::from_raw(case.packet as *mut Packet<T>));
                }
            }
            false
        }
    }

    fn deadline(&self) -> Option<Instant> {
        None
    }

    fn register(&self, _token: &mut Token, case_id: CaseId) -> bool {
        let packet = Box::into_raw(Box::new(Packet {
            on_stack: false,
            ready: AtomicBool::new(false),
            msg: Mutex::new(None::<T>),
        }));

        let mut inner = self.0.inner.lock();
        inner.senders.register_with_packet(case_id, packet as usize);
        !inner.receivers.can_notify()
    }

    fn unregister(&self, case_id: CaseId) {
        if let Some(case) = self.0.inner.lock().senders.unregister(case_id) {
            unsafe {
                drop(Box::from_raw(case.packet as *mut Packet<T>));
            }
        }
    }

    fn accept(&self, token: &mut Token) -> bool {
        token.zero = Some(context::current_wait_packet());
        true
    }
}
<commit_msg>Optimize zero-capacity flavor<commit_after>//! A zero-capacity channel.
//!
//! This kind of channel also known as *rendezvous* channel.

use std::cell::UnsafeCell;
use std::marker::PhantomData;
use std::mem::{self, ManuallyDrop};
use std::ptr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Instant;

use parking_lot::Mutex;

use internal::channel::RecvNonblocking;
use internal::context;
use internal::select::{CaseId, Select, Token};
use internal::utils::Backoff;
use internal::waker::Waker;

// TODO: anything that calls read/write in any flavor should have an abort guard

/// Result of a receive operation.
pub type ZeroToken = Option<usize>;

/// TODO
struct Packet<T> {
    on_stack: bool,
    ready: AtomicBool,
    msg: ManuallyDrop<UnsafeCell<T>>,
}

/// Inner representation of a zero-capacity channel.
struct Inner {
    /// Senders waiting to pair up with a receive operation.
    senders: Waker,

    /// Receivers waiting to pair up with a send operation.
    receivers: Waker,

    /// Equals `true` when the channel is closed.
    is_closed: bool,
}

/// A zero-capacity channel.
pub struct Channel<T> {
    /// Inner representation of the channel.
    inner: Mutex<Inner>,

    /// Indicates that dropping a `Channel<T>` may drop values of type `T`.
    _marker: PhantomData<T>,
}

impl<T> Channel<T> {
    /// Constructs a new zero-capacity channel.
    pub fn new() -> Self {
        Channel {
            inner: Mutex::new(Inner {
                senders: Waker::new(),
                receivers: Waker::new(),
                is_closed: false,
            }),
            _marker: PhantomData,
        }
    }

    /// Returns a receiver handle to the channel.
    pub fn receiver(&self) -> Receiver<T> {
        Receiver(self)
    }

    /// Returns a sender handle to the channel.
    pub fn sender(&self) -> Sender<T> {
        Sender(self)
    }

    /// Attempts to reserve a slot for sending a message.
    fn start_send(&self, token: &mut Token) -> bool {
        let mut inner = self.inner.lock();

        // If there's someone on the other side, exchange message with it.
        if let Some(case) = inner.receivers.wake_one() {
            token.zero = Some(case.packet);
            true
        } else {
            false
        }
    }

    /// TODO
    pub unsafe fn write(&self, token: &mut Token, msg: T) {
        let packet = token.zero.unwrap() as *const Packet<T>;

        ptr::write((*packet).msg.get(), msg);
        (*packet).ready.store(true, Ordering::Release);
    }

    /// TODO
    fn start_recv(&self, token: &mut Token) -> bool {
        let mut inner = self.inner.lock();

        if let Some(case) = inner.senders.wake_one() {
            token.zero = Some(case.packet);
            true
        } else if inner.is_closed {
            token.zero = None;
            true
        } else {
            false
        }
    }

    /// TODO
    pub unsafe fn read(&self, token: &mut Token) -> Option<T> {
        let packet;

        match token.zero {
            None => return None,
            Some(p) => {
                packet = p as *const Packet<T>;
            }
        }

        if (*packet).on_stack {
            let msg = ptr::read((*packet).msg.get());
            (*packet).ready.store(true, Ordering::Release);
            Some(msg)
        } else {
            let mut backoff = Backoff::new();
            while !(*packet).ready.load(Ordering::Acquire) {
                backoff.step();
            }
            let msg = ptr::read((*packet).msg.get());
            drop(Box::from_raw(packet as *mut Packet<T>));
            Some(msg)
        }
    }

    pub fn send(&self, mut msg: T) {
        let token = &mut Token::default();
        let case_id = CaseId::new(token as *mut Token as usize);

        loop {
            let packet;
            {
                let mut inner = self.inner.lock();
                // If there's someone on the other side, exchange message with it.
                if let Some(case) = inner.receivers.wake_one() {
                    token.zero = Some(case.packet);
                    drop(inner);
                    unsafe { self.write(token, msg); }
                    break;
                }

                context::current_reset();

                packet = Packet {
                    on_stack: true,
                    ready: AtomicBool::new(false),
                    msg: ManuallyDrop::new(UnsafeCell::new(msg)),
                };
                inner.senders.register_with_packet(case_id, &packet as *const _ as usize);
            }

            context::current_wait_until(None);

            let s = context::current_selected();
            if s == case_id {
                let mut backoff = Backoff::new();
                while !packet.ready.load(Ordering::Acquire) {
                    backoff.step();
                }
                break;
            } else {
                self.inner.lock().senders.unregister(case_id);
                msg = unsafe { ptr::read(packet.msg.get()) };
            }
        }
    }

    pub fn recv(&self) -> Option<T> {
        let token = &mut Token::default();
        let case_id = CaseId::new(token as *mut Token as usize);

        loop {
            let packet;
            {
                let mut inner = self.inner.lock();

                if let Some(case) = inner.senders.wake_one() {
                    token.zero = Some(case.packet);
                    drop(inner);
                    unsafe {
                        return self.read(token);
                    }
                }

                if inner.is_closed {
                    return None;
                }

                context::current_reset();

                packet = Packet::<T> {
                    on_stack: true,
                    ready: AtomicBool::new(false),
                    msg: unsafe { ManuallyDrop::new(UnsafeCell::new(mem::uninitialized())) },
                };
                inner.receivers.register_with_packet(case_id, &packet as *const _ as usize);
            }

            context::current_wait_until(None);

            let s = context::current_selected();
            if s == case_id {
                let mut backoff = Backoff::new();
                while !packet.ready.load(Ordering::Acquire) {
                    backoff.step();
                }
                let msg = unsafe { ptr::read(packet.msg.get()) };
                return Some(msg);
            } else {
                self.inner.lock().receivers.unregister(case_id);
            }
        }
    }

    pub fn recv_nonblocking(&self) -> RecvNonblocking<T> {
        let token = &mut Token::default();

        let mut inner = self.inner.lock();

        if let Some(case) = inner.senders.wake_one() {
            token.zero = Some(case.packet);
            drop(inner);

            match unsafe { self.read(token) } {
                None => RecvNonblocking::Closed,
                Some(msg) => RecvNonblocking::Message(msg),
            }
        } else if inner.is_closed {
            RecvNonblocking::Closed
        } else {
            RecvNonblocking::Empty
        }
    }

    /// Closes the channel and wakes up all currently blocked operations on it.
    pub fn close(&self) -> bool {
        let mut inner = self.inner.lock();

        if inner.is_closed {
            false
        } else {
            inner.is_closed = true;
            inner.receivers.abort_all();
            true
        }
    }

    /// Returns the current number of messages inside the channel.
    pub fn len(&self) -> usize {
        0
    }

    /// Returns the capacity of the channel.
    pub fn capacity(&self) -> Option<usize> {
        Some(0)
    }

    /// Returns `true` if the channel is empty.
    pub fn is_empty(&self) -> bool {
        true
    }

    /// Returns `true` if the channel is full.
    pub fn is_full(&self) -> bool {
        true
    }
}

/// A receiver handle to a channel.
pub struct Receiver<'a, T: 'a>(&'a Channel<T>);

/// A sender handle to a channel.
pub struct Sender<'a, T: 'a>(&'a Channel<T>);

impl<'a, T> Select for Receiver<'a, T> {
    fn try(&self, token: &mut Token) -> bool {
        self.0.start_recv(token)
    }

    fn retry(&self, token: &mut Token) -> bool {
        // self.0.start_recv(token)

        let case_id = CaseId::new(&token as *const _ as usize);
        let mut inner = self.0.inner.lock();

        if let Some(case) = inner.senders.wake_one() {
            token.zero = Some(case.packet);
            return true;
        } else if inner.is_closed {
            token.zero = None;
            return true;
        }

        context::current_reset();

        let packet = Box::into_raw(Box::new(Packet::<T> {
            on_stack: false,
            ready: AtomicBool::new(false),
            msg: unsafe { ManuallyDrop::new(UnsafeCell::new(mem::uninitialized())) },
        }));
        inner.receivers.register_with_packet(case_id, packet as usize);

        drop(inner);

        thread::yield_now();
        context::current_try_abort();

        if context::current_selected() != CaseId::abort() {
            token.zero = Some(context::current_wait_packet());
            true
        } else {
            if let Some(case) = self.0.inner.lock().receivers.unregister(case_id) {
                unsafe {
                    drop(Box::from_raw(case.packet as *mut Packet<T>));
                }
            }
            false
        }
    }

    fn deadline(&self) -> Option<Instant> {
        None
    }

    fn register(&self, _token: &mut Token, case_id: CaseId) -> bool {
        let packet = Box::into_raw(Box::new(Packet::<T> {
            on_stack: false,
            ready: AtomicBool::new(false),
            msg: unsafe { ManuallyDrop::new(UnsafeCell::new(mem::uninitialized())) },
        }));

        let mut inner = self.0.inner.lock();
        inner.receivers.register_with_packet(case_id, packet as usize);
        !inner.senders.can_notify() && !inner.is_closed
    }

    fn unregister(&self, case_id: CaseId) {
        if let Some(case) = self.0.inner.lock().receivers.unregister(case_id) {
            unsafe {
                drop(Box::from_raw(case.packet as *mut Packet<T>));
            }
        }
    }

    fn accept(&self, token: &mut Token) -> bool {
        token.zero = Some(context::current_wait_packet());
        true
    }
}

impl<'a, T> Select for Sender<'a, T> {
    fn try(&self, token: &mut Token) -> bool {
        self.0.start_send(token)
    }

    fn retry(&self, token: &mut Token) -> bool {
        // self.0.start_send(token)

        let case_id = CaseId::new(&token as *const _ as usize);
        let mut inner = self.0.inner.lock();

        // If there's someone on the other side, exchange message with it.
        if let Some(case) = inner.receivers.wake_one() {
            token.zero = Some(case.packet);
            return true;
        }

        context::current_reset();

        let packet = Box::into_raw(Box::new(Packet::<T> {
            on_stack: false,
            ready: AtomicBool::new(false),
            msg: unsafe { ManuallyDrop::new(UnsafeCell::new(mem::uninitialized())) },
        }));
        inner.senders.register_with_packet(case_id, packet as usize);

        drop(inner);

        thread::yield_now();
        context::current_try_abort();

        if context::current_selected() != CaseId::abort() {
            token.zero = Some(context::current_wait_packet());
            true
        } else {
            if let Some(case) = self.0.inner.lock().senders.unregister(case_id) {
                unsafe {
                    drop(Box::from_raw(case.packet as *mut Packet<T>));
                }
            }
            false
        }
    }

    fn deadline(&self) -> Option<Instant> {
        None
    }

    fn register(&self, _token: &mut Token, case_id: CaseId) -> bool {
        let packet = Box::into_raw(Box::new(Packet::<T> {
            on_stack: false,
            ready: AtomicBool::new(false),
            msg: unsafe { ManuallyDrop::new(UnsafeCell::new(mem::uninitialized())) },
        }));

        let mut inner = self.0.inner.lock();
        inner.senders.register_with_packet(case_id, packet as usize);
        !inner.receivers.can_notify()
    }

    fn unregister(&self, case_id: CaseId) {
        if let Some(case) = self.0.inner.lock().senders.unregister(case_id) {
            unsafe {
                drop(Box::from_raw(case.packet as *mut Packet<T>));
            }
        }
    }

    fn accept(&self, token: &mut Token) -> bool {
        token.zero = Some(context::current_wait_packet());
        true
    }
}
<|endoftext|>


<commit_before>use nom::{
  be_u8, be_u16,
  IResult,
  ErrorCode, Err,
};

use frame::{
  ChannelAssignment, NumberType,
  Frame,
  Header, Footer,
};

use metadata::StreamInfo;
use utility::{crc8, crc16, to_u32};

pub fn frame_parser<'a>(input: &'a [u8], stream_info: &StreamInfo)
                        -> IResult<'a, &'a [u8], Frame> {
  let result = chain!(input,
    frame_header: apply!(header, stream_info) ~
    frame_footer: footer,
    || {
      Frame {
        header: frame_header,
        footer: frame_footer,
      }
    }
  );

  match result {
    IResult::Done(i, frame)   => {
      // All frame bytes before the crc-16
      let end         = (input.len() - i.len()) - 2;
      let Footer(crc) = frame.footer;

      if crc16(&input[0..end]) == crc {
        IResult::Done(i, frame)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn blocking_strategy(input: &[u8]) -> IResult<&[u8], bool> {
  match take!(input, 2) {
    IResult::Done(i, bytes)   => {
      let sync_code = ((bytes[0] as u16) << 6) +
                      (bytes[1] as u16) >> 2;
      let is_valid  = ((bytes[1] >> 1) & 0b01) == 0;

      if sync_code == 0b11111111111110 && is_valid {
        let is_variable_block_size = (bytes[1] & 0b01) == 1;

        IResult::Done(i, is_variable_block_size)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn block_sample(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let block_byte  = bytes[0] >> 4;
      let sample_byte = bytes[0] & 0x0f;
      let is_valid    = block_byte != 0b0000 && sample_byte != 0b1111;

      if is_valid {
        IResult::Done(i, (block_byte, sample_byte))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn channel_bits(input: &[u8]) -> IResult<&[u8], (ChannelAssignment, u8)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let channel_byte       = bytes[0] >> 4
      let channel_assignment = match channel_byte {
        0b0000...0b0111 => ChannelAssignment::Independent,
        0b1000          => ChannelAssignment::LeftSide,
        0b1001          => ChannelAssignment::RightSide,
        0b1010          => ChannelAssignment::MiddleSide,
        _               => ChannelAssignment::Independent,
      };
      let size_byte = (bytes[0] >> 1) & 0b0111;

      // Checks the validity of:
      //
      // * (4 bits) channel assignment
      // * (3 bits) sample size
      // * (1 bit) last bit
      //
      // All these checks are whether of not they are reserved and should
      // return an error if so.
      let is_valid = channel_byte < 0b1011 &&
                     (size_byte != 0b0011 && size_byte != 0b0111) &&
                     (bytes[0] & 0b01) == 0;

      if is_valid {
        IResult::Done(i, (channel_assignment, size_byte))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn utf8_size(input: &[u8], is_u64: bool)
             -> IResult<&[u8], Option<(usize, u8)>> {
  map!(input, be_u8, |utf8_header| {
    match utf8_header {
      0b00000000...0b01111111 => Some((0, utf8_header)),
      0b11000000...0b11011111 => Some((1, utf8_header & 0b00011111)),
      0b11100000...0b11101111 => Some((2, utf8_header & 0b00001111)),
      0b11110000...0b11110111 => Some((3, utf8_header & 0b00000111)),
      0b11111000...0b11111011 => Some((4, utf8_header & 0b00000011)),
      0b11111100...0b11111101 => Some((5, utf8_header & 0b00000001)),
      0b11111110              => if is_u64 { Some((6, 0)) } else { None },
      _                       => None,
    }
  })
}

fn sample_or_frame_number(input: &[u8], is_sample: bool,
                          (size, value): (usize, u8))
                          -> IResult<&[u8], NumberType> {
  let mut result   = value as u64;
  let mut is_error = false;

  match take!(input, size) {
    IResult::Done(i, bytes)   => {
      for i in 0..size {
        let byte = bytes[i] as u64;

        if byte >= 0b10000000 && byte <= 0b10111111 {
          result = (result << 6) + (byte & 0b00111111);
        } else {
          is_error = true;
          break;
        }
      }

      if is_error {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      } else if is_sample {
        IResult::Done(i, NumberType::Sample(result))
      } else {
        IResult::Done(i, NumberType::Frame(result as u32))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn secondary_block_size(input: &[u8], block_byte: u8)
                        -> IResult<&[u8], Option<u32>> {
  match block_byte {
    0b0110 => opt!(input, map!(take!(1), to_u32)),
    0b0111 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

fn secondary_sample_rate(input: &[u8], sample_byte: u8)
                        -> IResult<&[u8], Option<u32>> {
  match sample_byte {
    0b1100 => opt!(input, map!(take!(1), to_u32)),
    0b1101 => opt!(input, map!(take!(2), to_u32)),
    0b1110 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

fn header<'a>(input: &'a [u8], stream_info: &StreamInfo)
              -> IResult<'a, &'a [u8], Header> {
  let result = chain!(input,
    is_variable_block_size: blocking_strategy ~
    tuple0: block_sample ~
    tuple1: channel_bits ~
    number_opt: apply!(utf8_size, is_variable_block_size) ~
    number_length: expr_opt!(number_opt) ~
    number: apply!(sample_or_frame_number, is_variable_block_size,
                   number_length) ~
    alt_block_size: apply!(secondary_block_size, tuple0.0) ~
    alt_sample_rate: apply!(secondary_sample_rate, tuple0.1) ~
    crc: be_u8,
    || {
      let (block_byte, sample_byte)       = tuple0;
      let (channel_assignment, size_byte) = tuple1;

      let block_size = match block_byte {
        0b0001          => 192,
        0b0010...0b0101 => 576 * 2_u32.pow(block_byte as u32 - 2),
        0b0110 | 0b0111 => alt_block_size.unwrap() + 1,
        0b1000...0b1111 => 256 * 2_u32.pow(block_byte as u32 - 8),
        _               => unreachable!(),
      };

      let sample_rate = match sample_byte {
        0b0000 => stream_info.sample_rate,
        0b0001 => 88200,
        0b0010 => 176400,
        0b0011 => 192000,
        0b0100 => 8000,
        0b0101 => 16000,
        0b0110 => 22050,
        0b0111 => 24000,
        0b1000 => 32000,
        0b1001 => 44100,
        0b1010 => 48000,
        0b1011 => 96000,
        0b1100 => alt_sample_rate.unwrap() * 1000,
        0b1101 => alt_sample_rate.unwrap(),
        0b1110 => alt_sample_rate.unwrap() * 10,
        _      => unreachable!(),
      };

      let bits_per_sample = match size_byte {
        0b0000 => stream_info.bits_per_sample as usize,
        0b0001 => 8,
        0b0010 => 12,
        0b0100 => 16,
        0b0101 => 20,
        0b0110 => 24,
        _      => unreachable!(),
      };

      Header {
        block_size: block_size,
        sample_rate: sample_rate,
        channel_assignment: channel_assignment,
        bits_per_sample: bits_per_sample,
        number: number,
        crc: crc,
      }
    }
  );

  match result {
    IResult::Done(i, frame_header) => {
      // All header bytes before the crc-8
      let end = (input.len() - i.len()) - 1;

      if crc8(&input[0..end]) == frame_header.crc {
        IResult::Done(i, frame_header)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)          => IResult::Error(error),
    IResult::Incomplete(need)      => IResult::Incomplete(need),
  }
}

named!(footer <&[u8], Footer>, map!(be_u16, Footer));
<commit_msg>Add missing semicolon<commit_after>use nom::{
  be_u8, be_u16,
  IResult,
  ErrorCode, Err,
};

use frame::{
  ChannelAssignment, NumberType,
  Frame,
  Header, Footer,
};

use metadata::StreamInfo;
use utility::{crc8, crc16, to_u32};

pub fn frame_parser<'a>(input: &'a [u8], stream_info: &StreamInfo)
                        -> IResult<'a, &'a [u8], Frame> {
  let result = chain!(input,
    frame_header: apply!(header, stream_info) ~
    frame_footer: footer,
    || {
      Frame {
        header: frame_header,
        footer: frame_footer,
      }
    }
  );

  match result {
    IResult::Done(i, frame)   => {
      // All frame bytes before the crc-16
      let end         = (input.len() - i.len()) - 2;
      let Footer(crc) = frame.footer;

      if crc16(&input[0..end]) == crc {
        IResult::Done(i, frame)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn blocking_strategy(input: &[u8]) -> IResult<&[u8], bool> {
  match take!(input, 2) {
    IResult::Done(i, bytes)   => {
      let sync_code = ((bytes[0] as u16) << 6) +
                      (bytes[1] as u16) >> 2;
      let is_valid  = ((bytes[1] >> 1) & 0b01) == 0;

      if sync_code == 0b11111111111110 && is_valid {
        let is_variable_block_size = (bytes[1] & 0b01) == 1;

        IResult::Done(i, is_variable_block_size)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn block_sample(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let block_byte  = bytes[0] >> 4;
      let sample_byte = bytes[0] & 0x0f;
      let is_valid    = block_byte != 0b0000 && sample_byte != 0b1111;

      if is_valid {
        IResult::Done(i, (block_byte, sample_byte))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn channel_bits(input: &[u8]) -> IResult<&[u8], (ChannelAssignment, u8)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let channel_byte       = bytes[0] >> 4;
      let channel_assignment = match channel_byte {
        0b0000...0b0111 => ChannelAssignment::Independent,
        0b1000          => ChannelAssignment::LeftSide,
        0b1001          => ChannelAssignment::RightSide,
        0b1010          => ChannelAssignment::MiddleSide,
        _               => ChannelAssignment::Independent,
      };
      let size_byte = (bytes[0] >> 1) & 0b0111;

      // Checks the validity of:
      //
      // * (4 bits) channel assignment
      // * (3 bits) sample size
      // * (1 bit) last bit
      //
      // All these checks are whether of not they are reserved and should
      // return an error if so.
      let is_valid = channel_byte < 0b1011 &&
                     (size_byte != 0b0011 && size_byte != 0b0111) &&
                     (bytes[0] & 0b01) == 0;

      if is_valid {
        IResult::Done(i, (channel_assignment, size_byte))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn utf8_size(input: &[u8], is_u64: bool)
             -> IResult<&[u8], Option<(usize, u8)>> {
  map!(input, be_u8, |utf8_header| {
    match utf8_header {
      0b00000000...0b01111111 => Some((0, utf8_header)),
      0b11000000...0b11011111 => Some((1, utf8_header & 0b00011111)),
      0b11100000...0b11101111 => Some((2, utf8_header & 0b00001111)),
      0b11110000...0b11110111 => Some((3, utf8_header & 0b00000111)),
      0b11111000...0b11111011 => Some((4, utf8_header & 0b00000011)),
      0b11111100...0b11111101 => Some((5, utf8_header & 0b00000001)),
      0b11111110              => if is_u64 { Some((6, 0)) } else { None },
      _                       => None,
    }
  })
}

fn sample_or_frame_number(input: &[u8], is_sample: bool,
                          (size, value): (usize, u8))
                          -> IResult<&[u8], NumberType> {
  let mut result   = value as u64;
  let mut is_error = false;

  match take!(input, size) {
    IResult::Done(i, bytes)   => {
      for i in 0..size {
        let byte = bytes[i] as u64;

        if byte >= 0b10000000 && byte <= 0b10111111 {
          result = (result << 6) + (byte & 0b00111111);
        } else {
          is_error = true;
          break;
        }
      }

      if is_error {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      } else if is_sample {
        IResult::Done(i, NumberType::Sample(result))
      } else {
        IResult::Done(i, NumberType::Frame(result as u32))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn secondary_block_size(input: &[u8], block_byte: u8)
                        -> IResult<&[u8], Option<u32>> {
  match block_byte {
    0b0110 => opt!(input, map!(take!(1), to_u32)),
    0b0111 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

fn secondary_sample_rate(input: &[u8], sample_byte: u8)
                        -> IResult<&[u8], Option<u32>> {
  match sample_byte {
    0b1100 => opt!(input, map!(take!(1), to_u32)),
    0b1101 => opt!(input, map!(take!(2), to_u32)),
    0b1110 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

fn header<'a>(input: &'a [u8], stream_info: &StreamInfo)
              -> IResult<'a, &'a [u8], Header> {
  let result = chain!(input,
    is_variable_block_size: blocking_strategy ~
    tuple0: block_sample ~
    tuple1: channel_bits ~
    number_opt: apply!(utf8_size, is_variable_block_size) ~
    number_length: expr_opt!(number_opt) ~
    number: apply!(sample_or_frame_number, is_variable_block_size,
                   number_length) ~
    alt_block_size: apply!(secondary_block_size, tuple0.0) ~
    alt_sample_rate: apply!(secondary_sample_rate, tuple0.1) ~
    crc: be_u8,
    || {
      let (block_byte, sample_byte)       = tuple0;
      let (channel_assignment, size_byte) = tuple1;

      let block_size = match block_byte {
        0b0001          => 192,
        0b0010...0b0101 => 576 * 2_u32.pow(block_byte as u32 - 2),
        0b0110 | 0b0111 => alt_block_size.unwrap() + 1,
        0b1000...0b1111 => 256 * 2_u32.pow(block_byte as u32 - 8),
        _               => unreachable!(),
      };

      let sample_rate = match sample_byte {
        0b0000 => stream_info.sample_rate,
        0b0001 => 88200,
        0b0010 => 176400,
        0b0011 => 192000,
        0b0100 => 8000,
        0b0101 => 16000,
        0b0110 => 22050,
        0b0111 => 24000,
        0b1000 => 32000,
        0b1001 => 44100,
        0b1010 => 48000,
        0b1011 => 96000,
        0b1100 => alt_sample_rate.unwrap() * 1000,
        0b1101 => alt_sample_rate.unwrap(),
        0b1110 => alt_sample_rate.unwrap() * 10,
        _      => unreachable!(),
      };

      let bits_per_sample = match size_byte {
        0b0000 => stream_info.bits_per_sample as usize,
        0b0001 => 8,
        0b0010 => 12,
        0b0100 => 16,
        0b0101 => 20,
        0b0110 => 24,
        _      => unreachable!(),
      };

      Header {
        block_size: block_size,
        sample_rate: sample_rate,
        channel_assignment: channel_assignment,
        bits_per_sample: bits_per_sample,
        number: number,
        crc: crc,
      }
    }
  );

  match result {
    IResult::Done(i, frame_header) => {
      // All header bytes before the crc-8
      let end = (input.len() - i.len()) - 1;

      if crc8(&input[0..end]) == frame_header.crc {
        IResult::Done(i, frame_header)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)          => IResult::Error(error),
    IResult::Incomplete(need)      => IResult::Incomplete(need),
  }
}

named!(footer <&[u8], Footer>, map!(be_u16, Footer));
<|endoftext|>


<commit_before>// A genetic algorithm in Rust, for testing of stochastic methods for
// accelerating rigorous global maximization.

// Adapted from https://github.com/andschwa/rust-genetic-algorithm
// By Andy Schwartzmeyer (https://github.com/andschwa)

extern crate rand;
use rand::{Rng};

extern crate gu;
use gu::{Parameters, INF, Flt};

extern crate gr;
use gr::{GI, upper_gaol, lower_gaol, func};

use rand::distributions::{Range, IndependentSample};

use std::cmp::{Eq, PartialEq, Ordering, PartialOrd};

use std::mem;

use std::sync::{Barrier, RwLock, Arc};

use std::sync::atomic::{AtomicBool};
use std::sync::atomic::Ordering as AtOrd;

/// A genetic algorithm that searches for convergence to the given
/// tolerance for the problem across the n-dimensional hypercube,
/// using a population of individuals, up to a maximum iterations
/// number of generations.
pub fn ea(x_0: Vec<GI>, params: Parameters,
          population: Arc<RwLock<Vec<Individual>>>,
          f_bestag: Arc<RwLock<Flt>>,
          x_bestbb: Arc<RwLock<Vec<GI>>>,
          b1: Arc<Barrier>, b2: Arc<Barrier>,
          stop: Arc<AtomicBool>, sync: Arc<AtomicBool>) {
    // SETUP
    // get thread local random number generator
    let mut rng = rand::thread_rng();

    // initialize population of individuals
    {
        let mut population_w = population.write().unwrap();
        for _ in 0..params.population {
            population_w.push(Individual::new(&x_0, &mut rng));
        }
        assert!(population_w.len() == params.population);
    }

    // start timing the search
    //let start_time = precise_time_s();
    // END SETUP
    // search iterations number of generations
    //for i in 0..params.iterations {
    while !stop.load(AtOrd::SeqCst) {
        if sync.load(AtOrd::SeqCst) {
            b1.wait();
            b2.wait();
        }
        let mut population = population.write().unwrap();
        {
            let mut fbest = f_bestag.write().unwrap();
            *fbest = match (*population).iter().max() {
                Some(i) => i.fitness,
                None => panic!("wtf"),
                }
        }
        // select, mutate, and crossover individuals for next generation
        let mut offspring: Vec<Individual> = Vec::with_capacity(population.len());
        for _ in 0..population.len()/2 {
            let (mut x, mut y) = (select(&population, params.selection, &mut rng),
                                  select(&population, params.selection, &mut rng));
            x.mutate(&x_0, params.mutation, &mut rng);
            y.mutate(&x_0, params.mutation, &mut rng);
            Individual::crossover(&mut x, &mut y, params.crossover, &mut rng);
            offspring.push(x);
            offspring.push(y);
        }
        assert!(offspring.len() == population.len());

        // replace 2 random individuals with elite of prior generation
        for _ in 0..params.elitism {
            if let Some(x) = population.iter().max() {
                offspring[rng.gen_range(0, population.len())] = x.clone();
            }
        }

        // Replace worst with bestbb
        let mut worst_i = -1;
        let mut worst = INF;
        for i in 0..offspring.len() {
            if offspring[i].fitness < worst {
                worst = offspring[i].fitness;
                worst_i = i;
            }
        }
        {
            let bestbb = x_bestbb.read().unwrap();
            offspring[worst_i] = Individual::new(&bestbb, &mut rng);
        }

        // replace population with next generation
        *population = offspring;
    }
}

/// Tournament selection from n random individuals
fn select<R: Rng>(population: &[Individual], n: usize, rng: &mut R) -> Individual {
    if let Some(selected) = (0..n).map(|_| rng.choose(population)).max() {
        selected.unwrap().clone()
    } else {
        unimplemented!();
    }
}

#[derive(Clone)]
pub struct Individual {
    pub solution: Vec<GI>,
    pub fitness: Flt,
}

impl Individual {
    /// Constructs a new Individual to solve Problem with n random values
    pub fn new<R: Rng>(x: &Vec<GI>, rng: &mut R) -> Self {
        let mut result = Vec::new();
        for i in 0..x.len() {
            let num = Range::new(lower_gaol(&x[i]), upper_gaol(&x[i])).ind_sample(rng);
            result.push(GI::new_d(num, num));
        }
        let fitness = lower_gaol(&func(&result));
        Individual{solution: result, fitness: fitness}
    }

    /// Mutate with chance n a single gene to a new value in the
    /// problem's domain (a "jump" mutation).
    ///
    /// Fitness is NOT evaluated as it is ALWAYS done in `crossover()`
    pub fn mutate<R: Rng>(&mut self, x: &Vec<GI>, chance: f64, rng: &mut R) {
        if rng.gen_range(0_f64, 1_f64) < chance {
            let i = rng.gen_range(0, self.solution.len());
            let num = Range::new(lower_gaol(&x[i]),
                                 upper_gaol(&x[i])).ind_sample(rng);
            self.solution[i] = GI::new_d(num, num);
        }
    }

    /// Performs two-point crossover with chance n to swap a random
    /// set of [0, dimension] genes between a pair of individuals.
    ///
    /// Fitness is ALWAYS evaluated because it is NOT done in mutate()
    pub fn crossover<R: Rng>(x: &mut Individual, y: &mut Individual,
                             chance: f64, rng: &mut R) {
        // assert_eq!(x.problem, y.problem);
        if rng.gen_range(0_f64, 1_f64) < chance {
            let len = x.solution.len();
            let (start, n) = (rng.gen_range(0, len), rng.gen_range(0, len));
            for i in start..start + n {
                mem::swap(&mut x.solution[i % len], &mut y.solution[i % len]);
            }
        }
        x.fitness = lower_gaol(&func(&x.solution));
        y.fitness = lower_gaol(&func(&y.solution));
    }
}

impl Eq for Individual {}

impl Ord for Individual {
    /// This dangerously delegates to `partial_cmp`; NaN will panic
    fn cmp(&self, other: &Self) -> Ordering {
        if let Some(result) = self.fitness.partial_cmp(&other.fitness) {
            return result;
        }
        unimplemented!();
    }
}

impl PartialEq<Individual> for Individual {
    /// This doesn't use `fitness.eq()` because it needs to be
    /// consistent with `Eq`
    fn eq(&self, other: &Individual) -> bool {
        if let Some(result) = self.fitness.partial_cmp(&other.fitness) {
            return result == Ordering::Equal;
        }
        unimplemented!();
    }
}

impl PartialOrd for Individual {
    /// This delegates to `fitness.partial_cmp()`
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.fitness.partial_cmp(&other.fitness)
    }
}
<commit_msg>Fix GA on point interval input<commit_after>// A genetic algorithm in Rust, for testing of stochastic methods for
// accelerating rigorous global maximization.

// Adapted from https://github.com/andschwa/rust-genetic-algorithm
// By Andy Schwartzmeyer (https://github.com/andschwa)

extern crate rand;
use rand::{Rng};

extern crate gu;
use gu::{Parameters, INF, Flt};

extern crate gr;
use gr::{GI, upper_gaol, lower_gaol, func};

use rand::distributions::{Range, IndependentSample};

use std::cmp::{Eq, PartialEq, Ordering, PartialOrd};

use std::mem;

use std::sync::{Barrier, RwLock, Arc};

use std::sync::atomic::{AtomicBool};
use std::sync::atomic::Ordering as AtOrd;

/// A genetic algorithm that searches for convergence to the given
/// tolerance for the problem across the n-dimensional hypercube,
/// using a population of individuals, up to a maximum iterations
/// number of generations.
pub fn ea(x_0: Vec<GI>, params: Parameters,
          population: Arc<RwLock<Vec<Individual>>>,
          f_bestag: Arc<RwLock<Flt>>,
          x_bestbb: Arc<RwLock<Vec<GI>>>,
          b1: Arc<Barrier>, b2: Arc<Barrier>,
          stop: Arc<AtomicBool>, sync: Arc<AtomicBool>) {
    // SETUP
    // get thread local random number generator
    let mut rng = rand::thread_rng();

    // initialize population of individuals
    {
        let mut population_w = population.write().unwrap();
        for _ in 0..params.population {
            population_w.push(Individual::new(&x_0, &mut rng));
        }
        assert!(population_w.len() == params.population);
    }

    // start timing the search
    //let start_time = precise_time_s();
    // END SETUP
    // search iterations number of generations
    //for i in 0..params.iterations {
    while !stop.load(AtOrd::SeqCst) {
        if sync.load(AtOrd::SeqCst) {
            b1.wait();
            b2.wait();
        }
        let mut population = population.write().unwrap();
        {
            let mut fbest = f_bestag.write().unwrap();
            *fbest = match (*population).iter().max() {
                Some(i) => i.fitness,
                None => panic!("wtf"),
                }
        }
        // select, mutate, and crossover individuals for next generation
        let mut offspring: Vec<Individual> = Vec::with_capacity(population.len());
        for _ in 0..population.len()/2 {
            let (mut x, mut y) = (select(&population, params.selection, &mut rng),
                                  select(&population, params.selection, &mut rng));
            x.mutate(&x_0, params.mutation, &mut rng);
            y.mutate(&x_0, params.mutation, &mut rng);
            Individual::crossover(&mut x, &mut y, params.crossover, &mut rng);
            offspring.push(x);
            offspring.push(y);
        }
        assert!(offspring.len() == population.len());

        // replace 2 random individuals with elite of prior generation
        for _ in 0..params.elitism {
            if let Some(x) = population.iter().max() {
                offspring[rng.gen_range(0, population.len())] = x.clone();
            }
        }

        // Replace worst with bestbb
        let mut worst_i = -1;
        let mut worst = INF;
        for i in 0..offspring.len() {
            if offspring[i].fitness < worst {
                worst = offspring[i].fitness;
                worst_i = i;
            }
        }
        {
            let bestbb = x_bestbb.read().unwrap();
            offspring[worst_i] = Individual::new(&bestbb, &mut rng);
        }

        // replace population with next generation
        *population = offspring;
    }
}

/// Tournament selection from n random individuals
fn select<R: Rng>(population: &[Individual], n: usize, rng: &mut R) -> Individual {
    if let Some(selected) = (0..n).map(|_| rng.choose(population)).max() {
        selected.unwrap().clone()
    } else {
        unimplemented!();
    }
}

#[derive(Clone)]
pub struct Individual {
    pub solution: Vec<GI>,
    pub fitness: Flt,
}

impl Individual {
    /// Constructs a new Individual to solve Problem with n random values
    pub fn new<R: Rng>(x: &Vec<GI>, rng: &mut R) -> Self {
        let mut result = Vec::new();
        for i in 0..x.len() {
            let up = upper_gaol(&x[i]);
            let low = lower_gaol(&x[i]);

            let num = if up == low {up} else {Range::new(lower_gaol(&x[i]), upper_gaol(&x[i])).ind_sample(rng)};
            result.push(GI::new_d(num, num));
        }
        let fitness = lower_gaol(&func(&result));
        Individual{solution: result, fitness: fitness}
    }

    /// Mutate with chance n a single gene to a new value in the
    /// problem's domain (a "jump" mutation).
    ///
    /// Fitness is NOT evaluated as it is ALWAYS done in `crossover()`
    pub fn mutate<R: Rng>(&mut self, x: &Vec<GI>, chance: f64, rng: &mut R) {
        if rng.gen_range(0_f64, 1_f64) < chance {
            let i = rng.gen_range(0, self.solution.len());
            let up = upper_gaol(&x[i]);
            let low = lower_gaol(&x[i]);

            let num = if up == low {up} else {Range::new(lower_gaol(&x[i]), upper_gaol(&x[i])).ind_sample(rng)};

            self.solution[i] = GI::new_d(num, num);
        }
    }

    /// Performs two-point crossover with chance n to swap a random
    /// set of [0, dimension] genes between a pair of individuals.
    ///
    /// Fitness is ALWAYS evaluated because it is NOT done in mutate()
    pub fn crossover<R: Rng>(x: &mut Individual, y: &mut Individual,
                             chance: f64, rng: &mut R) {
        // assert_eq!(x.problem, y.problem);
        if rng.gen_range(0_f64, 1_f64) < chance {
            let len = x.solution.len();
            let (start, n) = (rng.gen_range(0, len), rng.gen_range(0, len));
            for i in start..start + n {
                mem::swap(&mut x.solution[i % len], &mut y.solution[i % len]);
            }
        }
        x.fitness = lower_gaol(&func(&x.solution));
        y.fitness = lower_gaol(&func(&y.solution));
    }
}

impl Eq for Individual {}

impl Ord for Individual {
    /// This dangerously delegates to `partial_cmp`; NaN will panic
    fn cmp(&self, other: &Self) -> Ordering {
        if let Some(result) = self.fitness.partial_cmp(&other.fitness) {
            return result;
        }
        unimplemented!();
    }
}

impl PartialEq<Individual> for Individual {
    /// This doesn't use `fitness.eq()` because it needs to be
    /// consistent with `Eq`
    fn eq(&self, other: &Individual) -> bool {
        if let Some(result) = self.fitness.partial_cmp(&other.fitness) {
            return result == Ordering::Equal;
        }
        unimplemented!();
    }
}

impl PartialOrd for Individual {
    /// This delegates to `fitness.partial_cmp()`
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.fitness.partial_cmp(&other.fitness)
    }
}
<|endoftext|>


<commit_before>use ray::Ray;
use hitable::{Hitable, hit_record};
use vector::{Vec3, dot, cross, unit_vector};

pub struct Hitable_list {
  pub list_size : i64,
  pub list : Vec<Box<Hitable>>,
}

impl Hitable_list {
  pub fn new(l : Vec<Box<Hitable>>) -> Hitable_list {
    Hitable_list { list_size : l.len() as i64, list: l }
  }
}

impl Hitable for Hitable_list {
  fn hit(&self, r: Ray, t_min: f64, t_max: f64, rec: &mut hit_record) -> bool {
    let mut temp_rec = hit_record::new(0.0, Vec3::origin(), Vec3::origin());
    let mut hit_anything = false;
    let mut closest_so_far = t_max;

    for item in self.list.iter() {
      if item.hit(r, t_min, closest_so_far, &mut temp_rec) {
        hit_anything = true;
        closest_so_far = temp_rec.t;
        rec.t = temp_rec.t;
        rec.p = temp_rec.p;
        rec.normal = temp_rec.normal;
      }
    }
    return hit_anything;
  }
}<commit_msg>Remove unused imports<commit_after>use ray::Ray;
use hitable::{Hitable, hit_record};
use vector::Vec3;

pub struct Hitable_list {
  pub list_size : i64,
  pub list : Vec<Box<Hitable>>,
}

impl Hitable_list {
  pub fn new(l : Vec<Box<Hitable>>) -> Hitable_list {
    Hitable_list { list_size : l.len() as i64, list: l }
  }
}

impl Hitable for Hitable_list {
  fn hit(&self, r: Ray, t_min: f64, t_max: f64, rec: &mut hit_record) -> bool {
    let mut temp_rec = hit_record::new(0.0, Vec3::origin(), Vec3::origin());
    let mut hit_anything = false;
    let mut closest_so_far = t_max;

    for item in self.list.iter() {
      if item.hit(r, t_min, closest_so_far, &mut temp_rec) {
        hit_anything = true;
        closest_so_far = temp_rec.t;
        rec.t = temp_rec.t;
        rec.p = temp_rec.p;
        rec.normal = temp_rec.normal;
      }
    }
    return hit_anything;
  }
}<|endoftext|>


<commit_before>extern crate schannel;

use std::io;
use std::fmt;
use std::error;
use std::error::Error;
use std::sync::Arc;
use self::schannel::cert_store::{PfxImportOptions, Memory, CertStore, CertAdd};
use self::schannel::cert_context::CertContext;
use self::schannel::schannel_cred::{Direction, SchannelCred, Protocol};
use self::schannel::tls_stream;

fn convert_protocols(protocols: &[::Protocol]) -> Vec<Protocol> {
    protocols
        .iter()
        .map(|p| match *p {
            ::Protocol::Sslv3 => Protocol::Ssl3,
            ::Protocol::Tlsv10 => Protocol::Tls10,
            ::Protocol::Tlsv11 => Protocol::Tls11,
            ::Protocol::Tlsv12 => Protocol::Tls12,
            ::Protocol::__NonExhaustive => unreachable!(),
        })
        .collect()
}

pub struct Error(io::Error);

impl error::Error for Error {
    fn description(&self) -> &str {
        error::Error::description(&self.0)
    }

    fn cause(&self) -> Option<&error::Error> {
        error::Error::cause(&self.0)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, fmt)
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl From<io::Error> for Error {
    fn from(error: io::Error) -> Error {
        Error(error)
    }
}

pub struct Pkcs12 {
    cert: CertContext,
}

impl Pkcs12 {
    pub fn from_der(buf: &[u8], pass: &str) -> Result<Pkcs12, Error> {
        let mut store = try!(PfxImportOptions::new().password(pass).import(buf));
        let mut identity = None;

        for cert in store.certs() {
            if cert.private_key()
                .silent(true)
                .compare_key(true)
                .acquire()
                .is_ok()
            {
                identity = Some(cert);
            }
        }

        let identity = match identity {
            Some(identity) => identity,
            None => {
                return Err(
                    io::Error::new(
                        io::ErrorKind::InvalidInput,
                        "No identity found in PKCS #12 archive",
                    ).into(),
                );
            }
        };

        Ok(Pkcs12 { cert: identity })
    }
}

pub struct Certificate(CertContext);

impl Certificate {
    pub fn from_der(buf: &[u8]) -> Result<Certificate, Error> {
        let cert = try!(CertContext::new(buf));
        Ok(Certificate(cert))
    }
    pub fn from_pem(buf: &[u8]) -> Result<Certificate, Error> {
        match ::std::str::from_utf8(buf) {
            Ok(s) => {
                let cert = try!(CertContext::from_pem(s));
                Ok(Certificate(cert))
            }
            Err(_) => {
                Err( io::Error::new( io::ErrorKind::InvalidInput, "PEM representation contains non-UTF-8 bytes")).into())
            }
        }
    }
}

pub struct MidHandshakeTlsStream<S>(tls_stream::MidHandshakeTlsStream<S>);

impl<S> fmt::Debug for MidHandshakeTlsStream<S>
where
    S: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<S> MidHandshakeTlsStream<S>
where
    S: io::Read + io::Write,
{
    pub fn get_ref(&self) -> &S {
        self.0.get_ref()
    }

    pub fn get_mut(&mut self) -> &mut S {
        self.0.get_mut()
    }

    pub fn handshake(self) -> Result<TlsStream<S>, HandshakeError<S>> {
        match self.0.handshake() {
            Ok(s) => Ok(TlsStream(s)),
            Err(e) => Err(e.into()),
        }
    }
}

pub enum HandshakeError<S> {
    Failure(Error),
    Interrupted(MidHandshakeTlsStream<S>),
}

impl<S> From<tls_stream::HandshakeError<S>> for HandshakeError<S> {
    fn from(e: tls_stream::HandshakeError<S>) -> HandshakeError<S> {
        match e {
            tls_stream::HandshakeError::Failure(e) => HandshakeError::Failure(e.into()),
            tls_stream::HandshakeError::Interrupted(s) => {
                HandshakeError::Interrupted(MidHandshakeTlsStream(s))
            }
        }
    }
}

impl<S> From<io::Error> for HandshakeError<S> {
    fn from(e: io::Error) -> HandshakeError<S> {
        HandshakeError::Failure(e.into())
    }
}

pub struct TlsConnectorBuilder(TlsConnector);

impl TlsConnectorBuilder {
    pub fn identity(&mut self, pkcs12: Pkcs12) -> Result<(), Error> {
        self.0.cert = Some(pkcs12.cert);
        Ok(())
    }

    pub fn add_root_certificate(&mut self, cert: Certificate) -> Result<(), Error> {
        try!(self.0.roots.add_cert(&cert.0, CertAdd::ReplaceExisting));
        Ok(())
    }

    pub fn supported_protocols(&mut self, protocols: &[::Protocol]) -> Result<(), Error> {
        self.0.protocols = convert_protocols(protocols);
        Ok(())
    }

    pub fn build(self) -> Result<TlsConnector, Error> {
        Ok(self.0)
    }
}

#[derive(Clone)]
pub struct TlsConnector {
    cert: Option<CertContext>,
    roots: CertStore,
    protocols: Vec<Protocol>,
    callback: Option<Arc<Fn(tls_stream::CertValidationResult) -> io::Result<()> + Sync + Send>>,
}

impl TlsConnector {
    pub fn builder() -> Result<TlsConnectorBuilder, Error> {
        Ok(TlsConnectorBuilder(TlsConnector {
            cert: None,
            roots: try!(Memory::new()).into_store(),
            protocols: vec![Protocol::Tls10, Protocol::Tls11, Protocol::Tls12],
            callback: None,
        }))
    }

    pub fn connect<S>(&self, domain: &str, stream: S) -> Result<TlsStream<S>, HandshakeError<S>>
    where
        S: io::Read + io::Write,
    {
        self._connect(Some(domain), stream)
    }

    pub fn connect_no_domain<S>(&self, stream: S) -> Result<TlsStream<S>, HandshakeError<S>>
    where
        S: io::Read + io::Write,
    {
        self._connect(None, stream)
    }

    fn _connect<S>(
        &self,
        domain: Option<&str>,
        stream: S,
    ) -> Result<TlsStream<S>, HandshakeError<S>>
    where
        S: io::Read + io::Write,
    {
        let mut builder = SchannelCred::builder();
        builder.enabled_protocols(&self.protocols);
        if let Some(cert) = self.cert.as_ref() {
            builder.cert(cert.clone());
        }
        let cred = try!(builder.acquire(Direction::Outbound));
        let mut builder = tls_stream::Builder::new();
        if let Some(domain) = domain {
            builder.domain(domain);
        }
        if let Some(ref callback) = self.callback {
            let callback = callback.clone();
            builder.verify_callback(move |r| callback(r));
        }
        builder.cert_store(self.roots.clone());
        match builder.connect(cred, stream) {
            Ok(s) => Ok(TlsStream(s)),
            Err(e) => Err(e.into()),
        }
    }
}

pub struct TlsAcceptorBuilder(TlsAcceptor);

impl TlsAcceptorBuilder {
    pub fn supported_protocols(&mut self, protocols: &[::Protocol]) -> Result<(), Error> {
        self.0.protocols = convert_protocols(protocols);
        Ok(())
    }

    pub fn build(self) -> Result<TlsAcceptor, Error> {
        Ok(self.0)
    }
}

#[derive(Clone)]
pub struct TlsAcceptor {
    cert: CertContext,
    protocols: Vec<Protocol>,
}

impl TlsAcceptor {
    pub fn builder(pkcs12: Pkcs12) -> Result<TlsAcceptorBuilder, Error> {
        Ok(TlsAcceptorBuilder(TlsAcceptor {
            cert: pkcs12.cert,
            protocols: vec![Protocol::Tls10, Protocol::Tls11, Protocol::Tls12],
        }))
    }

    pub fn accept<S>(&self, stream: S) -> Result<TlsStream<S>, HandshakeError<S>>
    where
        S: io::Read + io::Write,
    {
        let mut builder = SchannelCred::builder();
        builder.enabled_protocols(&self.protocols);
        builder.cert(self.cert.clone());
        // FIXME we're probably missing the certificate chain?
        let cred = try!(builder.acquire(Direction::Inbound));
        match tls_stream::Builder::new().accept(cred, stream) {
            Ok(s) => Ok(TlsStream(s)),
            Err(e) => Err(e.into()),
        }
    }
}

pub struct TlsStream<S>(tls_stream::TlsStream<S>);

impl<S: fmt::Debug> fmt::Debug for TlsStream<S> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<S: io::Read + io::Write> TlsStream<S> {
    pub fn buffered_read_size(&self) -> Result<usize, Error> {
        Ok(self.0.get_buf().len())
    }

    pub fn shutdown(&mut self) -> io::Result<()> {
        try!(self.0.shutdown());
        Ok(())
    }

    pub fn get_ref(&self) -> &S {
        self.0.get_ref()
    }

    pub fn get_mut(&mut self) -> &mut S {
        self.0.get_mut()
    }
}

impl<S: io::Read + io::Write> io::Read for TlsStream<S> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

impl<S: io::Read + io::Write> io::Write for TlsStream<S> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }

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

/// SChannel-specific extensions to `TlsConnectorBuilder`.
pub trait TlsConnectorBuilderExt {
    /// Sets a callback function which decides if the server's certificate chain
    /// is to be trusted.
    fn verify_callback<F>(&mut self, callback: F)
    where
        F: Fn(tls_stream::CertValidationResult) -> io::Result<()> + 'static + Send + Sync;
}

impl TlsConnectorBuilderExt for ::TlsConnectorBuilder {
    fn verify_callback<F>(&mut self, callback: F)
    where
        F: Fn(tls_stream::CertValidationResult) -> io::Result<()> + 'static + Send + Sync,
    {
        (self.0).0.callback = Some(Arc::new(callback));
    }
}

/// SChannel-specific extensions to `TlsStream`.
pub trait TlsStreamExt<S> {
    /// Returns a shared reference to the SChannel `TlsStream`.
    fn raw_stream(&self) -> &tls_stream::TlsStream<S>;

    /// Returns a mutable reference to the SChannel `TlsStream`.
    fn raw_stream_mut(&mut self) -> &mut tls_stream::TlsStream<S>;
}

impl<S> TlsStreamExt<S> for ::TlsStream<S> {
    fn raw_stream(&self) -> &tls_stream::TlsStream<S> {
        &(self.0).0
    }

    fn raw_stream_mut(&mut self) -> &mut tls_stream::TlsStream<S> {
        &mut (self.0).0
    }
}

/// SChannel-specific extensions to `Error`
pub trait ErrorExt {
    /// Extract the underlying SChannel error for inspection.
    fn schannel_error(&self) -> &io::Error;
}

impl ErrorExt for ::Error {
    fn schannel_error(&self) -> &io::Error {
        &(self.0).0
    }
}

/// SChannel-specific extensions to `Certificate`.
pub trait CertificateExt {
    /// builds a native_Tls `Certificate` from an schannel `CertContext`
    fn from_cert_context(CertContext) -> ::Certificate;
}

impl CertificateExt for ::Certificate {
    fn from_cert_context(cert: CertContext) -> ::Certificate {
        ::Certificate(Certificate(cert))
    }
}
<commit_msg>Well...<commit_after>extern crate schannel;

use std::io;
use std::fmt;
use std::error;
use std::error::Error;
use std::sync::Arc;
use self::schannel::cert_store::{PfxImportOptions, Memory, CertStore, CertAdd};
use self::schannel::cert_context::CertContext;
use self::schannel::schannel_cred::{Direction, SchannelCred, Protocol};
use self::schannel::tls_stream;

fn convert_protocols(protocols: &[::Protocol]) -> Vec<Protocol> {
    protocols
        .iter()
        .map(|p| match *p {
            ::Protocol::Sslv3 => Protocol::Ssl3,
            ::Protocol::Tlsv10 => Protocol::Tls10,
            ::Protocol::Tlsv11 => Protocol::Tls11,
            ::Protocol::Tlsv12 => Protocol::Tls12,
            ::Protocol::__NonExhaustive => unreachable!(),
        })
        .collect()
}

pub struct Error(io::Error);

impl error::Error for Error {
    fn description(&self) -> &str {
        error::Error::description(&self.0)
    }

    fn cause(&self) -> Option<&error::Error> {
        error::Error::cause(&self.0)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, fmt)
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl From<io::Error> for Error {
    fn from(error: io::Error) -> Error {
        Error(error)
    }
}

pub struct Pkcs12 {
    cert: CertContext,
}

impl Pkcs12 {
    pub fn from_der(buf: &[u8], pass: &str) -> Result<Pkcs12, Error> {
        let mut store = try!(PfxImportOptions::new().password(pass).import(buf));
        let mut identity = None;

        for cert in store.certs() {
            if cert.private_key()
                .silent(true)
                .compare_key(true)
                .acquire()
                .is_ok()
            {
                identity = Some(cert);
            }
        }

        let identity = match identity {
            Some(identity) => identity,
            None => {
                return Err(
                    io::Error::new(
                        io::ErrorKind::InvalidInput,
                        "No identity found in PKCS #12 archive",
                    ).into(),
                );
            }
        };

        Ok(Pkcs12 { cert: identity })
    }
}

pub struct Certificate(CertContext);

impl Certificate {
    pub fn from_der(buf: &[u8]) -> Result<Certificate, Error> {
        let cert = try!(CertContext::new(buf));
        Ok(Certificate(cert))
    }
    pub fn from_pem(buf: &[u8]) -> Result<Certificate, Error> {
        match ::std::str::from_utf8(buf) {
            Ok(s) => {
                let cert = try!(CertContext::from_pem(s));
                Ok(Certificate(cert))
            }
            Err(_) => {
                Err(
                    io::Error::new(
                        io::ErrorKind::InvalidInput,
                        "PEM representation contains non-UTF-8 bytes",
                    ).into(),
                )
            }
        }
    }
}

pub struct MidHandshakeTlsStream<S>(tls_stream::MidHandshakeTlsStream<S>);

impl<S> fmt::Debug for MidHandshakeTlsStream<S>
where
    S: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<S> MidHandshakeTlsStream<S>
where
    S: io::Read + io::Write,
{
    pub fn get_ref(&self) -> &S {
        self.0.get_ref()
    }

    pub fn get_mut(&mut self) -> &mut S {
        self.0.get_mut()
    }

    pub fn handshake(self) -> Result<TlsStream<S>, HandshakeError<S>> {
        match self.0.handshake() {
            Ok(s) => Ok(TlsStream(s)),
            Err(e) => Err(e.into()),
        }
    }
}

pub enum HandshakeError<S> {
    Failure(Error),
    Interrupted(MidHandshakeTlsStream<S>),
}

impl<S> From<tls_stream::HandshakeError<S>> for HandshakeError<S> {
    fn from(e: tls_stream::HandshakeError<S>) -> HandshakeError<S> {
        match e {
            tls_stream::HandshakeError::Failure(e) => HandshakeError::Failure(e.into()),
            tls_stream::HandshakeError::Interrupted(s) => {
                HandshakeError::Interrupted(MidHandshakeTlsStream(s))
            }
        }
    }
}

impl<S> From<io::Error> for HandshakeError<S> {
    fn from(e: io::Error) -> HandshakeError<S> {
        HandshakeError::Failure(e.into())
    }
}

pub struct TlsConnectorBuilder(TlsConnector);

impl TlsConnectorBuilder {
    pub fn identity(&mut self, pkcs12: Pkcs12) -> Result<(), Error> {
        self.0.cert = Some(pkcs12.cert);
        Ok(())
    }

    pub fn add_root_certificate(&mut self, cert: Certificate) -> Result<(), Error> {
        try!(self.0.roots.add_cert(&cert.0, CertAdd::ReplaceExisting));
        Ok(())
    }

    pub fn supported_protocols(&mut self, protocols: &[::Protocol]) -> Result<(), Error> {
        self.0.protocols = convert_protocols(protocols);
        Ok(())
    }

    pub fn build(self) -> Result<TlsConnector, Error> {
        Ok(self.0)
    }
}

#[derive(Clone)]
pub struct TlsConnector {
    cert: Option<CertContext>,
    roots: CertStore,
    protocols: Vec<Protocol>,
    callback: Option<Arc<Fn(tls_stream::CertValidationResult) -> io::Result<()> + Sync + Send>>,
}

impl TlsConnector {
    pub fn builder() -> Result<TlsConnectorBuilder, Error> {
        Ok(TlsConnectorBuilder(TlsConnector {
            cert: None,
            roots: try!(Memory::new()).into_store(),
            protocols: vec![Protocol::Tls10, Protocol::Tls11, Protocol::Tls12],
            callback: None,
        }))
    }

    pub fn connect<S>(&self, domain: &str, stream: S) -> Result<TlsStream<S>, HandshakeError<S>>
    where
        S: io::Read + io::Write,
    {
        self._connect(Some(domain), stream)
    }

    pub fn connect_no_domain<S>(&self, stream: S) -> Result<TlsStream<S>, HandshakeError<S>>
    where
        S: io::Read + io::Write,
    {
        self._connect(None, stream)
    }

    fn _connect<S>(
        &self,
        domain: Option<&str>,
        stream: S,
    ) -> Result<TlsStream<S>, HandshakeError<S>>
    where
        S: io::Read + io::Write,
    {
        let mut builder = SchannelCred::builder();
        builder.enabled_protocols(&self.protocols);
        if let Some(cert) = self.cert.as_ref() {
            builder.cert(cert.clone());
        }
        let cred = try!(builder.acquire(Direction::Outbound));
        let mut builder = tls_stream::Builder::new();
        if let Some(domain) = domain {
            builder.domain(domain);
        }
        if let Some(ref callback) = self.callback {
            let callback = callback.clone();
            builder.verify_callback(move |r| callback(r));
        }
        builder.cert_store(self.roots.clone());
        match builder.connect(cred, stream) {
            Ok(s) => Ok(TlsStream(s)),
            Err(e) => Err(e.into()),
        }
    }
}

pub struct TlsAcceptorBuilder(TlsAcceptor);

impl TlsAcceptorBuilder {
    pub fn supported_protocols(&mut self, protocols: &[::Protocol]) -> Result<(), Error> {
        self.0.protocols = convert_protocols(protocols);
        Ok(())
    }

    pub fn build(self) -> Result<TlsAcceptor, Error> {
        Ok(self.0)
    }
}

#[derive(Clone)]
pub struct TlsAcceptor {
    cert: CertContext,
    protocols: Vec<Protocol>,
}

impl TlsAcceptor {
    pub fn builder(pkcs12: Pkcs12) -> Result<TlsAcceptorBuilder, Error> {
        Ok(TlsAcceptorBuilder(TlsAcceptor {
            cert: pkcs12.cert,
            protocols: vec![Protocol::Tls10, Protocol::Tls11, Protocol::Tls12],
        }))
    }

    pub fn accept<S>(&self, stream: S) -> Result<TlsStream<S>, HandshakeError<S>>
    where
        S: io::Read + io::Write,
    {
        let mut builder = SchannelCred::builder();
        builder.enabled_protocols(&self.protocols);
        builder.cert(self.cert.clone());
        // FIXME we're probably missing the certificate chain?
        let cred = try!(builder.acquire(Direction::Inbound));
        match tls_stream::Builder::new().accept(cred, stream) {
            Ok(s) => Ok(TlsStream(s)),
            Err(e) => Err(e.into()),
        }
    }
}

pub struct TlsStream<S>(tls_stream::TlsStream<S>);

impl<S: fmt::Debug> fmt::Debug for TlsStream<S> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<S: io::Read + io::Write> TlsStream<S> {
    pub fn buffered_read_size(&self) -> Result<usize, Error> {
        Ok(self.0.get_buf().len())
    }

    pub fn shutdown(&mut self) -> io::Result<()> {
        try!(self.0.shutdown());
        Ok(())
    }

    pub fn get_ref(&self) -> &S {
        self.0.get_ref()
    }

    pub fn get_mut(&mut self) -> &mut S {
        self.0.get_mut()
    }
}

impl<S: io::Read + io::Write> io::Read for TlsStream<S> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

impl<S: io::Read + io::Write> io::Write for TlsStream<S> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }

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

/// SChannel-specific extensions to `TlsConnectorBuilder`.
pub trait TlsConnectorBuilderExt {
    /// Sets a callback function which decides if the server's certificate chain
    /// is to be trusted.
    fn verify_callback<F>(&mut self, callback: F)
    where
        F: Fn(tls_stream::CertValidationResult) -> io::Result<()> + 'static + Send + Sync;
}

impl TlsConnectorBuilderExt for ::TlsConnectorBuilder {
    fn verify_callback<F>(&mut self, callback: F)
    where
        F: Fn(tls_stream::CertValidationResult) -> io::Result<()> + 'static + Send + Sync,
    {
        (self.0).0.callback = Some(Arc::new(callback));
    }
}

/// SChannel-specific extensions to `TlsStream`.
pub trait TlsStreamExt<S> {
    /// Returns a shared reference to the SChannel `TlsStream`.
    fn raw_stream(&self) -> &tls_stream::TlsStream<S>;

    /// Returns a mutable reference to the SChannel `TlsStream`.
    fn raw_stream_mut(&mut self) -> &mut tls_stream::TlsStream<S>;
}

impl<S> TlsStreamExt<S> for ::TlsStream<S> {
    fn raw_stream(&self) -> &tls_stream::TlsStream<S> {
        &(self.0).0
    }

    fn raw_stream_mut(&mut self) -> &mut tls_stream::TlsStream<S> {
        &mut (self.0).0
    }
}

/// SChannel-specific extensions to `Error`
pub trait ErrorExt {
    /// Extract the underlying SChannel error for inspection.
    fn schannel_error(&self) -> &io::Error;
}

impl ErrorExt for ::Error {
    fn schannel_error(&self) -> &io::Error {
        &(self.0).0
    }
}

/// SChannel-specific extensions to `Certificate`.
pub trait CertificateExt {
    /// builds a native_Tls `Certificate` from an schannel `CertContext`
    fn from_cert_context(CertContext) -> ::Certificate;
}

impl CertificateExt for ::Certificate {
    fn from_cert_context(cert: CertContext) -> ::Certificate {
        ::Certificate(Certificate(cert))
    }
}
<|endoftext|>