<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

//! The Peer actor owns the underlying connection and is responsible for listening for
//! and opening substreams as well as negotiating particular protocols on those substreams.
use crate::{
    counters,
    peer_manager::PeerManagerError,
    protocols::wire::messaging::v1::{ErrorCode, NetworkMessage},
    transport,
    transport::{Connection, ConnectionMetadata},
    ProtocolId,
};
use bytes::BytesMut;
use futures::{
    self,
    channel::oneshot,
    io::{AsyncRead, AsyncWrite},
    stream::StreamExt,
    FutureExt, SinkExt, TryFutureExt,
};
use libra_config::network_id::NetworkContext;
use libra_logger::prelude::*;
use libra_types::PeerId;
use netcore::compat::IoCompat;
use serde::{export::Formatter, Serialize};
use std::{fmt::Debug, io, sync::Arc, time::Duration};
use stream_ratelimiter::*;
use tokio::runtime::Handle;
use tokio_util::codec::{FramedRead, FramedWrite, LengthDelimitedCodec};

// Rate-limit configuration for inbound messages. Allows 100 messages for every 10ms window.
pub const MESSAGE_RATE_LIMIT_WINDOW: Duration = Duration::from_millis(10);
pub const MESSAGE_RATE_LIMIT_COUNT: usize = 100;

#[cfg(test)]
mod test;

#[derive(Debug)]
pub enum PeerRequest {
    SendMessage(
        NetworkMessage,
        ProtocolId,
        oneshot::Sender<Result<(), PeerManagerError>>,
    ),
    CloseConnection,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
pub enum DisconnectReason {
    Requested,
    ConnectionLost,
}

impl std::fmt::Display for DisconnectReason {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{}",
            match self {
                DisconnectReason::Requested => "Requested",
                DisconnectReason::ConnectionLost => "ConnectionLost",
            }
        )
    }
}

#[derive(Debug)]
pub enum PeerNotification {
    NewMessage(NetworkMessage),
    PeerDisconnected(ConnectionMetadata, DisconnectReason),
}

enum State {
    Connected,
    ShuttingDown(DisconnectReason),
}

pub struct Peer<TSocket> {
    /// The network instance this Peer actor is running under.
    _network_context: Arc<NetworkContext>,
    /// A handle to a tokio executor.
    executor: Handle,
    /// Connection specific information.
    connection_metadata: ConnectionMetadata,
    /// Underlying connection.
    connection: Option<TSocket>,
    /// Channel to receive requests for opening new outbound substreams.
    requests_rx: channel::Receiver<PeerRequest>,
    /// Channel to send peer notifications to PeerManager.
    peer_notifs_tx: channel::Sender<PeerNotification>,
    /// Channel to notify about new inbound RPC substreams.
    rpc_notifs_tx: channel::Sender<PeerNotification>,
    /// Channel to notify about new inbound DirectSend substreams.
    direct_send_notifs_tx: channel::Sender<PeerNotification>,
    /// Flag to indicate if the actor is being shut down.
    state: State,
    /// The maximum size of an inbound or outbound request frame
    /// Currently, requests are only a single frame
    max_frame_size: usize,
}

impl<TSocket> Peer<TSocket>
where
    TSocket: AsyncRead + AsyncWrite + Send + 'static,
{
    pub fn new(
        network_context: Arc<NetworkContext>,
        executor: Handle,
        connection: Connection<TSocket>,
        requests_rx: channel::Receiver<PeerRequest>,
        peer_notifs_tx: channel::Sender<PeerNotification>,
        rpc_notifs_tx: channel::Sender<PeerNotification>,
        direct_send_notifs_tx: channel::Sender<PeerNotification>,
        max_frame_size: usize,
    ) -> Self {
        let Connection {
            metadata: connection_metadata,
            socket,
        } = connection;
        Self {
            _network_context: network_context,
            executor,
            connection_metadata,
            connection: Some(socket),
            requests_rx,
            peer_notifs_tx,
            rpc_notifs_tx,
            direct_send_notifs_tx,
            state: State::Connected,
            max_frame_size,
        }
    }

    fn peer_id(&self) -> PeerId {
        self.connection_metadata.remote_peer_id
    }

    pub async fn start(mut self) {
        let self_peer_id = self.peer_id();
        info!(
            "Starting Peer actor for peer: {:?}",
            self_peer_id.short_str()
        );

        // Split the connection into a ReadHalf and a WriteHalf.
        let (reader, writer) = tokio::io::split(IoCompat::new(self.connection.take().unwrap()));
        let mut codec_builder = LengthDelimitedCodec::builder();
        codec_builder
            .max_frame_length(self.max_frame_size)
            .length_field_length(4)
            .big_endian();
        // Convert ReadHalf to Stream of length-delimited messages.

        let reader = FramedRead::new(reader, codec_builder.new_codec()).fuse();
        // Create a rate-limited stream of inbound messages.
        let mut reader = reader
            .ratelimit(MESSAGE_RATE_LIMIT_WINDOW, MESSAGE_RATE_LIMIT_COUNT)
            .fuse();

        // Convert WriteHalf to Sink of length-delimited messages.
        let writer = FramedWrite::new(writer, codec_builder.new_codec());
        // Start writer "process" as a separate task. We receive two handles to communicate with
        // the task:
        // `write_reqs_tx`: Instruction to send a NetworkMessage on the wire.
        // `close_tx`: Instruction to close the underlying connection.
        let (write_reqs_tx, close_tx) =
            Self::start_writer_task(&self.executor, self_peer_id, writer);
        // Start main Peer event loop.
        loop {
            match self.state {
                State::Connected => {
                    futures::select! {
                        maybe_req = self.requests_rx.next() => {
                            if let Some(request) = maybe_req {
                                self.handle_request(request, write_reqs_tx.clone()).await;
                            } else {
                                // This branch will only be taken if all PeerRequest senders for this Peer
                                // get dropped.
                                break;
                            }
                        },
                        maybe_message = reader.next() => {
                            match maybe_message {
                                Some(Ok(message)) =>  {
                                    if let Err(err) = self.handle_inbound_message(message, write_reqs_tx.clone()).await {
                                        warn!("Error in handling inbound message from peer: {}. Error: {:?}",
                                            self_peer_id.short_str(), err);
                                    }
                                },
                                Some(Err(err)) => {
                                    warn!("Failure in reading messages from socket from peer: {}. Error: {:?}",
                                        self_peer_id.short_str(), err);
                                    self.close_connection(DisconnectReason::ConnectionLost).await;
                                }
                                None => {
                                    warn!("Received connection closed event for peer: {}",
                                        self_peer_id.short_str());
                                    self.close_connection(DisconnectReason::ConnectionLost).await;
                                }
                            }
                        },
                    }
                }
                State::ShuttingDown(reason) => {
                    // Send a close instruction to the writer task. On receipt of this instruction, the writer
                    // task drops all pending outbound messages and closes the connection.
                    if let Err(e) = close_tx.send(()) {
                        info!(
                            "Failed to send close instruction to writer task. It must already be terminating/terminated. Error: {:?}",
                            e
                        );
                    }
                    // Send a PeerDisconnected event to upstream.
                    if let Err(e) = self
                        .peer_notifs_tx
                        .send(PeerNotification::PeerDisconnected(
                            self.connection_metadata.clone(),
                            reason,
                        ))
                        .await
                    {
                        warn!(
                            "Failed to notify upstream about disconnection of peer: {}; error: {:?}",
                            self.peer_id().short_str(),
                            e
                        );
                    }
                    debug!("Peer actor '{}' shutdown", self.peer_id().short_str());
                    break;
                }
            }
        }
    }

    // Start a new task on the given executor which is responsible for writing outbound messages on
    // the wire. The function returns two channels which can be used to send intructions to the
    // task:
    // 1. The first channel is used to send outbound NetworkMessages to the task
    // 2. The second channel is used to instruct the task to close the connection and terminate.
    // If outbound messages are queued when the task receives a close instruction, it discards
    // them and immediately closes the connection.
    fn start_writer_task<T: tokio::io::AsyncWrite + Send + Unpin + 'static>(
        executor: &Handle,
        self_peer_id: PeerId,
        mut writer: FramedWrite<T, LengthDelimitedCodec>,
    ) -> (
        channel::Sender<(
            NetworkMessage,
            oneshot::Sender<Result<(), PeerManagerError>>,
        )>,
        oneshot::Sender<()>,
    ) {
        let (write_reqs_tx, mut write_reqs_rx): (
            channel::Sender<(
                NetworkMessage,
                oneshot::Sender<Result<(), PeerManagerError>>,
            )>,
            _,
        ) = channel::new(1024, &counters::PENDING_WIRE_MESSAGES);
        let (close_tx, close_rx) = oneshot::channel();
        let writer_task = async move {
            let mut close_rx = close_rx.into_stream();
            loop {
                futures::select! {
                    (message, ack_ch) = write_reqs_rx.select_next_some() => {
                        if let Err(e) = writer
                            .send(
                                lcs::to_bytes(&message)
                                    .expect("Outbound message failed to serialize")
                                    .into(),
                            )
                            .map_ok(|_| ack_ch.send(Ok(())))
                            .await
                        {
                            warn!(
                                "Error in sending message to peer: {}. Error: {:?}",
                                self_peer_id.short_str(),
                                e
                            );
                            break;
                        }
                    },
                    _ = close_rx.select_next_some() => {
                        break;
                    }
                }
            }
            info!("Closing connection to peer: {}", self_peer_id.short_str());
            let flush_and_close = async move {
                writer.flush().await?;
                writer.close().await?;
                Ok(()) as io::Result<()>
            };
            match tokio::time::timeout(transport::TRANSPORT_TIMEOUT, flush_and_close).await {
                Err(_) => {
                    info!(
                        "Timeout in flush/close of connection to peer: {}",
                        self_peer_id.short_str()
                    );
                }
                Ok(Err(e)) => {
                    info!(
                        "Failure in flush/close of connection to peer: {}. Error: {:?}",
                        self_peer_id.short_str(),
                        e
                    );
                }
                Ok(Ok(())) => {
                    info!("Closed connection to peer: {}", self_peer_id.short_str());
                }
            }
        };
        executor.spawn(writer_task);
        (write_reqs_tx, close_tx)
    }

    async fn handle_inbound_message(
        &mut self,
        message: BytesMut,
        mut write_reqs_tx: channel::Sender<(
            NetworkMessage,
            oneshot::Sender<Result<(), PeerManagerError>>,
        )>,
    ) -> Result<(), PeerManagerError> {
        trace!("Received message from Peer {}", self.peer_id().short_str());
        // Read inbound message from stream.
        let message = message.freeze();
        let message = match lcs::from_bytes(&message) {
            Ok(message) => message,
            Err(err) => {
                // Don't bother returning errors for tiny messages
                if message.len() >= 2 {
                    let error = ErrorCode::parsing_error(message[0], message[1]);
                    let message = NetworkMessage::Error(error);
                    let (ack_tx, _) = oneshot::channel();
                    write_reqs_tx.send((message, ack_tx)).await?;
                }
                return Err(err.into());
            }
        };
        match message {
            NetworkMessage::DirectSendMsg(_) => {
                let notif = PeerNotification::NewMessage(message);
                self.direct_send_notifs_tx
                    .send(notif)
                    .await
                    .map_err(|err| {
                        warn!(
                            "Failed to send notification to DirectSend actor. Error: {:?}",
                            err
                        );
                        err
                    })?;
            }
            NetworkMessage::Error(error) => {
                warn!(
                    "Peer {} sent an error message: {:?}",
                    self.peer_id().short_str(),
                    error,
                );
            }
            NetworkMessage::RpcRequest(_) | NetworkMessage::RpcResponse(_) => {
                let notif = PeerNotification::NewMessage(message);
                self.rpc_notifs_tx.send(notif).await.map_err(|err| {
                    warn!("Failed to send notification to RPC actor. Error: {:?}", err);
                    err
                })?;
            }
        };
        Ok(())
    }

    async fn handle_request<'a>(
        &'a mut self,
        request: PeerRequest,
        mut write_reqs_tx: channel::Sender<(
            NetworkMessage,
            oneshot::Sender<Result<(), PeerManagerError>>,
        )>,
    ) {
        trace!(
            "Peer {} PeerRequest::{:?}",
            self.peer_id().short_str(),
            request
        );
        match request {
            PeerRequest::SendMessage(message, protocol, channel) => {
                if let Err(e) = write_reqs_tx.send((message, channel)).await {
                    error!(
                        "Failed to send message for protocol {} to peer: {}. Error: {:?}",
                        protocol,
                        self.peer_id().short_str(),
                        e
                    );
                }
            }
            PeerRequest::CloseConnection => {
                self.close_connection(DisconnectReason::Requested).await;
            }
        }
    }

    async fn close_connection(&mut self, reason: DisconnectReason) {
        // Set the state of the actor to `State::ShuttingDown` to true ensures that the peer actor
        // will terminate and close the connection.
        self.state = State::ShuttingDown(reason);
    }
}

