<commit_before>/// The event system will have a trigger function that takes an
/// argument that decides if the event will be triggered this tick
/// or the next tick. The default should be next tick to prevent
/// inadvertent infinite loop bugs.
///
/// The event system can then schedule all events handlers that
/// do not mutate components to be run in parallel.
/// All handlers that do mutate the component list can be run
/// sequentially after that. Perhaps we can even schedule
/// those with non-overlapping mutable component lists to
/// run in parallel.
///
/// The event loop should trigger every n ms and execute any
/// events that are queued up. Every event has a function
/// that is called by the trigger! macro that puts the event
/// on the queue.
///
use std::collections::{ HashSet, HashMap };
use std::any::{ Any, TypeId };
use shared_mutex::{ SharedMutex };

pub mod example;

pub trait Handler {
	fn run(self, Vec<&Any>, Vec<&mut Any>);
	fn component_types(self) -> Vec<TypeId>;
	fn mut_component_types(self) -> Vec<TypeId>;
}

pub struct Event {
	pub name: String,
	pub get_handler_instances: fn () -> Vec<Box<Handler>>
}

// The new events sets contain the events that have data in their queues so
// are ready to be ran.
lazy_static! {
	pub static ref THIS_TICK_NEW_EVENTS: SharedMutex<HashSet<String>> = SharedMutex::new(HashSet::new());
	pub static ref NEXT_TICK_NEW_EVENTS: SharedMutex<HashSet<String>> = SharedMutex::new(HashSet::new());
	pub static ref REGISTERED_EVENTS: SharedMutex<HashMap<String, Event>> = SharedMutex::new(HashMap::new());
}

pub fn trigger_this_tick(event_name: &String) {
	let mut new_events_set = THIS_TICK_NEW_EVENTS.write().expect("THIS_TICK_NEW_EVENTS mutex was corrupted.");
	new_events_set.insert(event_name.clone());
}

pub fn trigger_next_tick(event_name: &String) {
	let mut new_events_set = NEXT_TICK_NEW_EVENTS.write().expect("NEXT_TICK_NEW_EVENTS mutex was corrupted.");
	new_events_set.insert(event_name.clone());
}

pub fn register_event(event : Event) {
	let mut events = REGISTERED_EVENTS.write().expect("REGISTERED_EVENTS mutex was corrupted.");
	events.insert(event.name.clone(), event);
}

// Runs a single iteration of the event system. Can be run in a loop to process events
// continuously, but should be interleaved with `next_tick` to progress properly.
pub fn run_events() {
	//{
	//   Get (clone) the events for this tick
	//   Clear the events
	// }
	// Then we get the handlers for the ticks
	// for each handler
	// {
	//  	we obtain the correct component locks
	// 		we run the handlers
	// }
}

// Progresses the system to the next tick.
// Interleave `next_tick` between `run_events` invocations to make sure events that are
// scheduled to run only once per tick are triggered.
// A good scheme could be to run `next_tick` every 16ms, while `run_events` is ran continuously.
pub fn next_tick() {
	// get NEXT_TICK_NEW_EVENTS
	// get THIS_TICK_NEW_EVENTS
	// append NEXT_TICK_NEW_EVENTS to THIS_TICK_NEW_EVENTS
	// same for queues
}

#[macro_export]
macro_rules! event {
	( $name:ident, $( $field_name:ident : $field_typ:ty ),* ) => (
		pub mod $name {
			use shared_mutex::{ SharedMutex };
			use std::any::{ Any, TypeId };
			use entity_rust::events;
			use uuid::Uuid;

			/// Example component
			#[derive(PartialEq,Eq,Clone)]
			pub struct Data {
				$(pub $field_name : $field_typ),*
			}

			pub type HandlerFn = fn(Vec<Data>, Vec<&Any>, Vec<&mut Any>);

			pub struct Handler {
				handler_fn: HandlerFn,
				component_types: Vec<TypeId>,
				mut_component_types: Vec<TypeId>
			}

			pub struct HandlerInstance {
				handler_fn: HandlerFn,
				component_types: Vec<TypeId>,
				mut_component_types: Vec<TypeId>,
				data: Vec<Data>
			}

			impl HandlerInstance {
				pub fn new(h: &Handler, d: Vec<Data>) -> HandlerInstance {
					HandlerInstance {
						handler_fn: h.handler_fn,
						// TODO are these clones really necessary? would be cool if they could be static refs
						component_types: h.component_types.clone(),
						mut_component_types: h.mut_component_types.clone(),
						data: d
					}
				}
			}

			impl events::Handler for HandlerInstance {
				fn run(self, components: Vec<&Any>, mut_components: Vec<&mut Any>) {
					(self.handler_fn)(self.data, components, mut_components)
				}

				fn component_types(self) -> Vec<TypeId> { self.component_types }
				fn mut_component_types(self) -> Vec<TypeId> { self.mut_component_types }
			}

			lazy_static! {
				/// EVENT_UUID is used internally to index events, is randomly
				/// generated at first access.
				pub static ref EVENT_UUID: String = Uuid::new_v4().simple().to_string();
				pub static ref HANDLERS: SharedMutex<Vec<Handler>> = SharedMutex::new(vec![]);
				pub static ref THIS_TICK_DATA: SharedMutex<Vec<Data>> = SharedMutex::new(vec![]);
				pub static ref NEXT_TICK_DATA: SharedMutex<Vec<Data>> = SharedMutex::new(vec![]);
			}

			/// Listeners are a list of functions that should be called by trigger
			pub fn trigger(argument: Data) {
				let mut data = THIS_TICK_DATA.write().expect("THIS_TICK_DATA mutex corrupted");
				data.push(argument);

				events::trigger_this_tick(&*EVENT_UUID);
			}

			pub fn register_handler(handler_fn: HandlerFn, component_types: Vec<TypeId>, mut_component_types: Vec<TypeId>) {
				let mut handlers = HANDLERS.write().expect("Events HANDLERS mutex corrupted");
				let handler = Handler {
					handler_fn : handler_fn,
					// TODO are these clones really necessary? would be cool if they could be static refs
					component_types : component_types.clone(),
					mut_component_types : mut_component_types.clone()
				};
				handlers.push(handler);

				let event = events::Event {
					name: (&*EVENT_UUID).clone(),
					get_handler_instances: get_handler_instances
				};

				events::register_event(event)
			}

			pub fn get_handler_instances() -> Vec<Box<events::Handler>> {
				let mut data_old = THIS_TICK_DATA.write().expect("TICK DATA mutex corrupted");
				let data : Vec<Data> = data_old.drain(..).collect();

				let handlers_lock = HANDLERS.read().expect("HANDLERS mutex corrupted");
				handlers_lock.iter().map(|h|
					//TODO eliminate this data.clone
					Box::new(HandlerInstance::new(h, data.clone())) as Box<events::Handler>
				).collect()
			}
		}
	)
}

/// Queues an event to be dispatched.
/// This means that the argument is put into the trigger queue for the
/// event and the event handlers will be invoked either at the next run loop.
/// or immediately.
macro_rules! trigger {
	() => ()
}
<commit_msg>try implement first part of run loop<commit_after>/// The event system will have a trigger function that takes an
/// argument that decides if the event will be triggered this tick
/// or the next tick. The default should be next tick to prevent
/// inadvertent infinite loop bugs.
///
/// The event system can then schedule all events handlers that
/// do not mutate components to be run in parallel.
/// All handlers that do mutate the component list can be run
/// sequentially after that. Perhaps we can even schedule
/// those with non-overlapping mutable component lists to
/// run in parallel.
///
/// The event loop should trigger every n ms and execute any
/// events that are queued up. Every event has a function
/// that is called by the trigger! macro that puts the event
/// on the queue.
///
use std::collections::{ HashSet, HashMap };
use std::any::{ Any, TypeId };
use shared_mutex::{ SharedMutex };

pub mod example;

pub trait Handler {
	fn run(self, Vec<&Any>, Vec<&mut Any>);
	fn component_types(self) -> Vec<TypeId>;
	fn mut_component_types(self) -> Vec<TypeId>;
}

#[derive(Clone)]
pub struct Event {
	pub name: String,
	pub get_handler_instances: fn () -> Vec<Box<Handler>>
}

// The new events sets contain the events that have data in their queues so
// are ready to be ran.
lazy_static! {
	pub static ref THIS_TICK_NEW_EVENTS: SharedMutex<HashSet<String>> = SharedMutex::new(HashSet::new());
	pub static ref NEXT_TICK_NEW_EVENTS: SharedMutex<HashSet<String>> = SharedMutex::new(HashSet::new());
	pub static ref REGISTERED_EVENTS: SharedMutex<HashMap<String, Event>> = SharedMutex::new(HashMap::new());
}

pub fn trigger_this_tick(event_name: &String) {
	let mut new_events_set = THIS_TICK_NEW_EVENTS.write().expect("THIS_TICK_NEW_EVENTS mutex was corrupted.");
	new_events_set.insert(event_name.clone());
}

pub fn trigger_next_tick(event_name: &String) {
	let mut new_events_set = NEXT_TICK_NEW_EVENTS.write().expect("NEXT_TICK_NEW_EVENTS mutex was corrupted.");
	new_events_set.insert(event_name.clone());
}

pub fn register_event(event : Event) {
	let mut events = REGISTERED_EVENTS.write().expect("REGISTERED_EVENTS mutex was corrupted.");
	events.insert(event.name.clone(), event);
}

// Runs a single iteration of the event system. Can be run in a loop to process events
// continuously, but should be interleaved with `next_tick` to progress properly.
pub fn run_events() {
	let events = {
		let event_names = {
			let mut event_names_lock = THIS_TICK_NEW_EVENTS.write().expect("THIS_TICK_NEW_EVENTS mutex was corrupted");
			event_names_lock.drain().collect()
		};

		let events_lock = REGISTERED_EVENTS.read().expect("REGISTERED_EVENTS mutex was corrupted");

		event_names.iter().map(|n|
			events_lock.get(&*n).cloned().expect("Unknown event triggered")
		)
	};
	// Then we get the handlers for the ticks
	// for each handler
	// {
	//  	we obtain the correct component locks
	// 		we run the handlers
	// }
}

// Progresses the system to the next tick.
// Interleave `next_tick` between `run_events` invocations to make sure events that are
// scheduled to run only once per tick are triggered.
// A good scheme could be to run `next_tick` every 16ms, while `run_events` is ran continuously.
pub fn next_tick() {
	// get NEXT_TICK_NEW_EVENTS
	// get THIS_TICK_NEW_EVENTS
	// append NEXT_TICK_NEW_EVENTS to THIS_TICK_NEW_EVENTS
	// same for queues
}

