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

use futures::{Future, Stream, Sink, IntoFuture, Poll, Async};
use futures::future::Either;
use futures::sync::mpsc;
use tokio_core::net::{TcpListener, TcpStream, TcpStreamNew};
use tokio_core::reactor::{Core, Timeout, Handle, Interval};
use tokio_io::AsyncRead;

use std::cmp;
use std::io;
use std::fmt;
use std::net::SocketAddr;
use std::time::{Duration, SystemTime};
use std::collections::HashMap;

use messages::{Any, Connect, RawMessage};
use node::{ExternalMessage, NodeTimeout};
use helpers::Milliseconds;

use super::EventHandler;
use super::error::{other_error, result_ok, forget_result, into_other, log_error};
use super::codec::MessagesCodec;
use super::EventsAggregator;

#[derive(Debug)]
pub enum NetworkEvent {
    MessageReceived(SocketAddr, RawMessage),
    PeerConnected(SocketAddr, Connect),
    PeerDisconnected(SocketAddr),
}

#[derive(Debug, Clone)]
pub enum NetworkRequest {
    SendMessage(SocketAddr, RawMessage),
    DisconnectWithPeer(SocketAddr),
}

#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
pub struct NetworkConfiguration {
    // TODO: think more about config parameters
    pub max_incoming_connections: usize,
    pub max_outgoing_connections: usize,
    pub tcp_nodelay: bool,
    pub tcp_keep_alive: Option<u64>,
    pub tcp_reconnect_timeout: u64,
    pub tcp_reconnect_timeout_max: u64,
}

impl Default for NetworkConfiguration {
    fn default() -> NetworkConfiguration {
        NetworkConfiguration {
            max_incoming_connections: 128,
            max_outgoing_connections: 128,
            tcp_keep_alive: None,
            tcp_nodelay: false,
            tcp_reconnect_timeout: 500,
            tcp_reconnect_timeout_max: 600_000,
        }
    }
}

#[derive(Debug)]
pub struct HandlerPart<H: EventHandler> {
    pub core: Core,
    pub handler: H,
    pub timeout_rx: mpsc::Receiver<NodeTimeout>,
    pub network_rx: mpsc::Receiver<NetworkEvent>,
    pub api_rx: mpsc::Receiver<ExternalMessage>,
}

#[derive(Debug)]
pub struct NetworkPart {
    pub listen_address: SocketAddr,
    pub network_config: NetworkConfiguration,
    pub network_requests: (mpsc::Sender<NetworkRequest>, mpsc::Receiver<NetworkRequest>),
    pub network_tx: mpsc::Sender<NetworkEvent>,
}

impl<H: EventHandler> HandlerPart<H> {
    pub fn run(self) -> Result<(), ()> {
        let mut core = self.core;
        let mut handler = self.handler;

        let events_handle = EventsAggregator::new(self.timeout_rx, self.network_rx, self.api_rx)
            .for_each(move |event| {
                handler.handle_event(event);
                Ok(())
            });
        core.run(events_handle)
    }
}

macro_rules! try_future_boxed {
    ($e:expr) =>(
        match $e {
            Ok(v) => v,
            Err(e) => {
                return Err(into_other(e)).into_future().boxed();
            }
        }
    )
}

impl NetworkPart {
    pub fn run(self) -> Result<(), ()> {
        let mut core = Core::new().unwrap();

        // Outgoing connections handler
        let mut outgoing_connections: HashMap<SocketAddr, mpsc::Sender<RawMessage>> =
            HashMap::new();

        // Requests handler
        let handle = core.handle();
        let network_tx = self.network_tx.clone();
        let requests_tx = self.network_requests.0.clone();
        let network_config = self.network_config.clone();
        let requests_handle = self.network_requests.1.for_each(|request| {
            match request {
                NetworkRequest::SendMessage(peer, msg) => {
                    let conn_tx = if let Some(conn_tx) = outgoing_connections.get(&peer).cloned() {
                        conn_tx
                    } else {
                        let (conn_tx, conn_rx) = mpsc::channel(10);
                        outgoing_connections.insert(peer, conn_tx.clone());

                        let requests_tx = requests_tx.clone();
                        // let connect_handle = TcpStream::connect(&peer, &handle)
                        let connect_handle = NewConnection::create(
                            peer,
                            handle.clone(),
                            network_config.tcp_reconnect_timeout,
                            network_config.tcp_reconnect_timeout_max,
                        ).and_then(move |sock| {
                            try_future_boxed!(sock.set_nodelay(network_config.tcp_nodelay));
                            try_future_boxed!(sock.set_keepalive(
                                network_config.tcp_keep_alive.map(Duration::from_millis),
                            ));

                            info!("Established connection with peer={}", peer);

                            let stream = sock.framed(MessagesCodec);
                            let (sink, stream) = stream.split();

                            let writer = conn_rx
                                .map_err(|_| other_error("Can't send data into socket"))
                                .forward(sink);
                            let reader = stream.for_each(result_ok).map_err(into_other);

                            reader
                                .select2(writer)
                                .map_err(|_| other_error("Socket error"))
                                .and_then(|res| match res {
                                    Either::A((_, _reader)) => Ok(()).into_future(),
                                    Either::B((_, _writer)) => Ok(()).into_future(),
                                })
                                .boxed()
                        })
                            .then(move |res| {
                                info!("Connection with peer={} closed, reason={:?}", peer, res);
                                // outgoing_connections.remove(&peer);

                                let request = NetworkRequest::DisconnectWithPeer(peer);
                                requests_tx
                                    .clone()
                                    .send(request)
                                    .map(forget_result)
                                    .map_err(into_other)
                            })
                            .map_err(log_error);
                        handle.spawn(connect_handle);
                        conn_tx
                    };

                    let duration = Duration::from_secs(5);
                    let send_timeout = Timeout::new(duration, &handle)
                        .unwrap()
                        .and_then(result_ok)
                        .map_err(|_| other_error("Can't timeout"));

                    let send_handle = conn_tx.send(msg).map(forget_result).map_err(log_error);

                    let timeouted_connect = send_handle
                        .select2(send_timeout)
                        .map_err(|_| other_error("Unable to send message"))
                        .and_then(move |either| match either {
                            Either::A((send, _timeout_fut)) => Ok(send),
                            Either::B((_, _connect_fut)) => Err(other_error("Send timeout")),
                        })
                        .map_err(log_error);

                    handle.spawn(timeouted_connect);
                }
                NetworkRequest::DisconnectWithPeer(peer) => {
                    outgoing_connections.remove(&peer);

                    let event = NetworkEvent::PeerDisconnected(peer);
                    let event_handle = network_tx.clone().send(event).map(forget_result).map_err(
                        log_error,
                    );
                    handle.spawn(event_handle);
                }
            }

            Ok(())
        });

        // Incoming connections handler
        let listener = TcpListener::bind(&self.listen_address, &core.handle()).unwrap();
        let network_tx = network_tx.clone();
        let handle = core.handle();
        let server = listener
            .incoming()
            .for_each(move |(sock, addr)| {
                info!("Accepted incoming connection with peer={}", addr);

                let stream = sock.framed(MessagesCodec);
                let (_, stream) = stream.split();
                let network_tx = network_tx.clone();
                let connection_handler = stream
                    .into_future()
                    .map_err(|e| e.0)
                    .and_then(move |(raw, stream)| {
                        let msg = raw.map(Any::from_raw);
                        if let Some(Ok(Any::Connect(msg))) = msg {
                            Ok((msg, stream))
                        } else {
                            Err(other_error("First message is not Connect"))
                        }
                    })
                    .and_then(move |(connect, stream)| {
                        info!("Received handshake message={:?}", connect);

                        let event = NetworkEvent::PeerConnected(addr, connect);
                        let connect_event = network_tx.clone().send(event).map_err(into_other);

                        let network_tx = network_tx.clone();
                        let messages_stream = stream.for_each(move |raw| {
                            let event = NetworkEvent::MessageReceived(addr, raw);
                            network_tx.clone().send(event).map(forget_result).map_err(
                                into_other,
                            )
                        });

                        messages_stream
                            .join(connect_event)
                            .map(move |(_, stream)| stream)
                            .map_err(into_other)
                    })
                    .map(forget_result)
                    .map_err(log_error);
                handle.spawn(connection_handler);
                Ok(())
            })
            .map_err(log_error);
        core.handle().spawn(server);

        core.run(requests_handle)
    }
}

pub struct NewConnection {
    socket: Option<TcpStreamNew>,
    timeout: Interval,
    address: SocketAddr,
    handle: Handle,
    groth_factor: f32,
    start_time: SystemTime,
    reconnect_timeout: Milliseconds,
    reconnect_timeout_max: Milliseconds,
}

impl NewConnection {
    pub fn create(
        address: SocketAddr,
        handle: Handle,
        reconnect_timeout: Milliseconds,
        reconnect_timeout_max: Milliseconds,
    ) -> NewConnection {
        NewConnection {
            socket: Some(TcpStream::connect(&address, &handle)),
            timeout: Interval::new(Duration::from_millis(reconnect_timeout), &handle).unwrap(),
            address,
            handle,
            groth_factor: 1.5,
            start_time: SystemTime::now(),
            reconnect_timeout,
            reconnect_timeout_max,
        }
    }

    fn next_attempt(&mut self) -> Poll<TcpStream, io::Error> {
        self.start_time = SystemTime::now();
        if self.reconnect_timeout == self.reconnect_timeout_max {
            return Err(other_error(
                &format!("Maximum reconnect timeout reached for connection with the peer: {}",
                self.address,
            ),
            ));
        }

        self.reconnect_timeout = (self.reconnect_timeout as f32 * self.groth_factor) as
            Milliseconds;
        self.reconnect_timeout = cmp::min(self.reconnect_timeout, self.reconnect_timeout_max);
        self.socket = Some(TcpStream::connect(&self.address, &self.handle));
        self.timeout = Interval::new(Duration::from_millis(self.reconnect_timeout), &self.handle)
            .unwrap();

        trace!(
            "Add reconnect timeout to {}, delay = {} ms",
            self.address,
            self.reconnect_timeout
        );
        self.socket.as_mut().unwrap().poll()
    }

    fn poll_timeout(&mut self) -> Poll<TcpStream, io::Error> {
        match self.timeout.poll() {
            Ok(Async::Ready(_)) => self.next_attempt(),
            Ok(Async::NotReady) => Ok(Async::NotReady),
            Err(e) => Err(into_other(e)),
        }
    }
}

impl Future for NewConnection {
    type Item = TcpStream;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<TcpStream, io::Error> {
        if let Some(mut stream) = self.socket.take() {
            match stream.poll() {
                Ok(Async::Ready(stream)) => Ok(Async::Ready(stream)),
                Ok(Async::NotReady) => {
                    self.socket = Some(stream);
                    Ok(Async::NotReady)
                }
                Err(e) => {
                    trace!(
                        "An error occured during connecting to the peer: {}, error: {}",
                        self.address,
                        e
                    );
                    self.socket = None;
                    self.poll_timeout()
                }
            }
        } else {
            self.poll_timeout()
        }
    }
}