pub struct PeerHandle {
    peer_id: PeerId,
    sender: channel::Sender<PeerRequest>,
}

impl Clone for PeerHandle {
    fn clone(&self) -> Self {
        Self {
            peer_id: self.peer_id,
            sender: self.sender.clone(),
        }
    }
}

impl PeerHandle {
    pub fn new(peer_id: PeerId, sender: channel::Sender<PeerRequest>) -> Self {
        Self { peer_id, sender }
    }

    pub fn peer_id(&self) -> PeerId {
        self.peer_id
    }

    pub async fn send_message(
        &mut self,
        message: NetworkMessage,
        protocol: ProtocolId,
    ) -> Result<(), PeerManagerError> {
        // If we fail to send the request to the Peer, then it must have already been shutdown.
        let (oneshot_tx, oneshot_rx) = oneshot::channel();
        if self
            .sender
            .send(PeerRequest::SendMessage(message, protocol, oneshot_tx))
            .await
            .is_err()
        {
            error!(
                "Sending message to Peer {} \
                 failed because it has already been shutdown.",
                self.peer_id.short_str()
            );
        }
        oneshot_rx
            .await
            // The send_message request can get dropped/canceled if the peer
            // connection is in the process of shutting down.
            .map_err(|_| PeerManagerError::NotConnected(self.peer_id))?
    }

    pub async fn disconnect(&mut self) {
        // If we fail to send the request to the Peer, then it must have already been shutdown.
        if self
            .sender
            .send(PeerRequest::CloseConnection)
            .await
            .is_err()
        {
            error!(
                "Sending CloseConnection request to Peer {} \
                 failed because it has already been shutdown.",
                self.peer_id.short_str()
            );
        }
    }
}
<commit_msg>[network] Fix peer_id naming in Peer actor<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

//! The Peer actor owns the underlying connection and is responsible for listening for
//! and opening substreams as well as negotiating particular protocols on those substreams.
use crate::{
    counters,
    peer_manager::PeerManagerError,
    protocols::wire::messaging::v1::{ErrorCode, NetworkMessage},
    transport,
    transport::{Connection, ConnectionMetadata},
    ProtocolId,
};
use bytes::BytesMut;
use futures::{
    self,
    channel::oneshot,
    io::{AsyncRead, AsyncWrite},
    stream::StreamExt,
    FutureExt, SinkExt, TryFutureExt,
};
use libra_config::network_id::NetworkContext;
use libra_logger::prelude::*;
use libra_types::PeerId;
use netcore::compat::IoCompat;
use serde::{export::Formatter, Serialize};
use std::{fmt::Debug, io, sync::Arc, time::Duration};
use stream_ratelimiter::*;
use tokio::runtime::Handle;
use tokio_util::codec::{FramedRead, FramedWrite, LengthDelimitedCodec};

// Rate-limit configuration for inbound messages. Allows 100 messages for every 10ms window.
pub const MESSAGE_RATE_LIMIT_WINDOW: Duration = Duration::from_millis(10);
pub const MESSAGE_RATE_LIMIT_COUNT: usize = 100;

#[cfg(test)]
mod test;

#[derive(Debug)]
pub enum PeerRequest {
    SendMessage(
        NetworkMessage,
        ProtocolId,
        oneshot::Sender<Result<(), PeerManagerError>>,
    ),
    CloseConnection,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
pub enum DisconnectReason {
    Requested,
    ConnectionLost,
}

impl std::fmt::Display for DisconnectReason {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{}",
            match self {
                DisconnectReason::Requested => "Requested",
                DisconnectReason::ConnectionLost => "ConnectionLost",
            }
        )
    }
}

#[derive(Debug)]
pub enum PeerNotification {
    NewMessage(NetworkMessage),
    PeerDisconnected(ConnectionMetadata, DisconnectReason),
}

enum State {
    Connected,
    ShuttingDown(DisconnectReason),
}

pub struct Peer<TSocket> {
    /// The network instance this Peer actor is running under.
    _network_context: Arc<NetworkContext>,
    /// A handle to a tokio executor.
    executor: Handle,
    /// Connection specific information.
    connection_metadata: ConnectionMetadata,
    /// Underlying connection.
    connection: Option<TSocket>,
    /// Channel to receive requests for opening new outbound substreams.
    requests_rx: channel::Receiver<PeerRequest>,
    /// Channel to send peer notifications to PeerManager.
    peer_notifs_tx: channel::Sender<PeerNotification>,
    /// Channel to notify about new inbound RPC substreams.
    rpc_notifs_tx: channel::Sender<PeerNotification>,
    /// Channel to notify about new inbound DirectSend substreams.
    direct_send_notifs_tx: channel::Sender<PeerNotification>,
    /// Flag to indicate if the actor is being shut down.
    state: State,
    /// The maximum size of an inbound or outbound request frame
    /// Currently, requests are only a single frame
    max_frame_size: usize,
}