#[macro_export]
macro_rules! event {
	( $name:ident, $( $field_name:ident : $field_typ:ty ),* ) => (
		pub mod $name {
			use shared_mutex::{ SharedMutex };
			use std::any::{ Any, TypeId };
			use entity_rust::events;
			use uuid::Uuid;

			/// Example component
			#[derive(PartialEq,Eq,Clone)]
			pub struct Data {
				$(pub $field_name : $field_typ),*
			}

			pub type HandlerFn = fn(Vec<Data>, Vec<&Any>, Vec<&mut Any>);

			pub struct Handler {
				handler_fn: HandlerFn,
				component_types: Vec<TypeId>,
				mut_component_types: Vec<TypeId>
			}

			pub struct HandlerInstance {
				handler_fn: HandlerFn,
				component_types: Vec<TypeId>,
				mut_component_types: Vec<TypeId>,
				data: Vec<Data>
			}

			impl HandlerInstance {
				pub fn new(h: &Handler, d: Vec<Data>) -> HandlerInstance {
					HandlerInstance {
						handler_fn: h.handler_fn,
						// TODO are these clones really necessary? would be cool if they could be static refs
						component_types: h.component_types.clone(),
						mut_component_types: h.mut_component_types.clone(),
						data: d
					}
				}
			}

			impl events::Handler for HandlerInstance {
				fn run(self, components: Vec<&Any>, mut_components: Vec<&mut Any>) {
					(self.handler_fn)(self.data, components, mut_components)
				}

				fn component_types(self) -> Vec<TypeId> { self.component_types }
				fn mut_component_types(self) -> Vec<TypeId> { self.mut_component_types }
			}

			lazy_static! {
				/// EVENT_UUID is used internally to index events, is randomly
				/// generated at first access.
				pub static ref EVENT_UUID: String = Uuid::new_v4().simple().to_string();
				pub static ref HANDLERS: SharedMutex<Vec<Handler>> = SharedMutex::new(vec![]);
				pub static ref THIS_TICK_DATA: SharedMutex<Vec<Data>> = SharedMutex::new(vec![]);
				pub static ref NEXT_TICK_DATA: SharedMutex<Vec<Data>> = SharedMutex::new(vec![]);
			}

			/// Listeners are a list of functions that should be called by trigger
			pub fn trigger(argument: Data) {
				let mut data = THIS_TICK_DATA.write().expect("THIS_TICK_DATA mutex corrupted");
				data.push(argument);

				events::trigger_this_tick(&*EVENT_UUID);
			}

			pub fn register_handler(handler_fn: HandlerFn, component_types: Vec<TypeId>, mut_component_types: Vec<TypeId>) {
				let mut handlers = HANDLERS.write().expect("Events HANDLERS mutex corrupted");
				let handler = Handler {
					handler_fn : handler_fn,
					// TODO are these clones really necessary? would be cool if they could be static refs
					component_types : component_types.clone(),
					mut_component_types : mut_component_types.clone()
				};
				handlers.push(handler);

				let event = events::Event {
					name: (&*EVENT_UUID).clone(),
					get_handler_instances: get_handler_instances
				};

				events::register_event(event)
			}

			pub fn get_handler_instances() -> Vec<Box<events::Handler>> {
				let mut data_old = THIS_TICK_DATA.write().expect("TICK DATA mutex corrupted");
				let data : Vec<Data> = data_old.drain(..).collect();

				let handlers_lock = HANDLERS.read().expect("HANDLERS mutex corrupted");
				handlers_lock.iter().map(|h|
					//TODO eliminate this data.clone
					Box::new(HandlerInstance::new(h, data.clone())) as Box<events::Handler>
				).collect()
			}
		}
	)
}

/// Queues an event to be dispatched.
/// This means that the argument is put into the trigger queue for the
/// event and the event handlers will be invoked either at the next run loop.
/// or immediately.
macro_rules! trigger {
	() => ()
}
<|endoftext|>


<commit_before>use std::convert::{From, TryFrom, TryInto};
use std::str::FromStr;
use stack::Stack;
use operate::Operate;

#[derive(Debug, Copy, Clone)]
pub enum Arithm<T, O: Operate<T>> {
    Operand(T),
    Operator(O),
}

#[derive(Debug)]
pub struct Expression<T, O: Operate<T>>(Vec<Arithm<T, O>>);

impl<T: Copy, O: Operate<T> + Copy> Expression<T, O> {
    pub fn operate(&self) -> Result<T, O::Err> {
        let mut stack = Stack::new();
        for arithm in &self.0 {
            match *arithm {
                Arithm::Operand(operand) => stack.push(operand),
                Arithm::Operator(operator) => operator.operate(&mut stack)?,
            }
        }
        Ok(stack.pop().unwrap())
    }
}

#[derive(Debug, PartialEq)]
pub enum ExprResult<A, B> {
    TooManyOperands,
    NotEnoughOperand,
    InvalidToken(A, B),
}

use self::ExprResult::*;

impl<'a, T, O> TryFrom<&'a str> for Expression<T, O>
    where T: FromStr,
          O: Operate<T> + TryFrom<&'a str>
{
    type Err = ExprResult<<T as FromStr>::Err, <O as TryFrom<&'a str>>::Err>;
    fn try_from(expr: &'a str) -> Result<Self, Self::Err> {
        let mut final_expr = Vec::new();
        let mut num_operands: usize = 0;
        for token in expr.split_whitespace() {
            let arithm = match token.parse() {
                Ok(operand) => {
                    num_operands += 1;
                    Arithm::Operand(operand)
                }
                Err(operand_err) => {
                    match TryInto::<O>::try_into(token) {
                        Ok(operator) => {
                            let needed = operator.operands_needed();
                            num_operands = num_operands.checked_sub(needed)
                                .ok_or(NotEnoughOperand)?;
                            num_operands += operator.operands_generated();
                            Arithm::Operator(operator)
                        }
                        Err(operator_err) => return Err(InvalidToken(operand_err, operator_err)),
                    }
                }
            };
            final_expr.push(arithm);
        }
        match num_operands {
            0 => Err(NotEnoughOperand),
            1 => Ok(Expression(final_expr)),
            _ => Err(TooManyOperands),
        }
    }
}

impl<T, O: Operate<T>> From<Vec<Arithm<T, O>>> for Expression<T, O> {
    fn from(expr: Vec<Arithm<T, O>>) -> Self {
        Expression(expr)
    }
}

impl<T, O: Operate<T>> Into<Vec<Arithm<T, O>>> for Expression<T, O> {
    fn into(self) -> Vec<Arithm<T, O>> {
        self.0
    }
}
<commit_msg>expression: Add deref_mut to help managing expressions<commit_after>use std::convert::{From, TryFrom, TryInto};
use std::ops::{Deref, DerefMut};
use std::str::FromStr;
use stack::Stack;
use operate::Operate;

#[derive(Debug, Copy, Clone)]
pub enum Arithm<T, O: Operate<T>> {
    Operand(T),
    Operator(O),
}

#[derive(Debug)]
pub struct Expression<T, O: Operate<T>>(Vec<Arithm<T, O>>);

impl<T: Copy, O: Operate<T> + Copy> Expression<T, O> {
    pub fn operate(&self) -> Result<T, O::Err> {
        let mut stack = Stack::new();
        for arithm in &self.0 {
            match *arithm {
                Arithm::Operand(operand) => stack.push(operand),
                Arithm::Operator(operator) => operator.operate(&mut stack)?,
            }
        }
        Ok(stack.pop().unwrap())
    }
}

#[derive(Debug, PartialEq)]
pub enum ExprResult<A, B> {
    TooManyOperands,
    NotEnoughOperand,
    InvalidToken(A, B),
}

use self::ExprResult::*;

impl<'a, T, O> TryFrom<&'a str> for Expression<T, O>
    where T: FromStr,
          O: Operate<T> + TryFrom<&'a str>
{
    type Err = ExprResult<<T as FromStr>::Err, <O as TryFrom<&'a str>>::Err>;
    fn try_from(expr: &'a str) -> Result<Self, Self::Err> {
        let mut final_expr = Vec::new();
        let mut num_operands: usize = 0;
        for token in expr.split_whitespace() {
            let arithm = match token.parse() {
                Ok(operand) => {
                    num_operands += 1;
                    Arithm::Operand(operand)
                }
                Err(operand_err) => {
                    match TryInto::<O>::try_into(token) {
                        Ok(operator) => {
                            let needed = operator.operands_needed();
                            num_operands = num_operands.checked_sub(needed)
                                .ok_or(NotEnoughOperand)?;
                            num_operands += operator.operands_generated();
                            Arithm::Operator(operator)
                        }
                        Err(operator_err) => return Err(InvalidToken(operand_err, operator_err)),
                    }
                }
            };
            final_expr.push(arithm);
        }
        match num_operands {
            0 => Err(NotEnoughOperand),
            1 => Ok(Expression(final_expr)),
            _ => Err(TooManyOperands),
        }
    }
}

impl<T, O: Operate<T>> From<Vec<Arithm<T, O>>> for Expression<T, O> {
    fn from(expr: Vec<Arithm<T, O>>) -> Self {
        Expression(expr)
    }
}

impl<T, O: Operate<T>> Into<Vec<Arithm<T, O>>> for Expression<T, O> {
    fn into(self) -> Vec<Arithm<T, O>> {
        self.0
    }
}

impl<T, O: Operate<T>> Deref for Expression<T, O> {
    type Target = Vec<Arithm<T, O>>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<T, O: Operate<T>> DerefMut for Expression<T, O> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
<|endoftext|>


<commit_before>
// generics
struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn swap(&mut self) {
        std::mem::swap(&mut self.x, &mut self.y);
    }
}

fn main() {

}
<commit_msg>got a set of traits knowledge<commit_after>
// generics
struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn swap(&mut self) {
        std::mem::swap(&mut self.x, &mut self.y);
    }
}

impl<T: PartialEq> Point<T> {
    fn is_uniform(&self) -> bool {
        self.x == self.y
    }
}

struct Circle {
    radius: f64,
}

trait HasArea {
    fn area(&self) -> f64;
}

impl HasArea for Circle {
    fn area(&self) -> f64 {
        std::f64::consts::PI * (self.radius * self.radius)
    }
}

struct Square {
    length: f64,
    width: f64,
}

impl HasArea for Square {
    fn area(&self) -> f64 {
        self.length * self.width
    }
}

fn main() {
    let c = Circle { radius: 1.2 };

    println!("{}", c.area());

    let s = Square { length: 1.2, width: 4.5 };
    print_area(s);
}

fn print_area<T: HasArea>(shape: T) {
    println!("{}", shape.area());
}

// multiple trait bound use + sign
use std::fmt::Debug;

fn foo<T: Clone + Debug>(x: T) {
    x.clone();
    println!("{:?}", x);
}

// where clause
fn bar<T, K>(x: T, y: K) where T: Clone, K: Clone + Debug {
    x.clone();
    println!("{:?}", y);
}

// inheritence
trait Foo {
}

trait Bar : Foo {
}
<|endoftext|>


<commit_before><commit_msg>generics basics<commit_after>
// generics
struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn swap(&mut self) {
        std::mem::swap(&mut self.x, &mut self.y);
    }
}

fn main() {

}
<|endoftext|>