impl fmt::Debug for NewConnection {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("NewConnection { .. }")
    }
}
<commit_msg>Resolve clippy warnings<commit_after>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use futures::{Future, Stream, Sink, IntoFuture, Poll, Async};
use futures::future::Either;
use futures::sync::mpsc;
use tokio_core::net::{TcpListener, TcpStream, TcpStreamNew};
use tokio_core::reactor::{Core, Timeout, Handle, Interval};
use tokio_io::AsyncRead;

use std::cmp;
use std::io;
use std::fmt;
use std::net::SocketAddr;
use std::time::{Duration, SystemTime};
use std::collections::HashMap;

use messages::{Any, Connect, RawMessage};
use node::{ExternalMessage, NodeTimeout};
use helpers::Milliseconds;

use super::EventHandler;
use super::error::{other_error, result_ok, forget_result, into_other, log_error};
use super::codec::MessagesCodec;
use super::EventsAggregator;

#[derive(Debug)]
pub enum NetworkEvent {
    MessageReceived(SocketAddr, RawMessage),
    PeerConnected(SocketAddr, Connect),
    PeerDisconnected(SocketAddr),
}

#[derive(Debug, Clone)]
pub enum NetworkRequest {
    SendMessage(SocketAddr, RawMessage),
    DisconnectWithPeer(SocketAddr),
}

#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
pub struct NetworkConfiguration {
    // TODO: think more about config parameters
    pub max_incoming_connections: usize,
    pub max_outgoing_connections: usize,
    pub tcp_nodelay: bool,
    pub tcp_keep_alive: Option<u64>,
    pub tcp_reconnect_timeout: u64,
    pub tcp_reconnect_timeout_max: u64,
}

impl Default for NetworkConfiguration {
    fn default() -> NetworkConfiguration {
        NetworkConfiguration {
            max_incoming_connections: 128,
            max_outgoing_connections: 128,
            tcp_keep_alive: None,
            tcp_nodelay: false,
            tcp_reconnect_timeout: 500,
            tcp_reconnect_timeout_max: 600_000,
        }
    }
}

#[derive(Debug)]
pub struct HandlerPart<H: EventHandler> {
    pub core: Core,
    pub handler: H,
    pub timeout_rx: mpsc::Receiver<NodeTimeout>,
    pub network_rx: mpsc::Receiver<NetworkEvent>,
    pub api_rx: mpsc::Receiver<ExternalMessage>,
}

#[derive(Debug)]
pub struct NetworkPart {
    pub listen_address: SocketAddr,
    pub network_config: NetworkConfiguration,
    pub network_requests: (mpsc::Sender<NetworkRequest>, mpsc::Receiver<NetworkRequest>),
    pub network_tx: mpsc::Sender<NetworkEvent>,
}

impl<H: EventHandler> HandlerPart<H> {
    pub fn run(self) -> Result<(), ()> {
        let mut core = self.core;
        let mut handler = self.handler;

        let events_handle = EventsAggregator::new(self.timeout_rx, self.network_rx, self.api_rx)
            .for_each(move |event| {
                handler.handle_event(event);
                Ok(())
            });
        core.run(events_handle)
    }
}

macro_rules! try_future_boxed {
    ($e:expr) =>(
        match $e {
            Ok(v) => v,
            Err(e) => {
                return Err(into_other(e)).into_future().boxed();
            }
        }
    )
}

impl NetworkPart {
    pub fn run(self) -> Result<(), ()> {
        let mut core = Core::new().unwrap();

        // Outgoing connections handler
        let mut outgoing_connections: HashMap<SocketAddr, mpsc::Sender<RawMessage>> =
            HashMap::new();

        // Requests handler
        let handle = core.handle();
        let network_tx = self.network_tx.clone();
        let requests_tx = self.network_requests.0.clone();
        let network_config = self.network_config;
        let requests_handle = self.network_requests.1.for_each(|request| {
            match request {
                NetworkRequest::SendMessage(peer, msg) => {
                    let conn_tx = if let Some(conn_tx) = outgoing_connections.get(&peer).cloned() {
                        conn_tx
                    } else {
                        let (conn_tx, conn_rx) = mpsc::channel(10);
                        outgoing_connections.insert(peer, conn_tx.clone());

                        let requests_tx = requests_tx.clone();
                        let connect_handle = NewConnection::create(
                            peer,
                            handle.clone(),
                            network_config.tcp_reconnect_timeout,
                            network_config.tcp_reconnect_timeout_max,
                        ).and_then(move |sock| {
                            try_future_boxed!(sock.set_nodelay(network_config.tcp_nodelay));
                            try_future_boxed!(sock.set_keepalive(
                                network_config.tcp_keep_alive.map(Duration::from_millis),
                            ));

                            info!("Established connection with peer={}", peer);

                            let stream = sock.framed(MessagesCodec);
                            let (sink, stream) = stream.split();

                            let writer = conn_rx
                                .map_err(|_| other_error("Can't send data into socket"))
                                .forward(sink);
                            let reader = stream.for_each(result_ok).map_err(into_other);

                            reader
                                .select2(writer)
                                .map_err(|_| other_error("Socket error"))
                                .and_then(|res| match res {
                                    Either::A((_, _reader)) => Ok(()).into_future(),
                                    Either::B((_, _writer)) => Ok(()).into_future(),
                                })
                                .boxed()
                        })
                            .then(move |res| {
                                info!("Connection with peer={} closed, reason={:?}", peer, res);
                                // outgoing_connections.remove(&peer);

                                let request = NetworkRequest::DisconnectWithPeer(peer);
                                requests_tx
                                    .clone()
                                    .send(request)
                                    .map(forget_result)
                                    .map_err(into_other)
                            })
                            .map_err(log_error);
                        handle.spawn(connect_handle);
                        conn_tx
                    };

                    let duration = Duration::from_secs(5);
                    let send_timeout = Timeout::new(duration, &handle)
                        .unwrap()
                        .and_then(result_ok)
                        .map_err(|_| other_error("Can't timeout"));

                    let send_handle = conn_tx.send(msg).map(forget_result).map_err(log_error);

                    let timeouted_connect = send_handle
                        .select2(send_timeout)
                        .map_err(|_| other_error("Unable to send message"))
                        .and_then(move |either| match either {
                            Either::A((send, _timeout_fut)) => Ok(send),
                            Either::B((_, _connect_fut)) => Err(other_error("Send timeout")),
                        })
                        .map_err(log_error);

                    handle.spawn(timeouted_connect);
                }
                NetworkRequest::DisconnectWithPeer(peer) => {
                    outgoing_connections.remove(&peer);

                    let event = NetworkEvent::PeerDisconnected(peer);
                    let event_handle = network_tx.clone().send(event).map(forget_result).map_err(
                        log_error,
                    );
                    handle.spawn(event_handle);
                }
            }

            Ok(())
        });

        // Incoming connections handler
        let listener = TcpListener::bind(&self.listen_address, &core.handle()).unwrap();
        let network_tx = network_tx.clone();
        let handle = core.handle();
        let server = listener
            .incoming()
            .for_each(move |(sock, addr)| {
                info!("Accepted incoming connection with peer={}", addr);

                let stream = sock.framed(MessagesCodec);
                let (_, stream) = stream.split();
                let network_tx = network_tx.clone();
                let connection_handler = stream
                    .into_future()
                    .map_err(|e| e.0)
                    .and_then(move |(raw, stream)| {
                        let msg = raw.map(Any::from_raw);
                        if let Some(Ok(Any::Connect(msg))) = msg {
                            Ok((msg, stream))
                        } else {
                            Err(other_error("First message is not Connect"))
                        }
                    })
                    .and_then(move |(connect, stream)| {
                        info!("Received handshake message={:?}", connect);

                        let event = NetworkEvent::PeerConnected(addr, connect);
                        let connect_event = network_tx.clone().send(event).map_err(into_other);

                        let network_tx = network_tx.clone();
                        let messages_stream = stream.for_each(move |raw| {
                            let event = NetworkEvent::MessageReceived(addr, raw);
                            network_tx.clone().send(event).map(forget_result).map_err(
                                into_other,
                            )
                        });

                        messages_stream
                            .join(connect_event)
                            .map(move |(_, stream)| stream)
                            .map_err(into_other)
                    })
                    .map(forget_result)
                    .map_err(log_error);
                handle.spawn(connection_handler);
                Ok(())
            })
            .map_err(log_error);
        core.handle().spawn(server);

        core.run(requests_handle)
    }
}

pub struct NewConnection {
    socket: Option<TcpStreamNew>,
    timeout: Interval,
    address: SocketAddr,
    handle: Handle,
    groth_factor: f32,
    start_time: SystemTime,
    reconnect_timeout: Milliseconds,
    reconnect_timeout_max: Milliseconds,
}

impl NewConnection {
    pub fn create(
        address: SocketAddr,
        handle: Handle,
        reconnect_timeout: Milliseconds,
        reconnect_timeout_max: Milliseconds,
    ) -> NewConnection {
        NewConnection {
            socket: Some(TcpStream::connect(&address, &handle)),
            timeout: Interval::new(Duration::from_millis(reconnect_timeout), &handle).unwrap(),
            address,
            handle,
            groth_factor: 1.5,
            start_time: SystemTime::now(),
            reconnect_timeout,
            reconnect_timeout_max,
        }
    }

    fn next_attempt(&mut self) -> Poll<TcpStream, io::Error> {
        self.start_time = SystemTime::now();
        if self.reconnect_timeout == self.reconnect_timeout_max {
            return Err(other_error(
                &format!("Maximum reconnect timeout reached for connection with the peer: {}",
                self.address,
            ),
            ));
        }

        self.reconnect_timeout = (self.reconnect_timeout as f32 * self.groth_factor) as
            Milliseconds;
        self.reconnect_timeout = cmp::min(self.reconnect_timeout, self.reconnect_timeout_max);
        self.socket = Some(TcpStream::connect(&self.address, &self.handle));
        self.timeout = Interval::new(Duration::from_millis(self.reconnect_timeout), &self.handle)
            .unwrap();

        trace!(
            "Add reconnect timeout to {}, delay = {} ms",
            self.address,
            self.reconnect_timeout
        );
        self.socket.as_mut().unwrap().poll()
    }

    fn poll_timeout(&mut self) -> Poll<TcpStream, io::Error> {
        match self.timeout.poll() {
            Ok(Async::Ready(_)) => self.next_attempt(),
            Ok(Async::NotReady) => Ok(Async::NotReady),
            Err(e) => Err(into_other(e)),
        }
    }
}

impl Future for NewConnection {
    type Item = TcpStream;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<TcpStream, io::Error> {
        if let Some(mut stream) = self.socket.take() {
            match stream.poll() {
                Ok(Async::Ready(stream)) => Ok(Async::Ready(stream)),
                Ok(Async::NotReady) => {
                    self.socket = Some(stream);
                    Ok(Async::NotReady)
                }
                Err(e) => {
                    trace!(
                        "An error occured during connecting to the peer: {}, error: {}",
                        self.address,
                        e
                    );
                    self.socket = None;
                    self.poll_timeout()
                }
            }
        } else {
            self.poll_timeout()
        }
    }
}