impl<TSocket> Peer<TSocket>
where
    TSocket: AsyncRead + AsyncWrite + Send + 'static,
{
    pub fn new(
        network_context: Arc<NetworkContext>,
        executor: Handle,
        connection: Connection<TSocket>,
        requests_rx: channel::Receiver<PeerRequest>,
        peer_notifs_tx: channel::Sender<PeerNotification>,
        rpc_notifs_tx: channel::Sender<PeerNotification>,
        direct_send_notifs_tx: channel::Sender<PeerNotification>,
        max_frame_size: usize,
    ) -> Self {
        let Connection {
            metadata: connection_metadata,
            socket,
        } = connection;
        Self {
            _network_context: network_context,
            executor,
            connection_metadata,
            connection: Some(socket),
            requests_rx,
            peer_notifs_tx,
            rpc_notifs_tx,
            direct_send_notifs_tx,
            state: State::Connected,
            max_frame_size,
        }
    }

    fn remote_peer_id(&self) -> PeerId {
        self.connection_metadata.remote_peer_id
    }

    pub async fn start(mut self) {
        let remote_peer_id = self.remote_peer_id();
        info!(
            "Starting Peer actor for peer: {:?}",
            remote_peer_id.short_str()
        );

        // Split the connection into a ReadHalf and a WriteHalf.
        let (reader, writer) = tokio::io::split(IoCompat::new(self.connection.take().unwrap()));
        let mut codec_builder = LengthDelimitedCodec::builder();
        codec_builder
            .max_frame_length(self.max_frame_size)
            .length_field_length(4)
            .big_endian();
        // Convert ReadHalf to Stream of length-delimited messages.

        let reader = FramedRead::new(reader, codec_builder.new_codec()).fuse();
        // Create a rate-limited stream of inbound messages.
        let mut reader = reader
            .ratelimit(MESSAGE_RATE_LIMIT_WINDOW, MESSAGE_RATE_LIMIT_COUNT)
            .fuse();

        // Convert WriteHalf to Sink of length-delimited messages.
        let writer = FramedWrite::new(writer, codec_builder.new_codec());
        // Start writer "process" as a separate task. We receive two handles to communicate with
        // the task:
        // `write_reqs_tx`: Instruction to send a NetworkMessage on the wire.
        // `close_tx`: Instruction to close the underlying connection.
        let (write_reqs_tx, close_tx) =
            Self::start_writer_task(&self.executor, remote_peer_id, writer);
        // Start main Peer event loop.
        loop {
            match self.state {
                State::Connected => {
                    futures::select! {
                        maybe_req = self.requests_rx.next() => {
                            if let Some(request) = maybe_req {
                                self.handle_request(request, write_reqs_tx.clone()).await;
                            } else {
                                // This branch will only be taken if all PeerRequest senders for this Peer
                                // get dropped.
                                break;
                            }
                        },
                        maybe_message = reader.next() => {
                            match maybe_message {
                                Some(Ok(message)) =>  {
                                    if let Err(err) = self.handle_inbound_message(message, write_reqs_tx.clone()).await {
                                        warn!("Error in handling inbound message from peer: {}. Error: {:?}",
                                            remote_peer_id.short_str(), err);
                                    }
                                },
                                Some(Err(err)) => {
                                    warn!("Failure in reading messages from socket from peer: {}. Error: {:?}",
                                        remote_peer_id.short_str(), err);
                                    self.close_connection(DisconnectReason::ConnectionLost).await;
                                }
                                None => {
                                    warn!("Received connection closed event for peer: {}",
                                        remote_peer_id.short_str());
                                    self.close_connection(DisconnectReason::ConnectionLost).await;
                                }
                            }
                        },
                    }
                }
                State::ShuttingDown(reason) => {
                    // Send a close instruction to the writer task. On receipt of this instruction, the writer
                    // task drops all pending outbound messages and closes the connection.
                    if let Err(e) = close_tx.send(()) {
                        info!(
                            "Failed to send close instruction to writer task. It must already be terminating/terminated. Error: {:?}",
                            e
                        );
                    }
                    // Send a PeerDisconnected event to upstream.
                    if let Err(e) = self
                        .peer_notifs_tx
                        .send(PeerNotification::PeerDisconnected(
                            self.connection_metadata.clone(),
                            reason,
                        ))
                        .await
                    {
                        warn!(
                            "Failed to notify upstream about disconnection of peer: {}; error: {:?}",
                            self.remote_peer_id().short_str(),
                            e
                        );
                    }
                    debug!(
                        "Peer actor '{}' shutdown",
                        self.remote_peer_id().short_str()
                    );
                    break;
                }
            }
        }
    }

    // Start a new task on the given executor which is responsible for writing outbound messages on
    // the wire. The function returns two channels which can be used to send intructions to the
    // task:
    // 1. The first channel is used to send outbound NetworkMessages to the task
    // 2. The second channel is used to instruct the task to close the connection and terminate.
    // If outbound messages are queued when the task receives a close instruction, it discards
    // them and immediately closes the connection.
    fn start_writer_task<T: tokio::io::AsyncWrite + Send + Unpin + 'static>(
        executor: &Handle,
        remote_peer_id: PeerId,
        mut writer: FramedWrite<T, LengthDelimitedCodec>,
    ) -> (
        channel::Sender<(
            NetworkMessage,
            oneshot::Sender<Result<(), PeerManagerError>>,
        )>,
        oneshot::Sender<()>,
    ) {
        let (write_reqs_tx, mut write_reqs_rx): (
            channel::Sender<(
                NetworkMessage,
                oneshot::Sender<Result<(), PeerManagerError>>,
            )>,
            _,
        ) = channel::new(1024, &counters::PENDING_WIRE_MESSAGES);
        let (close_tx, close_rx) = oneshot::channel();
        let writer_task = async move {
            let mut close_rx = close_rx.into_stream();
            loop {
                futures::select! {
                    (message, ack_ch) = write_reqs_rx.select_next_some() => {
                        if let Err(e) = writer
                            .send(
                                lcs::to_bytes(&message)
                                    .expect("Outbound message failed to serialize")
                                    .into(),
                            )
                            .map_ok(|_| ack_ch.send(Ok(())))
                            .await
                        {
                            warn!(
                                "Error in sending message to peer: {}. Error: {:?}",
                                remote_peer_id.short_str(),
                                e
                            );
                            break;
                        }
                    },
                    _ = close_rx.select_next_some() => {
                        break;
                    }
                }
            }
            info!("Closing connection to peer: {}", remote_peer_id.short_str());
            let flush_and_close = async move {
                writer.flush().await?;
                writer.close().await?;
                Ok(()) as io::Result<()>
            };
            match tokio::time::timeout(transport::TRANSPORT_TIMEOUT, flush_and_close).await {
                Err(_) => {
                    info!(
                        "Timeout in flush/close of connection to peer: {}",
                        remote_peer_id.short_str()
                    );
                }
                Ok(Err(e)) => {
                    info!(
                        "Failure in flush/close of connection to peer: {}. Error: {:?}",
                        remote_peer_id.short_str(),
                        e
                    );
                }
                Ok(Ok(())) => {
                    info!("Closed connection to peer: {}", remote_peer_id.short_str());
                }
            }
        };
        executor.spawn(writer_task);
        (write_reqs_tx, close_tx)
    }

    async fn handle_inbound_message(
        &mut self,
        message: BytesMut,
        mut write_reqs_tx: channel::Sender<(
            NetworkMessage,
            oneshot::Sender<Result<(), PeerManagerError>>,
        )>,
    ) -> Result<(), PeerManagerError> {
        trace!(
            "Received message from Peer {}",
            self.remote_peer_id().short_str()
        );
        // Read inbound message from stream.
        let message = message.freeze();
        let message = match lcs::from_bytes(&message) {
            Ok(message) => message,
            Err(err) => {
                // Don't bother returning errors for tiny messages
                if message.len() >= 2 {
                    let error = ErrorCode::parsing_error(message[0], message[1]);
                    let message = NetworkMessage::Error(error);
                    let (ack_tx, _) = oneshot::channel();
                    write_reqs_tx.send((message, ack_tx)).await?;
                }
                return Err(err.into());
            }
        };
        match message {
            NetworkMessage::DirectSendMsg(_) => {
                let notif = PeerNotification::NewMessage(message);
                self.direct_send_notifs_tx
                    .send(notif)
                    .await
                    .map_err(|err| {
                        warn!(
                            "Failed to send notification to DirectSend actor. Error: {:?}",
                            err
                        );
                        err
                    })?;
            }
            NetworkMessage::Error(error) => {
                warn!(
                    "Peer {} sent an error message: {:?}",
                    self.remote_peer_id().short_str(),
                    error,
                );
            }
            NetworkMessage::RpcRequest(_) | NetworkMessage::RpcResponse(_) => {
                let notif = PeerNotification::NewMessage(message);
                self.rpc_notifs_tx.send(notif).await.map_err(|err| {
                    warn!("Failed to send notification to RPC actor. Error: {:?}", err);
                    err
                })?;
            }
        };
        Ok(())
    }

    async fn handle_request<'a>(
        &'a mut self,
        request: PeerRequest,
        mut write_reqs_tx: channel::Sender<(
            NetworkMessage,
            oneshot::Sender<Result<(), PeerManagerError>>,
        )>,
    ) {
        trace!(
            "Peer {} PeerRequest::{:?}",
            self.remote_peer_id().short_str(),
            request
        );
        match request {
            PeerRequest::SendMessage(message, protocol, channel) => {
                if let Err(e) = write_reqs_tx.send((message, channel)).await {
                    error!(
                        "Failed to send message for protocol {} to peer: {}. Error: {:?}",
                        protocol,
                        self.remote_peer_id().short_str(),
                        e
                    );
                }
            }
            PeerRequest::CloseConnection => {
                self.close_connection(DisconnectReason::Requested).await;
            }
        }
    }

    async fn close_connection(&mut self, reason: DisconnectReason) {
        // Set the state of the actor to `State::ShuttingDown` to true ensures that the peer actor
        // will terminate and close the connection.
        self.state = State::ShuttingDown(reason);
    }
}

pub struct PeerHandle {
    peer_id: PeerId,
    sender: channel::Sender<PeerRequest>,
}

impl Clone for PeerHandle {
    fn clone(&self) -> Self {
        Self {
            peer_id: self.peer_id,
            sender: self.sender.clone(),
        }
    }
}

impl PeerHandle {
    pub fn new(peer_id: PeerId, sender: channel::Sender<PeerRequest>) -> Self {
        Self { peer_id, sender }
    }

    pub fn peer_id(&self) -> PeerId {
        self.peer_id
    }

    pub async fn send_message(
        &mut self,
        message: NetworkMessage,
        protocol: ProtocolId,
    ) -> Result<(), PeerManagerError> {
        // If we fail to send the request to the Peer, then it must have already been shutdown.
        let (oneshot_tx, oneshot_rx) = oneshot::channel();
        if self
            .sender
            .send(PeerRequest::SendMessage(message, protocol, oneshot_tx))
            .await
            .is_err()
        {
            error!(
                "Sending message to Peer {} \
                 failed because it has already been shutdown.",
                self.peer_id.short_str()
            );
        }
        oneshot_rx
            .await
            // The send_message request can get dropped/canceled if the peer
            // connection is in the process of shutting down.
            .map_err(|_| PeerManagerError::NotConnected(self.peer_id))?
    }

    pub async fn disconnect(&mut self) {
        // If we fail to send the request to the Peer, then it must have already been shutdown.
        if self
            .sender
            .send(PeerRequest::CloseConnection)
            .await
            .is_err()
        {
            error!(
                "Sending CloseConnection request to Peer {} \
                 failed because it has already been shutdown.",
                self.peer_id.short_str()
            );
        }
    }
}
<|endoftext|>


<commit_before>
pub fn parse_spirv(data: &[u8]) -> Result<Spirv, ParseError> {
    if data.len() < 20 {
        return Err(ParseError::MissingHeader);
    }

    // we need to determine whether we are in big endian order or little endian order depending
    // on the magic number at the start of the file
    let data = if data[0] == 0x07 && data[1] == 0x23 && data[2] == 0x02 && data[3] == 0x03 {
        // big endian
        data.chunks(4).map(|c| {
            ((c[0] as u32) << 24) | ((c[1] as u32) << 16) | ((c[2] as u32) << 8) | c[3] as u32
        }).collect::<Vec<_>>()

    } else if data[3] == 0x07 && data[2] == 0x23 && data[1] == 0x02 && data[0] == 0x03 {
        // little endian
        data.chunks(4).map(|c| {
            ((c[3] as u32) << 24) | ((c[2] as u32) << 16) | ((c[1] as u32) << 8) | c[0] as u32
        }).collect::<Vec<_>>()

    } else {
        return Err(ParseError::MissingHeader);
    };

    parse_u32s(&data)
}

fn parse_u32s(i: &[u32]) -> Result<Spirv, ParseError> {
    if i.len() < 5 {
        return Err(ParseError::MissingHeader);
    }

    if i[0] != 0x07230203 {
        return Err(ParseError::WrongHeader);
    }

    let version = (((i[1] & 0x00ff0000) >> 16) as u8, ((i[1] & 0x0000ff00) >> 8) as u8);

    let instructions = {
        let mut ret = Vec::new();
        let mut i = &i[5..];
        while i.len() >= 1 {
            let (instruction, rest) = try!(parse_instruction(i));
            ret.push(instruction);
            i = rest;
        }
        ret
    };

    Ok(Spirv {
        version: version,
        bound: i[3],
        instructions: instructions,
    })
}

#[derive(Debug, Clone)]
pub enum ParseError {
    MissingHeader,
    WrongHeader,
    IncompleteInstruction,
    UnknownCapability(u32),
    UnknownExecutionModel(u32),
}

#[derive(Debug, Clone)]
pub struct Spirv {
    pub version: (u8, u8),
    pub bound: u32,
    pub instructions: Vec<Instruction>,
}

#[derive(Debug, Clone)]
pub enum Instruction {
    Unknown(u16, Vec<u32>),
    Nop,
    ExtInstImport { result_id: u32, name: String },
    EntryPoint { execution: ExecutionModel, id: u32, name: String, interface: Vec<u32> },
    Capability(Capability),
    FunctionEnd,
    Kill,
    Return,
}

fn parse_instruction(i: &[u32]) -> Result<(Instruction, &[u32]), ParseError> {
    assert!(i.len() >= 1);

    let word_count = (i[0] >> 16) as usize;
    assert!(word_count >= 1);
    let opcode = (i[0] & 0xffff) as u16;

    if i.len() < word_count {
        return Err(ParseError::IncompleteInstruction);
    }

    let opcode = try!(decode_instruction(opcode, &i[1 .. word_count]));
    Ok((opcode, &i[word_count..]))
}

fn decode_instruction(opcode: u16, operands: &[u32]) -> Result<Instruction, ParseError> {
    Ok(match opcode {
        0 => Instruction::Nop,
        11 => Instruction::ExtInstImport {
            result_id: operands[0],
            name: parse_string(&operands[1..]).0
        },
        15 => {
            let (n, r) = parse_string(&operands[2..]);
            Instruction::EntryPoint {
                execution: try!(ExecutionModel::from_num(operands[0])),
                id: operands[1],
                name: n,
                interface: r.to_owned(),
            }
        },
        17 => Instruction::Capability(try!(Capability::from_num(operands[0]))),
        56 => Instruction::FunctionEnd,
        252 => Instruction::Kill,
        253 => Instruction::Return,
        _ => Instruction::Unknown(opcode, operands.to_owned()),
    })
}

fn parse_string(data: &[u32]) -> (String, &[u32]) {
    let bytes = data.iter().flat_map(|&n| {
        let b1 = (n & 0xff) as u8;
        let b2 = ((n >> 8) & 0xff) as u8;
        let b3 = ((n >> 16) & 0xff) as u8;
        let b4 = ((n >> 24) & 0xff) as u8;
        vec![b1, b2, b3, b4].into_iter()
    }).take_while(|&b| b != 0).collect::<Vec<u8>>();

    let r = 1 + bytes.len() / 4;
    let s = String::from_utf8(bytes).expect("Shader content is not UTF-8");

    (s, &data[r..])
}