<commit_before>use crate::{
    channel::Channel,
    channels::Channels,
    configuration::Configuration,
    connection_closer::ConnectionCloser,
    connection_properties::ConnectionProperties,
    connection_status::{ConnectionState, ConnectionStatus, ConnectionStep},
    executor::{DefaultExecutor, Executor},
    frames::Frames,
    internal_rpc::{InternalRPC, InternalRPCHandle},
    io_loop::IoLoop,
    reactor::DefaultReactorBuilder,
    socket_state::{SocketState, SocketStateHandle},
    tcp::{AMQPUriTcpExt, HandshakeResult, TLSConfig},
    thread::ThreadHandle,
    types::ShortUInt,
    uri::AMQPUri,
    Error, Promise, PromiseChain, Result,
};
use amq_protocol::frame::{AMQPFrame, ProtocolVersion};
use log::{log_enabled, Level::Trace};
use std::{fmt, io, sync::Arc};

pub struct Connection {
    configuration: Configuration,
    status: ConnectionStatus,
    channels: Channels,
    io_loop: ThreadHandle,
    closer: Arc<ConnectionCloser>,
}

impl Connection {
    fn new(
        waker: SocketStateHandle,
        internal_rpc: InternalRPCHandle,
        frames: Frames,
        executor: Arc<dyn Executor>,
    ) -> Self {
        let configuration = Configuration::default();
        let status = ConnectionStatus::default();
        let channels = Channels::new(
            configuration.clone(),
            status.clone(),
            waker,
            internal_rpc.clone(),
            frames,
            executor,
        );
        let closer = Arc::new(ConnectionCloser::new(status.clone(), internal_rpc));
        let connection = Self {
            configuration,
            status,
            channels,
            io_loop: ThreadHandle::default(),
            closer,
        };

        connection.channels.create_zero();
        connection
    }

    /// Connect to an AMQP Server
    pub fn connect(uri: &str, options: ConnectionProperties) -> PromiseChain<Connection> {
        Connect::connect(uri, options, TLSConfig::default())
    }

    /// Connect to an AMQP Server
    pub fn connect_with_config(
        uri: &str,
        options: ConnectionProperties,
        config: TLSConfig<'_, '_, '_>,
    ) -> PromiseChain<Connection> {
        Connect::connect(uri, options, config)
    }

    /// Connect to an AMQP Server
    pub fn connect_uri(uri: AMQPUri, options: ConnectionProperties) -> PromiseChain<Connection> {
        Connect::connect(uri, options, TLSConfig::default())
    }

    /// Connect to an AMQP Server
    pub fn connect_uri_with_identity(
        uri: AMQPUri,
        options: ConnectionProperties,
        config: TLSConfig<'_, '_, '_>,
    ) -> PromiseChain<Connection> {
        Connect::connect(uri, options, config)
    }

    pub fn create_channel(&self) -> PromiseChain<Channel> {
        if !self.status.connected() {
            return PromiseChain::new_with_data(Err(Error::InvalidConnectionState(
                self.status.state(),
            )));
        }
        match self.channels.create(self.closer.clone()) {
            Ok(channel) => channel.clone().channel_open(channel),
            Err(error) => PromiseChain::new_with_data(Err(error)),
        }
    }

    /// Block current thread while the connection is still active.
    /// This is useful when you only have a consumer and nothing else keeping your application
    /// "alive".
    pub fn run(self) -> Result<()> {
        let io_loop = self.io_loop.clone();
        drop(self);
        io_loop.wait("io loop")
    }

    pub fn on_error<E: FnMut(Error) + Send + 'static>(&self, handler: E) {
        self.channels.set_error_handler(handler);
    }

    pub fn configuration(&self) -> &Configuration {
        &self.configuration
    }

    pub fn status(&self) -> &ConnectionStatus {
        &self.status
    }

    pub fn close(&self, reply_code: ShortUInt, reply_text: &str) -> Promise<()> {
        self.channels
            .get(0)
            .map(|channel0| channel0.connection_close(reply_code, reply_text, 0, 0))
            .unwrap_or_else(|| Promise::new_with_data(Ok(())))
    }

    /// Block all consumers and publishers on this connection
    pub fn block(&self, reason: &str) -> Promise<()> {
        self.channels
            .get(0)
            .map(|channel0| channel0.connection_blocked(reason))
            .unwrap_or_else(|| {
                Promise::new_with_data(Err(Error::InvalidConnectionState(self.status.state())))
            })
    }

    /// Unblock all consumers and publishers on this connection
    pub fn unblock(&self) -> Promise<()> {
        self.channels
            .get(0)
            .map(|channel0| channel0.connection_unblocked())
            .unwrap_or_else(|| {
                Promise::new_with_data(Err(Error::InvalidConnectionState(self.status.state())))
            })
    }

    /// Update the secret used by some authentication module such as OAuth2
    pub fn update_secret(&self, new_secret: &str, reason: &str) -> Promise<()> {
        self.channels
            .get(0)
            .map(|channel0| channel0.connection_update_secret(new_secret, reason))
            .unwrap_or_else(|| {
                Promise::new_with_data(Err(Error::InvalidConnectionState(self.status.state())))
            })
    }

    pub fn connector(
        mut options: ConnectionProperties,
    ) -> impl FnOnce(AMQPUri, HandshakeResult) -> PromiseChain<Connection> + 'static {
        move |uri, handshake_result| {
            let executor = options
                .executor
                .take()
                .unwrap_or_else(|| Arc::new(DefaultExecutor::default()));
            let reactor_builder = options
                .reactor_builder
                .take()
                .unwrap_or_else(|| Arc::new(DefaultReactorBuilder));
            let socket_state = SocketState::default();
            let waker = socket_state.handle();
            let internal_rpc = InternalRPC::new(executor.clone(), waker.clone());
            let frames = Frames::default();
            let conn = Connection::new(waker, internal_rpc.handle(), frames.clone(), executor);
            let status = conn.status.clone();
            let configuration = conn.configuration.clone();
            status.set_vhost(&uri.vhost);
            status.set_username(&uri.authority.userinfo.username);
            if let Some(frame_max) = uri.query.frame_max {
                configuration.set_frame_max(frame_max);
            }
            if let Some(channel_max) = uri.query.channel_max {
                configuration.set_channel_max(channel_max);
            }
            if let Some(heartbeat) = uri.query.heartbeat {
                configuration.set_heartbeat(heartbeat);
            }
            let (promise, resolver) = Promise::new();
            if log_enabled!(Trace) {
                promise.set_marker("ProtocolHeader".into());
            }
            let channels = conn.channels.clone();
            channels.get(0).map(|channel0| {
                channel0.send_frame(
                    AMQPFrame::ProtocolHeader(ProtocolVersion::amqp_0_9_1()),
                    resolver,
                    None,
                )
            });
            let (promise, resolver) = PromiseChain::after(promise);
            if log_enabled!(Trace) {
                promise.set_marker("ProtocolHeader.Ok".into());
            }
            let io_loop_handle = conn.io_loop.clone();
            status.set_state(ConnectionState::Connecting);
            status.set_connection_step(ConnectionStep::ProtocolHeader(
                resolver,
                conn,
                uri.authority.userinfo.into(),
                uri.query.auth_mechanism.unwrap_or_default(),
                options,
            ));
            IoLoop::new(
                status,
                configuration,
                channels,
                internal_rpc,
                frames,
                socket_state,
                io_loop_handle,
                handshake_result,
                &*reactor_builder,
            )
            .and_then(IoLoop::start)
            .map(|()| promise)
            .unwrap_or_else(|err| PromiseChain::new_with_data(Err(err)))
        }
    }
}

impl fmt::Debug for Connection {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Connection")
            .field("configuration", &self.configuration)
            .field("status", &self.status)
            .field("channels", &self.channels)
            .finish()
    }
}

/// Trait providing a method to connect to an AMQP server
pub trait Connect {
    /// connect to an AMQP server
    fn connect(
        self,
        options: ConnectionProperties,
        config: TLSConfig<'_, '_, '_>,
    ) -> PromiseChain<Connection>;
}

impl Connect for AMQPUri {
    fn connect(
        self,
        options: ConnectionProperties,
        config: TLSConfig<'_, '_, '_>,
    ) -> PromiseChain<Connection> {
        let stream = AMQPUriTcpExt::connect_with_config(&self, config);
        Connection::connector(options)(self, stream)
    }
}