impl fmt::Debug for NewConnection {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("NewConnection { .. }")
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code, unused_variables)]
use alloc::heap::{Heap, Alloc, Layout};
use bytes::BytesMut;

use std::sync::Arc;

use audiosample::*;
use pixel::*;
use timeinfo::*;

pub mod error {
    error_chain! {
        errors {
            InvalidIndex
            InvalidConversion
        }
    }
}

use self::error::*;

// TODO: Document
// TODO: Change it to provide Droppable/Seekable information or use a separate enum?
#[derive(Clone, Debug, PartialEq)]
pub enum PictureType {
    UNKNOWN,
    I,
    P,
    B,
    S,
    SI,
    SP,
    SB,
    BI,
}

#[derive(Clone, Debug, PartialEq)]
pub struct VideoInfo {
    pub pic_type: PictureType,
    pub width: usize,
    pub height: usize,
    pub format: Arc<Formaton>,
}

impl VideoInfo {
    fn size(&self, align: usize) -> usize {
        let mut size = 0;
        for &component in self.format.into_iter() {
            if let Some(c) = component {
                size += c.get_data_size(self.width, self.height, align);
            }
        }
        size
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct AudioInfo {
    pub samples: usize,
    pub rate: usize,
    pub map: ChannelMap,
    pub format: Arc<Soniton>,
}

impl AudioInfo {
    fn size(&self, align: usize) -> usize {
        self.format.get_audio_size(self.samples, align) * self.map.len()
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum MediaKind {
    Video(VideoInfo),
    Audio(AudioInfo),
}

use std::convert::From;

impl From<VideoInfo> for MediaKind {
    fn from(v: VideoInfo) -> Self {
        MediaKind::Video(v)
    }
}

impl From<AudioInfo> for MediaKind {
    fn from(a: AudioInfo) -> Self {
        MediaKind::Audio(a)
    }
}

use self::MediaKind::*;

pub trait FrameBuffer {
    fn linesize(&self, idx: usize) -> Result<usize>;
    fn count(&self) -> usize;
    fn as_slice_inner<'a>(&'a self, idx: usize) -> Result<&'a [u8]>;
    fn as_mut_slice_inner<'a>(&'a mut self, idx: usize) -> Result<&'a mut [u8]>;
}

pub trait FrameBufferConv<T> : FrameBuffer {
    fn as_slice<'a>(&'a self, idx: usize) -> Result<&'a [T]> {
        let size = mem::size_of::<T>();
        if (self.linesize(idx)? % size) != 0 {
            Err(ErrorKind::InvalidConversion.into())
        } else {
            let s = self.as_slice_inner(idx)?;
            let r = unsafe {
                slice::from_raw_parts::<T>(mem::transmute(s.as_ptr()), s.len() / size)
            };

            Ok(r)
        }
    }
    fn as_mut_slice<'a>(&'a mut self, idx: usize) -> Result<&'a mut [T]> {
        let size = mem::size_of::<T>();
        if (self.linesize(idx)? % size) != 0 {
            Err(ErrorKind::InvalidConversion.into())
        } else {
            let s = self.as_mut_slice_inner(idx)?;
            let r = unsafe {
                slice::from_raw_parts_mut::<T>(mem::transmute(s.as_ptr()), s.len() / size)
            };

            Ok(r)
        }
    }
}

impl FrameBufferConv<u8> for FrameBuffer {}
impl FrameBufferConv<i16> for FrameBuffer {}
impl FrameBufferConv<f32> for FrameBuffer {}

use std::fmt;

impl fmt::Debug for FrameBuffer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "FrameBuffer")
    }
}

#[derive(Debug)]
pub struct Frame {
    pub kind: MediaKind,
    pub buf: Box<FrameBuffer>,
    pub t: TimeInfo,
}

const ALIGNMENT: usize = 32;

struct Plane {
    buf: BytesMut,
    linesize: usize,
}

struct DefaultFrameBuffer {
    buf: BytesMut,
    planes: Vec<Plane>,
}

impl FrameBuffer for DefaultFrameBuffer {
    fn linesize(&self, idx: usize) -> Result<usize> {
        match self.planes.get(idx) {
            None => Err(Error::from_kind(ErrorKind::InvalidIndex)),
            Some(plane) => Ok(plane.linesize),
        }
    }
    fn count(&self) -> usize {
        self.planes.len()
    }

    fn as_slice_inner<'a>(&'a self, idx: usize) -> Result<&'a [u8]> {
        match self.planes.get(idx) {
            None => Err(Error::from_kind(ErrorKind::InvalidIndex)),
            Some(plane) => Ok(&plane.buf),
        }
    }
    fn as_mut_slice_inner<'a>(&'a mut self, idx: usize) -> Result<&'a mut [u8]> {
        match self.planes.get_mut(idx) {
            None => Err(Error::from_kind(ErrorKind::InvalidIndex)),
            Some(plane) => Ok(&mut plane.buf),
        }
    }
}

impl DefaultFrameBuffer {
    pub fn new<'a>(kind: &'a MediaKind) -> DefaultFrameBuffer {
        match kind {
            &Video(ref video) => {
                let size = video.size(ALIGNMENT);
                let data = unsafe {
                    Heap.alloc(Layout::from_size_align(size, ALIGNMENT).unwrap())
                        .unwrap()
                };
                //let data = unsafe { Heap.alloc_zeroed(Layout::from_size_align(size, ALIGNMENT)) };
                let buf = BytesMut::from(unsafe { Vec::from_raw_parts(data, size, size) });
                let mut buffer = DefaultFrameBuffer {
                    buf: buf,
                    planes: Vec::new(),
                };
                for &component in video.format.iter() {
                    if let Some(c) = component {
                        let planesize = c.get_data_size(video.width, video.height, ALIGNMENT);
                        let linesize = c.get_linesize(video.width, ALIGNMENT);
                        buffer.planes.push(Plane {
                            buf: buffer.buf.split_to(planesize),
                            linesize: linesize,
                        });
                    }
                }
                buffer
            },
            &Audio(ref audio) => {
                let size = audio.size(ALIGNMENT);
                let data = unsafe {
                    Heap.alloc(Layout::from_size_align(size, ALIGNMENT).unwrap())
                        .unwrap()
                };
                let buf = BytesMut::from(unsafe { Vec::from_raw_parts(data, size, size) });
                let mut buffer = DefaultFrameBuffer {
                    buf: buf,
                    planes: Vec::new(),
                };
                for _ in 0..audio.map.len() {
                    let size = audio.format.get_audio_size(audio.samples, ALIGNMENT);
                    buffer.planes.push(Plane {
                        buf: buffer.buf.split_to(size),
                        linesize: size,
                    });
                }
                buffer
            },
        }
    }
}

pub type ArcFrame = Arc<Frame>;

pub fn new_default_frame<T>(kind: T, t: Option<TimeInfo>) -> Frame
where T: Into<MediaKind> + Clone
{
    let k = kind.into();
    let buf = DefaultFrameBuffer::new(&k);

    Frame {
        kind: k,
        buf: box buf,
        t: t.unwrap_or_default(),
    }
}

use std::ptr::copy_nonoverlapping;

fn copy_plane(
    dst: &mut [u8],
    dst_linesize: usize,
    src: &[u8],
    src_linesize: usize,
    w: usize,
    h: usize,
) {
    let dst_chunks = dst.chunks_mut(dst_linesize);
    let src_chunks = src.chunks(src_linesize);

    for (d, s) in dst_chunks.zip(src_chunks).take(h) {
        unsafe {
            copy_nonoverlapping(s.as_ptr(), d.as_mut_ptr(), w);
        }
    }
}

fn copy_image<'a, IM, IU, I>(
    dst: IM,
    dst_linesizes: IU,
    src: I,
    src_linesizes: IU,
    w: usize,
    h: usize,
    fmt: &Formaton,
) where
    IM: Iterator<Item = &'a mut [u8]>,
    I: Iterator<Item = &'a [u8]>,
    IU: Iterator<Item = usize>,
{
    let dst_iter = dst.zip(dst_linesizes);
    let src_iter = src.zip(src_linesizes);
    let iter = dst_iter.zip(src_iter).zip(fmt.iter());

    for (((d, d_linesize), (s, s_linesize)), c) in iter {
        copy_plane(
            d,
            d_linesize,
            s,
            s_linesize,
            c.unwrap().get_width(w),
            c.unwrap().get_height(h),
        );
    }
}

// TODO: Add proper tests
fn copy_to_frame<'a, I, IU>(dst: &mut Frame, mut src: I, mut src_linesize: IU, w: usize, h: usize)
where
    I: Iterator<Item = &'a [u8]>,
    IU: Iterator<Item = usize>,
{
    if let MediaKind::Video(ref fmt) = dst.kind {
        let mut f_iter = fmt.format.iter();
        let w = fmt.width;
        let h = fmt.height;
        for i in 0..dst.buf.count() {
            let d_linesize = dst.buf.linesize(i).unwrap();
            let s_linesize = src_linesize.next().unwrap();
            let d = dst.buf.as_mut_slice(i).unwrap();
            let s = src.next().unwrap();
            let c = f_iter.next().unwrap();
            copy_plane(
                d,
                d_linesize,
                s,
                s_linesize,
                c.unwrap().get_width(w),
                c.unwrap().get_height(h),
            );
        }
    } else {
        unimplemented!();
    }
}

use std::mem;
use std::slice;

// TODO make it a separate trait
impl Frame {
    pub fn copy_from_slice<'a, I, IU>(&mut self, mut src: I, mut src_linesize: IU)
    where
        I: Iterator<Item = &'a [u8]>,
        IU: Iterator<Item = usize>,
    {
        if let MediaKind::Video(ref fmt) = self.kind {
            let mut f_iter = fmt.format.iter();
            let w = fmt.width;
            let h = fmt.height;
            for i in 0..self.buf.count() {
                let d_linesize = self.buf.linesize(i).unwrap();
                let s_linesize = src_linesize.next().unwrap();
                let d = self.buf.as_mut_slice(i).unwrap();
                let s = src.next().unwrap();
                let c = f_iter.next().unwrap();
                copy_plane(
                    d,
                    d_linesize,
                    s,
                    s_linesize,
                    c.unwrap().get_width(w),
                    c.unwrap().get_height(h),
                );
            }
        } else {
            unimplemented!();
        }
    }

    pub fn copy_from_raw_parts<'a, I, IU>(&mut self, mut src: I, mut src_linesize: IU)
    where
        I: Iterator<Item = *const u8>,
        IU: Iterator<Item = usize>,
    {
        if let MediaKind::Video(ref fmt) = self.kind {
            let mut f_iter = fmt.format.iter();
            let w = fmt.width;
            let h = fmt.height;
            for i in 0..self.buf.count() {
                let d_linesize = self.buf.linesize(i).unwrap();
                let s_linesize = src_linesize.next().unwrap();
                let d = self.buf.as_mut_slice(i).unwrap();
                let c = f_iter.next().unwrap();
                let r = src.next().unwrap();
                let hb = c.unwrap().get_height(h);
                let s = unsafe { slice::from_raw_parts(r, hb * s_linesize) };
                copy_plane(d, d_linesize, s, s_linesize, c.unwrap().get_width(w), hb);
                mem::forget(s);
            }
        } else {
            unimplemented!();
        }
    }
}