#[derive(Debug, Clone)]
pub enum Capability {
    Matrix,
    Shader,
    Geometry,
    Tessellation,
    Addresses,
    Linkage,
    Kernel,
    Vector16,
    Float16Buffer,
    Float16,
    Float64,
    Int64,
    Int64Atomics,
    ImageBasic,
    ImageReadWrite,
    ImageMipmap,
    Pipes,
    Groups,
    DeviceEnqueue,
    LiteralSampler,
    AtomicStorage,
    Int16,
    TessellationPointSize,
    GeometryPointSize,
    ImageGatherExtended,
    StorageImageMultisample,
    UniformBufferArrayDynamicIndexing,
    SampledImageArrayDynamicIndexing,
    StorageBufferArrayDynamicIndexing,
    StorageImageArrayDynamicIndexing,
    ClipDistance,
    CullDistance,
    ImageCubeArray,
    SampleRateShading,
    ImageRect,
    SampledRect,
    GenericPointer,
    Int8,
    InputAttachment,
    SparseResidency,
    MinLod,
    Sampled1D,
    Image1D,
    SampledCubeArray,
    SampledBuffer,
    ImageBuffer,
    ImageMSArray,
    StorageImageExtendedFormats,
    ImageQuery,
    DerivativeControl,
    InterpolationFunction,
    TransformFeedback,
    GeometryStreams,
    StorageImageReadWithoutFormat,
    StorageImageWriteWithoutFormat,
}

impl Capability {
    fn from_num(num: u32) -> Result<Capability, ParseError> {
        match num {
            0 => Ok(Capability::Matrix),
            1 => Ok(Capability::Shader),
            2 => Ok(Capability::Geometry),
            3 => Ok(Capability::Tessellation),
            4 => Ok(Capability::Addresses),
            5 => Ok(Capability::Linkage),
            6 => Ok(Capability::Kernel),
            7 => Ok(Capability::Vector16),
            8 => Ok(Capability::Float16Buffer),
            9 => Ok(Capability::Float16),
            10 => Ok(Capability::Float64),
            11 => Ok(Capability::Int64),
            12 => Ok(Capability::Int64Atomics),
            13 => Ok(Capability::ImageBasic),
            14 => Ok(Capability::ImageReadWrite),
            15 => Ok(Capability::ImageMipmap),
            17 => Ok(Capability::Pipes),
            18 => Ok(Capability::Groups),
            19 => Ok(Capability::DeviceEnqueue),
            20 => Ok(Capability::LiteralSampler),
            21 => Ok(Capability::AtomicStorage),
            22 => Ok(Capability::Int16),
            23 => Ok(Capability::TessellationPointSize),
            24 => Ok(Capability::GeometryPointSize),
            25 => Ok(Capability::ImageGatherExtended),
            27 => Ok(Capability::StorageImageMultisample),
            28 => Ok(Capability::UniformBufferArrayDynamicIndexing),
            29 => Ok(Capability::SampledImageArrayDynamicIndexing),
            30 => Ok(Capability::StorageBufferArrayDynamicIndexing),
            31 => Ok(Capability::StorageImageArrayDynamicIndexing),
            32 => Ok(Capability::ClipDistance),
            33 => Ok(Capability::CullDistance),
            34 => Ok(Capability::ImageCubeArray),
            35 => Ok(Capability::SampleRateShading),
            36 => Ok(Capability::ImageRect),
            37 => Ok(Capability::SampledRect),
            38 => Ok(Capability::GenericPointer),
            39 => Ok(Capability::Int8),
            40 => Ok(Capability::InputAttachment),
            41 => Ok(Capability::SparseResidency),
            42 => Ok(Capability::MinLod),
            43 => Ok(Capability::Sampled1D),
            44 => Ok(Capability::Image1D),
            45 => Ok(Capability::SampledCubeArray),
            46 => Ok(Capability::SampledBuffer),
            47 => Ok(Capability::ImageBuffer),
            48 => Ok(Capability::ImageMSArray),
            49 => Ok(Capability::StorageImageExtendedFormats),
            50 => Ok(Capability::ImageQuery),
            51 => Ok(Capability::DerivativeControl),
            52 => Ok(Capability::InterpolationFunction),
            53 => Ok(Capability::TransformFeedback),
            54 => Ok(Capability::GeometryStreams),
            55 => Ok(Capability::StorageImageReadWithoutFormat),
            56 => Ok(Capability::StorageImageWriteWithoutFormat),
            _ => Err(ParseError::UnknownCapability(num)),
        }
    }
}

#[derive(Debug, Clone)]
pub enum ExecutionModel {
    Vertex,
    TessellationControl,
    TessellationEvaluation,
    Geometry,
    Fragment,
    GLCompute,
    Kernel,
}

impl ExecutionModel {
    fn from_num(num: u32) -> Result<ExecutionModel, ParseError> {
        match num {
            0 => Ok(ExecutionModel::Vertex),
            1 => Ok(ExecutionModel::TessellationControl),
            2 => Ok(ExecutionModel::TessellationEvaluation),
            3 => Ok(ExecutionModel::Geometry),
            4 => Ok(ExecutionModel::Fragment),
            5 => Ok(ExecutionModel::GLCompute),
            6 => Ok(ExecutionModel::Kernel),
            _ => Err(ParseError::UnknownExecutionModel(num)),
        }
    }
}

#[cfg(test)]
mod test {
    use parse;

    #[test]
    fn test() {
        let data = include_bytes!("../tests/frag.spv");
        let doc = parse::parse_spirv(data).unwrap();

        println!("{:?}", doc);
    }
}
<commit_msg>Remove debugging println in tests<commit_after>
/// Parses a SPIR-V document.
pub fn parse_spirv(data: &[u8]) -> Result<Spirv, ParseError> {
    if data.len() < 20 {
        return Err(ParseError::MissingHeader);
    }

    // we need to determine whether we are in big endian order or little endian order depending
    // on the magic number at the start of the file
    let data = if data[0] == 0x07 && data[1] == 0x23 && data[2] == 0x02 && data[3] == 0x03 {
        // big endian
        data.chunks(4).map(|c| {
            ((c[0] as u32) << 24) | ((c[1] as u32) << 16) | ((c[2] as u32) << 8) | c[3] as u32
        }).collect::<Vec<_>>()

    } else if data[3] == 0x07 && data[2] == 0x23 && data[1] == 0x02 && data[0] == 0x03 {
        // little endian
        data.chunks(4).map(|c| {
            ((c[3] as u32) << 24) | ((c[2] as u32) << 16) | ((c[1] as u32) << 8) | c[0] as u32
        }).collect::<Vec<_>>()

    } else {
        return Err(ParseError::MissingHeader);
    };

    parse_u32s(&data)
}

/// Parses a SPIR-V document from a list of u32s.
///
/// Endianess has already been handled.
fn parse_u32s(i: &[u32]) -> Result<Spirv, ParseError> {
    if i.len() < 5 {
        return Err(ParseError::MissingHeader);
    }

    if i[0] != 0x07230203 {
        return Err(ParseError::WrongHeader);
    }

    let version = (((i[1] & 0x00ff0000) >> 16) as u8, ((i[1] & 0x0000ff00) >> 8) as u8);

    let instructions = {
        let mut ret = Vec::new();
        let mut i = &i[5..];
        while i.len() >= 1 {
            let (instruction, rest) = try!(parse_instruction(i));
            ret.push(instruction);
            i = rest;
        }
        ret
    };

    Ok(Spirv {
        version: version,
        bound: i[3],
        instructions: instructions,
    })
}

/// Error that can happen when parsing.
#[derive(Debug, Clone)]
pub enum ParseError {
    MissingHeader,
    WrongHeader,
    IncompleteInstruction,
    UnknownCapability(u32),
    UnknownExecutionModel(u32),
}

#[derive(Debug, Clone)]
pub struct Spirv {
    pub version: (u8, u8),
    pub bound: u32,
    pub instructions: Vec<Instruction>,
}

#[derive(Debug, Clone)]
pub enum Instruction {
    Unknown(u16, Vec<u32>),
    Nop,
    ExtInstImport { result_id: u32, name: String },
    EntryPoint { execution: ExecutionModel, id: u32, name: String, interface: Vec<u32> },
    Capability(Capability),
    FunctionEnd,
    Kill,
    Return,
}

fn parse_instruction(i: &[u32]) -> Result<(Instruction, &[u32]), ParseError> {
    assert!(i.len() >= 1);

    let word_count = (i[0] >> 16) as usize;
    assert!(word_count >= 1);
    let opcode = (i[0] & 0xffff) as u16;

    if i.len() < word_count {
        return Err(ParseError::IncompleteInstruction);
    }

    let opcode = try!(decode_instruction(opcode, &i[1 .. word_count]));
    Ok((opcode, &i[word_count..]))
}

fn decode_instruction(opcode: u16, operands: &[u32]) -> Result<Instruction, ParseError> {
    Ok(match opcode {
        0 => Instruction::Nop,
        11 => Instruction::ExtInstImport {
            result_id: operands[0],
            name: parse_string(&operands[1..]).0
        },
        15 => {
            let (n, r) = parse_string(&operands[2..]);
            Instruction::EntryPoint {
                execution: try!(ExecutionModel::from_num(operands[0])),
                id: operands[1],
                name: n,
                interface: r.to_owned(),
            }
        },
        17 => Instruction::Capability(try!(Capability::from_num(operands[0]))),
        56 => Instruction::FunctionEnd,
        252 => Instruction::Kill,
        253 => Instruction::Return,
        _ => Instruction::Unknown(opcode, operands.to_owned()),
    })
}

fn parse_string(data: &[u32]) -> (String, &[u32]) {
    let bytes = data.iter().flat_map(|&n| {
        let b1 = (n & 0xff) as u8;
        let b2 = ((n >> 8) & 0xff) as u8;
        let b3 = ((n >> 16) & 0xff) as u8;
        let b4 = ((n >> 24) & 0xff) as u8;
        vec![b1, b2, b3, b4].into_iter()
    }).take_while(|&b| b != 0).collect::<Vec<u8>>();

    let r = 1 + bytes.len() / 4;
    let s = String::from_utf8(bytes).expect("Shader content is not UTF-8");

    (s, &data[r..])
}

#[derive(Debug, Clone)]
pub enum Capability {
    Matrix,
    Shader,
    Geometry,
    Tessellation,
    Addresses,
    Linkage,
    Kernel,
    Vector16,
    Float16Buffer,
    Float16,
    Float64,
    Int64,
    Int64Atomics,
    ImageBasic,
    ImageReadWrite,
    ImageMipmap,
    Pipes,
    Groups,
    DeviceEnqueue,
    LiteralSampler,
    AtomicStorage,
    Int16,
    TessellationPointSize,
    GeometryPointSize,
    ImageGatherExtended,
    StorageImageMultisample,
    UniformBufferArrayDynamicIndexing,
    SampledImageArrayDynamicIndexing,
    StorageBufferArrayDynamicIndexing,
    StorageImageArrayDynamicIndexing,
    ClipDistance,
    CullDistance,
    ImageCubeArray,
    SampleRateShading,
    ImageRect,
    SampledRect,
    GenericPointer,
    Int8,
    InputAttachment,
    SparseResidency,
    MinLod,
    Sampled1D,
    Image1D,
    SampledCubeArray,
    SampledBuffer,
    ImageBuffer,
    ImageMSArray,
    StorageImageExtendedFormats,
    ImageQuery,
    DerivativeControl,
    InterpolationFunction,
    TransformFeedback,
    GeometryStreams,
    StorageImageReadWithoutFormat,
    StorageImageWriteWithoutFormat,
}