impl Connect for &str {
    fn connect(
        self,
        options: ConnectionProperties,
        config: TLSConfig<'_, '_, '_>,
    ) -> PromiseChain<Connection> {
        match self.parse::<AMQPUri>() {
            Ok(uri) => Connect::connect(uri, options, config),
            Err(err) => {
                PromiseChain::new_with_data(Err(io::Error::new(io::ErrorKind::Other, err).into()))
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use env_logger;

    use super::*;
    use crate::channel_receiver_state::ChannelReceiverState;
    use crate::channel_status::ChannelState;
    use crate::types::ShortString;
    use crate::BasicProperties;
    use amq_protocol::frame::AMQPContentHeader;
    use amq_protocol::protocol::{basic, AMQPClass};

    #[test]
    fn basic_consume_small_payload() {
        let _ = env_logger::try_init();

        use crate::consumer::Consumer;
        use crate::queue::{Queue, QueueState};

        // Bootstrap connection state to a consuming state
        let executor = Arc::new(DefaultExecutor::default());
        let socket_state = SocketState::default();
        let waker = socket_state.handle();
        let internal_rpc = InternalRPC::new(executor.clone(), waker.clone());
        let conn = Connection::new(
            waker,
            internal_rpc.handle(),
            Frames::default(),
            executor.clone(),
        );
        conn.status.set_state(ConnectionState::Connected);
        conn.configuration.set_channel_max(2047);
        let channel = conn.channels.create(conn.closer.clone()).unwrap();
        channel.set_state(ChannelState::Connected);
        let queue_name = ShortString::from("consumed");
        let mut queue: QueueState = Queue::new(queue_name.clone(), 0, 0).into();
        let consumer_tag = ShortString::from("consumer-tag");
        let consumer = Consumer::new(consumer_tag.clone(), executor);
        queue.register_consumer(consumer_tag.clone(), consumer);
        conn.channels
            .get(channel.id())
            .map(|c| c.register_queue(queue));
        // Now test the state machine behaviour
        {
            let method = AMQPClass::Basic(basic::AMQPMethod::Deliver(basic::Deliver {
                consumer_tag: consumer_tag.clone(),
                delivery_tag: 1,
                redelivered: false,
                exchange: "".into(),
                routing_key: queue_name.clone(),
            }));
            let class_id = method.get_amqp_class_id();
            let deliver_frame = AMQPFrame::Method(channel.id(), method);
            conn.channels.handle_frame(deliver_frame).unwrap();
            let channel_state = channel.status().receiver_state();
            let expected_state = ChannelReceiverState::WillReceiveContent(
                class_id,
                Some(queue_name.clone()),
                Some(consumer_tag.clone()),
            );
            assert_eq!(channel_state, expected_state);
        }
        {
            let header_frame = AMQPFrame::Header(
                channel.id(),
                60,
                Box::new(AMQPContentHeader {
                    class_id: 60,
                    weight: 0,
                    body_size: 2,
                    properties: BasicProperties::default(),
                }),
            );
            conn.channels.handle_frame(header_frame).unwrap();
            let channel_state = channel.status().receiver_state();
            let expected_state = ChannelReceiverState::ReceivingContent(
                Some(queue_name.clone()),
                Some(consumer_tag.clone()),
                2,
            );
            assert_eq!(channel_state, expected_state);
        }
        {
            let body_frame = AMQPFrame::Body(channel.id(), "{}".as_bytes().to_vec());
            conn.channels.handle_frame(body_frame).unwrap();
            let channel_state = channel.status().state();
            let expected_state = ChannelState::Connected;
            assert_eq!(channel_state, expected_state);
        }
    }

    #[test]
    fn basic_consume_empty_payload() {
        let _ = env_logger::try_init();

        use crate::consumer::Consumer;
        use crate::queue::{Queue, QueueState};

        // Bootstrap connection state to a consuming state
        let socket_state = SocketState::default();
        let waker = socket_state.handle();
        let executor = Arc::new(DefaultExecutor::default());
        let internal_rpc = InternalRPC::new(executor.clone(), waker.clone());
        let conn = Connection::new(
            waker,
            internal_rpc.handle(),
            Frames::default(),
            executor.clone(),
        );
        conn.status.set_state(ConnectionState::Connected);
        conn.configuration.set_channel_max(2047);
        let channel = conn.channels.create(conn.closer.clone()).unwrap();
        channel.set_state(ChannelState::Connected);
        let queue_name = ShortString::from("consumed");
        let mut queue: QueueState = Queue::new(queue_name.clone(), 0, 0).into();
        let consumer_tag = ShortString::from("consumer-tag");
        let consumer = Consumer::new(consumer_tag.clone(), executor);
        queue.register_consumer(consumer_tag.clone(), consumer);
        conn.channels
            .get(channel.id())
            .map(|c| c.register_queue(queue));
        // Now test the state machine behaviour
        {
            let method = AMQPClass::Basic(basic::AMQPMethod::Deliver(basic::Deliver {
                consumer_tag: consumer_tag.clone(),
                delivery_tag: 1,
                redelivered: false,
                exchange: "".into(),
                routing_key: queue_name.clone(),
            }));
            let class_id = method.get_amqp_class_id();
            let deliver_frame = AMQPFrame::Method(channel.id(), method);
            conn.channels.handle_frame(deliver_frame).unwrap();
            let channel_state = channel.status().receiver_state();
            let expected_state = ChannelReceiverState::WillReceiveContent(
                class_id,
                Some(queue_name.clone()),
                Some(consumer_tag.clone()),
            );
            assert_eq!(channel_state, expected_state);
        }
        {
            let header_frame = AMQPFrame::Header(
                channel.id(),
                60,
                Box::new(AMQPContentHeader {
                    class_id: 60,
                    weight: 0,
                    body_size: 0,
                    properties: BasicProperties::default(),
                }),
            );
            conn.channels.handle_frame(header_frame).unwrap();
            let channel_state = channel.status().state();
            let expected_state = ChannelState::Connected;
            assert_eq!(channel_state, expected_state);
        }
    }
}
<commit_msg>silence clippy<commit_after>use crate::{
    channel::Channel,
    channels::Channels,
    configuration::Configuration,
    connection_closer::ConnectionCloser,
    connection_properties::ConnectionProperties,
    connection_status::{ConnectionState, ConnectionStatus, ConnectionStep},
    executor::{DefaultExecutor, Executor},
    frames::Frames,
    internal_rpc::{InternalRPC, InternalRPCHandle},
    io_loop::IoLoop,
    reactor::DefaultReactorBuilder,
    socket_state::{SocketState, SocketStateHandle},
    tcp::{AMQPUriTcpExt, HandshakeResult, TLSConfig},
    thread::ThreadHandle,
    types::ShortUInt,
    uri::AMQPUri,
    Error, Promise, PromiseChain, Result,
};
use amq_protocol::frame::{AMQPFrame, ProtocolVersion};
use log::{log_enabled, Level::Trace};
use std::{fmt, io, sync::Arc};

pub struct Connection {
    configuration: Configuration,
    status: ConnectionStatus,
    channels: Channels,
    io_loop: ThreadHandle,
    closer: Arc<ConnectionCloser>,
}

impl Connection {
    fn new(
        waker: SocketStateHandle,
        internal_rpc: InternalRPCHandle,
        frames: Frames,
        executor: Arc<dyn Executor>,
    ) -> Self {
        let configuration = Configuration::default();
        let status = ConnectionStatus::default();
        let channels = Channels::new(
            configuration.clone(),
            status.clone(),
            waker,
            internal_rpc.clone(),
            frames,
            executor,
        );
        let closer = Arc::new(ConnectionCloser::new(status.clone(), internal_rpc));
        let connection = Self {
            configuration,
            status,
            channels,
            io_loop: ThreadHandle::default(),
            closer,
        };

        connection.channels.create_zero();
        connection
    }

    /// Connect to an AMQP Server
    pub fn connect(uri: &str, options: ConnectionProperties) -> PromiseChain<Connection> {
        Connect::connect(uri, options, TLSConfig::default())
    }

    /// Connect to an AMQP Server
    pub fn connect_with_config(
        uri: &str,
        options: ConnectionProperties,
        config: TLSConfig<'_, '_, '_>,
    ) -> PromiseChain<Connection> {
        Connect::connect(uri, options, config)
    }

    /// Connect to an AMQP Server
    pub fn connect_uri(uri: AMQPUri, options: ConnectionProperties) -> PromiseChain<Connection> {
        Connect::connect(uri, options, TLSConfig::default())
    }

    /// Connect to an AMQP Server
    pub fn connect_uri_with_identity(
        uri: AMQPUri,
        options: ConnectionProperties,
        config: TLSConfig<'_, '_, '_>,
    ) -> PromiseChain<Connection> {
        Connect::connect(uri, options, config)
    }

    pub fn create_channel(&self) -> PromiseChain<Channel> {
        if !self.status.connected() {
            return PromiseChain::new_with_data(Err(Error::InvalidConnectionState(
                self.status.state(),
            )));
        }
        match self.channels.create(self.closer.clone()) {
            Ok(channel) => channel.clone().channel_open(channel),
            Err(error) => PromiseChain::new_with_data(Err(error)),
        }
    }

    /// Block current thread while the connection is still active.
    /// This is useful when you only have a consumer and nothing else keeping your application
    /// "alive".
    pub fn run(self) -> Result<()> {
        let io_loop = self.io_loop.clone();
        drop(self);
        io_loop.wait("io loop")
    }

    pub fn on_error<E: FnMut(Error) + Send + 'static>(&self, handler: E) {
        self.channels.set_error_handler(handler);
    }

    pub fn configuration(&self) -> &Configuration {
        &self.configuration
    }

    pub fn status(&self) -> &ConnectionStatus {
        &self.status
    }

    pub fn close(&self, reply_code: ShortUInt, reply_text: &str) -> Promise<()> {
        self.channels
            .get(0)
            .map(|channel0| channel0.connection_close(reply_code, reply_text, 0, 0))
            .unwrap_or_else(|| Promise::new_with_data(Ok(())))
    }

    /// Block all consumers and publishers on this connection
    pub fn block(&self, reason: &str) -> Promise<()> {
        self.channels
            .get(0)
            .map(|channel0| channel0.connection_blocked(reason))
            .unwrap_or_else(|| {
                Promise::new_with_data(Err(Error::InvalidConnectionState(self.status.state())))
            })
    }

    /// Unblock all consumers and publishers on this connection
    pub fn unblock(&self) -> Promise<()> {
        self.channels
            .get(0)
            .map(|channel0| channel0.connection_unblocked())
            .unwrap_or_else(|| {
                Promise::new_with_data(Err(Error::InvalidConnectionState(self.status.state())))
            })
    }

    /// Update the secret used by some authentication module such as OAuth2
    pub fn update_secret(&self, new_secret: &str, reason: &str) -> Promise<()> {
        self.channels
            .get(0)
            .map(|channel0| channel0.connection_update_secret(new_secret, reason))
            .unwrap_or_else(|| {
                Promise::new_with_data(Err(Error::InvalidConnectionState(self.status.state())))
            })
    }

    pub fn connector(
        mut options: ConnectionProperties,
    ) -> impl FnOnce(AMQPUri, HandshakeResult) -> PromiseChain<Connection> + 'static {
        move |uri, handshake_result| {
            let executor = options
                .executor
                .take()
                .unwrap_or_else(|| Arc::new(DefaultExecutor::default()));
            let reactor_builder = options
                .reactor_builder
                .take()
                .unwrap_or_else(|| Arc::new(DefaultReactorBuilder));
            let socket_state = SocketState::default();
            let waker = socket_state.handle();
            let internal_rpc = InternalRPC::new(executor.clone(), waker.clone());
            let frames = Frames::default();
            let conn = Connection::new(waker, internal_rpc.handle(), frames.clone(), executor);
            let status = conn.status.clone();
            let configuration = conn.configuration.clone();
            status.set_vhost(&uri.vhost);
            status.set_username(&uri.authority.userinfo.username);
            if let Some(frame_max) = uri.query.frame_max {
                configuration.set_frame_max(frame_max);
            }
            if let Some(channel_max) = uri.query.channel_max {
                configuration.set_channel_max(channel_max);
            }
            if let Some(heartbeat) = uri.query.heartbeat {
                configuration.set_heartbeat(heartbeat);
            }
            let (promise, resolver) = Promise::new();
            if log_enabled!(Trace) {
                promise.set_marker("ProtocolHeader".into());
            }
            let channels = conn.channels.clone();
            if let Some(channel0) = channels.get(0) {
                channel0.send_frame(
                    AMQPFrame::ProtocolHeader(ProtocolVersion::amqp_0_9_1()),
                    resolver,
                    None,
                )
            };
            let (promise, resolver) = PromiseChain::after(promise);
            if log_enabled!(Trace) {
                promise.set_marker("ProtocolHeader.Ok".into());
            }
            let io_loop_handle = conn.io_loop.clone();
            status.set_state(ConnectionState::Connecting);
            status.set_connection_step(ConnectionStep::ProtocolHeader(
                resolver,
                conn,
                uri.authority.userinfo.into(),
                uri.query.auth_mechanism.unwrap_or_default(),
                options,
            ));
            IoLoop::new(
                status,
                configuration,
                channels,
                internal_rpc,
                frames,
                socket_state,
                io_loop_handle,
                handshake_result,
                &*reactor_builder,
            )
            .and_then(IoLoop::start)
            .map(|()| promise)
            .unwrap_or_else(|err| PromiseChain::new_with_data(Err(err)))
        }
    }
}

impl fmt::Debug for Connection {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Connection")
            .field("configuration", &self.configuration)
            .field("status", &self.status)
            .field("channels", &self.channels)
            .finish()
    }
}

/// Trait providing a method to connect to an AMQP server
pub trait Connect {
    /// connect to an AMQP server
    fn connect(
        self,
        options: ConnectionProperties,
        config: TLSConfig<'_, '_, '_>,
    ) -> PromiseChain<Connection>;
}