<commit_msg>data: Require the FrameBuffer to be thread-safe<commit_after>#![allow(dead_code, unused_variables)]
use alloc::heap::{Heap, Alloc, Layout};
use bytes::BytesMut;

use std::sync::Arc;

use audiosample::*;
use pixel::*;
use timeinfo::*;

pub mod error {
    error_chain! {
        errors {
            InvalidIndex
            InvalidConversion
        }
    }
}

use self::error::*;

// TODO: Document
// TODO: Change it to provide Droppable/Seekable information or use a separate enum?
#[derive(Clone, Debug, PartialEq)]
pub enum PictureType {
    UNKNOWN,
    I,
    P,
    B,
    S,
    SI,
    SP,
    SB,
    BI,
}

#[derive(Clone, Debug, PartialEq)]
pub struct VideoInfo {
    pub pic_type: PictureType,
    pub width: usize,
    pub height: usize,
    pub format: Arc<Formaton>,
}

impl VideoInfo {
    fn size(&self, align: usize) -> usize {
        let mut size = 0;
        for &component in self.format.into_iter() {
            if let Some(c) = component {
                size += c.get_data_size(self.width, self.height, align);
            }
        }
        size
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct AudioInfo {
    pub samples: usize,
    pub rate: usize,
    pub map: ChannelMap,
    pub format: Arc<Soniton>,
}

impl AudioInfo {
    fn size(&self, align: usize) -> usize {
        self.format.get_audio_size(self.samples, align) * self.map.len()
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum MediaKind {
    Video(VideoInfo),
    Audio(AudioInfo),
}

use std::convert::From;

impl From<VideoInfo> for MediaKind {
    fn from(v: VideoInfo) -> Self {
        MediaKind::Video(v)
    }
}

impl From<AudioInfo> for MediaKind {
    fn from(a: AudioInfo) -> Self {
        MediaKind::Audio(a)
    }
}

use self::MediaKind::*;

pub trait FrameBuffer : Send + Sync {
    fn linesize(&self, idx: usize) -> Result<usize>;
    fn count(&self) -> usize;
    fn as_slice_inner<'a>(&'a self, idx: usize) -> Result<&'a [u8]>;
    fn as_mut_slice_inner<'a>(&'a mut self, idx: usize) -> Result<&'a mut [u8]>;
}

pub trait FrameBufferConv<T> : FrameBuffer {
    fn as_slice<'a>(&'a self, idx: usize) -> Result<&'a [T]> {
        let size = mem::size_of::<T>();
        if (self.linesize(idx)? % size) != 0 {
            Err(ErrorKind::InvalidConversion.into())
        } else {
            let s = self.as_slice_inner(idx)?;
            let r = unsafe {
                slice::from_raw_parts::<T>(mem::transmute(s.as_ptr()), s.len() / size)
            };

            Ok(r)
        }
    }
    fn as_mut_slice<'a>(&'a mut self, idx: usize) -> Result<&'a mut [T]> {
        let size = mem::size_of::<T>();
        if (self.linesize(idx)? % size) != 0 {
            Err(ErrorKind::InvalidConversion.into())
        } else {
            let s = self.as_mut_slice_inner(idx)?;
            let r = unsafe {
                slice::from_raw_parts_mut::<T>(mem::transmute(s.as_ptr()), s.len() / size)
            };

            Ok(r)
        }
    }
}

impl FrameBufferConv<u8> for FrameBuffer {}
impl FrameBufferConv<i16> for FrameBuffer {}
impl FrameBufferConv<f32> for FrameBuffer {}

use std::fmt;

impl fmt::Debug for FrameBuffer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "FrameBuffer")
    }
}

#[derive(Debug)]
pub struct Frame {
    pub kind: MediaKind,
    pub buf: Box<FrameBuffer>,
    pub t: TimeInfo,
}

const ALIGNMENT: usize = 32;

struct Plane {
    buf: BytesMut,
    linesize: usize,
}

struct DefaultFrameBuffer {
    buf: BytesMut,
    planes: Vec<Plane>,
}

impl FrameBuffer for DefaultFrameBuffer {
    fn linesize(&self, idx: usize) -> Result<usize> {
        match self.planes.get(idx) {
            None => Err(Error::from_kind(ErrorKind::InvalidIndex)),
            Some(plane) => Ok(plane.linesize),
        }
    }
    fn count(&self) -> usize {
        self.planes.len()
    }

    fn as_slice_inner<'a>(&'a self, idx: usize) -> Result<&'a [u8]> {
        match self.planes.get(idx) {
            None => Err(Error::from_kind(ErrorKind::InvalidIndex)),
            Some(plane) => Ok(&plane.buf),
        }
    }
    fn as_mut_slice_inner<'a>(&'a mut self, idx: usize) -> Result<&'a mut [u8]> {
        match self.planes.get_mut(idx) {
            None => Err(Error::from_kind(ErrorKind::InvalidIndex)),
            Some(plane) => Ok(&mut plane.buf),
        }
    }
}

impl DefaultFrameBuffer {
    pub fn new<'a>(kind: &'a MediaKind) -> DefaultFrameBuffer {
        match kind {
            &Video(ref video) => {
                let size = video.size(ALIGNMENT);
                let data = unsafe {
                    Heap.alloc(Layout::from_size_align(size, ALIGNMENT).unwrap())
                        .unwrap()
                };
                //let data = unsafe { Heap.alloc_zeroed(Layout::from_size_align(size, ALIGNMENT)) };
                let buf = BytesMut::from(unsafe { Vec::from_raw_parts(data, size, size) });
                let mut buffer = DefaultFrameBuffer {
                    buf: buf,
                    planes: Vec::new(),
                };
                for &component in video.format.iter() {
                    if let Some(c) = component {
                        let planesize = c.get_data_size(video.width, video.height, ALIGNMENT);
                        let linesize = c.get_linesize(video.width, ALIGNMENT);
                        buffer.planes.push(Plane {
                            buf: buffer.buf.split_to(planesize),
                            linesize: linesize,
                        });
                    }
                }
                buffer
            },
            &Audio(ref audio) => {
                let size = audio.size(ALIGNMENT);
                let data = unsafe {
                    Heap.alloc(Layout::from_size_align(size, ALIGNMENT).unwrap())
                        .unwrap()
                };
                let buf = BytesMut::from(unsafe { Vec::from_raw_parts(data, size, size) });
                let mut buffer = DefaultFrameBuffer {
                    buf: buf,
                    planes: Vec::new(),
                };
                for _ in 0..audio.map.len() {
                    let size = audio.format.get_audio_size(audio.samples, ALIGNMENT);
                    buffer.planes.push(Plane {
                        buf: buffer.buf.split_to(size),
                        linesize: size,
                    });
                }
                buffer
            },
        }
    }
}

pub type ArcFrame = Arc<Frame>;

pub fn new_default_frame<T>(kind: T, t: Option<TimeInfo>) -> Frame
where T: Into<MediaKind> + Clone
{
    let k = kind.into();
    let buf = DefaultFrameBuffer::new(&k);

    Frame {
        kind: k,
        buf: box buf,
        t: t.unwrap_or_default(),
    }
}

use std::ptr::copy_nonoverlapping;

fn copy_plane(
    dst: &mut [u8],
    dst_linesize: usize,
    src: &[u8],
    src_linesize: usize,
    w: usize,
    h: usize,
) {
    let dst_chunks = dst.chunks_mut(dst_linesize);
    let src_chunks = src.chunks(src_linesize);

    for (d, s) in dst_chunks.zip(src_chunks).take(h) {
        unsafe {
            copy_nonoverlapping(s.as_ptr(), d.as_mut_ptr(), w);
        }
    }
}

fn copy_image<'a, IM, IU, I>(
    dst: IM,
    dst_linesizes: IU,
    src: I,
    src_linesizes: IU,
    w: usize,
    h: usize,
    fmt: &Formaton,
) where
    IM: Iterator<Item = &'a mut [u8]>,
    I: Iterator<Item = &'a [u8]>,
    IU: Iterator<Item = usize>,
{
    let dst_iter = dst.zip(dst_linesizes);
    let src_iter = src.zip(src_linesizes);
    let iter = dst_iter.zip(src_iter).zip(fmt.iter());

    for (((d, d_linesize), (s, s_linesize)), c) in iter {
        copy_plane(
            d,
            d_linesize,
            s,
            s_linesize,
            c.unwrap().get_width(w),
            c.unwrap().get_height(h),
        );
    }
}

// TODO: Add proper tests
fn copy_to_frame<'a, I, IU>(dst: &mut Frame, mut src: I, mut src_linesize: IU, w: usize, h: usize)
where
    I: Iterator<Item = &'a [u8]>,
    IU: Iterator<Item = usize>,
{
    if let MediaKind::Video(ref fmt) = dst.kind {
        let mut f_iter = fmt.format.iter();
        let w = fmt.width;
        let h = fmt.height;
        for i in 0..dst.buf.count() {
            let d_linesize = dst.buf.linesize(i).unwrap();
            let s_linesize = src_linesize.next().unwrap();
            let d = dst.buf.as_mut_slice(i).unwrap();
            let s = src.next().unwrap();
            let c = f_iter.next().unwrap();
            copy_plane(
                d,
                d_linesize,
                s,
                s_linesize,
                c.unwrap().get_width(w),
                c.unwrap().get_height(h),
            );
        }
    } else {
        unimplemented!();
    }
}

use std::mem;
use std::slice;

// TODO make it a separate trait
impl Frame {
    pub fn copy_from_slice<'a, I, IU>(&mut self, mut src: I, mut src_linesize: IU)
    where
        I: Iterator<Item = &'a [u8]>,
        IU: Iterator<Item = usize>,
    {
        if let MediaKind::Video(ref fmt) = self.kind {
            let mut f_iter = fmt.format.iter();
            let w = fmt.width;
            let h = fmt.height;
            for i in 0..self.buf.count() {
                let d_linesize = self.buf.linesize(i).unwrap();
                let s_linesize = src_linesize.next().unwrap();
                let d = self.buf.as_mut_slice(i).unwrap();
                let s = src.next().unwrap();
                let c = f_iter.next().unwrap();
                copy_plane(
                    d,
                    d_linesize,
                    s,
                    s_linesize,
                    c.unwrap().get_width(w),
                    c.unwrap().get_height(h),
                );
            }
        } else {
            unimplemented!();
        }
    }