impl Capability {
    fn from_num(num: u32) -> Result<Capability, ParseError> {
        match num {
            0 => Ok(Capability::Matrix),
            1 => Ok(Capability::Shader),
            2 => Ok(Capability::Geometry),
            3 => Ok(Capability::Tessellation),
            4 => Ok(Capability::Addresses),
            5 => Ok(Capability::Linkage),
            6 => Ok(Capability::Kernel),
            7 => Ok(Capability::Vector16),
            8 => Ok(Capability::Float16Buffer),
            9 => Ok(Capability::Float16),
            10 => Ok(Capability::Float64),
            11 => Ok(Capability::Int64),
            12 => Ok(Capability::Int64Atomics),
            13 => Ok(Capability::ImageBasic),
            14 => Ok(Capability::ImageReadWrite),
            15 => Ok(Capability::ImageMipmap),
            17 => Ok(Capability::Pipes),
            18 => Ok(Capability::Groups),
            19 => Ok(Capability::DeviceEnqueue),
            20 => Ok(Capability::LiteralSampler),
            21 => Ok(Capability::AtomicStorage),
            22 => Ok(Capability::Int16),
            23 => Ok(Capability::TessellationPointSize),
            24 => Ok(Capability::GeometryPointSize),
            25 => Ok(Capability::ImageGatherExtended),
            27 => Ok(Capability::StorageImageMultisample),
            28 => Ok(Capability::UniformBufferArrayDynamicIndexing),
            29 => Ok(Capability::SampledImageArrayDynamicIndexing),
            30 => Ok(Capability::StorageBufferArrayDynamicIndexing),
            31 => Ok(Capability::StorageImageArrayDynamicIndexing),
            32 => Ok(Capability::ClipDistance),
            33 => Ok(Capability::CullDistance),
            34 => Ok(Capability::ImageCubeArray),
            35 => Ok(Capability::SampleRateShading),
            36 => Ok(Capability::ImageRect),
            37 => Ok(Capability::SampledRect),
            38 => Ok(Capability::GenericPointer),
            39 => Ok(Capability::Int8),
            40 => Ok(Capability::InputAttachment),
            41 => Ok(Capability::SparseResidency),
            42 => Ok(Capability::MinLod),
            43 => Ok(Capability::Sampled1D),
            44 => Ok(Capability::Image1D),
            45 => Ok(Capability::SampledCubeArray),
            46 => Ok(Capability::SampledBuffer),
            47 => Ok(Capability::ImageBuffer),
            48 => Ok(Capability::ImageMSArray),
            49 => Ok(Capability::StorageImageExtendedFormats),
            50 => Ok(Capability::ImageQuery),
            51 => Ok(Capability::DerivativeControl),
            52 => Ok(Capability::InterpolationFunction),
            53 => Ok(Capability::TransformFeedback),
            54 => Ok(Capability::GeometryStreams),
            55 => Ok(Capability::StorageImageReadWithoutFormat),
            56 => Ok(Capability::StorageImageWriteWithoutFormat),
            _ => Err(ParseError::UnknownCapability(num)),
        }
    }
}

#[derive(Debug, Clone)]
pub enum ExecutionModel {
    Vertex,
    TessellationControl,
    TessellationEvaluation,
    Geometry,
    Fragment,
    GLCompute,
    Kernel,
}

impl ExecutionModel {
    fn from_num(num: u32) -> Result<ExecutionModel, ParseError> {
        match num {
            0 => Ok(ExecutionModel::Vertex),
            1 => Ok(ExecutionModel::TessellationControl),
            2 => Ok(ExecutionModel::TessellationEvaluation),
            3 => Ok(ExecutionModel::Geometry),
            4 => Ok(ExecutionModel::Fragment),
            5 => Ok(ExecutionModel::GLCompute),
            6 => Ok(ExecutionModel::Kernel),
            _ => Err(ParseError::UnknownExecutionModel(num)),
        }
    }
}

#[cfg(test)]
mod test {
    use parse;

    #[test]
    fn test() {
        let data = include_bytes!("../tests/frag.spv");
        parse::parse_spirv(data).unwrap();
    }
}
<|endoftext|>


<commit_before>use std;
use java;
use java::lang::IObject;
use jvm;
use jvm::ToValue;

jvm_object!(ResultSetMetaData, "java/sql/ResultSetMetaData");

pub trait TResultSetMetaData : IObject /* + TWrapper */ {
  fn get_catalog_name(&self, column: i32) -> java::Result<Option<std::string::String>> {
    return jvm_call!(string: self, "getCatalogName", "(I)Ljava/lang/String;", &[&column.to_value()]);
  }

  fn get_column_class_name(&self, column: i32) -> java::Result<Option<std::string::String>> {
    return jvm_call!(string: self, "getColumnClassName", "(I)Ljava/lang/String;", &[&column.to_value()]);
  }

  fn get_column_count(&self) -> java::Result<i32> {
    return jvm_call!(int: self, "getColumnCount", "()I", &[]);
  }

  // int 	getColumnDisplaySize(int column)
  // String 	getColumnLabel(int column)
  // String 	getColumnName(int column)
  // int 	getColumnType(int column)
  // String 	getColumnTypeName(int column)
  // int 	getPrecision(int column)
  // int 	getScale(int column)
  // String 	getSchemaName(int column)
  // String 	getTableName(int column)
  // boolean 	isAutoIncrement(int column)
  // boolean 	isCaseSensitive(int column)
  // boolean 	isCurrency(int column)
  // boolean 	isDefinitelyWritable(int column)
  // int 	isNullable(int column)
  // boolean 	isReadOnly(int column)
  // boolean 	isSearchable(int column)
  // boolean 	isSigned(int column)
  // boolean 	isWritable(int column)
}

impl TResultSetMetaData for ResultSetMetaData {}
<commit_msg>'Complete' ResultSetMetaData wrapper<commit_after>use std;
use java;
use java::lang::IObject;
use jvm;
use jvm::ToValue;

jvm_object!(ResultSetMetaData, "java/sql/ResultSetMetaData");

pub trait TResultSetMetaData : IObject /* + TWrapper */ {
  fn get_catalog_name(&self, column: i32) -> java::Result<Option<std::string::String>> {
    return jvm_call!(string: self, "getCatalogName", "(I)Ljava/lang/String;", &[&column.to_value()]);
  }

  fn get_column_class_name(&self, column: i32) -> java::Result<Option<std::string::String>> {
    return jvm_call!(string: self, "getColumnClassName", "(I)Ljava/lang/String;", &[&column.to_value()]);
  }

  fn get_column_count(&self) -> java::Result<i32> {
    return jvm_call!(int: self, "getColumnCount", "()I", &[]);
  }

  fn get_column_display_size(&self, column: i32) -> java::Result<i32> {
    return jvm_call!(int: self, "getColumnDisplaySize", "(I)I", &[&column.to_value()]);
  }

  fn get_column_label(&self, column: i32) -> java::Result<Option<std::string::String>> {
    return jvm_call!(string: self, "getColumnLabel", "(I)Ljava/lang/String;", &[&column.to_value()]);
  }

  fn get_column_name(&self, column: i32) -> java::Result<Option<std::string::String>> {
    return jvm_call!(string: self, "getColumnName", "(I)Ljava/lang/String;", &[&column.to_value()]);
  }

  fn get_column_type(&self, column: i32) -> java::Result<i32> {
    return jvm_call!(int: self, "getColumnType", "(I)I", &[&column.to_value()]);
  }

  fn get_column_type_name(&self, column: i32) -> java::Result<Option<std::string::String>> {
    return jvm_call!(string: self, "getColumnTypeName", "(I)Ljava/lang/String;", &[&column.to_value()]);
  }

  fn get_precision(&self, column: i32) -> java::Result<i32> {
    return jvm_call!(int: self, "getPrecision", "(I)I", &[&column.to_value()]);
  }

  fn get_scale(&self, column: i32) -> java::Result<i32> {
    return jvm_call!(int: self, "getScale", "(I)I", &[&column.to_value()]);
  }

  fn get_schema_name(&self, column: i32) -> java::Result<Option<std::string::String>> {
    return jvm_call!(string: self, "getSchemaName", "(I)Ljava/lang/String;", &[&column.to_value()]);
  }

  fn get_table_name(&self, column: i32) -> java::Result<Option<std::string::String>> {
    return jvm_call!(string: self, "getTableName", "(I)Ljava/lang/String;", &[&column.to_value()]);
  }

  fn is_auto_increment(&self, column: i32) -> java::Result<bool> {
    return jvm_call!(bool: self, "isAutoIncrement", "(I)Z", &[&column.to_value()]);
  }

  fn is_case_sensitive(&self, column: i32) -> java::Result<bool> {
    return jvm_call!(bool: self, "isCaseSensitive", "(I)Z", &[&column.to_value()]);
  }

  fn is_currency(&self, column: i32) -> java::Result<bool> {
    return jvm_call!(bool: self, "isCurrency", "(I)Z", &[&column.to_value()]);
  }

  fn is_definitely_writable(&self, column: i32) -> java::Result<bool> {
    return jvm_call!(bool: self, "isDefinitelyWritable", "(I)Z", &[&column.to_value()]);
  }

  fn is_nullable(&self, column: i32) -> java::Result<i32> {
    return jvm_call!(int: self, "isNullable", "(I)I", &[&column.to_value()]);
  }

  fn is_read_only(&self, column: i32) -> java::Result<bool> {
    return jvm_call!(bool: self, "isReadOnly", "(I)Z", &[&column.to_value()]);
  }

  fn is_searchable(&self, column: i32) -> java::Result<bool> {
    return jvm_call!(bool: self, "isSearchable", "(I)Z", &[&column.to_value()]);
  }

  fn is_signed(&self, column: i32) -> java::Result<bool> {
    return jvm_call!(bool: self, "isSigned", "(I)Z", &[&column.to_value()]);
  }

  fn is_writable(&self, column: i32) -> java::Result<bool> {
    return jvm_call!(bool: self, "isWritable", "(I)Z", &[&column.to_value()]);
  }
}

impl TResultSetMetaData for ResultSetMetaData {}
<|endoftext|>


<commit_before>// compile-pass
#![feature(existential_type)]

use std::fmt::Debug;

fn main() {}

existential type Two<A, B>: Debug;

fn two<T: Debug + Copy, U>(t: T, u: U) -> Two<T, U> {
    (t, t)
}

fn three<T: Debug, U>(t: T, t2: T, u: U) -> Two<T, U> {
    (t, t2)
}
<commit_msg>Test more related cases<commit_after>// compile-pass
#![feature(existential_type)]

use std::fmt::Debug;

fn main() {}

existential type Two<A, B>: Debug;

fn two<T: Debug + Copy, U>(t: T, u: U) -> Two<T, U> {
    (t, t)
}

fn three<T: Debug, U>(t: T, t2: T, u: U) -> Two<T, U> {
    (t, t2)
}

fn four<T: Debug, U, V>(t: T, t2: T, u: U, v: V) -> Two<T, U> {
    (t, t2)
}

fn five<X, Y: Debug>(x: X, y: Y, y2: Y) -> Two<Y, X> {
    (y, y2)
}

<|endoftext|>