impl Connect for AMQPUri {
    fn connect(
        self,
        options: ConnectionProperties,
        config: TLSConfig<'_, '_, '_>,
    ) -> PromiseChain<Connection> {
        let stream = AMQPUriTcpExt::connect_with_config(&self, config);
        Connection::connector(options)(self, stream)
    }
}

impl Connect for &str {
    fn connect(
        self,
        options: ConnectionProperties,
        config: TLSConfig<'_, '_, '_>,
    ) -> PromiseChain<Connection> {
        match self.parse::<AMQPUri>() {
            Ok(uri) => Connect::connect(uri, options, config),
            Err(err) => {
                PromiseChain::new_with_data(Err(io::Error::new(io::ErrorKind::Other, err).into()))
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use env_logger;

    use super::*;
    use crate::channel_receiver_state::ChannelReceiverState;
    use crate::channel_status::ChannelState;
    use crate::types::ShortString;
    use crate::BasicProperties;
    use amq_protocol::frame::AMQPContentHeader;
    use amq_protocol::protocol::{basic, AMQPClass};

    #[test]
    fn basic_consume_small_payload() {
        let _ = env_logger::try_init();

        use crate::consumer::Consumer;
        use crate::queue::{Queue, QueueState};

        // Bootstrap connection state to a consuming state
        let executor = Arc::new(DefaultExecutor::default());
        let socket_state = SocketState::default();
        let waker = socket_state.handle();
        let internal_rpc = InternalRPC::new(executor.clone(), waker.clone());
        let conn = Connection::new(
            waker,
            internal_rpc.handle(),
            Frames::default(),
            executor.clone(),
        );
        conn.status.set_state(ConnectionState::Connected);
        conn.configuration.set_channel_max(2047);
        let channel = conn.channels.create(conn.closer.clone()).unwrap();
        channel.set_state(ChannelState::Connected);
        let queue_name = ShortString::from("consumed");
        let mut queue: QueueState = Queue::new(queue_name.clone(), 0, 0).into();
        let consumer_tag = ShortString::from("consumer-tag");
        let consumer = Consumer::new(consumer_tag.clone(), executor);
        queue.register_consumer(consumer_tag.clone(), consumer);
        conn.channels
            .get(channel.id())
            .map(|c| c.register_queue(queue));
        // Now test the state machine behaviour
        {
            let method = AMQPClass::Basic(basic::AMQPMethod::Deliver(basic::Deliver {
                consumer_tag: consumer_tag.clone(),
                delivery_tag: 1,
                redelivered: false,
                exchange: "".into(),
                routing_key: queue_name.clone(),
            }));
            let class_id = method.get_amqp_class_id();
            let deliver_frame = AMQPFrame::Method(channel.id(), method);
            conn.channels.handle_frame(deliver_frame).unwrap();
            let channel_state = channel.status().receiver_state();
            let expected_state = ChannelReceiverState::WillReceiveContent(
                class_id,
                Some(queue_name.clone()),
                Some(consumer_tag.clone()),
            );
            assert_eq!(channel_state, expected_state);
        }
        {
            let header_frame = AMQPFrame::Header(
                channel.id(),
                60,
                Box::new(AMQPContentHeader {
                    class_id: 60,
                    weight: 0,
                    body_size: 2,
                    properties: BasicProperties::default(),
                }),
            );
            conn.channels.handle_frame(header_frame).unwrap();
            let channel_state = channel.status().receiver_state();
            let expected_state = ChannelReceiverState::ReceivingContent(
                Some(queue_name.clone()),
                Some(consumer_tag.clone()),
                2,
            );
            assert_eq!(channel_state, expected_state);
        }
        {
            let body_frame = AMQPFrame::Body(channel.id(), "{}".as_bytes().to_vec());
            conn.channels.handle_frame(body_frame).unwrap();
            let channel_state = channel.status().state();
            let expected_state = ChannelState::Connected;
            assert_eq!(channel_state, expected_state);
        }
    }

    #[test]
    fn basic_consume_empty_payload() {
        let _ = env_logger::try_init();

        use crate::consumer::Consumer;
        use crate::queue::{Queue, QueueState};

        // Bootstrap connection state to a consuming state
        let socket_state = SocketState::default();
        let waker = socket_state.handle();
        let executor = Arc::new(DefaultExecutor::default());
        let internal_rpc = InternalRPC::new(executor.clone(), waker.clone());
        let conn = Connection::new(
            waker,
            internal_rpc.handle(),
            Frames::default(),
            executor.clone(),
        );
        conn.status.set_state(ConnectionState::Connected);
        conn.configuration.set_channel_max(2047);
        let channel = conn.channels.create(conn.closer.clone()).unwrap();
        channel.set_state(ChannelState::Connected);
        let queue_name = ShortString::from("consumed");
        let mut queue: QueueState = Queue::new(queue_name.clone(), 0, 0).into();
        let consumer_tag = ShortString::from("consumer-tag");
        let consumer = Consumer::new(consumer_tag.clone(), executor);
        queue.register_consumer(consumer_tag.clone(), consumer);
        conn.channels
            .get(channel.id())
            .map(|c| c.register_queue(queue));
        // Now test the state machine behaviour
        {
            let method = AMQPClass::Basic(basic::AMQPMethod::Deliver(basic::Deliver {
                consumer_tag: consumer_tag.clone(),
                delivery_tag: 1,
                redelivered: false,
                exchange: "".into(),
                routing_key: queue_name.clone(),
            }));
            let class_id = method.get_amqp_class_id();
            let deliver_frame = AMQPFrame::Method(channel.id(), method);
            conn.channels.handle_frame(deliver_frame).unwrap();
            let channel_state = channel.status().receiver_state();
            let expected_state = ChannelReceiverState::WillReceiveContent(
                class_id,
                Some(queue_name.clone()),
                Some(consumer_tag.clone()),
            );
            assert_eq!(channel_state, expected_state);
        }
        {
            let header_frame = AMQPFrame::Header(
                channel.id(),
                60,
                Box::new(AMQPContentHeader {
                    class_id: 60,
                    weight: 0,
                    body_size: 0,
                    properties: BasicProperties::default(),
                }),
            );
            conn.channels.handle_frame(header_frame).unwrap();
            let channel_state = channel.status().state();
            let expected_state = ChannelState::Connected;
            assert_eq!(channel_state, expected_state);
        }
    }
}
<|endoftext|>


<commit_before>use std::str::FromStr;
use ::token::parse_expressions;
use ::token::{Expression, Token, Multiplicity};

#[derive(PartialEq,Debug)]
pub struct Regex {
    pub expressions: Vec<Expression>
}

impl Regex {
    pub fn from(pattern: &str) -> Result<Regex, &str> {
        parse_expressions(pattern).map(|exprs| Regex {
            expressions: exprs
        })
    }

    pub fn first(&self, text: &str) -> Option<(usize, usize)> {
        let mut regex_i = 0;
        let mut text_i = 0;
        let mut match_start = 0;

        // a stack of valid offsets, in the order we encountered them
        let mut backtrack_stack = Vec::<(usize, usize, usize)>::new();

        while regex_i < self.expressions.len() {
            let mut options = Self::ways_to_grab_text(&text[text_i..], &self.expressions[regex_i]);

            for option in options {
                backtrack_stack.push((regex_i, text_i, option));
            }

            if backtrack_stack.len() == 0 {
                text_i += 1;
                match_start = text_i;

                if text_i >= text.len() {
                    return None;
                }

                continue;
            }

            let (reg_i,tex_i,chosen_option) = backtrack_stack.pop().unwrap();

            text_i = tex_i + chosen_option;
            regex_i = reg_i + 1;
        }

        Some((match_start, text_i))
    }

    fn ways_to_grab_text(text: &str, expr: &Expression) -> Vec<usize> {
        let mut valid_offsets = Vec::<usize>::new();
        let mut valid_chars = Vec::new();
        let mut expr_is_dot = false;
        let mut valid_multiplicity = Multiplicity::one();

        match expr {
            &Expression::Token(ref token, ref multiplicity) => {
                valid_multiplicity = multiplicity.clone();
                match token {
                    &Token::Literal(ref value) => {
                        valid_chars.push(value.clone());
                    },
                    &Token::Class(ref values) => {
                        valid_chars.append(&mut values.clone());
                    },
                    &Token::Any => {
                        expr_is_dot = true;
                    }
                }
            },
            _ => ()
        }

        if valid_multiplicity.minimum == 0 {
            valid_offsets.push(0); //it is an option to do nothing with this expr
        }

        let mut offset = 0;

        for c in text.chars() {
            if !expr_is_dot && !valid_chars.contains(&c) {
                break;
            }

            if expr_is_dot && c == '\n' { // the 'dot' metachar should not match newline
                break;
            }

            offset += 1;

            if offset < valid_multiplicity.minimum {
                continue;
            }

            match valid_multiplicity.maximum {
                Some(max) => {
                    if offset > max { continue; }
                },
                None => ()
            }

            valid_offsets.push(offset);
        }

        valid_offsets
    }

    pub fn is_match(&self, text: &str) -> bool {
        return self.first(text).is_some();
    }
}

#[cfg(test)]
mod match_spec {
    use super::Regex;

    #[test]
    fn matches_simple_examples() {
        assert!(Regex::from("ab?c").unwrap().is_match("zac"));
        assert!(Regex::from("ab?c").unwrap().is_match("abbbc"));
        assert!(Regex::from("a?").unwrap().is_match(""));
        assert!(Regex::from("a+").unwrap().is_match("a"));
        assert!(Regex::from("ab+").unwrap().is_match("abbbb"));
    }

    #[test]
    fn does_not_match() {
        assert!(!Regex::from("ab?c").unwrap().is_match("z"));
        assert!(!Regex::from("a+").unwrap().is_match(""));
        assert!(!Regex::from("ab+").unwrap().is_match("bbbb"));
    }

    #[test]
    fn matches_character_class() {
        let regex = Regex::from("[abc]").unwrap();
        assert!(regex.is_match("a"));
        assert!(regex.is_match("b"));
        assert!(regex.is_match("c"));
        assert!(!regex.is_match("["));
        assert!(!regex.is_match("]"));
        assert!(!regex.is_match("z"));
    }

    #[test]
    fn backtracks_to_find_match() {
        let regex = Regex::from("[bc]?c").unwrap();
        assert!(regex.is_match("cb"));
        assert!(regex.is_match("cc"));
        assert!(regex.is_match("c"));
        assert!(!regex.is_match("b"));
    }

    #[test]
    fn finds_correct_match() {
        let regex = Regex::from("[bc]?c").unwrap();
        assert_eq!(Some((0,1)),
                   regex.first("cb"));
        assert_eq!(Some((0,2)),
                   regex.first("cc"));
        assert_eq!(Some((0,1)),
                   regex.first("c"));
    }

    #[test]
    fn matches_zero_or_more() {
        let regex = Regex::from("ab*").unwrap();
        assert!(regex.is_match("abbbb"));
        assert!(regex.is_match("ab"));
        assert!(regex.is_match("a"));
        assert!(!regex.is_match("bb"));
    }

    #[test]
    fn finds_correct_match_position() {
        let regex = Regex::from("a").unwrap();
        assert_eq!(Some((0,1)), regex.first("a"));
        assert_eq!(Some((3,4)), regex.first("bbba"));
        assert_eq!(Some((0,4)), Regex::from("aaaa").unwrap().first("aaaa"));
    }

    #[test]
    fn finds_first_occurrence() {
        assert_eq!(Some((1,2)), Regex::from("z").unwrap().first("azzzzzzz"));
        assert_eq!(Some((2,5)), Regex::from("abc").unwrap().first("zxabcabc"));
        assert_eq!(Some((0,5)), Regex::from("[zx]+abc").unwrap().first("zxabczxabc"));
    }

    #[test]
    fn optional_metachar_is_greedy() {
        assert_eq!(Some((0,1)), Regex::from("a?").unwrap().first("aa"));
    }

    #[test]
    fn one_or_more_metachar_is_greedy() {
        assert_eq!(Some((0,2)), Regex::from("a+").unwrap().first("aa"));
    }

    #[test]
    fn zero_or_more_metachar_is_greedy() {
        assert_eq!(Some((0,2)), Regex::from("a*").unwrap().first("aa"));
    }

    #[test]
    fn dot_matches_any_one_character() {
        assert_eq!(Some((0,1)), Regex::from(".").unwrap().first("abc"));
    }

    #[test]
    fn dot_does_not_match_newline() {
        assert_eq!(None, Regex::from(".").unwrap().first("\n"));
        let regex = Regex::from(".*").unwrap();
        assert_eq!(Some((0,0)), regex.first("\n\n"));

        assert_eq!(None, Regex::from(".+").unwrap().first("\n\n"));
    }

    #[test]
    fn dot_matches_with_multiplicity() {
        assert_eq!(Some((0,10)),
                   Regex::from(".*").unwrap().first("some stuff\nmore stuff"));
        assert_eq!(Some((3, 8)),
                   Regex::from(".+").unwrap().first("\n\n\nstuff"));
    }
}

<commit_msg>refactor some regex evaluation<commit_after>use std::str::FromStr;
use ::token::parse_expressions;
use ::token::{Expression, Token, Multiplicity};

#[derive(PartialEq,Debug)]
pub struct Regex {
    pub expressions: Vec<Expression>
}

impl Regex {
    pub fn from(pattern: &str) -> Result<Regex, &str> {
        parse_expressions(pattern).map(|exprs| Regex {
            expressions: exprs
        })
    }

    pub fn first(&self, text: &str) -> Option<(usize, usize)> {
        let mut regex_i = 0; // the current position in the list of regex "expressions"
        let mut text_i = 0; // the current position in the text
        let mut match_start = 0; // the start position of the current match

        // a stack of valid offsets, in the order we encountered them
        let mut backtrack_stack = Vec::<(usize, usize, usize)>::new();

        while regex_i < self.expressions.len() {
            let mut options = Self::valid_expression_offsets(&text[text_i..], &self.expressions[regex_i]);

            backtrack_stack.extend(options.iter()
                                     .map(|&option| (regex_i, text_i, option))
                                     .collect::<Vec<_>>());

            if backtrack_stack.len() == 0 {
                text_i += 1;
                match_start = text_i;

                if text_i >= text.len() {
                    return None;
                }

                continue;
            }

            let (reg_i,tex_i,chosen_option) = backtrack_stack.pop().unwrap();

            text_i = tex_i + chosen_option;
            regex_i = reg_i + 1;
        }

        Some((match_start, text_i))
    }

    // returns a stack of valid offsets, given a string and a certain
    // Regex "expression" (token and multiplicity)
    // Multiplicity operator greediness is handled by ensuring that
    // the offsets on the top of the stack are the largest valid offsets
    fn valid_expression_offsets(text: &str, expr: &Expression) -> Vec<usize> {
        let mut valid_offsets = Vec::<usize>::new();
        let mut valid_chars = Vec::new();
        let mut expr_is_dot = false;
        let mut valid_multiplicity = Multiplicity::one();

        match expr {
            &Expression::Token(ref token, ref multiplicity) => {
                valid_multiplicity = multiplicity.clone();
                match token {
                    &Token::Literal(ref value) => {
                        valid_chars.push(value.clone());
                    },
                    &Token::Class(ref values) => {
                        valid_chars.append(&mut values.clone());
                    },
                    &Token::Any => {
                        expr_is_dot = true;
                    }
                }
            },
            _ => ()
        }

        if valid_multiplicity.minimum == 0 {
            valid_offsets.push(0); //it is an option to do nothing with this expr
        }

        let mut offset = 0;

        for c in text.chars() {
            if !expr_is_dot && !valid_chars.contains(&c) {
                break;
            }

            if expr_is_dot && c == '\n' { // the 'dot' metachar should not match newline
                break;
            }

            offset += 1;

            if offset < valid_multiplicity.minimum {
                continue;
            }

            match valid_multiplicity.maximum {
                Some(max) => {
                    if offset > max { continue; }
                },
                None => ()
            }

            valid_offsets.push(offset);
        }

        valid_offsets
    }

    pub fn is_match(&self, text: &str) -> bool {
        return self.first(text).is_some();
    }
}

#[cfg(test)]
mod match_spec {
    use super::Regex;

    #[test]
    fn matches_simple_examples() {
        assert!(Regex::from("ab?c").unwrap().is_match("zac"));
        assert!(Regex::from("ab?c").unwrap().is_match("abbbc"));
        assert!(Regex::from("a?").unwrap().is_match(""));
        assert!(Regex::from("a+").unwrap().is_match("a"));
        assert!(Regex::from("ab+").unwrap().is_match("abbbb"));
    }

    #[test]
    fn does_not_match() {
        assert!(!Regex::from("ab?c").unwrap().is_match("z"));
        assert!(!Regex::from("a+").unwrap().is_match(""));
        assert!(!Regex::from("ab+").unwrap().is_match("bbbb"));
    }

    #[test]
    fn matches_character_class() {
        let regex = Regex::from("[abc]").unwrap();
        assert!(regex.is_match("a"));
        assert!(regex.is_match("b"));
        assert!(regex.is_match("c"));
        assert!(!regex.is_match("["));
        assert!(!regex.is_match("]"));
        assert!(!regex.is_match("z"));
    }

    #[test]
    fn backtracks_to_find_match() {
        let regex = Regex::from("[bc]?c").unwrap();
        assert!(regex.is_match("cb"));
        assert!(regex.is_match("cc"));
        assert!(regex.is_match("c"));
        assert!(!regex.is_match("b"));
    }

    #[test]
    fn finds_correct_match() {
        let regex = Regex::from("[bc]?c").unwrap();
        assert_eq!(Some((0,1)),
                   regex.first("cb"));
        assert_eq!(Some((0,2)),
                   regex.first("cc"));
        assert_eq!(Some((0,1)),
                   regex.first("c"));
    }

    #[test]
    fn matches_zero_or_more() {
        let regex = Regex::from("ab*").unwrap();
        assert!(regex.is_match("abbbb"));
        assert!(regex.is_match("ab"));
        assert!(regex.is_match("a"));
        assert!(!regex.is_match("bb"));
    }

    #[test]
    fn finds_correct_match_position() {
        let regex = Regex::from("a").unwrap();
        assert_eq!(Some((0,1)), regex.first("a"));
        assert_eq!(Some((3,4)), regex.first("bbba"));
        assert_eq!(Some((0,4)), Regex::from("aaaa").unwrap().first("aaaa"));
    }

    #[test]
    fn finds_first_occurrence() {
        assert_eq!(Some((1,2)), Regex::from("z").unwrap().first("azzzzzzz"));
        assert_eq!(Some((2,5)), Regex::from("abc").unwrap().first("zxabcabc"));
        assert_eq!(Some((0,5)), Regex::from("[zx]+abc").unwrap().first("zxabczxabc"));
    }

    #[test]
    fn optional_metachar_is_greedy() {
        assert_eq!(Some((0,1)), Regex::from("a?").unwrap().first("aa"));
    }

    #[test]
    fn one_or_more_metachar_is_greedy() {
        assert_eq!(Some((0,2)), Regex::from("a+").unwrap().first("aa"));
    }

    #[test]
    fn zero_or_more_metachar_is_greedy() {
        assert_eq!(Some((0,2)), Regex::from("a*").unwrap().first("aa"));
    }

    #[test]
    fn dot_matches_any_one_character() {
        assert_eq!(Some((0,1)), Regex::from(".").unwrap().first("abc"));
    }

    #[test]
    fn dot_does_not_match_newline() {
        assert_eq!(None, Regex::from(".").unwrap().first("\n"));
        let regex = Regex::from(".*").unwrap();
        assert_eq!(Some((0,0)), regex.first("\n\n"));

        assert_eq!(None, Regex::from(".+").unwrap().first("\n\n"));
    }

    #[test]
    fn dot_matches_with_multiplicity() {
        assert_eq!(Some((0,10)),
                   Regex::from(".*").unwrap().first("some stuff\nmore stuff"));
        assert_eq!(Some((3, 8)),
                   Regex::from(".+").unwrap().first("\n\n\nstuff"));
    }
}

<|endoftext|>


<commit_before>use std::ptr;
use std::mem;
use std::convert::{From, Into, AsRef, AsMut};
use typenum::{self, Cmp, Equal};
use alga::general::{SubsetOf, SupersetOf};

use core::{Scalar, Matrix};
use core::dimension::{Dim, DimName, DimNameMul, DimNameProd, U1, U2, U3, U4, U5, U6};
use core::constraint::{ShapeConstraint, SameNumberOfRows, SameNumberOfColumns};
use core::storage::OwnedStorage;
use core::allocator::{OwnedAllocator, SameShapeAllocator};

// FIXME: too bad this won't work allo slice conversions.
impl<N1, N2, R1, C1, R2, C2, SA, SB> SubsetOf<Matrix<N2, R2, C2, SB>> for Matrix<N1, R1, C1, SA>
    where R1: Dim, C1: Dim, R2: Dim, C2: Dim,
          N1: Scalar,
          N2: Scalar + SupersetOf<N1>,
          SA: OwnedStorage<N1, R1, C1>,
          SB: OwnedStorage<N2, R2, C2>,
          SB::Alloc: OwnedAllocator<N2, R2, C2, SB>,
          SA::Alloc: OwnedAllocator<N1, R1, C1, SA> +
                     SameShapeAllocator<N1, R1, C1, R2, C2, SA>,
          ShapeConstraint: SameNumberOfRows<R1, R2> + SameNumberOfColumns<C1, C2> {
    #[inline]
    fn to_superset(&self) -> Matrix<N2, R2, C2, SB> {
        let (nrows, ncols) = self.shape();
        let nrows2 = R2::from_usize(nrows);
        let ncols2 = C2::from_usize(ncols);

        let mut res = unsafe { Matrix::<N2, R2, C2, SB>::new_uninitialized_generic(nrows2, ncols2) };
        for i in 0 .. nrows {
            for j in 0 .. ncols {
                unsafe {
                    *res.get_unchecked_mut(i, j) = N2::from_subset(self.get_unchecked(i, j))
                }
            }
        }

        res
    }

    #[inline]
    fn is_in_subset(m: &Matrix<N2, R2, C2, SB>) -> bool {
        m.iter().all(|e| e.is_in_subset())
    }

    #[inline]
    unsafe fn from_superset_unchecked(m: &Matrix<N2, R2, C2, SB>) -> Self {
        let (nrows2, ncols2) = m.shape();
        let nrows = R1::from_usize(nrows2);
        let ncols = C1::from_usize(ncols2);

        let mut res = Self::new_uninitialized_generic(nrows, ncols);
        for i in 0 .. nrows2 {
            for j in 0 .. ncols2 {
                *res.get_unchecked_mut(i, j) = m.get_unchecked(i, j).to_subset_unchecked()
            }
        }

        res
    }
}

macro_rules! impl_from_into_asref_1D(
    ($($Dim: ident => $SZ: expr);* $(;)*) => {$(
        impl<N, R, C, S> From<[N; $SZ]> for Matrix<N, R, C, S>
        where N: Scalar,
              R: DimName + DimNameMul<C>,
              C: DimName,
              S: OwnedStorage<N, R, C>,
              S::Alloc: OwnedAllocator<N, R, C, S>,
              <DimNameProd<R, C> as DimName>::Value: Cmp<typenum::$Dim, Output = Equal> {
            #[inline]
            fn from(arr: [N; $SZ]) -> Self {
                unsafe {
                    let mut res = Self::new_uninitialized();
                    ptr::copy_nonoverlapping(&arr[0], res.data.ptr_mut(), $SZ);

                    res
                }
            }
        }

        impl<N, R, C, S> Into<[N; $SZ]> for Matrix<N, R, C, S>
        where N: Scalar,
              R: DimName + DimNameMul<C>,
              C: DimName,
              S: OwnedStorage<N, R, C>,
              S::Alloc: OwnedAllocator<N, R, C, S>,
              <DimNameProd<R, C> as DimName>::Value: Cmp<typenum::$Dim, Output = Equal> {
            #[inline]
            fn into(self) -> [N; $SZ] {
                unsafe {
                    let mut res: [N; $SZ] = mem::uninitialized();
                    ptr::copy_nonoverlapping(self.data.ptr(), &mut res[0], $SZ);

                    res
                }
            }
        }

        impl<N, R, C, S> AsRef<[N; $SZ]> for Matrix<N, R, C, S>
        where N: Scalar,
              R: DimName + DimNameMul<C>,
              C: DimName,
              S: OwnedStorage<N, R, C>,
              S::Alloc: OwnedAllocator<N, R, C, S>,
              <DimNameProd<R, C> as DimName>::Value: Cmp<typenum::$Dim, Output = Equal> {
            #[inline]
            fn as_ref(&self) -> &[N; $SZ] {
                unsafe {
                    mem::transmute(self.data.ptr())
                }
            }
        }

        impl<N, R, C, S> AsMut<[N; $SZ]> for Matrix<N, R, C, S>
        where N: Scalar,
              R: DimName + DimNameMul<C>,
              C: DimName,
              S: OwnedStorage<N, R, C>,
              S::Alloc: OwnedAllocator<N, R, C, S>,
              <DimNameProd<R, C> as DimName>::Value: Cmp<typenum::$Dim, Output = Equal> {
            #[inline]
            fn as_mut(&mut self) -> &mut [N; $SZ] {
                unsafe {
                    mem::transmute(self.data.ptr_mut())
                }
            }
        }
    )*}
);

// Implement for vectors of dimension 1 .. 36 and matrices with shape 1x1 .. 6x6.
impl_from_into_asref_1D!(
    U1  => 1;  U2  => 2;  U3  => 3;  U4  => 4;  U5  => 5;  U6  => 6;
    U7  => 7;  U8  => 8;  U9  => 9;  U10 => 10; U11 => 11; U12 => 12;
    U13 => 13; U14 => 14; U15 => 15; U16 => 16; U17 => 17; U18 => 18;
    U19 => 19; U20 => 20; U21 => 21; U22 => 22; U23 => 23; U24 => 24;
    U25 => 25; U26 => 26; U27 => 27; U28 => 28; U29 => 29; U30 => 30;
    U31 => 31; U32 => 32; U33 => 33; U34 => 34; U35 => 35; U36 => 36;
);

macro_rules! impl_from_into_asref_2D(
    ($(($NRows: ty, $NCols: ty) => ($SZRows: expr, $SZCols: expr));* $(;)*) => {$(
        impl<N, S> From<[[N; $SZRows]; $SZCols]> for Matrix<N, $NRows, $NCols, S>
        where N: Scalar,
              S: OwnedStorage<N, $NRows, $NCols>,
              S::Alloc: OwnedAllocator<N, $NRows, $NCols, S> {
            #[inline]
            fn from(arr: [[N; $SZRows]; $SZCols]) -> Self {
                unsafe {
                    let mut res = Self::new_uninitialized();
                    ptr::copy_nonoverlapping(&arr[0][0], res.data.ptr_mut(), $SZRows * $SZCols);

                    res
                }
            }
        }

        impl<N, S> Into<[[N; $SZRows]; $SZCols]> for Matrix<N, $NRows, $NCols, S>
        where N: Scalar,
              S: OwnedStorage<N, $NRows, $NCols>,
              S::Alloc: OwnedAllocator<N, $NRows, $NCols, S> {
            #[inline]
            fn into(self) -> [[N; $SZRows]; $SZCols] {
                unsafe {
                    let mut res: [[N; $SZRows]; $SZCols] = mem::uninitialized();
                    ptr::copy_nonoverlapping(self.data.ptr(), &mut res[0][0], $SZRows * $SZCols);

                    res
                }
            }
        }

        impl<N, S> AsRef<[[N; $SZRows]; $SZCols]> for Matrix<N, $NRows, $NCols, S>
        where N: Scalar,
              S: OwnedStorage<N, $NRows, $NCols>,
              S::Alloc: OwnedAllocator<N, $NRows, $NCols, S> {
            #[inline]
            fn as_ref(&self) -> &[[N; $SZRows]; $SZCols] {
                unsafe {
                    mem::transmute(self.data.ptr())
                }
            }
        }

        impl<N, S> AsMut<[[N; $SZRows]; $SZCols]> for Matrix<N, $NRows, $NCols, S>
        where N: Scalar,
              S: OwnedStorage<N, $NRows, $NCols>,
              S::Alloc: OwnedAllocator<N, $NRows, $NCols, S> {
            #[inline]
            fn as_mut(&mut self) -> &mut [[N; $SZRows]; $SZCols] {
                unsafe {
                    mem::transmute(self.data.ptr_mut())
                }
            }
        }
    )*}
);

// Implement for matrices with shape 1x1 .. 4x4.
impl_from_into_asref_2D!(
    (U1, U1) => (1, 1); (U1, U2) => (1, 2); (U1, U3) => (1, 3); (U1, U4) => (1, 4); (U1, U5) => (1, 5); (U1, U6) => (1, 6);
    (U2, U1) => (2, 1); (U2, U2) => (2, 2); (U2, U3) => (2, 3); (U2, U4) => (2, 4); (U2, U5) => (2, 5); (U2, U6) => (2, 6);
    (U3, U1) => (3, 1); (U3, U2) => (3, 2); (U3, U3) => (3, 3); (U3, U4) => (3, 4); (U3, U5) => (3, 5); (U3, U6) => (3, 6);
    (U4, U1) => (4, 1); (U4, U2) => (4, 2); (U4, U3) => (4, 3); (U4, U4) => (4, 4); (U4, U5) => (4, 5); (U4, U6) => (4, 6);
    (U5, U1) => (5, 1); (U5, U2) => (5, 2); (U5, U3) => (5, 3); (U5, U4) => (5, 4); (U5, U5) => (5, 5); (U5, U6) => (5, 6);
    (U6, U1) => (6, 1); (U6, U2) => (6, 2); (U6, U3) => (6, 3); (U6, U4) => (6, 4); (U6, U5) => (6, 5); (U6, U6) => (6, 6);
);
<commit_msg>Implement IntoIterator for &Matrix and &mut Matrix<commit_after>use std::ptr;
use std::mem;
use std::convert::{From, Into, AsRef, AsMut};
use typenum::{self, Cmp, Equal};
use alga::general::{SubsetOf, SupersetOf};

use core::{Scalar, Matrix};
use core::dimension::{Dim, DimName, DimNameMul, DimNameProd, U1, U2, U3, U4, U5, U6};
use core::constraint::{ShapeConstraint, SameNumberOfRows, SameNumberOfColumns};
use core::storage::{Storage, StorageMut, OwnedStorage};
use core::iter::{MatrixIter, MatrixIterMut};
use core::allocator::{OwnedAllocator, SameShapeAllocator};

// FIXME: too bad this won't work allo slice conversions.
impl<N1, N2, R1, C1, R2, C2, SA, SB> SubsetOf<Matrix<N2, R2, C2, SB>> for Matrix<N1, R1, C1, SA>
    where R1: Dim, C1: Dim, R2: Dim, C2: Dim,
          N1: Scalar,
          N2: Scalar + SupersetOf<N1>,
          SA: OwnedStorage<N1, R1, C1>,
          SB: OwnedStorage<N2, R2, C2>,
          SB::Alloc: OwnedAllocator<N2, R2, C2, SB>,
          SA::Alloc: OwnedAllocator<N1, R1, C1, SA> +
                     SameShapeAllocator<N1, R1, C1, R2, C2, SA>,
          ShapeConstraint: SameNumberOfRows<R1, R2> + SameNumberOfColumns<C1, C2> {
    #[inline]
    fn to_superset(&self) -> Matrix<N2, R2, C2, SB> {
        let (nrows, ncols) = self.shape();
        let nrows2 = R2::from_usize(nrows);
        let ncols2 = C2::from_usize(ncols);

        let mut res = unsafe { Matrix::<N2, R2, C2, SB>::new_uninitialized_generic(nrows2, ncols2) };
        for i in 0 .. nrows {
            for j in 0 .. ncols {
                unsafe {
                    *res.get_unchecked_mut(i, j) = N2::from_subset(self.get_unchecked(i, j))
                }
            }
        }

        res
    }

    #[inline]
    fn is_in_subset(m: &Matrix<N2, R2, C2, SB>) -> bool {
        m.iter().all(|e| e.is_in_subset())
    }

    #[inline]
    unsafe fn from_superset_unchecked(m: &Matrix<N2, R2, C2, SB>) -> Self {
        let (nrows2, ncols2) = m.shape();
        let nrows = R1::from_usize(nrows2);
        let ncols = C1::from_usize(ncols2);

        let mut res = Self::new_uninitialized_generic(nrows, ncols);
        for i in 0 .. nrows2 {
            for j in 0 .. ncols2 {
                *res.get_unchecked_mut(i, j) = m.get_unchecked(i, j).to_subset_unchecked()
            }
        }

        res
    }
}

impl<'a, N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> IntoIterator for &'a Matrix<N, R, C, S> {
    type Item     = &'a N;
    type IntoIter = MatrixIter<'a, N, R, C, S>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a, N: Scalar, R: Dim, C: Dim, S: StorageMut<N, R, C>> IntoIterator for &'a mut Matrix<N, R, C, S> {
    type Item     = &'a mut N;
    type IntoIter = MatrixIterMut<'a, N, R, C, S>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}

macro_rules! impl_from_into_asref_1D(
    ($($Dim: ident => $SZ: expr);* $(;)*) => {$(
        impl<N, R, C, S> From<[N; $SZ]> for Matrix<N, R, C, S>
        where N: Scalar,
              R: DimName + DimNameMul<C>,
              C: DimName,
              S: OwnedStorage<N, R, C>,
              S::Alloc: OwnedAllocator<N, R, C, S>,
              <DimNameProd<R, C> as DimName>::Value: Cmp<typenum::$Dim, Output = Equal> {
            #[inline]
            fn from(arr: [N; $SZ]) -> Self {
                unsafe {
                    let mut res = Self::new_uninitialized();
                    ptr::copy_nonoverlapping(&arr[0], res.data.ptr_mut(), $SZ);

                    res
                }
            }
        }

        impl<N, R, C, S> Into<[N; $SZ]> for Matrix<N, R, C, S>
        where N: Scalar,
              R: DimName + DimNameMul<C>,
              C: DimName,
              S: OwnedStorage<N, R, C>,
              S::Alloc: OwnedAllocator<N, R, C, S>,
              <DimNameProd<R, C> as DimName>::Value: Cmp<typenum::$Dim, Output = Equal> {
            #[inline]
            fn into(self) -> [N; $SZ] {
                unsafe {
                    let mut res: [N; $SZ] = mem::uninitialized();
                    ptr::copy_nonoverlapping(self.data.ptr(), &mut res[0], $SZ);

                    res
                }
            }
        }

        impl<N, R, C, S> AsRef<[N; $SZ]> for Matrix<N, R, C, S>
        where N: Scalar,
              R: DimName + DimNameMul<C>,
              C: DimName,
              S: OwnedStorage<N, R, C>,
              S::Alloc: OwnedAllocator<N, R, C, S>,
              <DimNameProd<R, C> as DimName>::Value: Cmp<typenum::$Dim, Output = Equal> {
            #[inline]
            fn as_ref(&self) -> &[N; $SZ] {
                unsafe {
                    mem::transmute(self.data.ptr())
                }
            }
        }

        impl<N, R, C, S> AsMut<[N; $SZ]> for Matrix<N, R, C, S>
        where N: Scalar,
              R: DimName + DimNameMul<C>,
              C: DimName,
              S: OwnedStorage<N, R, C>,
              S::Alloc: OwnedAllocator<N, R, C, S>,
              <DimNameProd<R, C> as DimName>::Value: Cmp<typenum::$Dim, Output = Equal> {
            #[inline]
            fn as_mut(&mut self) -> &mut [N; $SZ] {
                unsafe {
                    mem::transmute(self.data.ptr_mut())
                }
            }
        }
    )*}
);

// Implement for vectors of dimension 1 .. 36 and matrices with shape 1x1 .. 6x6.
impl_from_into_asref_1D!(
    U1  => 1;  U2  => 2;  U3  => 3;  U4  => 4;  U5  => 5;  U6  => 6;
    U7  => 7;  U8  => 8;  U9  => 9;  U10 => 10; U11 => 11; U12 => 12;
    U13 => 13; U14 => 14; U15 => 15; U16 => 16; U17 => 17; U18 => 18;
    U19 => 19; U20 => 20; U21 => 21; U22 => 22; U23 => 23; U24 => 24;
    U25 => 25; U26 => 26; U27 => 27; U28 => 28; U29 => 29; U30 => 30;
    U31 => 31; U32 => 32; U33 => 33; U34 => 34; U35 => 35; U36 => 36;
);

macro_rules! impl_from_into_asref_2D(
    ($(($NRows: ty, $NCols: ty) => ($SZRows: expr, $SZCols: expr));* $(;)*) => {$(
        impl<N, S> From<[[N; $SZRows]; $SZCols]> for Matrix<N, $NRows, $NCols, S>
        where N: Scalar,
              S: OwnedStorage<N, $NRows, $NCols>,
              S::Alloc: OwnedAllocator<N, $NRows, $NCols, S> {
            #[inline]
            fn from(arr: [[N; $SZRows]; $SZCols]) -> Self {
                unsafe {
                    let mut res = Self::new_uninitialized();
                    ptr::copy_nonoverlapping(&arr[0][0], res.data.ptr_mut(), $SZRows * $SZCols);

                    res
                }
            }
        }

        impl<N, S> Into<[[N; $SZRows]; $SZCols]> for Matrix<N, $NRows, $NCols, S>
        where N: Scalar,
              S: OwnedStorage<N, $NRows, $NCols>,
              S::Alloc: OwnedAllocator<N, $NRows, $NCols, S> {
            #[inline]
            fn into(self) -> [[N; $SZRows]; $SZCols] {
                unsafe {
                    let mut res: [[N; $SZRows]; $SZCols] = mem::uninitialized();
                    ptr::copy_nonoverlapping(self.data.ptr(), &mut res[0][0], $SZRows * $SZCols);

                    res
                }
            }
        }

        impl<N, S> AsRef<[[N; $SZRows]; $SZCols]> for Matrix<N, $NRows, $NCols, S>
        where N: Scalar,
              S: OwnedStorage<N, $NRows, $NCols>,
              S::Alloc: OwnedAllocator<N, $NRows, $NCols, S> {
            #[inline]
            fn as_ref(&self) -> &[[N; $SZRows]; $SZCols] {
                unsafe {
                    mem::transmute(self.data.ptr())
                }
            }
        }

        impl<N, S> AsMut<[[N; $SZRows]; $SZCols]> for Matrix<N, $NRows, $NCols, S>
        where N: Scalar,
              S: OwnedStorage<N, $NRows, $NCols>,
              S::Alloc: OwnedAllocator<N, $NRows, $NCols, S> {
            #[inline]
            fn as_mut(&mut self) -> &mut [[N; $SZRows]; $SZCols] {
                unsafe {
                    mem::transmute(self.data.ptr_mut())
                }
            }
        }
    )*}
);

// Implement for matrices with shape 1x1 .. 4x4.
impl_from_into_asref_2D!(
    (U1, U1) => (1, 1); (U1, U2) => (1, 2); (U1, U3) => (1, 3); (U1, U4) => (1, 4); (U1, U5) => (1, 5); (U1, U6) => (1, 6);
    (U2, U1) => (2, 1); (U2, U2) => (2, 2); (U2, U3) => (2, 3); (U2, U4) => (2, 4); (U2, U5) => (2, 5); (U2, U6) => (2, 6);
    (U3, U1) => (3, 1); (U3, U2) => (3, 2); (U3, U3) => (3, 3); (U3, U4) => (3, 4); (U3, U5) => (3, 5); (U3, U6) => (3, 6);
    (U4, U1) => (4, 1); (U4, U2) => (4, 2); (U4, U3) => (4, 3); (U4, U4) => (4, 4); (U4, U5) => (4, 5); (U4, U6) => (4, 6);
    (U5, U1) => (5, 1); (U5, U2) => (5, 2); (U5, U3) => (5, 3); (U5, U4) => (5, 4); (U5, U5) => (5, 5); (U5, U6) => (5, 6);
    (U6, U1) => (6, 1); (U6, U2) => (6, 2); (U6, U3) => (6, 3); (U6, U4) => (6, 4); (U6, U5) => (6, 5); (U6, U6) => (6, 6);
);
<|endoftext|>


<commit_before>#[cfg(test)]
use ::card::*;

#[test]
fn create_hand() {
    let mut deck = ::deck::Deck::new();
    let mut cards: Vec<::card::Card> = vec![];
    for _i in 0..5 {
        cards.push(deck.draw().unwrap());
    }
    let hand = ::hand::Hand::new(cards);

    assert_eq!(hand.cards.len(), 5);
}

#[test]
fn has_flush() {
    let a = Card {
        value: Value::Three,
        suit: Suit::Hearts
    };
    let b = Card {
        value: Value::Six,
        suit: Suit::Hearts
    };
    let c = Card {
        value: Value::Ten,
        suit: Suit::Hearts
    };
    let d = Card {
        value: Value::Queen,
        suit: Suit::Hearts
    };
    let e = Card {
        value: Value::Two,
        suit: Suit::Hearts
    };
    let cards: Vec<Card> = vec![a, b, c, d, e];
    let hand: ::hand::Hand = ::hand::Hand::new(cards);

    assert_eq!(hand.has_flush(), true);
}

#[test]
fn no_flush() {
    let a = Card {
        value: Value::Three,
        suit: Suit::Hearts
    };
    let b = Card {
        value: Value::Six,
        suit: Suit::Spades
    };
    let c = Card {
        value: Value::Ten,
        suit: Suit::Hearts
    };
    let d = Card {
        value: Value::Queen,
        suit: Suit::Hearts
    };
    let e = Card {
        value: Value::Two,
        suit: Suit::Hearts
    };
    let cards: Vec<Card> = vec![a, b, c, d, e];
    let hand: ::hand::Hand = ::hand::Hand::new(cards);

    assert_eq!(hand.has_flush(), false);
}
<commit_msg>Updated hand unit tests to use the Card constructor<commit_after>#[cfg(test)]
use ::card::*;

#[test]
fn create_hand() {
    let mut deck = ::deck::Deck::new();
    let mut cards: Vec<::card::Card> = vec![];
    for _i in 0..5 {
        cards.push(deck.draw().unwrap());
    }
    let hand = ::hand::Hand::new(cards);

    assert_eq!(hand.cards.len(), 5);
}

#[test]
fn has_flush() {
    let a = Card::new(Value::Three, Suit::Hearts);
    let b = Card::new(Value::Six, Suit::Hearts);
    let c = Card::new(Value::Ten, Suit::Hearts);
    let d = Card::new(Value::Queen, Suit::Hearts);
    let e = Card::new(Value::Two, Suit::Hearts);
    let cards: Vec<Card> = vec![a, b, c, d, e];
    let hand: ::hand::Hand = ::hand::Hand::new(cards);

    assert_eq!(hand.has_flush(), true);
}

#[test]
fn no_flush() {
    let a = Card::new(Value::Three, Suit::Hearts);
    let b = Card::new(Value::Six, Suit::Spades);
    let c = Card::new(Value::Ten, Suit::Hearts);
    let d = Card::new(Value::Queen, Suit::Hearts);
    let e = Card::new(Value::Two, Suit::Hearts);
    let cards: Vec<Card> = vec![a, b, c, d, e];
    let hand: ::hand::Hand = ::hand::Hand::new(cards);

    assert_eq!(hand.has_flush(), false);
}

#[test]
fn high_card_raw_value() {

}
<|endoftext|>