    pub fn copy_from_raw_parts<'a, I, IU>(&mut self, mut src: I, mut src_linesize: IU)
    where
        I: Iterator<Item = *const u8>,
        IU: Iterator<Item = usize>,
    {
        if let MediaKind::Video(ref fmt) = self.kind {
            let mut f_iter = fmt.format.iter();
            let w = fmt.width;
            let h = fmt.height;
            for i in 0..self.buf.count() {
                let d_linesize = self.buf.linesize(i).unwrap();
                let s_linesize = src_linesize.next().unwrap();
                let d = self.buf.as_mut_slice(i).unwrap();
                let c = f_iter.next().unwrap();
                let r = src.next().unwrap();
                let hb = c.unwrap().get_height(h);
                let s = unsafe { slice::from_raw_parts(r, hb * s_linesize) };
                copy_plane(d, d_linesize, s, s_linesize, c.unwrap().get_width(w), hb);
                mem::forget(s);
            }
        } else {
            unimplemented!();
        }
    }
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use crate::INTERNAL_METADATA_DIRECTIVE;
use common::{NamedItem, WithLocation};
use graphql_ir::{
    Argument, ConstantArgument, ConstantValue, Directive, OperationDefinition, Program, Selection,
    Transformed, Transformer, Value,
};
use graphql_syntax::OperationKind;
use indexmap::IndexMap;
use interner::{Intern, StringKey};
use lazy_static::lazy_static;
use schema::{EnumValue, Field, Schema, Type};

lazy_static! {
    static ref TEST_OPERATION_DIRECTIVE: StringKey = "relay_test_operation".intern();
    static ref TEST_OPERATION_METADATA_KEY: StringKey = "relayTestingSelectionTypeInfo".intern();
    static ref ENUM_VALUES_KEY: StringKey = "enumValues".intern();
    static ref NULLABLE_KEY: StringKey = "nullable".intern();
    static ref PLURAL_KEY: StringKey = "plural".intern();
    static ref TYPE_KEY: StringKey = "type".intern();
}

pub fn generate_test_operation_metadata(program: &Program) -> Program {
    let mut transformer = GenerateTestOperationMetadata::new(program);
    transformer
        .transform_program(program)
        .replace_or_else(|| program.clone())
}

struct GenerateTestOperationMetadata<'s> {
    pub program: &'s Program,
}

impl<'s> GenerateTestOperationMetadata<'s> {
    fn new(program: &'s Program) -> Self {
        GenerateTestOperationMetadata { program }
    }
}

impl<'s> Transformer for GenerateTestOperationMetadata<'s> {
    const NAME: &'static str = "GenerateTestOperationMetadata";
    const VISIT_ARGUMENTS: bool = false;
    const VISIT_DIRECTIVES: bool = false;

    fn transform_operation(
        &mut self,
        operation: &OperationDefinition,
    ) -> Transformed<OperationDefinition> {
        match operation.kind {
            OperationKind::Query => {
                if operation
                    .directives
                    .named(*TEST_OPERATION_DIRECTIVE)
                    .is_some()
                {
                    let mut next_directives = Vec::with_capacity(operation.directives.len());
                    for directive in &operation.directives {
                        // replace @relay_test_operation with @__metadata
                        if directive.name.item == *TEST_OPERATION_DIRECTIVE {
                            next_directives.push(Directive {
                                name: WithLocation::new(
                                    operation.name.location,
                                    *INTERNAL_METADATA_DIRECTIVE,
                                ),
                                arguments: vec![Argument {
                                    name: WithLocation::new(
                                        operation.name.location,
                                        *TEST_OPERATION_METADATA_KEY,
                                    ),
                                    value: WithLocation::new(
                                        operation.name.location,
                                        Value::Constant(ConstantValue::Object(From::from(
                                            RelayTestOperationMetadata::new(
                                                &self.program.schema,
                                                &operation.selections,
                                            ),
                                        ))),
                                    ),
                                }],
                            });
                        } else {
                            next_directives.push(directive.clone());
                        }
                    }

                    Transformed::Replace(OperationDefinition {
                        directives: next_directives,
                        ..operation.clone()
                    })
                } else {
                    Transformed::Keep
                }
            }
            _ => Transformed::Keep,
        }
    }
}

impl From<RelayTestOperationMetadata> for Vec<ConstantArgument> {
    fn from(test_metadata: RelayTestOperationMetadata) -> Self {
        let mut metadata: Vec<ConstantArgument> =
            Vec::with_capacity(test_metadata.selection_type_info.len());
        for (path, type_info) in test_metadata.selection_type_info {
            metadata.push(ConstantArgument {
                name: WithLocation::generated(path),
                value: WithLocation::generated(ConstantValue::Object(From::from(type_info))),
            })
        }
        metadata
    }
}

impl From<RelayTestOperationSelectionTypeInfo> for Vec<ConstantArgument> {
    fn from(type_info: RelayTestOperationSelectionTypeInfo) -> Self {
        vec![
            ConstantArgument {
                name: WithLocation::generated(*ENUM_VALUES_KEY),
                value: WithLocation::generated(match type_info.enum_values {
                    Some(enums) => ConstantValue::List(
                        enums
                            .iter()
                            .map(|enum_| ConstantValue::String(enum_.value))
                            .collect(),
                    ),
                    None => ConstantValue::Null(),
                }),
            },
            ConstantArgument {
                name: WithLocation::generated(*NULLABLE_KEY),
                value: WithLocation::generated(ConstantValue::Boolean(type_info.nullable)),
            },
            ConstantArgument {
                name: WithLocation::generated(*PLURAL_KEY),
                value: WithLocation::generated(ConstantValue::Boolean(type_info.plural)),
            },
            ConstantArgument {
                name: WithLocation::generated(*TYPE_KEY),
                value: WithLocation::generated(ConstantValue::String(type_info.type_)),
            },
        ]
    }
}

#[derive(Debug, Clone)]
pub struct RelayTestOperationSelectionTypeInfo {
    pub type_: StringKey,
    pub enum_values: Option<Vec<EnumValue>>,
    pub plural: bool,
    pub nullable: bool,
}

impl RelayTestOperationSelectionTypeInfo {
    fn new(schema: &Schema, field: &Field) -> Self {
        let type_ = field.type_.inner();
        RelayTestOperationSelectionTypeInfo {
            type_: schema.get_type_name(type_),
            enum_values: match type_ {
                Type::Enum(enum_id) => Some(schema.enum_(enum_id).values.clone()),
                _ => None,
            },
            plural: field.type_.is_list(),
            nullable: !field.type_.is_non_null(),
        }
    }
}

#[derive(Debug)]
pub struct RelayTestOperationMetadata {
    pub selection_type_info: IndexMap<StringKey, RelayTestOperationSelectionTypeInfo>,
}

impl RelayTestOperationMetadata {
    pub fn new(schema: &Schema, selections: &[Selection]) -> Self {
        let mut selection_type_info: IndexMap<StringKey, RelayTestOperationSelectionTypeInfo> =
            Default::default();

        let mut processing_queue: Vec<(Option<StringKey>, &[Selection])> = vec![(None, selections)];
        while !processing_queue.is_empty() {
            if let Some(current_item) = processing_queue.pop() {
                let (path, selections) = current_item;
                for selection in selections {
                    match selection {
                        Selection::ScalarField(scalar_field) => {
                            let field = schema.field(scalar_field.definition.item);
                            if !field.is_extension {
                                let alias_or_name = scalar_field.alias_or_name(schema);
                                let next_path = next_path(path, alias_or_name);
                                selection_type_info.insert(
                                    next_path,
                                    RelayTestOperationSelectionTypeInfo::new(schema, field),
                                );
                            }
                        }
                        Selection::LinkedField(linked_field) => {
                            let field = schema.field(linked_field.definition.item);
                            if !field.is_extension {
                                let alias_or_name = linked_field.alias_or_name(schema);
                                let next_path = next_path(path, alias_or_name);
                                selection_type_info.insert(
                                    next_path,
                                    RelayTestOperationSelectionTypeInfo::new(schema, field),
                                );
                                processing_queue.push((Some(next_path), &linked_field.selections));
                            }
                        }
                        Selection::Condition(condition) => {
                            processing_queue.push((path, &condition.selections));
                        }
                        Selection::InlineFragment(inline_fragment) => {
                            processing_queue.push((path, &inline_fragment.selections));
                        }
                        Selection::FragmentSpread(_fragment_spread) => {
                            panic!(
                                "We do not expect to visit fragment spreads in the test operation"
                            );
                        }
                    }
                }
            }
        }

        RelayTestOperationMetadata {
            selection_type_info,
        }
    }
}

fn next_path(current_path: Option<StringKey>, field_alias_or_name: StringKey) -> StringKey {
    match current_path {
        None => field_alias_or_name,
        Some(path) => format!("{}.{}", path, field_alias_or_name).intern(),
    }
}
<commit_msg>Generate test metadata for all kinds of operations<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use crate::INTERNAL_METADATA_DIRECTIVE;
use common::{NamedItem, WithLocation};
use graphql_ir::{
    Argument, ConstantArgument, ConstantValue, Directive, OperationDefinition, Program, Selection,
    Transformed, Transformer, Value,
};
use indexmap::IndexMap;
use interner::{Intern, StringKey};
use lazy_static::lazy_static;
use schema::{EnumValue, Field, Schema, Type};

lazy_static! {
    static ref TEST_OPERATION_DIRECTIVE: StringKey = "relay_test_operation".intern();
    static ref TEST_OPERATION_METADATA_KEY: StringKey = "relayTestingSelectionTypeInfo".intern();
    static ref ENUM_VALUES_KEY: StringKey = "enumValues".intern();
    static ref NULLABLE_KEY: StringKey = "nullable".intern();
    static ref PLURAL_KEY: StringKey = "plural".intern();
    static ref TYPE_KEY: StringKey = "type".intern();
}

pub fn generate_test_operation_metadata(program: &Program) -> Program {
    let mut transformer = GenerateTestOperationMetadata::new(program);
    transformer
        .transform_program(program)
        .replace_or_else(|| program.clone())
}

struct GenerateTestOperationMetadata<'s> {
    pub program: &'s Program,
}

impl<'s> GenerateTestOperationMetadata<'s> {
    fn new(program: &'s Program) -> Self {
        GenerateTestOperationMetadata { program }
    }
}

impl<'s> Transformer for GenerateTestOperationMetadata<'s> {
    const NAME: &'static str = "GenerateTestOperationMetadata";
    const VISIT_ARGUMENTS: bool = false;
    const VISIT_DIRECTIVES: bool = false;

    fn transform_operation(
        &mut self,
        operation: &OperationDefinition,
    ) -> Transformed<OperationDefinition> {
        if operation
            .directives
            .named(*TEST_OPERATION_DIRECTIVE)
            .is_some()
        {
            let mut next_directives = Vec::with_capacity(operation.directives.len());
            for directive in &operation.directives {
                // replace @relay_test_operation with @__metadata
                if directive.name.item == *TEST_OPERATION_DIRECTIVE {
                    next_directives.push(Directive {
                        name: WithLocation::new(
                            operation.name.location,
                            *INTERNAL_METADATA_DIRECTIVE,
                        ),
                        arguments: vec![Argument {
                            name: WithLocation::new(
                                operation.name.location,
                                *TEST_OPERATION_METADATA_KEY,
                            ),
                            value: WithLocation::new(
                                operation.name.location,
                                Value::Constant(ConstantValue::Object(From::from(
                                    RelayTestOperationMetadata::new(
                                        &self.program.schema,
                                        &operation.selections,
                                    ),
                                ))),
                            ),
                        }],
                    });
                } else {
                    next_directives.push(directive.clone());
                }
            }

            Transformed::Replace(OperationDefinition {
                directives: next_directives,
                ..operation.clone()
            })
        } else {
            Transformed::Keep
        }
    }
}