<commit_before>pub fn max_matrix_sum(matrix: Vec<Vec<i32>>) -> i64 {
    todo!()
}

fn main() {
    println!("{}", max_matrix_sum(vec![vec![1, -1], vec![-1, 1]])); // 4
    println!(
        "{}",
        max_matrix_sum(vec![vec![1, 2, 3], vec![-1, -2, -3], vec![1, 2, 3]])
    ); // 16
    println!(
        "{}",
        max_matrix_sum(vec![
            vec![1, 2, 3, 4],
            vec![-1, -2, -3, 4],
            vec![1, 2, 3, 4],
            vec![1, 2, 3, 4]
        ])
    ); // 38
    println!(
        "{}",
        max_matrix_sum(vec![
            vec![1, 2, 3, 4],
            vec![-1, -2, -3, -4],
            vec![1, 2, 3, 4],
            vec![1, 2, 3, 4]
        ])
    ); // 40
}
<commit_msg>Update problem 1975<commit_after>pub fn max_matrix_sum(matrix: Vec<Vec<i32>>) -> i64 {
    todo!()
}

fn main() {
    println!("{}", max_matrix_sum(vec![vec![1, -1], vec![-1, 1]])); // 4
    println!(
        "{}",
        max_matrix_sum(vec![vec![1, 2, 3], vec![-1, -2, -3], vec![1, 2, 3]])
    ); // 16
    println!(
        "{}",
        max_matrix_sum(vec![
            vec![1, 2, 3, 4],
            vec![-1, -2, -3, 4],
            vec![1, 2, 3, 4],
            vec![1, 2, 3, 4]
        ])
    ); // 38
    println!(
        "{}",
        max_matrix_sum(vec![
            vec![1, 2, 3, 4],
            vec![-1, -2, -3, -4],
            vec![1, 2, 3, 4],
            vec![1, 2, 3, 4]
        ])
    ); // 40
    println!(
        "{}",
        max_matrix_sum(vec![
            vec![1, 2, 3, 4, 5],
            vec![1, 2, 3, 4, 5],
            vec![1, 2, -3, 4, 5],
            vec![1, 2, 3, 4, 5],
            vec![1, 2, 3, 4, 5],
        ])
    ); // 73
}
<|endoftext|>


<commit_before>// https://leetcode.com/problems/minimum-number-of-buckets-required-to-collect-rainwater-from-houses/
pub fn minimum_buckets(street: String) -> i32 {
    todo!()
}

fn main() {
    println!("{}", minimum_buckets(String::from("H..H"))); // 2
    println!("{}", minimum_buckets(String::from(".H.H."))); // 1
    println!("{}", minimum_buckets(String::from(".HHH."))); // -1
}
<commit_msg>Update problem 2086<commit_after>// https://leetcode.com/problems/minimum-number-of-buckets-required-to-collect-rainwater-from-houses/
pub fn minimum_buckets(street: String) -> i32 {
    todo!()
}

fn main() {
    println!("{}", minimum_buckets(String::from("H..H"))); // 2
    println!("{}", minimum_buckets(String::from(".H.H."))); // 1
    println!("{}", minimum_buckets(String::from(".HHH."))); // -1
    println!("{}", minimum_buckets(String::from(".H..H..H."))); // 3
    println!("{}", minimum_buckets(String::from(".H.H..H."))); // 2
    println!("{}", minimum_buckets(String::from(".H.H.H."))); // 2
}
<|endoftext|>


<commit_before>use ndarray::prelude::*;
use ndarray::{Data, DataMut, Zip};
use ndarray_rand::RandomExt;
use rand::distributions::Range;
use itertools::{Itertools};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OutputFunction {
    Linear,
    Logistic
}

fn activate_linear(f: f32) -> f32 { f }
fn activate_logistic(f: f32) -> f32 { 1.0 / (1.0 + (-f).exp()) }

fn grad_linear(_: f32, _g: f32) -> f32 { 1.0 }
fn grad_logistic(_f: f32, g: f32) -> f32 {
    g * (1.0 - g)
}

impl OutputFunction {
    fn af(&self) -> (fn(f32) -> f32) {
        use self::OutputFunction::*;
        match *self {
            Linear => activate_linear,
            Logistic => activate_logistic
        }
    }

    fn agf(&self) -> (fn(f32, f32) -> f32) {
        use self::OutputFunction::*;
        match *self {
            Linear => grad_linear,
            Logistic => grad_logistic
        }
    }

}

#[derive(Debug, Clone, Copy)]
pub struct LayerDesc {
    /// number of inputs, not includes bias
    pub num_inputs: usize,
    pub num_outputs: usize,
    pub activation: OutputFunction
}

impl LayerDesc {
    pub fn new(n_in: usize, n_out: usize, f: OutputFunction) -> LayerDesc {
        LayerDesc {num_inputs: n_in, num_outputs: n_out, activation: f }
    }

    // total number of weights activated
    // fn num_weights(self) -> usize {
    //     (self.num_inputs + 1) * self.num_outputs
    // }
}

#[derive(Debug, Clone)]
struct Layer {
    m: Array2<f32>,
    bias: Array1<f32>,
    act: OutputFunction,

    dm: Array2<f32>,
    dbias: Array1<f32>,

    //x: Array1<f32>
}

/// take the outer-product of a and b, applying it to c
fn outer_product<Ta, Tb, Tc>(c: &mut ArrayBase<Tc, Ix2>,
                             a: &ArrayBase<Ta, Ix1>,
                             b: &ArrayBase<Tb, Ix1>)
    where Ta: Data<Elem=f32>, Tb: Data<Elem=f32>, Tc: DataMut<Elem=f32> {
    for (mut row, ai) in izip!(c.outer_iter_mut(), a) {
        assert_eq!(row.dim(), b.dim());
        Zip::from(&mut row).and(b).apply(|r, bi| *r = *ai * *bi);
    }
}

// Quick matrix-vector multiplication
// c = A * b
#[allow(unused)]
fn mat_vec_mul<Ta, Tb, Tc>(c: &mut ArrayBase<Tc, Ix1>,
                           a: &ArrayBase<Ta, Ix2>,
                           b: &ArrayBase<Tb, Ix1>)
    where Ta: Data<Elem=f32>, Tb: Data<Elem=f32>, Tc: DataMut<Elem=f32> {
    for (ci, ar) in izip!(c, a.outer_iter()) {
        *ci = ar.dot(b);
    }
}

// c = A^t * b
fn mat_t_vec_mul<Ta, Tb, Tc>(c: &mut ArrayBase<Tc, Ix1>,
                           a: &ArrayBase<Ta, Ix2>,
                           b: &ArrayBase<Tb, Ix1>)
    where Ta: Data<Elem=f32>, Tb: Data<Elem=f32>, Tc: DataMut<Elem=f32> {

    for (ci, ar) in izip!(c, a.axis_iter(Axis(1))) {
        *ci = ar.dot(b);
    }
}

impl Layer {
    pub fn from_desc(desc: &LayerDesc) -> Layer {
        let m = Array::random((desc.num_outputs, desc.num_inputs), Range::new(-0.01, 0.01));
        let bias = Array::zeros( desc.num_outputs );
        //let x = Array::zeros( desc.num_outputs );

        let dm = Array::zeros((desc.num_outputs, desc.num_inputs));
        let dbias = Array::zeros(desc.num_outputs);

        Layer { m, bias, //x,
                dm, dbias, act: desc.activation }
    }

    pub fn num_inputs(&self) -> usize {
        self.m.dim().1
    }

    pub fn num_outputs(&self) -> usize {
        self.m.dim().0
    }

    /// Evaulate input, placing the result into output.
    pub fn evaluate_onto<T1, T2>(&self, input: &ArrayBase<T1, Ix1>,
                                 output: &mut ArrayBase<T2, Ix1>)

        where T1: Data<Elem=f32>, T2: DataMut<Elem=f32> {
        let f = self.act.af();
        for (a, r, b) in izip!(output.iter_mut(), self.m.outer_iter(), &self.bias) {
            *a = f(r.dot(input) + b);
        }
    }

    pub fn evaluate<T1>(&self, input: &ArrayBase<T1, Ix1>) -> Array1<f32>
        where T1: Data<Elem=f32> {
        let mut arr = Array::zeros(self.bias.dim());
        self.evaluate_onto(input, &mut arr);
        arr
    }

    pub fn evaluate_onto_partial_g<T1, T2>(&mut self,
                                           input: &ArrayBase<T1, Ix1>,
                                           output: &mut ArrayBase<T2, Ix1>)

        where T1: Data<Elem=f32>, T2: DataMut<Elem=f32> {
        let f = self.act.af();
        let g = self.act.agf();

        for (a, r, b, x) in izip!(output.iter_mut(), self.m.outer_iter(), &self.bias, &mut self.dbias) {
            let pa = r.dot(input) + b;
            *a = f(pa);
            *x = g(pa, *a);
        }

        // compute the gradient of the weights, with respect to the outputs
        outer_product(&mut self.dm, &self.dbias, input);
    }

    pub fn evaluate_partial_g<T1>(&mut self, input: &ArrayBase<T1, Ix1>) -> Array1<f32>
        where T1: Data<Elem=f32> {
        let mut arr = Array::zeros(self.bias.dim());
        self.evaluate_onto_partial_g(input, &mut arr);
        arr
    }

    /// Complete the evaluation of the gradient, taking in the
    /// gradient with respect to the outputs.
    fn complete_g<T: Data<Elem=f32>>(&mut self, dout: &ArrayBase<T, Ix1>) -> Array1<f32> {
        assert_eq!(dout.dim(), self.num_outputs());

        // We assume that we previously called evaluate*_partial_g. Now, we finish.
        // Finish gradient w/rt weight
        for (mut row, di) in self.dm.outer_iter_mut().zip(dout) {
            for x in row.iter_mut() {
                *x *= *di;
            }
        }

        // Finish gradient w/rt bias
        Zip::from(&mut self.dbias).and(dout).apply(|a, b| *a *= *b);

        let mut din = Array::zeros(self.num_inputs());
        mat_t_vec_mul(&mut din, &self.dm, dout);
        din
    }

    /// Apply the gradient
    fn gradient_step(&mut self, rate: f32) {
        Zip::from(&mut self.m).and(&self.dm).apply(|a, da| *a += da * rate);
        Zip::from(&mut self.bias).and(&self.dbias).apply(|a, da| *a += da * rate);
    }
}

pub struct NeuralNet {
    layers: Vec<Layer>
}

impl NeuralNet {
    pub fn new(layers: &[LayerDesc]) -> Option<NeuralNet>  {
        // make sure the layers are valid
        if layers.iter().tuple_windows::<(_,_)>()
            .any(|(d1, d2)| { d1.num_outputs == d2.num_inputs }) {
                return None;
            }

        Some(NeuralNet { layers: layers.iter().map(Layer::from_desc).collect() })
    }

    // Dimensions of the input
    pub fn num_inputs(&self) -> usize {
        self.layers[0].num_inputs()
    }

    // Dimensions of the output
    pub fn num_outputs(&self) -> usize {
        self.layers[self.layers.len() - 1].num_outputs()
    }

    /// Feed the input forward through the neural networks.
    pub fn evaluate<T1>(&self, input: &ArrayBase<T1, Ix1>) -> Array1<f32>
        where T1: Data<Elem=f32> {
        assert_eq!(input.dim(), self.layers[0].num_inputs());
        self.layers.iter().fold(input.to_owned(), |x, layer| layer.evaluate(&x))
    }