impl From<RelayTestOperationMetadata> for Vec<ConstantArgument> {
    fn from(test_metadata: RelayTestOperationMetadata) -> Self {
        let mut metadata: Vec<ConstantArgument> =
            Vec::with_capacity(test_metadata.selection_type_info.len());
        for (path, type_info) in test_metadata.selection_type_info {
            metadata.push(ConstantArgument {
                name: WithLocation::generated(path),
                value: WithLocation::generated(ConstantValue::Object(From::from(type_info))),
            })
        }
        metadata
    }
}

impl From<RelayTestOperationSelectionTypeInfo> for Vec<ConstantArgument> {
    fn from(type_info: RelayTestOperationSelectionTypeInfo) -> Self {
        vec![
            ConstantArgument {
                name: WithLocation::generated(*ENUM_VALUES_KEY),
                value: WithLocation::generated(match type_info.enum_values {
                    Some(enums) => ConstantValue::List(
                        enums
                            .iter()
                            .map(|enum_| ConstantValue::String(enum_.value))
                            .collect(),
                    ),
                    None => ConstantValue::Null(),
                }),
            },
            ConstantArgument {
                name: WithLocation::generated(*NULLABLE_KEY),
                value: WithLocation::generated(ConstantValue::Boolean(type_info.nullable)),
            },
            ConstantArgument {
                name: WithLocation::generated(*PLURAL_KEY),
                value: WithLocation::generated(ConstantValue::Boolean(type_info.plural)),
            },
            ConstantArgument {
                name: WithLocation::generated(*TYPE_KEY),
                value: WithLocation::generated(ConstantValue::String(type_info.type_)),
            },
        ]
    }
}

#[derive(Debug, Clone)]
pub struct RelayTestOperationSelectionTypeInfo {
    pub type_: StringKey,
    pub enum_values: Option<Vec<EnumValue>>,
    pub plural: bool,
    pub nullable: bool,
}

impl RelayTestOperationSelectionTypeInfo {
    fn new(schema: &Schema, field: &Field) -> Self {
        let type_ = field.type_.inner();
        RelayTestOperationSelectionTypeInfo {
            type_: schema.get_type_name(type_),
            enum_values: match type_ {
                Type::Enum(enum_id) => Some(schema.enum_(enum_id).values.clone()),
                _ => None,
            },
            plural: field.type_.is_list(),
            nullable: !field.type_.is_non_null(),
        }
    }
}

#[derive(Debug)]
pub struct RelayTestOperationMetadata {
    pub selection_type_info: IndexMap<StringKey, RelayTestOperationSelectionTypeInfo>,
}

impl RelayTestOperationMetadata {
    pub fn new(schema: &Schema, selections: &[Selection]) -> Self {
        let mut selection_type_info: IndexMap<StringKey, RelayTestOperationSelectionTypeInfo> =
            Default::default();

        let mut processing_queue: Vec<(Option<StringKey>, &[Selection])> = vec![(None, selections)];
        while !processing_queue.is_empty() {
            if let Some(current_item) = processing_queue.pop() {
                let (path, selections) = current_item;
                for selection in selections {
                    match selection {
                        Selection::ScalarField(scalar_field) => {
                            let field = schema.field(scalar_field.definition.item);
                            if !field.is_extension {
                                let alias_or_name = scalar_field.alias_or_name(schema);
                                let next_path = next_path(path, alias_or_name);
                                selection_type_info.insert(
                                    next_path,
                                    RelayTestOperationSelectionTypeInfo::new(schema, field),
                                );
                            }
                        }
                        Selection::LinkedField(linked_field) => {
                            let field = schema.field(linked_field.definition.item);
                            if !field.is_extension {
                                let alias_or_name = linked_field.alias_or_name(schema);
                                let next_path = next_path(path, alias_or_name);
                                selection_type_info.insert(
                                    next_path,
                                    RelayTestOperationSelectionTypeInfo::new(schema, field),
                                );
                                processing_queue.push((Some(next_path), &linked_field.selections));
                            }
                        }
                        Selection::Condition(condition) => {
                            processing_queue.push((path, &condition.selections));
                        }
                        Selection::InlineFragment(inline_fragment) => {
                            processing_queue.push((path, &inline_fragment.selections));
                        }
                        Selection::FragmentSpread(_fragment_spread) => {
                            panic!(
                                "We do not expect to visit fragment spreads in the test operation"
                            );
                        }
                    }
                }
            }
        }

        RelayTestOperationMetadata {
            selection_type_info,
        }
    }
}

fn next_path(current_path: Option<StringKey>, field_alias_or_name: StringKey) -> StringKey {
    match current_path {
        None => field_alias_or_name,
        Some(path) => format!("{}.{}", path, field_alias_or_name).intern(),
    }
}
<|endoftext|>


<commit_before>extern crate mli;
extern crate rand;
use self::rand::Rng;

pub type R = rand::isaac::Isaac64Rng;

pub mod nodebrain {
    //0, 1, 2, -1, rand, node energy, bot count, present node bot count, self energy, present node connections, node connections, and memory are inputs.
    pub const STATIC_INPUTS: usize = 11;
    pub const TOTAL_INPUTS: usize = STATIC_INPUTS + super::finalbrain::TOTAL_MEMORY;
    pub const TOTAL_OUTPUTS: usize = 5;
    pub const DEFAULT_MUTATE_SIZE: usize = 30;
    pub const DEFAULT_CROSSOVER_POINTS: usize = 1;
    pub const DEFAULT_INSTRUCTIONS: usize = 64;
}

pub mod botbrain {
    //0, 1, 2, -1, rand, node energy, bot count, self energy, bot energy, bot signal, present node connections, and memory are inputs.
    pub const STATIC_INPUTS: usize = 11;
    pub const TOTAL_INPUTS: usize = STATIC_INPUTS + super::finalbrain::TOTAL_MEMORY;
    pub const TOTAL_OUTPUTS: usize = 5;
    pub const DEFAULT_MUTATE_SIZE: usize = 30;
    pub const DEFAULT_CROSSOVER_POINTS: usize = 1;
    pub const DEFAULT_INSTRUCTIONS: usize = 64;
}

pub mod finalbrain {
    pub const TOTAL_BOT_INPUTS: usize = 4;
    pub const TOTAL_NODE_INPUTS: usize = 4;
    pub const TOTAL_MEMORY: usize = 4;
    //0, 1, 2, -1, rand, present node energy, bot count, self energy, self index, present node connections, and memory are inputs
    pub const STATIC_INPUTS: usize = 10;
    pub const TOTAL_INPUTS: usize = STATIC_INPUTS + TOTAL_MEMORY +
        //Add inputs for all the node brains
        TOTAL_NODE_INPUTS * super::nodebrain::TOTAL_OUTPUTS +
        //Add inputs for all the bot brains
        TOTAL_BOT_INPUTS * super::botbrain::TOTAL_OUTPUTS;
    //Mate, Node, Energy Rate (as a sigmoid), Signal, Connect Signal, Pull
    pub const STATIC_OUTPUTS: usize = 7;
    pub const TOTAL_OUTPUTS: usize = STATIC_OUTPUTS + TOTAL_MEMORY;
    pub const DEFAULT_MUTATE_SIZE: usize = 30;
    pub const DEFAULT_CROSSOVER_POINTS: usize = 1;
    pub const DEFAULT_INSTRUCTIONS: usize = 256;
}

pub const ENERGY_EXCHANGE_MAGNITUDE: i64 = 500;
pub const EXISTENCE_COST: i64 = 50;
pub const MAX_ENERGY: i64 = 20000;
const DEFAULT_ENERGY: i64 = 4 * EXISTENCE_COST;
const MUTATE_PROBABILITY: f64 = 1.0;

#[derive(Clone)]
pub enum Ins {
    _NOP,
    _ADD,
    _SUB,
    _MUL,
    _DIV,
    _MOD,
    _GRT,
    _LES,
    _EQL,
    _NEQ,
    _AND,
    _OR,
    _EXP,
    _SIN,
    _COS,
    _SQT,
    MAX,
}

fn processor(ins: &Ins, a: i64, b: i64) -> i64 {
    match *ins {
        Ins::_NOP => a,
        Ins::_ADD => a + b,
        Ins::_SUB => a - b,
        Ins::_MUL => a * b,
        Ins::_DIV => {
            match a.checked_div(b) {
                Some(v) => v,
                None => 0,
            }
        },
        Ins::_MOD => {
            if b == 0 {
                0
            } else {
                a.wrapping_rem(b)
            }
        },
        Ins::_GRT => if a > b {
            1
        } else {
            0
        },
        Ins::_LES => if a < b {
            1
        } else {
            0
        },
        Ins::_EQL => if a == b {
            1
        } else {
            0
        },
        Ins::_NEQ => if a == b {
            1
        } else {
            0
        },
        Ins::_AND => if a != 0 && b != 0 {
            1
        } else {
            0
        },
        Ins::_OR => if a != 0 || b != 0 {
            1
        } else {
            0
        },
        Ins::_EXP => (a as f64).powf(b as f64) as i64,
        Ins::_SIN => ((a as f64 / b as f64).sin() * b as f64) as i64,
        Ins::_COS => ((a as f64 / b as f64).cos() * b as f64) as i64,
        Ins::_SQT => ((a as f64 / b as f64).sqrt() * b as f64) as i64,
        Ins::MAX => unreachable!(),
    }
}

fn mutator(ins: &mut Ins, rng: &mut R) {
    use std::mem;
    *ins = unsafe{mem::transmute(rng.gen_range::<u8>(0, Ins::MAX as u8))};
}

#[derive(Clone)]
pub struct Decision {
    pub mate: i64,
    pub node: i64,
    //This will be ran through a sigmoid
    pub rate: i64,
    pub signal: i64,
    pub connect_signal: i64,
    pub sever_choice: i64,
    pub pull: i64,
}

impl Default for Decision {
    fn default() -> Self {
        Decision{
            mate: -1,
            node: -1,
            rate: 0,
            signal: 0,
            connect_signal: 0,
            sever_choice: 0,
            pull: 0,
        }
    }
}

#[derive(Clone)]
pub struct Bot {
    pub bot_brain: mli::Mep<Ins, R, i64, fn(&mut Ins, &mut R), fn(&Ins, i64, i64) -> i64>,
    pub node_brain: mli::Mep<Ins, R, i64, fn(&mut Ins, &mut R), fn(&Ins, i64, i64) -> i64>,
    pub final_brain: mli::Mep<Ins, R, i64, fn(&mut Ins, &mut R), fn(&Ins, i64, i64) -> i64>,
    pub energy: i64,
    pub signal: i64,
    pub connect_signal: i64,
    pub memory: [i64; finalbrain::TOTAL_MEMORY],
    pub decision: Decision,
}