    /// Evaluate, and internally store the gradient.
    pub fn evaluate_with_gradient<T1>(&mut self, input: &ArrayBase<T1, Ix1>) -> Array1<f32>
        where T1: Data<Elem=f32> {
        assert_eq!(input.dim(), self.layers[0].num_inputs());

        let output = self.layers.iter_mut()
            .fold(input.to_owned(), |x, layer| layer.evaluate_partial_g(&x));

        let dout = Array::from_elem(self.num_outputs(), 1.0);
        self.layers.iter_mut().rev()
            .fold(dout, |x, layer| layer.complete_g(&x));

        output
    }

    /// Move all weights by a factor of alpha * grad(x)
    pub fn gradient_step(&mut self, rate: f32) {
        for layer in self.layers.iter_mut() {
            layer.gradient_step(rate);
        }
    }
}

<commit_msg>add ReLu, SymmetricSigmoid activation<commit_after>use ndarray::prelude::*;
use ndarray::{Data, DataMut, Zip};
use ndarray_rand::RandomExt;
use rand::distributions::Range;
use itertools::{Itertools};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ActivationFunction {
    Linear,
    Sigmoid,
    SymmetricSigmoid,
    ReLU
}

fn activate_linear(x: f32) -> f32 { x }
fn activate_logistic(x: f32) -> f32 { 1.0 / (1.0 + (-x).exp()) }
const SS_FSCALE: f32 = 1.7159;
const SS_XSCALE: f32 = 2.0/3.0;
fn activate_ss(x: f32) -> f32 { SS_FSCALE * (SS_XSCALE * x).tanh() }
fn activate_relu(x: f32) -> f32 { if x > 0.0 { x } else { 0.0} }

fn grad_linear(_x: f32, _f: f32) -> f32 { 1.0 }
fn grad_logistic(_x: f32, f: f32) -> f32 {
    f * (1.0 - f)
}
fn grad_ss(_x: f32, f: f32) -> f32 {
    SS_XSCALE * (SS_FSCALE - f * f/ SS_FSCALE)
}
fn grad_relu(x: f32, _f: f32) -> f32 {
    if x >= 0.0 { 1.0 } else { 0.0 }
}

impl ActivationFunction {
    fn af(&self) -> (fn(f32) -> f32) {
        use self::ActivationFunction::*;
        match *self {
            Linear => activate_linear,
            Sigmoid => activate_logistic,
            SymmetricSigmoid => activate_ss,
            ReLU => activate_relu
        }
    }

    fn agf(&self) -> (fn(f32, f32) -> f32) {
        use self::ActivationFunction::*;
        match *self {
            Linear => grad_linear,
            Sigmoid => grad_logistic,
            SymmetricSigmoid => grad_ss,
            ReLU => grad_relu
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub struct LayerDesc {
    /// number of inputs, not includes bias
    pub num_inputs: usize,
    pub num_outputs: usize,
    pub activation: ActivationFunction
}

impl LayerDesc {
    pub fn new(n_in: usize, n_out: usize, f: ActivationFunction) -> LayerDesc {
        LayerDesc {num_inputs: n_in, num_outputs: n_out, activation: f }
    }

    // total number of weights activated
    // fn num_weights(self) -> usize {
    //     (self.num_inputs + 1) * self.num_outputs
    // }
}

#[derive(Debug, Clone)]
struct Layer {
    m: Array2<f32>,
    bias: Array1<f32>,
    act: ActivationFunction,

    dm: Array2<f32>,
    dbias: Array1<f32>,

    //x: Array1<f32>
}

/// take the outer-product of a and b, applying it to c
fn outer_product<Ta, Tb, Tc>(c: &mut ArrayBase<Tc, Ix2>,
                             a: &ArrayBase<Ta, Ix1>,
                             b: &ArrayBase<Tb, Ix1>)
    where Ta: Data<Elem=f32>, Tb: Data<Elem=f32>, Tc: DataMut<Elem=f32> {
    for (mut row, ai) in izip!(c.outer_iter_mut(), a) {
        assert_eq!(row.dim(), b.dim());
        Zip::from(&mut row).and(b).apply(|r, bi| *r = *ai * *bi);
    }
}

// Quick matrix-vector multiplication
// c = A * b
#[allow(unused)]
fn mat_vec_mul<Ta, Tb, Tc>(c: &mut ArrayBase<Tc, Ix1>,
                           a: &ArrayBase<Ta, Ix2>,
                           b: &ArrayBase<Tb, Ix1>)
    where Ta: Data<Elem=f32>, Tb: Data<Elem=f32>, Tc: DataMut<Elem=f32> {
    for (ci, ar) in izip!(c, a.outer_iter()) {
        *ci = ar.dot(b);
    }
}

// c = A^t * b
fn mat_t_vec_mul<Ta, Tb, Tc>(c: &mut ArrayBase<Tc, Ix1>,
                           a: &ArrayBase<Ta, Ix2>,
                           b: &ArrayBase<Tb, Ix1>)
    where Ta: Data<Elem=f32>, Tb: Data<Elem=f32>, Tc: DataMut<Elem=f32> {

    for (ci, ar) in izip!(c, a.axis_iter(Axis(1))) {
        *ci = ar.dot(b);
    }
}

impl Layer {
    pub fn from_desc(desc: &LayerDesc) -> Layer {
        let m = Array::random((desc.num_outputs, desc.num_inputs), Range::new(-0.01, 0.01));
        let bias = Array::zeros( desc.num_outputs );
        //let x = Array::zeros( desc.num_outputs );

        let dm = Array::zeros((desc.num_outputs, desc.num_inputs));
        let dbias = Array::zeros(desc.num_outputs);

        Layer { m, bias, //x,
                dm, dbias, act: desc.activation }
    }

    pub fn num_inputs(&self) -> usize {
        self.m.dim().1
    }

    pub fn num_outputs(&self) -> usize {
        self.m.dim().0
    }

    /// Evaulate input, placing the result into output.
    pub fn evaluate_onto<T1, T2>(&self, input: &ArrayBase<T1, Ix1>,
                                 output: &mut ArrayBase<T2, Ix1>)

        where T1: Data<Elem=f32>, T2: DataMut<Elem=f32> {
        let f = self.act.af();
        for (a, r, b) in izip!(output.iter_mut(), self.m.outer_iter(), &self.bias) {
            *a = f(r.dot(input) + b);
        }
    }

    pub fn evaluate<T1>(&self, input: &ArrayBase<T1, Ix1>) -> Array1<f32>
        where T1: Data<Elem=f32> {
        let mut arr = Array::zeros(self.bias.dim());
        self.evaluate_onto(input, &mut arr);
        arr
    }

    pub fn evaluate_onto_partial_g<T1, T2>(&mut self,
                                           input: &ArrayBase<T1, Ix1>,
                                           output: &mut ArrayBase<T2, Ix1>)

        where T1: Data<Elem=f32>, T2: DataMut<Elem=f32> {
        let f = self.act.af();
        let g = self.act.agf();

        for (a, r, b, x) in izip!(output.iter_mut(), self.m.outer_iter(), &self.bias, &mut self.dbias) {
            let pa = r.dot(input) + b;
            *a = f(pa);
            *x = g(pa, *a);
        }

        // compute the gradient of the weights, with respect to the outputs
        outer_product(&mut self.dm, &self.dbias, input);
    }

    pub fn evaluate_partial_g<T1>(&mut self, input: &ArrayBase<T1, Ix1>) -> Array1<f32>
        where T1: Data<Elem=f32> {
        let mut arr = Array::zeros(self.bias.dim());
        self.evaluate_onto_partial_g(input, &mut arr);
        arr
    }

    /// Complete the evaluation of the gradient, taking in the
    /// gradient with respect to the outputs.
    fn complete_g<T: Data<Elem=f32>>(&mut self, dout: &ArrayBase<T, Ix1>) -> Array1<f32> {
        assert_eq!(dout.dim(), self.num_outputs());

        // We assume that we previously called evaluate*_partial_g. Now, we finish.
        // Finish gradient w/rt weight
        for (mut row, di) in self.dm.outer_iter_mut().zip(dout) {
            for x in row.iter_mut() {
                *x *= *di;
            }
        }

        // Finish gradient w/rt bias
        Zip::from(&mut self.dbias).and(dout).apply(|a, b| *a *= *b);

        let mut din = Array::zeros(self.num_inputs());
        mat_t_vec_mul(&mut din, &self.dm, dout);
        din
    }

    /// Apply the gradient
    fn gradient_step(&mut self, rate: f32) {
        Zip::from(&mut self.m).and(&self.dm).apply(|a, da| *a += da * rate);
        Zip::from(&mut self.bias).and(&self.dbias).apply(|a, da| *a += da * rate);
    }
}

pub struct NeuralNet {
    layers: Vec<Layer>
}

impl NeuralNet {
    pub fn new(layers: &[LayerDesc]) -> Option<NeuralNet>  {
        // make sure the layers are valid
        if layers.iter().tuple_windows::<(_,_)>()
            .any(|(d1, d2)| { d1.num_outputs == d2.num_inputs }) {
                return None;
            }

        Some(NeuralNet { layers: layers.iter().map(Layer::from_desc).collect() })
    }

    // Dimensions of the input
    pub fn num_inputs(&self) -> usize {
        self.layers[0].num_inputs()
    }

    // Dimensions of the output
    pub fn num_outputs(&self) -> usize {
        self.layers[self.layers.len() - 1].num_outputs()
    }

    /// Feed the input forward through the neural networks.
    pub fn evaluate<T1>(&self, input: &ArrayBase<T1, Ix1>) -> Array1<f32>
        where T1: Data<Elem=f32> {
        assert_eq!(input.dim(), self.layers[0].num_inputs());
        self.layers.iter().fold(input.to_owned(), |x, layer| layer.evaluate(&x))
    }

    /// Evaluate, and internally store the gradient.
    pub fn evaluate_with_gradient<T1>(&mut self, input: &ArrayBase<T1, Ix1>) -> Array1<f32>
        where T1: Data<Elem=f32> {
        assert_eq!(input.dim(), self.layers[0].num_inputs());

        let output = self.layers.iter_mut()
            .fold(input.to_owned(), |x, layer| layer.evaluate_partial_g(&x));

        let dout = Array::from_elem(self.num_outputs(), 1.0);
        self.layers.iter_mut().rev()
            .fold(dout, |x, layer| layer.complete_g(&x));

        output
    }

    /// Move all weights by a factor of alpha * grad(x)
    pub fn gradient_step(&mut self, rate: f32) {
        for layer in self.layers.iter_mut() {
            layer.gradient_step(rate);
        }
    }
}

<|endoftext|>


<commit_before>//
// Copyright:: Copyright (c) 2015 Chef Software, Inc.
// License:: Apache License, Version 2.0
//
// 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 errors::{DeliveryError, Kind};
use http::*;
use hyper::status::StatusCode;
use serde_json;

use config::Config;

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd)]
pub struct Description {
    pub title: String,
    pub description: String
}

impl Description {
    pub fn payload(title: &str, desc: &str) -> Result<String, DeliveryError> {
        let desc = Description{ title: String::from(title),
                                description: String::from(desc) };
        desc.to_json()
    }

    pub fn to_json(&self) -> Result<String, DeliveryError> {
        let payload = serde_json::to_string(&self)?;
        Ok(payload)
    }