impl Bot {
    pub fn new(rng: &mut R) -> Self {
        let bvec = (0..botbrain::DEFAULT_INSTRUCTIONS).map(|_| {
                let mut ins = Ins::_NOP;
                mutator(&mut ins, rng);
                ins
            }).collect::<Vec<_>>();
        let nvec = (0..nodebrain::DEFAULT_INSTRUCTIONS).map(|_| {
                let mut ins = Ins::_NOP;
                mutator(&mut ins, rng);
                ins
            }).collect::<Vec<_>>();
        let fvec = (0..finalbrain::DEFAULT_INSTRUCTIONS).map(|_| {
                let mut ins = Ins::_NOP;
                mutator(&mut ins, rng);
                ins
            }).collect::<Vec<_>>();
        Bot {
            bot_brain: mli::Mep::new(botbrain::TOTAL_INPUTS, botbrain::TOTAL_OUTPUTS,
                botbrain::DEFAULT_MUTATE_SIZE, botbrain::DEFAULT_CROSSOVER_POINTS, rng,
                bvec.into_iter(),
                mutator, processor),

            node_brain: mli::Mep::new(nodebrain::TOTAL_INPUTS, nodebrain::TOTAL_OUTPUTS,
                nodebrain::DEFAULT_MUTATE_SIZE, nodebrain::DEFAULT_CROSSOVER_POINTS, rng,
                nvec.into_iter(),
                mutator, processor),

            final_brain: mli::Mep::new(finalbrain::TOTAL_INPUTS, finalbrain::TOTAL_OUTPUTS,
                finalbrain::DEFAULT_MUTATE_SIZE, finalbrain::DEFAULT_CROSSOVER_POINTS, rng,
                fvec.into_iter(),
                mutator, processor),

            energy: DEFAULT_ENERGY,

            signal: 0,
            connect_signal: 0,

            memory: [0; finalbrain::TOTAL_MEMORY],
            decision: Default::default(),
        }
    }

    pub fn mutate(&mut self, rng: &mut R) {
        use mli::Genetic;
        if rng.gen_range(0.0, 1.0) < MUTATE_PROBABILITY {
            self.bot_brain.mutate(rng);
            self.node_brain.mutate(rng);
            self.final_brain.mutate(rng);
        }
    }

    pub fn mate(&mut self, other: &Self, rng: &mut R) -> Self {
        use mli::Genetic;
        //Divide energy in half when mating for the mater
        self.energy /= 2;
        let mut b = Bot{
            bot_brain: mli::Genetic::mate((&self.bot_brain, &other.bot_brain), rng),
            node_brain: mli::Genetic::mate((&self.node_brain, &other.node_brain), rng),
            final_brain: mli::Genetic::mate((&self.final_brain, &other.final_brain), rng),
            energy: self.energy,
            signal: self.signal,
            connect_signal: 0,
            memory: self.memory,
            decision: self.decision.clone(),
        };
        //Perform unit mutations on offspring
        b.mutate(rng);
        b
    }

    pub fn divide(&mut self, rng: &mut R) -> Self {
        use mli::Genetic;
        //Divide energy in half when dividing
        self.energy /= 2;
        let mut b = Bot{
            bot_brain: self.bot_brain.clone(),
            node_brain: self.node_brain.clone(),
            final_brain: self.final_brain.clone(),
            energy: self.energy,
            signal: self.signal,
            connect_signal: 0,
            memory: self.memory,
            //Clone the rate of energy consumption in the decision
            decision: self.decision.clone(),
        };
        //Perform unit mutations on offspring
        b.mutate(rng);
        b
    }

    pub fn cycle(&mut self) {
        self.energy = self.energy.saturating_sub(EXISTENCE_COST);
        self.signal = self.decision.signal;
        self.connect_signal = self.decision.connect_signal;
    }
}
<commit_msg>remove cosine<commit_after>extern crate mli;
extern crate rand;
use self::rand::Rng;

pub type R = rand::isaac::Isaac64Rng;

pub mod nodebrain {
    //0, 1, 2, -1, rand, node energy, bot count, present node bot count, self energy, present node connections, node connections, and memory are inputs.
    pub const STATIC_INPUTS: usize = 11;
    pub const TOTAL_INPUTS: usize = STATIC_INPUTS + super::finalbrain::TOTAL_MEMORY;
    pub const TOTAL_OUTPUTS: usize = 5;
    pub const DEFAULT_MUTATE_SIZE: usize = 30;
    pub const DEFAULT_CROSSOVER_POINTS: usize = 1;
    pub const DEFAULT_INSTRUCTIONS: usize = 64;
}

pub mod botbrain {
    //0, 1, 2, -1, rand, node energy, bot count, self energy, bot energy, bot signal, present node connections, and memory are inputs.
    pub const STATIC_INPUTS: usize = 11;
    pub const TOTAL_INPUTS: usize = STATIC_INPUTS + super::finalbrain::TOTAL_MEMORY;
    pub const TOTAL_OUTPUTS: usize = 5;
    pub const DEFAULT_MUTATE_SIZE: usize = 30;
    pub const DEFAULT_CROSSOVER_POINTS: usize = 1;
    pub const DEFAULT_INSTRUCTIONS: usize = 64;
}

pub mod finalbrain {
    pub const TOTAL_BOT_INPUTS: usize = 4;
    pub const TOTAL_NODE_INPUTS: usize = 4;
    pub const TOTAL_MEMORY: usize = 4;
    //0, 1, 2, -1, rand, present node energy, bot count, self energy, self index, present node connections, and memory are inputs
    pub const STATIC_INPUTS: usize = 10;
    pub const TOTAL_INPUTS: usize = STATIC_INPUTS + TOTAL_MEMORY +
        //Add inputs for all the node brains
        TOTAL_NODE_INPUTS * super::nodebrain::TOTAL_OUTPUTS +
        //Add inputs for all the bot brains
        TOTAL_BOT_INPUTS * super::botbrain::TOTAL_OUTPUTS;
    //Mate, Node, Energy Rate (as a sigmoid), Signal, Connect Signal, Pull
    pub const STATIC_OUTPUTS: usize = 7;
    pub const TOTAL_OUTPUTS: usize = STATIC_OUTPUTS + TOTAL_MEMORY;
    pub const DEFAULT_MUTATE_SIZE: usize = 30;
    pub const DEFAULT_CROSSOVER_POINTS: usize = 1;
    pub const DEFAULT_INSTRUCTIONS: usize = 256;
}

pub const ENERGY_EXCHANGE_MAGNITUDE: i64 = 500;
pub const EXISTENCE_COST: i64 = 50;
pub const MAX_ENERGY: i64 = 20000;
const DEFAULT_ENERGY: i64 = 4 * EXISTENCE_COST;
const MUTATE_PROBABILITY: f64 = 1.0;

#[derive(Clone)]
pub enum Ins {
    _NOP,
    _ADD,
    _SUB,
    _MUL,
    _DIV,
    _MOD,
    _GRT,
    _LES,
    _EQL,
    _NEQ,
    _AND,
    _OR,
    _EXP,
    _SIN,
    _SQT,
    MAX,
}

fn processor(ins: &Ins, a: i64, b: i64) -> i64 {
    match *ins {
        Ins::_NOP => a,
        Ins::_ADD => a + b,
        Ins::_SUB => a - b,
        Ins::_MUL => a * b,
        Ins::_DIV => {
            match a.checked_div(b) {
                Some(v) => v,
                None => 0,
            }
        },
        Ins::_MOD => {
            if b == 0 {
                0
            } else {
                a.wrapping_rem(b)
            }
        },
        Ins::_GRT => if a > b {
            1
        } else {
            0
        },
        Ins::_LES => if a < b {
            1
        } else {
            0
        },
        Ins::_EQL => if a == b {
            1
        } else {
            0
        },
        Ins::_NEQ => if a == b {
            1
        } else {
            0
        },
        Ins::_AND => if a != 0 && b != 0 {
            1
        } else {
            0
        },
        Ins::_OR => if a != 0 || b != 0 {
            1
        } else {
            0
        },
        Ins::_EXP => (a as f64).powf(b as f64) as i64,
        Ins::_SIN => ((a as f64 / b as f64).sin() * b as f64) as i64,
        Ins::_SQT => ((a as f64 / b as f64).sqrt() * b as f64) as i64,
        Ins::MAX => unreachable!(),
    }
}

fn mutator(ins: &mut Ins, rng: &mut R) {
    use std::mem;
    *ins = unsafe{mem::transmute(rng.gen_range::<u8>(0, Ins::MAX as u8))};
}

#[derive(Clone)]
pub struct Decision {
    pub mate: i64,
    pub node: i64,
    //This will be ran through a sigmoid
    pub rate: i64,
    pub signal: i64,
    pub connect_signal: i64,
    pub sever_choice: i64,
    pub pull: i64,
}

impl Default for Decision {
    fn default() -> Self {
        Decision{
            mate: -1,
            node: -1,
            rate: 0,
            signal: 0,
            connect_signal: 0,
            sever_choice: 0,
            pull: 0,
        }
    }
}

#[derive(Clone)]
pub struct Bot {
    pub bot_brain: mli::Mep<Ins, R, i64, fn(&mut Ins, &mut R), fn(&Ins, i64, i64) -> i64>,
    pub node_brain: mli::Mep<Ins, R, i64, fn(&mut Ins, &mut R), fn(&Ins, i64, i64) -> i64>,
    pub final_brain: mli::Mep<Ins, R, i64, fn(&mut Ins, &mut R), fn(&Ins, i64, i64) -> i64>,
    pub energy: i64,
    pub signal: i64,
    pub connect_signal: i64,
    pub memory: [i64; finalbrain::TOTAL_MEMORY],
    pub decision: Decision,
}

impl Bot {
    pub fn new(rng: &mut R) -> Self {
        let bvec = (0..botbrain::DEFAULT_INSTRUCTIONS).map(|_| {
                let mut ins = Ins::_NOP;
                mutator(&mut ins, rng);
                ins
            }).collect::<Vec<_>>();
        let nvec = (0..nodebrain::DEFAULT_INSTRUCTIONS).map(|_| {
                let mut ins = Ins::_NOP;
                mutator(&mut ins, rng);
                ins
            }).collect::<Vec<_>>();
        let fvec = (0..finalbrain::DEFAULT_INSTRUCTIONS).map(|_| {
                let mut ins = Ins::_NOP;
                mutator(&mut ins, rng);
                ins
            }).collect::<Vec<_>>();
        Bot {
            bot_brain: mli::Mep::new(botbrain::TOTAL_INPUTS, botbrain::TOTAL_OUTPUTS,
                botbrain::DEFAULT_MUTATE_SIZE, botbrain::DEFAULT_CROSSOVER_POINTS, rng,
                bvec.into_iter(),
                mutator, processor),

            node_brain: mli::Mep::new(nodebrain::TOTAL_INPUTS, nodebrain::TOTAL_OUTPUTS,
                nodebrain::DEFAULT_MUTATE_SIZE, nodebrain::DEFAULT_CROSSOVER_POINTS, rng,
                nvec.into_iter(),
                mutator, processor),

            final_brain: mli::Mep::new(finalbrain::TOTAL_INPUTS, finalbrain::TOTAL_OUTPUTS,
                finalbrain::DEFAULT_MUTATE_SIZE, finalbrain::DEFAULT_CROSSOVER_POINTS, rng,
                fvec.into_iter(),
                mutator, processor),

            energy: DEFAULT_ENERGY,

            signal: 0,
            connect_signal: 0,

            memory: [0; finalbrain::TOTAL_MEMORY],
            decision: Default::default(),
        }
    }

    pub fn mutate(&mut self, rng: &mut R) {
        use mli::Genetic;
        if rng.gen_range(0.0, 1.0) < MUTATE_PROBABILITY {
            self.bot_brain.mutate(rng);
            self.node_brain.mutate(rng);
            self.final_brain.mutate(rng);
        }
    }

    pub fn mate(&mut self, other: &Self, rng: &mut R) -> Self {
        use mli::Genetic;
        //Divide energy in half when mating for the mater
        self.energy /= 2;
        let mut b = Bot{
            bot_brain: mli::Genetic::mate((&self.bot_brain, &other.bot_brain), rng),
            node_brain: mli::Genetic::mate((&self.node_brain, &other.node_brain), rng),
            final_brain: mli::Genetic::mate((&self.final_brain, &other.final_brain), rng),
            energy: self.energy,
            signal: self.signal,
            connect_signal: 0,
            memory: self.memory,
            decision: self.decision.clone(),
        };
        //Perform unit mutations on offspring
        b.mutate(rng);
        b
    }

    pub fn divide(&mut self, rng: &mut R) -> Self {
        use mli::Genetic;
        //Divide energy in half when dividing
        self.energy /= 2;
        let mut b = Bot{
            bot_brain: self.bot_brain.clone(),
            node_brain: self.node_brain.clone(),
            final_brain: self.final_brain.clone(),
            energy: self.energy,
            signal: self.signal,
            connect_signal: 0,
            memory: self.memory,
            //Clone the rate of energy consumption in the decision
            decision: self.decision.clone(),
        };
        //Perform unit mutations on offspring
        b.mutate(rng);
        b
    }

    pub fn cycle(&mut self) {
        self.energy = self.energy.saturating_sub(EXISTENCE_COST);
        self.signal = self.decision.signal;
        self.connect_signal = self.decision.connect_signal;
    }
}
<|endoftext|>


<commit_before>use uuid::{Builder, Uuid, Variant, Version};

use crate::{Dummy, Faker};
use crate::faker::uuid::raw::*;
use crate::locales::Data;

impl<L: Data> Dummy<UuidV1<L>> for Uuid {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(config: &UuidV1<L>, rng: &mut R) -> Self {
      let bytes: [u8;8] = rng.gen();
      let (ticks, _) = config.1.to_rfc4122();
      let time_low = (ticks & 0xFFFF_FFFF) as u32;
      let time_mid = ((ticks >> 32) & 0xFFFF) as u16;
      let time_high_and_version = (((ticks >> 48) & 0x0FFF) as u16) | (1 << 12);
      Uuid::from_fields(time_low, time_mid, time_high_and_version, &bytes).expect("generate uuid::Uuid::from_fields")
    }

    fn dummy(UuidV1(_, timestamp, node_id): &UuidV1<L>) -> Self {
        Self::new_v1(*timestamp, node_id).expect("generate uuid::Uuid::new_v1")
    }
}

impl<L: Data> Dummy<UuidV1<L>> for String {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(config: &UuidV1<L>, rng: &mut R) -> Self {
        Uuid::dummy_with_rng(config, rng).to_hyphenated().to_string()
    }

    fn dummy(config: &UuidV1<L>) -> Self {
        Uuid::dummy(config).to_hyphenated().to_string()
    }
}

impl<L: Data> Dummy<UuidV3<L>> for Uuid {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(_: &UuidV3<L>, rng: &mut R) -> Self {
        Builder::from_bytes(rng.gen())
        .set_variant(Variant::RFC4122)
        .set_version(Version::Md5)
        .build()
    }

    fn dummy(UuidV3(_, namespace, name): &UuidV3<L>) -> Self {
        Self::new_v3(namespace, name)
    }
}

impl<L: Data> Dummy<UuidV3<L>> for String {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(config: &UuidV3<L>, rng: &mut R) -> Self {
        Uuid::dummy_with_rng(config, rng).to_hyphenated().to_string()
    }

    fn dummy(config: &UuidV3<L>) -> Self {
        Uuid::dummy(config).to_hyphenated().to_string()
    }
}

impl<L: Data> Dummy<UuidV4<L>> for Uuid {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(_: &UuidV4<L>, _: &mut R) -> Self {
        unimplemented!()
    }

    fn dummy(_: &UuidV4<L>) -> Self {
        Self::new_v4()
    }
}

impl<L: Data> Dummy<UuidV4<L>> for String {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(_: &UuidV4<L>, _: &mut R) -> Self {
        unimplemented!()
    }

    fn dummy(config: &UuidV4<L>) -> Self {
        Uuid::dummy(config).to_hyphenated().to_string()
    }
}

impl<L: Data> Dummy<UuidV5<L>> for Uuid {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(_: &UuidV5<L>, rng: &mut R) -> Self {
      Builder::from_bytes(rng.gen())
      .set_variant(Variant::RFC4122)
      .set_version(Version::Sha1)
      .build()
    }

    fn dummy(UuidV5(_, namespace, name): &UuidV5<L>) -> Self {
        Self::new_v5(namespace, name)
    }
}

impl<L: Data> Dummy<UuidV5<L>> for String {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(config: &UuidV5<L>, rng: &mut R) -> Self {
        Uuid::dummy_with_rng(config, rng).to_hyphenated().to_string()
    }

    fn dummy(config: &UuidV5<L>) -> Self {
        Uuid::dummy(config).to_hyphenated().to_string()
    }
}

#[allow(unused_variables)]
impl<L: Data> Dummy<UuidSeed<L>> for Uuid {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(config: &UuidSeed<L>, rng: &mut R) -> Self {
        todo!()
    }

    fn dummy(UuidSeed(_, seed): &UuidSeed<L>) -> Self {
        Self::from_slice(&seed).expect("generate uuid::Uuid::from_slice")
    }
}

#[allow(unused_variables)]
impl Dummy<Faker> for Uuid {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(config: &Faker, rng: &mut R) -> Self {
        todo!()
    }

    fn dummy(config: &Faker) -> Self {
        Self::new_v4()
    }
}<commit_msg>comment attempt at implementing UuidSeed ()<commit_after>use uuid::{Builder, Uuid, Variant, Version};

use crate::{Dummy, Faker};
use crate::faker::uuid::raw::*;
use crate::locales::Data;

impl<L: Data> Dummy<UuidV1<L>> for Uuid {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(config: &UuidV1<L>, rng: &mut R) -> Self {
      let bytes: [u8;8] = rng.gen();
      let (ticks, _) = config.1.to_rfc4122();
      let time_low = (ticks & 0xFFFF_FFFF) as u32;
      let time_mid = ((ticks >> 32) & 0xFFFF) as u16;
      let time_high_and_version = (((ticks >> 48) & 0x0FFF) as u16) | (1 << 12);
      Uuid::from_fields(time_low, time_mid, time_high_and_version, &bytes).expect("generate uuid::Uuid::from_fields")
    }

    fn dummy(UuidV1(_, timestamp, node_id): &UuidV1<L>) -> Self {
        Self::new_v1(*timestamp, node_id).expect("generate uuid::Uuid::new_v1")
    }
}

impl<L: Data> Dummy<UuidV1<L>> for String {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(config: &UuidV1<L>, rng: &mut R) -> Self {
        Uuid::dummy_with_rng(config, rng).to_hyphenated().to_string()
    }

    fn dummy(config: &UuidV1<L>) -> Self {
        Uuid::dummy(config).to_hyphenated().to_string()
    }
}

impl<L: Data> Dummy<UuidV3<L>> for Uuid {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(_: &UuidV3<L>, rng: &mut R) -> Self {
        Builder::from_bytes(rng.gen())
        .set_variant(Variant::RFC4122)
        .set_version(Version::Md5)
        .build()
    }

    fn dummy(UuidV3(_, namespace, name): &UuidV3<L>) -> Self {
        Self::new_v3(namespace, name)
    }
}

impl<L: Data> Dummy<UuidV3<L>> for String {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(config: &UuidV3<L>, rng: &mut R) -> Self {
        Uuid::dummy_with_rng(config, rng).to_hyphenated().to_string()
    }

    fn dummy(config: &UuidV3<L>) -> Self {
        Uuid::dummy(config).to_hyphenated().to_string()
    }
}

impl<L: Data> Dummy<UuidV4<L>> for Uuid {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(_: &UuidV4<L>, _: &mut R) -> Self {
        unimplemented!()
    }

    fn dummy(_: &UuidV4<L>) -> Self {
        Self::new_v4()
    }
}

impl<L: Data> Dummy<UuidV4<L>> for String {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(_: &UuidV4<L>, _: &mut R) -> Self {
        unimplemented!()
    }

    fn dummy(config: &UuidV4<L>) -> Self {
        Uuid::dummy(config).to_hyphenated().to_string()
    }
}

impl<L: Data> Dummy<UuidV5<L>> for Uuid {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(_: &UuidV5<L>, rng: &mut R) -> Self {
      Builder::from_bytes(rng.gen())
      .set_variant(Variant::RFC4122)
      .set_version(Version::Sha1)
      .build()
    }

    fn dummy(UuidV5(_, namespace, name): &UuidV5<L>) -> Self {
        Self::new_v5(namespace, name)
    }
}

impl<L: Data> Dummy<UuidV5<L>> for String {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(config: &UuidV5<L>, rng: &mut R) -> Self {
        Uuid::dummy_with_rng(config, rng).to_hyphenated().to_string()
    }

    fn dummy(config: &UuidV5<L>) -> Self {
        Uuid::dummy(config).to_hyphenated().to_string()
    }
}

#[allow(unused_variables)]
impl<L: Data> Dummy<UuidSeed<L>> for Uuid {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(_: &UuidSeed<L>, rng: &mut R) -> Self {
        todo!()
        // let slice: &[u8; 128] = rng.gen();
        // Self::from_slice(slice).expect("generate uuid::Uuid::from_slice")
    }
}

#[allow(unused_variables)]
impl Dummy<Faker> for Uuid {
    fn dummy_with_rng<R: rand::Rng + ?Sized>(config: &Faker, rng: &mut R) -> Self {
        todo!()
    }

    fn dummy(config: &Faker) -> Self {
        Self::new_v4()
    }
}<|endoftext|>