    pub fn parse_json(response: &str) -> Result<Description, DeliveryError> {
        Ok(serde_json::from_str::<Description>(response)?)
    }

    pub fn parse_text(text: &str) -> Result<Description, DeliveryError> {
        let mut items: Vec<&str> = text.lines().collect();
        let title = items[0].to_string();
        let desc = if items.len() > 1 {
            items.remove(0);
            items.join("\n").trim().to_string()
        } else {
            "".to_string()
        };
        Ok(Description{ title: title, description: desc })
    }
}

/// Fetch the description for a change
pub fn get(config: &Config,
           change: &str) -> Result<Description, DeliveryError> {
    let org = try!(config.organization());
    let proj = try!(config.project());
    let client = try!(APIClient::from_config(&config));
    let path = format!("orgs/{}/projects/{}/changes/{}/description",
                       org, proj, change);
    debug!("description path: {}", path);
    let mut result = try!(client.get(&path));
    match result.status {
        StatusCode::Ok => {
            let mut body_string = String::new();
            let _x = try!(result.read_to_string(&mut body_string));
            let description = try!(Description::parse_json(&body_string));
            Ok(description)
        },
        StatusCode::NotFound => {
            let msg1 = "API request returned 404 (not found) while trying to fetch this change's description.\n".to_string();
            let msg2 = "This is usually because the Delivery organization in your config does not match the organization for this project.\n";
            let msg3 = "Your organization is current set to:\n\n";
            let msg4 = &org;
            let msg5 = "\n\nTo fix this, try editing your cli.toml file's organization setting to match the organization this project resides in.";
            let err_msg = msg1 + msg2 + msg3 + msg4 + msg5;
            Err(DeliveryError{ kind: Kind::ChangeNotFound,
                               detail: Some(err_msg)})
        },
        StatusCode::Unauthorized => {
            let msg = "API request returned 401 (unauthorized)".to_string();
            Err(DeliveryError{ kind: Kind::AuthenticationFailed,
                               detail: Some(msg)})
        },
        error_code @ _ => {
            let msg = format!("API request returned {}",
                              error_code);
            let mut detail = String::new();
            let e = match result.read_to_string(&mut detail) {
                Ok(_) => Ok(detail),
                Err(e) => Err(e)
            };
            Err(DeliveryError{ kind: Kind::ApiError(error_code, e),
                               detail: Some(msg)})
        }
    }
}

/// Set the description for a change
pub fn set(config: &Config,
           change: &str,
           description: &Description) -> Result<(), DeliveryError> {
    let org = try!(config.organization());
    let proj = try!(config.project());
    let client = try!(APIClient::from_config(&config));
    let path = format!("orgs/{}/projects/{}/changes/{}/description",
                       org, proj, change);
    let payload = try!(description.to_json());
    let mut result = try!(client.put(&path, &payload));
    match result.status {
        StatusCode::NoContent => Ok(()),
        StatusCode::Unauthorized => {
            let msg = "API request returned 401".to_string();
            Err(DeliveryError{ kind: Kind::AuthenticationFailed,
                               detail: Some(msg)})
        },
        error_code @ _ => {
            let msg = format!("API request returned {}", error_code);
            let mut detail = String::new();
            let e = result.read_to_string(&mut detail).and(Ok(detail));
            Err(DeliveryError::throw(Kind::ApiError(error_code, e),Some(msg)))
        }
    }
}

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

    #[test]
    fn description_payload_test() {
        let payload = Description::payload("a title", "so descriptive!");
        let expect = "{\"title\":\"a title\",\"description\":\"so descriptive!\"}";
        assert_eq!(expect, payload.unwrap());
    }

    #[test]
    fn description_to_json_test() {
        let desc = Description { title: "a title".to_string(),
                                 description: "so descriptive!".to_string() };
        let payload = desc.to_json().unwrap();
        let expect = "{\"title\":\"a title\",\"description\":\"so descriptive!\"}";
        assert_eq!(expect, payload);
    }

    #[test]
    fn description_parse_json_test() {
        let response = "{\"title\":\"a title\",\"description\":\"so descriptive!\"}";
        let expect = Description{ title: "a title".to_string(),
                                  description: "so descriptive!".to_string()};
        let description = Description::parse_json(response).unwrap();
        assert_eq!(expect, description);
    }

    #[test]
    fn description_parse_text_1_test() {
        let text = "Just a title";
        let expect = Description{ title: text.to_string(),
                                  description: "".to_string() };
        let desc = Description::parse_text(text).unwrap();
        assert_eq!(expect, desc);
    }

    #[test]
    fn description_parse_text_2_test() {
        let text = "Just a title\n\nWith some description";
        let expect = Description{ title: "Just a title".to_string(),
                                  description: "With some description".to_string() };
        let desc = Description::parse_text(text).unwrap();
        assert_eq!(expect, desc);
    }

    #[test]
    fn description_parse_text_3_test() {
        let text = "Just a title\n\nL1\nL2\nL3\n";
        let expect = Description{ title: "Just a title".to_string(),
                                  description: "L1\nL2\nL3".to_string() };
        let desc = Description::parse_text(text).unwrap();
        assert_eq!(expect, desc);
    }

}
<commit_msg>[CON-605] Clean out blank lines before generating title in delivery review --edit<commit_after>//
// Copyright:: Copyright (c) 2015 Chef Software, Inc.
// License:: Apache License, Version 2.0
//
// 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 errors::{DeliveryError, Kind};
use http::*;
use hyper::status::StatusCode;
use serde_json;

use config::Config;

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd)]
pub struct Description {
    pub title: String,
    pub description: String
}

impl Description {
    pub fn payload(title: &str, desc: &str) -> Result<String, DeliveryError> {
        let desc = Description{ title: String::from(title),
                                description: String::from(desc) };
        desc.to_json()
    }

    pub fn to_json(&self) -> Result<String, DeliveryError> {
        let payload = serde_json::to_string(&self)?;
        Ok(payload)
    }

    pub fn parse_json(response: &str) -> Result<Description, DeliveryError> {
        Ok(serde_json::from_str::<Description>(response)?)
    }

    pub fn parse_text(text: &str) -> Result<Description, DeliveryError> {
        let mut iter = text.lines();
        let title = iter.find(|&l| !l.trim().is_empty()).unwrap_or("").trim().to_string();
        let desc = iter.collect::<Vec<&str>>().join("\n").trim().to_string();
        Ok(Description{ title: title, description: desc })
    }
}

/// Fetch the description for a change
pub fn get(config: &Config,
           change: &str) -> Result<Description, DeliveryError> {
    let org = try!(config.organization());
    let proj = try!(config.project());
    let client = try!(APIClient::from_config(&config));
    let path = format!("orgs/{}/projects/{}/changes/{}/description",
                       org, proj, change);
    debug!("description path: {}", path);
    let mut result = try!(client.get(&path));
    match result.status {
        StatusCode::Ok => {
            let mut body_string = String::new();
            let _x = try!(result.read_to_string(&mut body_string));
            let description = try!(Description::parse_json(&body_string));
            Ok(description)
        },
        StatusCode::NotFound => {
            let msg1 = "API request returned 404 (not found) while trying to fetch this change's description.\n".to_string();
            let msg2 = "This is usually because the Delivery organization in your config does not match the organization for this project.\n";
            let msg3 = "Your organization is current set to:\n\n";
            let msg4 = &org;
            let msg5 = "\n\nTo fix this, try editing your cli.toml file's organization setting to match the organization this project resides in.";
            let err_msg = msg1 + msg2 + msg3 + msg4 + msg5;
            Err(DeliveryError{ kind: Kind::ChangeNotFound,
                               detail: Some(err_msg)})
        },
        StatusCode::Unauthorized => {
            let msg = "API request returned 401 (unauthorized)".to_string();
            Err(DeliveryError{ kind: Kind::AuthenticationFailed,
                               detail: Some(msg)})
        },
        error_code @ _ => {
            let msg = format!("API request returned {}",
                              error_code);
            let mut detail = String::new();
            let e = match result.read_to_string(&mut detail) {
                Ok(_) => Ok(detail),
                Err(e) => Err(e)
            };
            Err(DeliveryError{ kind: Kind::ApiError(error_code, e),
                               detail: Some(msg)})
        }
    }
}

/// Set the description for a change
pub fn set(config: &Config,
           change: &str,
           description: &Description) -> Result<(), DeliveryError> {
    let org = try!(config.organization());
    let proj = try!(config.project());
    let client = try!(APIClient::from_config(&config));
    let path = format!("orgs/{}/projects/{}/changes/{}/description",
                       org, proj, change);
    let payload = try!(description.to_json());
    let mut result = try!(client.put(&path, &payload));
    match result.status {
        StatusCode::NoContent => Ok(()),
        StatusCode::Unauthorized => {
            let msg = "API request returned 401".to_string();
            Err(DeliveryError{ kind: Kind::AuthenticationFailed,
                               detail: Some(msg)})
        },
        error_code @ _ => {
            let msg = format!("API request returned {}", error_code);
            let mut detail = String::new();
            let e = result.read_to_string(&mut detail).and(Ok(detail));
            Err(DeliveryError::throw(Kind::ApiError(error_code, e),Some(msg)))
        }
    }
}

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

    #[test]
    fn description_payload_test() {
        let payload = Description::payload("a title", "so descriptive!");
        let expect = "{\"title\":\"a title\",\"description\":\"so descriptive!\"}";
        assert_eq!(expect, payload.unwrap());
    }

    #[test]
    fn description_to_json_test() {
        let desc = Description { title: "a title".to_string(),
                                 description: "so descriptive!".to_string() };
        let payload = desc.to_json().unwrap();
        let expect = "{\"title\":\"a title\",\"description\":\"so descriptive!\"}";
        assert_eq!(expect, payload);
    }

    #[test]
    fn description_parse_json_test() {
        let response = "{\"title\":\"a title\",\"description\":\"so descriptive!\"}";
        let expect = Description{ title: "a title".to_string(),
                                  description: "so descriptive!".to_string()};
        let description = Description::parse_json(response).unwrap();
        assert_eq!(expect, description);
    }

    #[test]
    fn description_parse_text_1_test() {
        let text = "Just a title";
        let expect = Description{ title: text.to_string(),
                                  description: "".to_string() };
        let desc = Description::parse_text(text).unwrap();
        assert_eq!(expect, desc);
    }

    #[test]
    fn description_parse_text_2_test() {
        let text = "Just a title\n\nWith some description";
        let expect = Description{ title: "Just a title".to_string(),
                                  description: "With some description".to_string() };
        let desc = Description::parse_text(text).unwrap();
        assert_eq!(expect, desc);
    }

    #[test]
    fn description_parse_text_3_test() {
        let text = "Just a title\n\nL1\nL2\nL3\n";
        let expect = Description{ title: "Just a title".to_string(),
                                  description: "L1\nL2\nL3".to_string() };
        let desc = Description::parse_text(text).unwrap();
        assert_eq!(expect, desc);
    }

    #[test]
    fn description_parse_text_4_test() {
        let text = "\n  \nA title after some blank lines\n  \nL1\nL2\nL3\n";
        let expect = Description{ title: "A title after some blank lines".to_string(),
                                  description: "L1\nL2\nL3".to_string() };
        let desc = Description::parse_text(text).unwrap();
        assert_eq!(expect, desc);
    }

}
<|endoftext|>