<commit_before>//! Create and manage user-defined networks that containers can be attached to.
//!
//! API Reference: <https://docs.docker.com/engine/api/v1.41/#tag/Network>

use std::{
    collections::{BTreeMap, HashMap},
    hash::Hash,
};

use hyper::Body;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use url::form_urlencoded;

use crate::{
    docker::Docker,
    errors::{Error, Result},
};

/// Interface for docker network
///
/// API Reference: <https://docs.docker.com/engine/api/v1.41/#tag/Network>
pub struct Networks<'docker> {
    docker: &'docker Docker,
}

impl<'docker> Networks<'docker> {
    /// Exports an interface for interacting with docker Networks
    pub fn new(docker: &'docker Docker) -> Self {
        Networks { docker }
    }

    /// List the docker networks on the current docker host
    ///
    /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/NetworkList>
    pub async fn list(
        &self,
        opts: &NetworkListOptions,
    ) -> Result<Vec<NetworkInfo>> {
        let mut path = vec!["/networks".to_owned()];
        if let Some(query) = opts.serialize() {
            path.push(query);
        }
        self.docker.get_json(&path.join("?")).await
    }

    /// Returns a reference to a set of operations available to a specific network instance
    pub fn get<S>(
        &self,
        id: S,
    ) -> Network<'docker>
    where
        S: Into<String>,
    {
        Network::new(self.docker, id)
    }

    /// Create a new Network instance
    ///
    /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/NetworkCreate>
    pub async fn create(
        &self,
        opts: &NetworkCreateOptions,
    ) -> Result<NetworkCreateInfo> {
        let body: Body = opts.serialize()?.into();
        let path = vec!["/networks/create".to_owned()];

        self.docker
            .post_json(&path.join("?"), Some((body, mime::APPLICATION_JSON)))
            .await
    }
}

/// Interface for accessing and manipulating a docker network
pub struct Network<'docker> {
    docker: &'docker Docker,
    id: String,
}

impl<'docker> Network<'docker> {
    /// Exports an interface exposing operations against a network instance
    pub fn new<S>(
        docker: &'docker Docker,
        id: S,
    ) -> Self
    where
        S: Into<String>,
    {
        Network {
            docker,
            id: id.into(),
        }
    }

    /// a getter for the Network id
    pub fn id(&self) -> &str {
        &self.id
    }

    /// Inspects the current docker network instance's details
    ///
    /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/NetworkInspect>
    pub async fn inspect(&self) -> Result<NetworkInfo> {
        self.docker
            .get_json(&format!("/networks/{}", self.id)[..])
            .await
    }

    /// Delete the network instance
    ///
    /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/NetworkDelete>
    pub async fn delete(&self) -> Result<()> {
        self.docker
            .delete(&format!("/networks/{}", self.id)[..])
            .await?;
        Ok(())
    }

    /// Connect container to network
    ///
    /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/NetworkConnect>
    pub async fn connect(
        &self,
        opts: &ContainerConnectionOptions,
    ) -> Result<()> {
        self.do_connection("connect", opts).await
    }

    /// Disconnect container to network
    ///
    /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/NetworkDisconnect>
    pub async fn disconnect(
        &self,
        opts: &ContainerConnectionOptions,
    ) -> Result<()> {
        self.do_connection("disconnect", opts).await
    }

    async fn do_connection(
        &self,
        segment: &str,
        opts: &ContainerConnectionOptions,
    ) -> Result<()> {
        let body: Body = opts.serialize()?.into();

        self.docker
            .post(
                &format!("/networks/{}/{}", self.id, segment)[..],
                Some((body, mime::APPLICATION_JSON)),
            )
            .await?;
        Ok(())
    }
}

/// Options for filtering networks list results
#[derive(Default, Debug)]
pub struct NetworkListOptions {
    params: HashMap<&'static str, String>,
}

impl NetworkListOptions {
    /// serialize options as a string. returns None if no options are defined
    pub fn serialize(&self) -> Option<String> {
        if self.params.is_empty() {
            None
        } else {
            Some(
                form_urlencoded::Serializer::new(String::new())
                    .extend_pairs(&self.params)
                    .finish(),
            )
        }
    }
}

/// Interface for creating new docker network
#[derive(Serialize, Debug)]
pub struct NetworkCreateOptions {
    params: HashMap<&'static str, Value>,
}

impl NetworkCreateOptions {
    /// return a new instance of a builder for options
    pub fn builder(name: &str) -> NetworkCreateOptionsBuilder {
        NetworkCreateOptionsBuilder::new(name)
    }

    /// serialize options as a string. returns None if no options are defined
    pub fn serialize(&self) -> Result<String> {
        serde_json::to_string(&self.params).map_err(Error::from)
    }

    pub fn parse_from<'a, K, V>(
        &self,
        params: &'a HashMap<K, V>,
        body: &mut serde_json::Map<String, Value>,
    ) where
        &'a HashMap<K, V>: IntoIterator,
        K: ToString + Eq + Hash,
        V: Serialize,
    {
        for (k, v) in params.iter() {
            let key = k.to_string();
            let value = serde_json::to_value(v).unwrap();

            body.insert(key, value);
        }
    }
}

#[derive(Default)]
pub struct NetworkCreateOptionsBuilder {
    params: HashMap<&'static str, Value>,
}

impl NetworkCreateOptionsBuilder {
    pub(crate) fn new(name: &str) -> Self {
        let mut params = HashMap::new();
        params.insert("Name", json!(name));
        NetworkCreateOptionsBuilder { params }
    }

    pub fn driver(
        &mut self,
        name: &str,
    ) -> &mut Self {
        if !name.is_empty() {
            self.params.insert("Driver", json!(name));
        }
        self
    }

    pub fn label(
        &mut self,
        labels: HashMap<String, String>,
    ) -> &mut Self {
        self.params.insert("Labels", json!(labels));
        self
    }

    pub fn build(&self) -> NetworkCreateOptions {
        NetworkCreateOptions {
            params: self.params.clone(),
        }
    }
}

/// Interface for connect container to network
#[derive(Serialize, Debug)]
pub struct ContainerConnectionOptions {
    params: HashMap<&'static str, Value>,
}

impl ContainerConnectionOptions {
    /// serialize options as a string. returns None if no options are defined
    pub fn serialize(&self) -> Result<String> {
        serde_json::to_string(&self.params).map_err(Error::from)
    }

    pub fn parse_from<'a, K, V>(
        &self,
        params: &'a HashMap<K, V>,
        body: &mut BTreeMap<String, Value>,
    ) where
        &'a HashMap<K, V>: IntoIterator,
        K: ToString + Eq + Hash,
        V: Serialize,
    {
        for (k, v) in params.iter() {
            let key = k.to_string();
            let value = serde_json::to_value(v).unwrap();

            body.insert(key, value);
        }
    }

    /// return a new instance of a builder for options
    pub fn builder(container_id: &str) -> ContainerConnectionOptionsBuilder {
        ContainerConnectionOptionsBuilder::new(container_id)
    }
}

#[derive(Default)]
pub struct ContainerConnectionOptionsBuilder {
    params: HashMap<&'static str, Value>,
}

impl ContainerConnectionOptionsBuilder {
    pub(crate) fn new(container_id: &str) -> Self {
        let mut params = HashMap::new();
        params.insert("Container", json!(container_id));
        ContainerConnectionOptionsBuilder { params }
    }

    pub fn aliases(
        &mut self,
        aliases: Vec<&str>,
    ) -> &mut Self {
        self.params
            .insert("EndpointConfig", json!({ "Aliases": json!(aliases) }));
        self
    }

    pub fn force(&mut self) -> &mut Self {
        self.params.insert("Force", json!(true));
        self
    }

    pub fn build(&self) -> ContainerConnectionOptions {
        ContainerConnectionOptions {
            params: self.params.clone(),
        }
    }
}

type PortDescription = HashMap<String, Option<Vec<HashMap<String, String>>>>;

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct NetworkSettings {
    pub bridge: String,
    pub gateway: String,
    #[serde(rename = "IPAddress")]
    pub ip_address: String,
    #[serde(rename = "IPPrefixLen")]
    pub ip_prefix_len: u64,
    pub mac_address: String,
    pub ports: Option<PortDescription>,
    pub networks: HashMap<String, NetworkEntry>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct NetworkEntry {
    #[serde(rename = "NetworkID")]
    pub network_id: String,
    #[serde(rename = "EndpointID")]
    pub endpoint_id: String,
    pub gateway: String,
    #[serde(rename = "IPAddress")]
    pub ip_address: String,
    #[serde(rename = "IPPrefixLen")]
    pub ip_prefix_len: u64,
    #[serde(rename = "IPv6Gateway")]
    pub ipv6_gateway: String,
    #[serde(rename = "GlobalIPv6Address")]
    pub global_ipv6_address: String,
    #[serde(rename = "GlobalIPv6PrefixLen")]
    pub global_ipv6_prefix_len: u64,
    pub mac_address: String,
    pub links: Option<Vec<String>>,
    pub aliases: Option<Vec<String>>,
    #[serde(rename = "IPAMConfig")]
    pub ipam_config: Option<EndpointIPAMConfig>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct EndpointIPAMConfig {
    #[serde(rename = "IPv4Address")]
    pub ipv4_address: String,
    #[serde(rename = "IPv6Address")]
    pub ipv6_address: String,
    #[serde(rename = "LinkLocalIPs")]
    pub link_local_ips: Vec<String>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct NetworkInfo {
    pub rx_dropped: u64,
    pub rx_bytes: u64,
    pub rx_errors: u64,
    pub tx_packets: u64,
    pub tx_dropped: u64,
    pub rx_packets: u64,
    pub tx_errors: u64,
    pub tx_bytes: u64,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Ipam {
    pub driver: String,
    pub config: Vec<HashMap<String, String>>,
    pub options: Option<HashMap<String, String>>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct NetworkDetails {
    pub name: String,
    pub id: String,
    pub scope: String,
    pub driver: String,
    #[serde(rename = "EnableIPv6")]
    pub enable_ipv6: bool,
    #[serde(rename = "IPAM")]
    pub ipam: Ipam,
    pub internal: bool,
    pub attachable: bool,
    pub containers: HashMap<String, NetworkContainerDetails>,
    pub options: Option<HashMap<String, String>>,
    pub labels: Option<HashMap<String, String>>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct NetworkContainerDetails {
    #[serde(rename = "EndpointID")]
    pub endpoint_id: String,
    pub mac_address: String,
    #[serde(rename = "IPv4Address")]
    pub ipv4_address: String,
    #[serde(rename = "IPv6Address")]
    pub ipv6_address: String,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct NetworkCreateInfo {
    pub id: String,
    pub warning: String,
}
<commit_msg>Fix clippy: Allow upper case acronym here<commit_after>//! Create and manage user-defined networks that containers can be attached to.
//!
//! API Reference: <https://docs.docker.com/engine/api/v1.41/#tag/Network>

use std::{
    collections::{BTreeMap, HashMap},
    hash::Hash,
};

use hyper::Body;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use url::form_urlencoded;

use crate::{
    docker::Docker,
    errors::{Error, Result},
};

/// Interface for docker network
///
/// API Reference: <https://docs.docker.com/engine/api/v1.41/#tag/Network>
pub struct Networks<'docker> {
    docker: &'docker Docker,
}

impl<'docker> Networks<'docker> {
    /// Exports an interface for interacting with docker Networks
    pub fn new(docker: &'docker Docker) -> Self {
        Networks { docker }
    }

    /// List the docker networks on the current docker host
    ///
    /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/NetworkList>
    pub async fn list(
        &self,
        opts: &NetworkListOptions,
    ) -> Result<Vec<NetworkInfo>> {
        let mut path = vec!["/networks".to_owned()];
        if let Some(query) = opts.serialize() {
            path.push(query);
        }
        self.docker.get_json(&path.join("?")).await
    }

    /// Returns a reference to a set of operations available to a specific network instance
    pub fn get<S>(
        &self,
        id: S,
    ) -> Network<'docker>
    where
        S: Into<String>,
    {
        Network::new(self.docker, id)
    }

    /// Create a new Network instance
    ///
    /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/NetworkCreate>
    pub async fn create(
        &self,
        opts: &NetworkCreateOptions,
    ) -> Result<NetworkCreateInfo> {
        let body: Body = opts.serialize()?.into();
        let path = vec!["/networks/create".to_owned()];

        self.docker
            .post_json(&path.join("?"), Some((body, mime::APPLICATION_JSON)))
            .await
    }
}

/// Interface for accessing and manipulating a docker network
pub struct Network<'docker> {
    docker: &'docker Docker,
    id: String,
}

impl<'docker> Network<'docker> {
    /// Exports an interface exposing operations against a network instance
    pub fn new<S>(
        docker: &'docker Docker,
        id: S,
    ) -> Self
    where
        S: Into<String>,
    {
        Network {
            docker,
            id: id.into(),
        }
    }

    /// a getter for the Network id
    pub fn id(&self) -> &str {
        &self.id
    }

    /// Inspects the current docker network instance's details
    ///
    /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/NetworkInspect>
    pub async fn inspect(&self) -> Result<NetworkInfo> {
        self.docker
            .get_json(&format!("/networks/{}", self.id)[..])
            .await
    }

    /// Delete the network instance
    ///
    /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/NetworkDelete>
    pub async fn delete(&self) -> Result<()> {
        self.docker
            .delete(&format!("/networks/{}", self.id)[..])
            .await?;
        Ok(())
    }

    /// Connect container to network
    ///
    /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/NetworkConnect>
    pub async fn connect(
        &self,
        opts: &ContainerConnectionOptions,
    ) -> Result<()> {
        self.do_connection("connect", opts).await
    }

    /// Disconnect container to network
    ///
    /// API Reference: <https://docs.docker.com/engine/api/v1.41/#operation/NetworkDisconnect>
    pub async fn disconnect(
        &self,
        opts: &ContainerConnectionOptions,
    ) -> Result<()> {
        self.do_connection("disconnect", opts).await
    }

    async fn do_connection(
        &self,
        segment: &str,
        opts: &ContainerConnectionOptions,
    ) -> Result<()> {
        let body: Body = opts.serialize()?.into();

        self.docker
            .post(
                &format!("/networks/{}/{}", self.id, segment)[..],
                Some((body, mime::APPLICATION_JSON)),
            )
            .await?;
        Ok(())
    }
}

/// Options for filtering networks list results
#[derive(Default, Debug)]
pub struct NetworkListOptions {
    params: HashMap<&'static str, String>,
}

impl NetworkListOptions {
    /// serialize options as a string. returns None if no options are defined
    pub fn serialize(&self) -> Option<String> {
        if self.params.is_empty() {
            None
        } else {
            Some(
                form_urlencoded::Serializer::new(String::new())
                    .extend_pairs(&self.params)
                    .finish(),
            )
        }
    }
}

/// Interface for creating new docker network
#[derive(Serialize, Debug)]
pub struct NetworkCreateOptions {
    params: HashMap<&'static str, Value>,
}

impl NetworkCreateOptions {
    /// return a new instance of a builder for options
    pub fn builder(name: &str) -> NetworkCreateOptionsBuilder {
        NetworkCreateOptionsBuilder::new(name)
    }

    /// serialize options as a string. returns None if no options are defined
    pub fn serialize(&self) -> Result<String> {
        serde_json::to_string(&self.params).map_err(Error::from)
    }

    pub fn parse_from<'a, K, V>(
        &self,
        params: &'a HashMap<K, V>,
        body: &mut serde_json::Map<String, Value>,
    ) where
        &'a HashMap<K, V>: IntoIterator,
        K: ToString + Eq + Hash,
        V: Serialize,
    {
        for (k, v) in params.iter() {
            let key = k.to_string();
            let value = serde_json::to_value(v).unwrap();

            body.insert(key, value);
        }
    }
}

#[derive(Default)]
pub struct NetworkCreateOptionsBuilder {
    params: HashMap<&'static str, Value>,
}

impl NetworkCreateOptionsBuilder {
    pub(crate) fn new(name: &str) -> Self {
        let mut params = HashMap::new();
        params.insert("Name", json!(name));
        NetworkCreateOptionsBuilder { params }
    }

    pub fn driver(
        &mut self,
        name: &str,
    ) -> &mut Self {
        if !name.is_empty() {
            self.params.insert("Driver", json!(name));
        }
        self
    }

    pub fn label(
        &mut self,
        labels: HashMap<String, String>,
    ) -> &mut Self {
        self.params.insert("Labels", json!(labels));
        self
    }

    pub fn build(&self) -> NetworkCreateOptions {
        NetworkCreateOptions {
            params: self.params.clone(),
        }
    }
}

/// Interface for connect container to network
#[derive(Serialize, Debug)]
pub struct ContainerConnectionOptions {
    params: HashMap<&'static str, Value>,
}

impl ContainerConnectionOptions {
    /// serialize options as a string. returns None if no options are defined
    pub fn serialize(&self) -> Result<String> {
        serde_json::to_string(&self.params).map_err(Error::from)
    }

    pub fn parse_from<'a, K, V>(
        &self,
        params: &'a HashMap<K, V>,
        body: &mut BTreeMap<String, Value>,
    ) where
        &'a HashMap<K, V>: IntoIterator,
        K: ToString + Eq + Hash,
        V: Serialize,
    {
        for (k, v) in params.iter() {
            let key = k.to_string();
            let value = serde_json::to_value(v).unwrap();

            body.insert(key, value);
        }
    }

    /// return a new instance of a builder for options
    pub fn builder(container_id: &str) -> ContainerConnectionOptionsBuilder {
        ContainerConnectionOptionsBuilder::new(container_id)
    }
}

#[derive(Default)]
pub struct ContainerConnectionOptionsBuilder {
    params: HashMap<&'static str, Value>,
}

impl ContainerConnectionOptionsBuilder {
    pub(crate) fn new(container_id: &str) -> Self {
        let mut params = HashMap::new();
        params.insert("Container", json!(container_id));
        ContainerConnectionOptionsBuilder { params }
    }

    pub fn aliases(
        &mut self,
        aliases: Vec<&str>,
    ) -> &mut Self {
        self.params
            .insert("EndpointConfig", json!({ "Aliases": json!(aliases) }));
        self
    }

    pub fn force(&mut self) -> &mut Self {
        self.params.insert("Force", json!(true));
        self
    }

    pub fn build(&self) -> ContainerConnectionOptions {
        ContainerConnectionOptions {
            params: self.params.clone(),
        }
    }
}

type PortDescription = HashMap<String, Option<Vec<HashMap<String, String>>>>;

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct NetworkSettings {
    pub bridge: String,
    pub gateway: String,
    #[serde(rename = "IPAddress")]
    pub ip_address: String,
    #[serde(rename = "IPPrefixLen")]
    pub ip_prefix_len: u64,
    pub mac_address: String,
    pub ports: Option<PortDescription>,
    pub networks: HashMap<String, NetworkEntry>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct NetworkEntry {
    #[serde(rename = "NetworkID")]
    pub network_id: String,
    #[serde(rename = "EndpointID")]
    pub endpoint_id: String,
    pub gateway: String,
    #[serde(rename = "IPAddress")]
    pub ip_address: String,
    #[serde(rename = "IPPrefixLen")]
    pub ip_prefix_len: u64,
    #[serde(rename = "IPv6Gateway")]
    pub ipv6_gateway: String,
    #[serde(rename = "GlobalIPv6Address")]
    pub global_ipv6_address: String,
    #[serde(rename = "GlobalIPv6PrefixLen")]
    pub global_ipv6_prefix_len: u64,
    pub mac_address: String,
    pub links: Option<Vec<String>>,
    pub aliases: Option<Vec<String>>,
    #[serde(rename = "IPAMConfig")]
    pub ipam_config: Option<EndpointIPAMConfig>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[allow(clippy::upper_case_acronyms)]
pub struct EndpointIPAMConfig {
    #[serde(rename = "IPv4Address")]
    pub ipv4_address: String,
    #[serde(rename = "IPv6Address")]
    pub ipv6_address: String,
    #[serde(rename = "LinkLocalIPs")]
    pub link_local_ips: Vec<String>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct NetworkInfo {
    pub rx_dropped: u64,
    pub rx_bytes: u64,
    pub rx_errors: u64,
    pub tx_packets: u64,
    pub tx_dropped: u64,
    pub rx_packets: u64,
    pub tx_errors: u64,
    pub tx_bytes: u64,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Ipam {
    pub driver: String,
    pub config: Vec<HashMap<String, String>>,
    pub options: Option<HashMap<String, String>>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct NetworkDetails {
    pub name: String,
    pub id: String,
    pub scope: String,
    pub driver: String,
    #[serde(rename = "EnableIPv6")]
    pub enable_ipv6: bool,
    #[serde(rename = "IPAM")]
    pub ipam: Ipam,
    pub internal: bool,
    pub attachable: bool,
    pub containers: HashMap<String, NetworkContainerDetails>,
    pub options: Option<HashMap<String, String>>,
    pub labels: Option<HashMap<String, String>>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct NetworkContainerDetails {
    #[serde(rename = "EndpointID")]
    pub endpoint_id: String,
    pub mac_address: String,
    #[serde(rename = "IPv4Address")]
    pub ipv4_address: String,
    #[serde(rename = "IPv6Address")]
    pub ipv6_address: String,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct NetworkCreateInfo {
    pub id: String,
    pub warning: String,
}
<|endoftext|>


<commit_before>use address::Address;
use messages::outgoing;
use mio;
use node;
use routing_table::{InsertOutcome, InsertionResult, RoutingTable};
use std::collections::HashMap;
use std::io::Cursor;
use std::net::{UdpSocket, ToSocketAddrs, SocketAddr};
use std::sync::mpsc;
use std::thread;
use transaction::{TransactionId, TransactionIdGenerator};

pub enum ScheduledTask {
    ContinueBootstrap,
    ContinueHealthCheck,
    ContinueRefresh
}

#[derive(Debug)]
pub enum Event {
    ReceivedPacket(Vec<u8>)
}

pub enum OneshotTask {
    Incoming(Vec<u8>),
    StartBootstrap,
    SendPacket(Address, Vec<u8>)
}

enum TableAction {
    Bootstrap(mio::Timeout),
    HealthCheck(mio::Timeout),
    RefreshBucket(mio::Timeout)
}

pub type TaskSender = mio::Sender<OneshotTask>;

enum Status {
    Bootstrapping,
    Idle
}

pub struct Network {
    host: SocketAddr,
    routing_table: RoutingTable,
    self_node: Box<node::Node + 'static>,
    transaction_ids: TransactionIdGenerator,
    status: Status,
    pending_actions: HashMap<TransactionId, TableAction>,
    event_listeners: Vec<mpsc::Sender<Event>>
}

impl Network {
    pub fn new<N: node::Node + 'static, T: ToSocketAddrs>(self_node: N, host: T, routers: Vec<Box<node::Node>>) -> Network {
        let host = host.to_socket_addrs().unwrap().next().unwrap();
        let self_address = self_node.get_address().clone();
        let routing_table = RoutingTable::new(8, self_address, routers);

        Network {
            host: host,
            routing_table: routing_table,
            self_node: Box::new(self_node),
            transaction_ids: TransactionIdGenerator::new(),
            status: Status::Idle,
            pending_actions: HashMap::new(),
            event_listeners: vec![]
        }
    }

    pub fn run(self) -> TaskSender {
        let mut event_loop_config = mio::EventLoopConfig::new();
        event_loop_config.notify_capacity(16384);
        let mut event_loop = mio::EventLoop::configured(event_loop_config).unwrap();

        create_incoming_udp_channel(self.host, event_loop.channel());
        event_loop.channel().send(OneshotTask::StartBootstrap).unwrap();
        let mut handler = Handler::new(self);
        let task_sender = event_loop.channel();
        thread::spawn(move|| event_loop.run(&mut handler).unwrap());
        task_sender
    }

    pub fn register_event_listener(&mut self, event_listener: mpsc::Sender<Event>) {
        self.event_listeners.push(event_listener);
    }

    fn handle_incoming(&mut self, data: Vec<u8>, event_loop: &mut mio::EventLoop<Handler>) {
        use messages::incoming::{Message, Query, Response, self};
        let mut data = Cursor::new(data);
        let message = incoming::parse_from_reader(&mut data).unwrap();

        match message {
            Message::Query(transaction_id, origin, query) => {
                let origin_address = origin.get_address();
                match query {
                    Query::FindNode(target) => {
                        let response: Vec<u8> = outgoing::create_find_node_response(
                                transaction_id,
                                &self.self_node,
                                self.routing_table.nearest_to(&target, false));
                        origin.send(response);

                        self.insert_node(origin).unwrap();
                        {
                            if let Some(origin) = self.routing_table.find_node(&origin_address) {
                                origin.received_query(transaction_id);
                            }
                        }
                    },
                    Query::Packet(payload) => {
                        for listener in &self.event_listeners {
                            listener.send(Event::ReceivedPacket(payload.clone())).unwrap();
                        }
                        let response = outgoing::create_packet_response(
                            transaction_id, &self.self_node);
                        origin.send(response);
                    },
                    Query::Ping => {
                        let response = outgoing::create_ping_response(
                            transaction_id,
                            &self.self_node);
                        origin.send(response);

                        self.insert_node(origin).unwrap();
                        if let Some(origin) = self.routing_table.find_node(&origin_address) {
                            origin.received_query(transaction_id);
                        }
                    }
                }
            }
            Message::Response(transaction_id, origin, response) => {
                let origin_address = origin.get_address();
                match response {
                    Response::FindNode(mut nodes) => {
                        let mut encounted_new_node = false;
                        let mut tail = vec![origin];
                        for node in nodes.drain(..).chain(tail.drain(..)) {
                            match self.insert_node(node) {
                                Ok(InsertOutcome::Inserted) => {
                                    encounted_new_node = true;
                                }
                                Err(error) => { panic!(error) }
                                _ => { }
                            }
                        }

                        {
                            let mut origin = self.routing_table
                                .find_node(&origin_address)
                                .expect("Got find node response from unknown node");
                            origin.received_response(transaction_id);
                        }

                        match self.pending_actions.remove(&transaction_id) {
                            Some(TableAction::Bootstrap(timeout)) => {
                                event_loop.clear_timeout(timeout);
                                if encounted_new_node {
                                    self.continue_bootstrap(event_loop);
                                } else {
                                    self.continue_health_check(event_loop);
                                    self.continue_refresh(event_loop)
                                }
                            }
                            Some(TableAction::HealthCheck(_)) => {
                            },
                            Some(TableAction::RefreshBucket(_)) => {
                            }
                            None => { }
                        }

                        match self.status {
                            Status::Bootstrapping => {
                                self.status = Status::Idle;
                            }
                            _ => { }
                        }
                    }
                    Response::Packet => {
                        let mut origin = self.routing_table
                            .find_node(&origin_address)
                            .expect("Got packet response from unknown node");
                        origin.received_response(transaction_id);
                    }
                    Response::Ping => {
                        let mut origin = self.routing_table
                            .find_node(&origin_address)
                            .expect("Got ping response from unknown node");
                        origin.received_response(transaction_id);
                    }
                }
            }
        }
    }

    fn start_bootstrap(&mut self, event_loop: &mut mio::EventLoop<Handler>) {
        self.status = Status::Bootstrapping;
        self.continue_bootstrap(event_loop);
    }

    fn continue_bootstrap(&mut self, event_loop: &mut mio::EventLoop<Handler>) {
        let address = &self.self_node.get_address();
        let transaction_id = self.find_node(address);
        let timeout = event_loop.timeout_ms(ScheduledTask::ContinueBootstrap, 1000).unwrap();
        self.pending_actions.insert(transaction_id, TableAction::Bootstrap(timeout));
    }

    fn continue_health_check(&mut self, event_loop: &mut mio::EventLoop<Handler>) {
        let transaction_id = self.health_check();
        let timeout = event_loop.timeout_ms(ScheduledTask::ContinueHealthCheck, 1000).unwrap();
        self.pending_actions.insert(transaction_id, TableAction::HealthCheck(timeout));
    }

    fn continue_refresh(&mut self, event_loop: &mut mio::EventLoop<Handler>) {
        let timeout = event_loop.timeout_ms(ScheduledTask::ContinueRefresh, 1000).unwrap();

        match self.refresh_bucket() {
            Some(transaction_id) => {
                self.pending_actions.insert(transaction_id, TableAction::RefreshBucket(timeout));
            }
            None => { }
        }
    }

    fn find_node(&mut self, address: &Address) -> TransactionId {
        let transaction_id = self.transaction_ids.generate();
        let query = outgoing::create_find_node_query(
            transaction_id,
            &self.self_node,
            address);
        for node in self.routing_table.nearest() {
            node.send(query.clone());
            node.sent_query(transaction_id);
        }
        transaction_id
    }

    fn health_check(&mut self) -> TransactionId {
        let transaction_id = self.transaction_ids.generate();
        if let Some(node) = self.routing_table.questionable_nodes().get_mut(0) {
            let query = outgoing::create_ping_query(
                transaction_id, &self.self_node);
            node.send(query);
            node.sent_query(transaction_id);
        }
        transaction_id
    }

    fn refresh_bucket(&mut self) -> Option<TransactionId> {
        if let Some(address) = self.address_to_find_for_refresh() {
            Some(self.find_node(&address))
        } else {
            None
        }
    }

    fn address_to_find_for_refresh(&self) -> Option<Address> {
        match self.routing_table.bucket_needing_refresh() {
            Some(bucket) => {
                Some(bucket.random_address_in_space())
            }
            None => None
        }
    }

    fn insert_node(&mut self, node: Box<node::Node>) -> InsertionResult {
        self.routing_table.insert(node, &self.self_node, &mut self.transaction_ids)
    }

    fn send_packet(&mut self, recipient: Address, payload: Vec<u8>, event_loop: &mut mio::EventLoop<Handler>) {
        for node in self.routing_table.nearest_to(&recipient, false) {
            let transaction_id = self.transaction_ids.generate();
            let query = outgoing::create_packet_query(
                transaction_id, &self.self_node, payload.clone());
            node.send(query.clone());
            node.sent_query(transaction_id);
        }
    }
}

struct Handler {
    network: Network
}

impl Handler {
    fn new(network: Network) -> Handler {
        Handler {
            network: network
        }
    }
}

impl mio::Handler for Handler {
    type Timeout = ScheduledTask;
    type Message = OneshotTask;

    fn notify(&mut self, event_loop: &mut mio::EventLoop<Handler>, task: OneshotTask) {
        match task {
            OneshotTask::Incoming(data) => self.network.handle_incoming(data, event_loop),
            OneshotTask::StartBootstrap => self.network.start_bootstrap(event_loop),
            OneshotTask::SendPacket(recipient, payload) => {
                self.network.send_packet(recipient, payload, event_loop);
            }
        }
    }

    fn timeout(&mut self, event_loop: &mut mio::EventLoop<Handler>, timeout: ScheduledTask) {
        match timeout {
            ScheduledTask::ContinueBootstrap => self.network.continue_bootstrap(event_loop),
            ScheduledTask::ContinueHealthCheck => self.network.continue_health_check(event_loop),
            ScheduledTask::ContinueRefresh => self.network.continue_refresh(event_loop)
        }
    }
}

fn create_incoming_udp_channel(host: SocketAddr, sender: TaskSender) {
    thread::spawn(move || {
        let host = ("0.0.0.0", host.port());
        let socket = UdpSocket::bind(host).unwrap();
        loop {
            let mut buf = [0; 4096];
            match socket.recv_from(&mut buf) {
                Ok((size, _src)) => {
                    sender
                        .send(OneshotTask::Incoming(buf[..size].iter().cloned().collect()))
                        .unwrap_or_else(|err| info!("Couldn't handling incoming: {:?}", err));
                }
                Err(e) => panic!("Error receiving from server: {}", e)
            }
        }
    });
}
<commit_msg>Stop panicing when receiving unexpected responses<commit_after>use address::Address;
use messages::outgoing;
use mio;
use node;
use routing_table::{InsertOutcome, InsertionResult, RoutingTable};
use std::collections::HashMap;
use std::io::Cursor;
use std::net::{UdpSocket, ToSocketAddrs, SocketAddr};
use std::sync::mpsc;
use std::thread;
use transaction::{TransactionId, TransactionIdGenerator};

pub enum ScheduledTask {
    ContinueBootstrap,
    ContinueHealthCheck,
    ContinueRefresh
}

#[derive(Debug)]
pub enum Event {
    ReceivedPacket(Vec<u8>)
}

pub enum OneshotTask {
    Incoming(Vec<u8>),
    StartBootstrap,
    SendPacket(Address, Vec<u8>)
}

enum TableAction {
    Bootstrap(mio::Timeout),
    HealthCheck(mio::Timeout),
    RefreshBucket(mio::Timeout)
}

pub type TaskSender = mio::Sender<OneshotTask>;

enum Status {
    Bootstrapping,
    Idle
}

pub struct Network {
    host: SocketAddr,
    routing_table: RoutingTable,
    self_node: Box<node::Node + 'static>,
    transaction_ids: TransactionIdGenerator,
    status: Status,
    pending_actions: HashMap<TransactionId, TableAction>,
    event_listeners: Vec<mpsc::Sender<Event>>
}

impl Network {
    pub fn new<N: node::Node + 'static, T: ToSocketAddrs>(self_node: N, host: T, routers: Vec<Box<node::Node>>) -> Network {
        let host = host.to_socket_addrs().unwrap().next().unwrap();
        let self_address = self_node.get_address().clone();
        let routing_table = RoutingTable::new(8, self_address, routers);

        Network {
            host: host,
            routing_table: routing_table,
            self_node: Box::new(self_node),
            transaction_ids: TransactionIdGenerator::new(),
            status: Status::Idle,
            pending_actions: HashMap::new(),
            event_listeners: vec![]
        }
    }

    pub fn run(self) -> TaskSender {
        let mut event_loop_config = mio::EventLoopConfig::new();
        event_loop_config.notify_capacity(16384);
        let mut event_loop = mio::EventLoop::configured(event_loop_config).unwrap();

        create_incoming_udp_channel(self.host, event_loop.channel());
        event_loop.channel().send(OneshotTask::StartBootstrap).unwrap();
        let mut handler = Handler::new(self);
        let task_sender = event_loop.channel();
        thread::spawn(move|| event_loop.run(&mut handler).unwrap());
        task_sender
    }

    pub fn register_event_listener(&mut self, event_listener: mpsc::Sender<Event>) {
        self.event_listeners.push(event_listener);
    }

    fn handle_incoming(&mut self, data: Vec<u8>, event_loop: &mut mio::EventLoop<Handler>) {
        use messages::incoming::{Message, Query, Response, self};
        let mut data = Cursor::new(data);
        let message = incoming::parse_from_reader(&mut data).unwrap();

        match message {
            Message::Query(transaction_id, origin, query) => {
                let origin_address = origin.get_address();
                match query {
                    Query::FindNode(target) => {
                        let response: Vec<u8> = outgoing::create_find_node_response(
                                transaction_id,
                                &self.self_node,
                                self.routing_table.nearest_to(&target, false));
                        origin.send(response);

                        self.insert_node(origin).unwrap();
                        {
                            if let Some(origin) = self.routing_table.find_node(&origin_address) {
                                origin.received_query(transaction_id);
                            }
                        }
                    },
                    Query::Packet(payload) => {
                        for listener in &self.event_listeners {
                            listener.send(Event::ReceivedPacket(payload.clone())).unwrap();
                        }
                        let response = outgoing::create_packet_response(
                            transaction_id, &self.self_node);
                        origin.send(response);
                    },
                    Query::Ping => {
                        let response = outgoing::create_ping_response(
                            transaction_id,
                            &self.self_node);
                        origin.send(response);

                        self.insert_node(origin).unwrap();
                        if let Some(origin) = self.routing_table.find_node(&origin_address) {
                            origin.received_query(transaction_id);
                        }
                    }
                }
            }
            Message::Response(transaction_id, origin, response) => {
                let origin_address = origin.get_address();
                match response {
                    Response::FindNode(mut nodes) => {
                        let mut encounted_new_node = false;
                        let mut tail = vec![origin];
                        for node in nodes.drain(..).chain(tail.drain(..)) {
                            match self.insert_node(node) {
                                Ok(InsertOutcome::Inserted) => {
                                    encounted_new_node = true;
                                }
                                Err(error) => { panic!(error) }
                                _ => { }
                            }
                        }

                        {
                            if let Some(mut origin) = self.routing_table.find_node(&origin_address) {
                                origin.received_response(transaction_id);
                            }
                        }

                        match self.pending_actions.remove(&transaction_id) {
                            Some(TableAction::Bootstrap(timeout)) => {
                                event_loop.clear_timeout(timeout);
                                if encounted_new_node {
                                    self.continue_bootstrap(event_loop);
                                } else {
                                    self.continue_health_check(event_loop);
                                    self.continue_refresh(event_loop)
                                }
                            }
                            Some(TableAction::HealthCheck(_)) => {
                            },
                            Some(TableAction::RefreshBucket(_)) => {
                            }
                            None => { }
                        }

                        match self.status {
                            Status::Bootstrapping => {
                                self.status = Status::Idle;
                            }
                            _ => { }
                        }
                    }
                    Response::Packet => {
                        if let Some(mut origin) = self.routing_table.find_node(&origin_address) {
                            origin.received_response(transaction_id);
                        }
                    }
                    Response::Ping => {
                        if let Some(mut origin) = self.routing_table.find_node(&origin_address) {
                            origin.received_response(transaction_id);
                        }
                    }
                }
            }
        }
    }

    fn start_bootstrap(&mut self, event_loop: &mut mio::EventLoop<Handler>) {
        self.status = Status::Bootstrapping;
        self.continue_bootstrap(event_loop);
    }

    fn continue_bootstrap(&mut self, event_loop: &mut mio::EventLoop<Handler>) {
        let address = &self.self_node.get_address();
        let transaction_id = self.find_node(address);
        let timeout = event_loop.timeout_ms(ScheduledTask::ContinueBootstrap, 1000).unwrap();
        self.pending_actions.insert(transaction_id, TableAction::Bootstrap(timeout));
    }

    fn continue_health_check(&mut self, event_loop: &mut mio::EventLoop<Handler>) {
        let transaction_id = self.health_check();
        let timeout = event_loop.timeout_ms(ScheduledTask::ContinueHealthCheck, 1000).unwrap();
        self.pending_actions.insert(transaction_id, TableAction::HealthCheck(timeout));
    }

    fn continue_refresh(&mut self, event_loop: &mut mio::EventLoop<Handler>) {
        let timeout = event_loop.timeout_ms(ScheduledTask::ContinueRefresh, 1000).unwrap();

        match self.refresh_bucket() {
            Some(transaction_id) => {
                self.pending_actions.insert(transaction_id, TableAction::RefreshBucket(timeout));
            }
            None => { }
        }
    }

    fn find_node(&mut self, address: &Address) -> TransactionId {
        let transaction_id = self.transaction_ids.generate();
        let query = outgoing::create_find_node_query(
            transaction_id,
            &self.self_node,
            address);
        for node in self.routing_table.nearest() {
            node.send(query.clone());
            node.sent_query(transaction_id);
        }
        transaction_id
    }

    fn health_check(&mut self) -> TransactionId {
        let transaction_id = self.transaction_ids.generate();
        if let Some(node) = self.routing_table.questionable_nodes().get_mut(0) {
            let query = outgoing::create_ping_query(
                transaction_id, &self.self_node);
            node.send(query);
            node.sent_query(transaction_id);
        }
        transaction_id
    }

    fn refresh_bucket(&mut self) -> Option<TransactionId> {
        if let Some(address) = self.address_to_find_for_refresh() {
            Some(self.find_node(&address))
        } else {
            None
        }
    }

    fn address_to_find_for_refresh(&self) -> Option<Address> {
        match self.routing_table.bucket_needing_refresh() {
            Some(bucket) => {
                Some(bucket.random_address_in_space())
            }
            None => None
        }
    }

    fn insert_node(&mut self, node: Box<node::Node>) -> InsertionResult {
        self.routing_table.insert(node, &self.self_node, &mut self.transaction_ids)
    }

    fn send_packet(&mut self, recipient: Address, payload: Vec<u8>, event_loop: &mut mio::EventLoop<Handler>) {
        for node in self.routing_table.nearest_to(&recipient, false) {
            let transaction_id = self.transaction_ids.generate();
            let query = outgoing::create_packet_query(
                transaction_id, &self.self_node, payload.clone());
            node.send(query.clone());
            node.sent_query(transaction_id);
        }
    }
}

struct Handler {
    network: Network
}

impl Handler {
    fn new(network: Network) -> Handler {
        Handler {
            network: network
        }
    }
}

impl mio::Handler for Handler {
    type Timeout = ScheduledTask;
    type Message = OneshotTask;

    fn notify(&mut self, event_loop: &mut mio::EventLoop<Handler>, task: OneshotTask) {
        match task {
            OneshotTask::Incoming(data) => self.network.handle_incoming(data, event_loop),
            OneshotTask::StartBootstrap => self.network.start_bootstrap(event_loop),
            OneshotTask::SendPacket(recipient, payload) => {
                self.network.send_packet(recipient, payload, event_loop);
            }
        }
    }

    fn timeout(&mut self, event_loop: &mut mio::EventLoop<Handler>, timeout: ScheduledTask) {
        match timeout {
            ScheduledTask::ContinueBootstrap => self.network.continue_bootstrap(event_loop),
            ScheduledTask::ContinueHealthCheck => self.network.continue_health_check(event_loop),
            ScheduledTask::ContinueRefresh => self.network.continue_refresh(event_loop)
        }
    }
}

fn create_incoming_udp_channel(host: SocketAddr, sender: TaskSender) {
    thread::spawn(move || {
        let host = ("0.0.0.0", host.port());
        let socket = UdpSocket::bind(host).unwrap();
        loop {
            let mut buf = [0; 4096];
            match socket.recv_from(&mut buf) {
                Ok((size, _src)) => {
                    sender
                        .send(OneshotTask::Incoming(buf[..size].iter().cloned().collect()))
                        .unwrap_or_else(|err| info!("Couldn't handling incoming: {:?}", err));
                }
                Err(e) => panic!("Error receiving from server: {}", e)
            }
        }
    });
}
<|endoftext|>


<commit_before>extern crate serde;
extern crate serde_yaml;
extern crate std;

#[derive(Debug, Deserialize)]
pub struct Config {
    pub name: String,
    pub package_key: Option<String>,
    pub repo_key: Option<String>,
    pub srcdest: String,
    pub logdest: String,
    pub pkgbuild: String,
    pub builds: std::collections::HashMap<super::builder::Arch, BuildConfig>,
}

#[derive(Debug, Deserialize)]
pub struct BuildConfig {
    pub chroot: String,
}

impl Config {
    pub fn from_reader<R>(reader: R) -> serde_yaml::Result<Self>
        where R: std::io::Read
    {
        serde_yaml::from_reader(reader)
    }

    pub fn repo_dir(&self, arch: &super::builder::Arch) -> std::path::PathBuf {
        std::path::PathBuf::from(&self.name).join("os").join(format!("{}", arch))
    }

    pub fn db_path(&self, arch: &super::builder::Arch) -> std::path::PathBuf {
        let mut path = self.repo_dir(arch).into_os_string();
        path.push(".db");
        return std::path::PathBuf::from(path);
    }

    pub fn files_path(&self, arch: &super::builder::Arch) -> std::path::PathBuf {
        let mut path = self.repo_dir(arch).into_os_string();
        path.push(".files");
        return std::path::PathBuf::from(path);
    }

    pub fn abs_path(&self, arch: &super::builder::Arch) -> std::path::PathBuf {
        let mut path = self.repo_dir(arch).into_os_string();
        path.push(".abs.tar.gz");
        return std::path::PathBuf::from(path);
    }

    pub fn package_dir(&self, package_name: &str) -> std::path::PathBuf {
        std::path::PathBuf::from(&self.pkgbuild).join(package_name)
    }
}
<commit_msg>Fix directory name<commit_after>extern crate serde;
extern crate serde_yaml;
extern crate std;

#[derive(Debug, Deserialize)]
pub struct Config {
    pub name: String,
    pub package_key: Option<String>,
    pub repo_key: Option<String>,
    pub srcdest: String,
    pub logdest: String,
    pub pkgbuild: String,
    pub builds: std::collections::HashMap<super::builder::Arch, BuildConfig>,
}

#[derive(Debug, Deserialize)]
pub struct BuildConfig {
    pub chroot: String,
}

impl Config {
    pub fn from_reader<R>(reader: R) -> serde_yaml::Result<Self>
        where R: std::io::Read
    {
        serde_yaml::from_reader(reader)
    }

    pub fn repo_dir(&self, arch: &super::builder::Arch) -> std::path::PathBuf {
        std::path::PathBuf::from(&self.name).join("os").join(format!("{}", arch))
    }

    pub fn db_path(&self, arch: &super::builder::Arch) -> std::path::PathBuf {
        let mut path = self.repo_dir(arch).join(&self.name).into_os_string();
        path.push(".db");
        return std::path::PathBuf::from(path);
    }

    pub fn files_path(&self, arch: &super::builder::Arch) -> std::path::PathBuf {
        let mut path = self.repo_dir(arch).join(&self.name).into_os_string();
        path.push(".files");
        return std::path::PathBuf::from(path);
    }

    pub fn abs_path(&self, arch: &super::builder::Arch) -> std::path::PathBuf {
        let mut path = self.repo_dir(arch).join(&self.name).into_os_string();
        path.push(".abs.tar.gz");
        return std::path::PathBuf::from(path);
    }

    pub fn package_dir(&self, package_name: &str) -> std::path::PathBuf {
        std::path::PathBuf::from(&self.pkgbuild).join(package_name)
    }
}
<|endoftext|>


<commit_before>use prelude::*;
use super::{CheckpointFormat};
use rw::{ReadBuffer, WriteBuffer};

use csv::{Writer as CsvWriter};
use densearray::{Reshape, ReshapeMut};

use rand::{Rng, thread_rng};
use rustc_serialize::{Encodable};
use std::cmp::{max, min};
use std::fmt::{Debug};
use std::fs::{File, create_dir_all};
use std::io::{Write};
use std::path::{Path, PathBuf};
use std::thread::{sleep};
use std::time::{Duration, Instant};

//pub mod adagrad;
pub mod adagrad_new;
//pub mod adam;
pub mod adam_new;
//pub mod rmsprop;
//pub mod sgd;
pub mod sgd_new;
//pub mod shared_sgd;
pub mod shared_sgd_new;

#[derive(Clone, Debug)]
pub struct CheckpointConfig {
  pub prefix:   PathBuf,
  pub trace:    bool,
}

pub struct CheckpointState {
  pub cfg:          CheckpointConfig,
  pub config_file:  Option<File>,
  pub train_file:   Option<CsvWriter<File>>,
  pub valid_file:   Option<CsvWriter<File>>,
  start_time:   Instant,
  lap_time:     Instant,
  elapsed_s:    f64,
}

impl CheckpointState {
  pub fn new(cfg: CheckpointConfig) -> CheckpointState {
    Self::with_fields(cfg, "iter,loss,accuracy,elapsed")
  }

  pub fn with_fields(cfg: CheckpointConfig, fields: &str) -> CheckpointState {
    let delay_s = thread_rng().gen_range(0, 4);
    let delay_ns = thread_rng().gen_range(100_000_000, 500_000_000);
    sleep(Duration::new(delay_s, delay_ns));
    create_dir_all(&cfg.prefix).ok();
    loop {
      let mut lo_idx = Some(0);
      let mut hi_idx = None;
      let mut idx = 0;
      while lo_idx != hi_idx {
        match (lo_idx, hi_idx) {
          (Some(lo), None) => {
            idx = lo;
          }
          (Some(lo), Some(hi)) => {
            idx = (lo + hi) / 2;
          }
          _ => unreachable!(),
        }
        let mut config_path = PathBuf::from(&cfg.prefix);
        let mut config_filename = format!("config.{}", idx);
        config_path.push(&config_filename);
        if config_path.exists() {
          match (lo_idx, hi_idx) {
            (Some(lo), None) => {
              lo_idx = Some(lo + max(1, lo));
            }
            (Some(lo), Some(hi)) => {
              lo_idx = Some(min(hi, max(lo + 1, idx)));
            }
            _ => unreachable!(),
          }
        } else {
          match (lo_idx, hi_idx) {
            (Some(_), None) => {
              lo_idx = Some(idx / 2);
              hi_idx = Some(idx);
            }
            (Some(_), Some(_)) => {
              hi_idx = Some(idx);
            }
            _ => unreachable!(),
          }
        }
      }
      idx = hi_idx.unwrap();
      let mut cfg_f = None;
      let mut trace_f = None;
      let mut valid_f = None;
      let mut config_path = PathBuf::from(&cfg.prefix);
      let mut config_filename = format!("config.{}", idx);
      config_path.push(&config_filename);
      if config_path.exists() {
        continue;
      }
      match File::create(&config_path) {
        Err(_) => {
          continue;
        }
        Ok(f) => {
          cfg_f = Some(f);
        }
      }
      if cfg.trace {
        let mut train_path = PathBuf::from(&cfg.prefix);
        let mut train_filename = format!("train.log.{}", idx);
        train_path.push(&train_filename);
        assert!(!train_path.exists());
        let mut f = File::create(&train_path).unwrap();
        writeln!(&mut f, "{}", fields).unwrap();
        trace_f = Some(f);

        let mut valid_path = PathBuf::from(&cfg.prefix);
        let mut valid_filename = format!("valid.log.{}", idx);
        valid_path.push(&valid_filename);
        assert!(!valid_path.exists());
        let mut f = File::create(&valid_path).unwrap();
        writeln!(&mut f, "{}", fields).unwrap();
        valid_f = Some(f);
      }
      let init_time = Instant::now();
      return CheckpointState{
        cfg:          cfg,
        config_file:  cfg_f,
        train_file:   trace_f.map(|f| CsvWriter::from_writer(f)),
        valid_file:   valid_f.map(|f| CsvWriter::from_writer(f)),
        start_time:   init_time,
        lap_time:     init_time,
        elapsed_s:    0.0,
      };
    }
  }

  pub fn start_timing(&mut self) {
    self.start_time = Instant::now();
  }

  pub fn stop_timing(&mut self) {
    self.lap_time = Instant::now();
    let duration = self.lap_time - self.start_time;
    self.elapsed_s = duration.as_secs() as f64 + 1.0e-9 * duration.subsec_nanos() as f64;
  }

  pub fn elapsed(&self) -> f64 {
    self.elapsed_s
  }

  pub fn append_config_info<U>(&mut self, info: &U) where U: Debug {
    if let Some(ref mut config_file) = self.config_file {
      writeln!(config_file, "{:?}", info).unwrap();
    }
  }

  pub fn append_class_stats_train(&mut self, stats: &ClassLossStats) {
    let elapsed = self.elapsed_s;
    self.append_train_info(&stats.to_record(elapsed));
  }

  pub fn append_train_info<Rec>(&mut self, rec: &Rec) where Rec: Encodable {
    if let Some(ref mut train_file) = self.train_file {
      train_file.encode(rec).unwrap();
      //train_file.flush().unwrap();
    }
  }

  pub fn append_class_stats_valid(&mut self, stats: &ClassLossStats) {
    let elapsed = self.elapsed_s;
    self.append_valid_info(&stats.to_record(elapsed));
  }

  pub fn append_valid_info<Rec>(&mut self, rec: &Rec) where Rec: Encodable {
    if let Some(ref mut valid_file) = self.valid_file {
      valid_file.encode(rec).unwrap();
      valid_file.flush().unwrap();
    }
  }
}

pub trait TraceRecord {
  fn loss(&self) -> f32;
  fn other(&self) -> f32;
}

#[derive(Clone, Debug)]
pub enum StepSize {
  Constant(f32),
  Custom{init_step: f32, steps: Vec<(usize, f32)>},
  Decay{init_step: f32, step_decay: f32, decay_iters: usize},
  Adaptive{init_step: f32, test_iters: usize, epoch_iters: usize, sched: AdaptiveStepSizeSchedule},
  BacktrackingLineSearch{decay: f32, c: f32},
  //WeakWolfeLineSearch,
}

#[derive(Clone, Copy, Debug)]
pub enum AdaptiveStepSizeSchedule {
  Pow10,
  Decimal,
}

pub fn adaptive_pow10_step_size_factor(t: usize) -> f32 {
  const F1: [f32; 2] = [0.3,    0.1];
  const F2: [f32; 2] = [0.03,   0.01];
  const F3: [f32; 2] = [0.003,  0.001];
  const F4: [f32; 2] = [0.0003, 0.0001];
  if t == 0 {
    1.0
  } else if t > 0 && t <= 2 {
    F1[t-1]
  } else if t > 2 && t <= 4 {
    F2[t-2-1]
  } else if t > 4 && t <= 6 {
    F3[t-4-1]
  } else if t > 6 && t <= 8 {
    F4[t-6-1]
  } else {
    unimplemented!();
  }
}

pub fn adaptive_decimal_step_size_factor(t: usize) -> f32 {
  const F1: [f32; 9] = [0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1];
  const F2: [f32; 9] = [0.09, 0.08, 0.07, 0.06, 0.05, 0.04, 0.03, 0.02, 0.01];
  const F3: [f32; 9] = [0.009, 0.008, 0.007, 0.006, 0.005, 0.004, 0.003, 0.002, 0.001];
  if t == 0 {
    1.0
  } else if t > 0 && t <= 9 {
    F1[t-1]
  } else if t > 9 && t <= 18 {
    F2[t-9-1]
  } else if t > 18 && t <= 27 {
    F3[t-18-1]
  } else {
    unimplemented!();
  }
}

#[derive(Clone, Copy, Debug)]
pub enum GradientMomentum {
  HeavyBall(f32),
  Nesterov(f32),
}

#[derive(Clone, Copy, Debug)]
pub enum NesterovParamState {
  Orig,
  PlusMomentum,
}

#[derive(Clone, Copy, Debug)]
pub struct StepStats {
  pub elapsed:  Option<f64>,
}

pub trait OptWorker<T, S> {
  type Rng: Rng;

  //fn init_param(&mut self, rng: &mut Xorshiftplus128Rng);
  fn init_param(&mut self, rng: &mut Self::Rng);
  /*fn load_local_param(&mut self, param_reader: &mut ReadBuffer<T>);
  fn store_local_param(&mut self, param_writer: &mut WriteBuffer<T>);
  fn store_global_param(&mut self, param_writer: &mut WriteBuffer<T>);*/

  fn step(&mut self, samples: &mut Iterator<Item=S>) /* -> StepStats*/;
  fn eval(&mut self, epoch_size: usize, samples: &mut Iterator<Item=S>);
}

pub trait OptCheckpoint<Format> where Format: CheckpointFormat {
  fn save_checkpoint(&mut self, path: &Path) -> Result<(), ()>;
  fn restore_checkpoint(&mut self, path: &Path) -> Result<(), ()>;
}

pub trait OptStats<Stats> {
  fn reset_opt_stats(&mut self);
  fn get_opt_stats(&self) -> &Stats;
}

pub trait OptUpdateStats<Stats> {
  fn update_stats(&mut self, stats: &mut Stats);
}

#[derive(Clone, Default, Debug)]
pub struct ClassOptStats {
  pub iter_count:       usize,
  pub sample_count:     usize,
  pub correct_count:    usize,
  pub avg_loss:         f32,
}

impl ClassOptStats {
  pub fn reset(&mut self) {
    self.iter_count = 0;
    self.sample_count = 0;
    self.correct_count = 0;
    self.avg_loss = 0.0;
  }

  pub fn accuracy(&self) -> f32 {
    self.correct_count as f32 / self.sample_count as f32
  }
}

#[derive(Clone, Default, Debug)]
pub struct RegressOptStats {
  pub avg_loss:         f32,
}
<commit_msg>Add another delay.<commit_after>use prelude::*;
use super::{CheckpointFormat};
use rw::{ReadBuffer, WriteBuffer};

use csv::{Writer as CsvWriter};
use densearray::{Reshape, ReshapeMut};

use rand::{Rng, thread_rng};
use rustc_serialize::{Encodable};
use std::cmp::{max, min};
use std::fmt::{Debug};
use std::fs::{File, create_dir_all};
use std::io::{Write};
use std::path::{Path, PathBuf};
use std::thread::{sleep};
use std::time::{Duration, Instant};

//pub mod adagrad;
pub mod adagrad_new;
//pub mod adam;
pub mod adam_new;
//pub mod rmsprop;
//pub mod sgd;
pub mod sgd_new;
//pub mod shared_sgd;
pub mod shared_sgd_new;

#[derive(Clone, Debug)]
pub struct CheckpointConfig {
  pub prefix:   PathBuf,
  pub trace:    bool,
}

pub struct CheckpointState {
  pub cfg:          CheckpointConfig,
  pub config_file:  Option<File>,
  pub train_file:   Option<CsvWriter<File>>,
  pub valid_file:   Option<CsvWriter<File>>,
  start_time:   Instant,
  lap_time:     Instant,
  elapsed_s:    f64,
}

impl CheckpointState {
  pub fn new(cfg: CheckpointConfig) -> CheckpointState {
    Self::with_fields(cfg, "iter,loss,accuracy,elapsed")
  }

  pub fn with_fields(cfg: CheckpointConfig, fields: &str) -> CheckpointState {
    let delay_s = thread_rng().gen_range(0, 2);
    let delay_ns = thread_rng().gen_range(100_000_000, 500_000_000);
    sleep(Duration::new(delay_s, delay_ns));
    create_dir_all(&cfg.prefix).ok();
    loop {
      let mut lo_idx = Some(0);
      let mut hi_idx = None;
      let mut idx = 0;
      while lo_idx != hi_idx {
        match (lo_idx, hi_idx) {
          (Some(lo), None) => {
            idx = lo;
          }
          (Some(lo), Some(hi)) => {
            idx = (lo + hi) / 2;
          }
          _ => unreachable!(),
        }
        let mut config_path = PathBuf::from(&cfg.prefix);
        let mut config_filename = format!("config.{}", idx);
        config_path.push(&config_filename);
        if config_path.exists() {
          match (lo_idx, hi_idx) {
            (Some(lo), None) => {
              lo_idx = Some(lo + max(1, lo));
            }
            (Some(lo), Some(hi)) => {
              lo_idx = Some(min(hi, max(lo + 1, idx)));
            }
            _ => unreachable!(),
          }
        } else {
          match (lo_idx, hi_idx) {
            (Some(_), None) => {
              lo_idx = Some(idx / 2);
              hi_idx = Some(idx);
            }
            (Some(_), Some(_)) => {
              hi_idx = Some(idx);
            }
            _ => unreachable!(),
          }
        }
      }
      idx = hi_idx.unwrap();

      let delay_s = thread_rng().gen_range(0, 2);
      let delay_ns = thread_rng().gen_range(100_000_000, 500_000_000);
      sleep(Duration::new(delay_s, delay_ns));
      let mut cfg_f = None;
      let mut trace_f = None;
      let mut valid_f = None;
      let mut config_path = PathBuf::from(&cfg.prefix);
      let mut config_filename = format!("config.{}", idx);
      config_path.push(&config_filename);
      if config_path.exists() {
        continue;
      }
      match File::create(&config_path) {
        Err(_) => {
          continue;
        }
        Ok(f) => {
          cfg_f = Some(f);
        }
      }
      if cfg.trace {
        let mut train_path = PathBuf::from(&cfg.prefix);
        let mut train_filename = format!("train.log.{}", idx);
        train_path.push(&train_filename);
        assert!(!train_path.exists());
        let mut f = File::create(&train_path).unwrap();
        writeln!(&mut f, "{}", fields).unwrap();
        trace_f = Some(f);

        let mut valid_path = PathBuf::from(&cfg.prefix);
        let mut valid_filename = format!("valid.log.{}", idx);
        valid_path.push(&valid_filename);
        assert!(!valid_path.exists());
        let mut f = File::create(&valid_path).unwrap();
        writeln!(&mut f, "{}", fields).unwrap();
        valid_f = Some(f);
      }
      let init_time = Instant::now();
      return CheckpointState{
        cfg:          cfg,
        config_file:  cfg_f,
        train_file:   trace_f.map(|f| CsvWriter::from_writer(f)),
        valid_file:   valid_f.map(|f| CsvWriter::from_writer(f)),
        start_time:   init_time,
        lap_time:     init_time,
        elapsed_s:    0.0,
      };
    }
  }

  pub fn start_timing(&mut self) {
    self.start_time = Instant::now();
  }

  pub fn stop_timing(&mut self) {
    self.lap_time = Instant::now();
    let duration = self.lap_time - self.start_time;
    self.elapsed_s = duration.as_secs() as f64 + 1.0e-9 * duration.subsec_nanos() as f64;
  }

  pub fn elapsed(&self) -> f64 {
    self.elapsed_s
  }

  pub fn append_config_info<U>(&mut self, info: &U) where U: Debug {
    if let Some(ref mut config_file) = self.config_file {
      writeln!(config_file, "{:?}", info).unwrap();
    }
  }

  pub fn append_class_stats_train(&mut self, stats: &ClassLossStats) {
    let elapsed = self.elapsed_s;
    self.append_train_info(&stats.to_record(elapsed));
  }

  pub fn append_train_info<Rec>(&mut self, rec: &Rec) where Rec: Encodable {
    if let Some(ref mut train_file) = self.train_file {
      train_file.encode(rec).unwrap();
      //train_file.flush().unwrap();
    }
  }

  pub fn append_class_stats_valid(&mut self, stats: &ClassLossStats) {
    let elapsed = self.elapsed_s;
    self.append_valid_info(&stats.to_record(elapsed));
  }

  pub fn append_valid_info<Rec>(&mut self, rec: &Rec) where Rec: Encodable {
    if let Some(ref mut valid_file) = self.valid_file {
      valid_file.encode(rec).unwrap();
      valid_file.flush().unwrap();
    }
  }
}

pub trait TraceRecord {
  fn loss(&self) -> f32;
  fn other(&self) -> f32;
}

#[derive(Clone, Debug)]
pub enum StepSize {
  Constant(f32),
  Custom{init_step: f32, steps: Vec<(usize, f32)>},
  Decay{init_step: f32, step_decay: f32, decay_iters: usize},
  Adaptive{init_step: f32, test_iters: usize, epoch_iters: usize, sched: AdaptiveStepSizeSchedule},
  BacktrackingLineSearch{decay: f32, c: f32},
  //WeakWolfeLineSearch,
}

#[derive(Clone, Copy, Debug)]
pub enum AdaptiveStepSizeSchedule {
  Pow10,
  Decimal,
}

pub fn adaptive_pow10_step_size_factor(t: usize) -> f32 {
  const F1: [f32; 2] = [0.3,    0.1];
  const F2: [f32; 2] = [0.03,   0.01];
  const F3: [f32; 2] = [0.003,  0.001];
  const F4: [f32; 2] = [0.0003, 0.0001];
  if t == 0 {
    1.0
  } else if t > 0 && t <= 2 {
    F1[t-1]
  } else if t > 2 && t <= 4 {
    F2[t-2-1]
  } else if t > 4 && t <= 6 {
    F3[t-4-1]
  } else if t > 6 && t <= 8 {
    F4[t-6-1]
  } else {
    unimplemented!();
  }
}

pub fn adaptive_decimal_step_size_factor(t: usize) -> f32 {
  const F1: [f32; 9] = [0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1];
  const F2: [f32; 9] = [0.09, 0.08, 0.07, 0.06, 0.05, 0.04, 0.03, 0.02, 0.01];
  const F3: [f32; 9] = [0.009, 0.008, 0.007, 0.006, 0.005, 0.004, 0.003, 0.002, 0.001];
  if t == 0 {
    1.0
  } else if t > 0 && t <= 9 {
    F1[t-1]
  } else if t > 9 && t <= 18 {
    F2[t-9-1]
  } else if t > 18 && t <= 27 {
    F3[t-18-1]
  } else {
    unimplemented!();
  }
}

#[derive(Clone, Copy, Debug)]
pub enum GradientMomentum {
  HeavyBall(f32),
  Nesterov(f32),
}

#[derive(Clone, Copy, Debug)]
pub enum NesterovParamState {
  Orig,
  PlusMomentum,
}

#[derive(Clone, Copy, Debug)]
pub struct StepStats {
  pub elapsed:  Option<f64>,
}

pub trait OptWorker<T, S> {
  type Rng: Rng;

  //fn init_param(&mut self, rng: &mut Xorshiftplus128Rng);
  fn init_param(&mut self, rng: &mut Self::Rng);
  /*fn load_local_param(&mut self, param_reader: &mut ReadBuffer<T>);
  fn store_local_param(&mut self, param_writer: &mut WriteBuffer<T>);
  fn store_global_param(&mut self, param_writer: &mut WriteBuffer<T>);*/

  fn step(&mut self, samples: &mut Iterator<Item=S>) /* -> StepStats*/;
  fn eval(&mut self, epoch_size: usize, samples: &mut Iterator<Item=S>);
}

pub trait OptCheckpoint<Format> where Format: CheckpointFormat {
  fn save_checkpoint(&mut self, path: &Path) -> Result<(), ()>;
  fn restore_checkpoint(&mut self, path: &Path) -> Result<(), ()>;
}

pub trait OptStats<Stats> {
  fn reset_opt_stats(&mut self);
  fn get_opt_stats(&self) -> &Stats;
}

pub trait OptUpdateStats<Stats> {
  fn update_stats(&mut self, stats: &mut Stats);
}

#[derive(Clone, Default, Debug)]
pub struct ClassOptStats {
  pub iter_count:       usize,
  pub sample_count:     usize,
  pub correct_count:    usize,
  pub avg_loss:         f32,
}

impl ClassOptStats {
  pub fn reset(&mut self) {
    self.iter_count = 0;
    self.sample_count = 0;
    self.correct_count = 0;
    self.avg_loss = 0.0;
  }

  pub fn accuracy(&self) -> f32 {
    self.correct_count as f32 / self.sample_count as f32
  }
}

#[derive(Clone, Default, Debug)]
pub struct RegressOptStats {
  pub avg_loss:         f32,
}
<|endoftext|>


<commit_before>#[cfg(feature = "headless")]
pub use self::headless::HeadlessContext;

use {CreationError, Event};
use CreationError::OsError;
use libc;

#[cfg(feature = "window")]
use WindowBuilder;

use cocoa::base::{id, NSUInteger, nil, objc_allocateClassPair, class, objc_registerClassPair};
use cocoa::base::{selector, msg_send, class_addMethod, class_addIvar};
use cocoa::base::{object_setInstanceVariable, object_getInstanceVariable};
use cocoa::appkit;
use cocoa::appkit::*;

use core_foundation::base::TCFType;
use core_foundation::string::CFString;
use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};

use std::c_str::CString;
use std::mem;
use std::ptr;
use std::sync::atomic::{AtomicBool, Relaxed};

use events::Event::{MouseInput, MouseMoved, ReceivedCharacter, KeyboardInput};
use events::ElementState::{Pressed, Released};
use events::MouseButton::{LeftMouseButton, RightMouseButton};
use events;

pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};

mod monitor;
mod event;

#[cfg(feature = "headless")]
mod headless;

static mut shift_pressed: bool = false;
static mut ctrl_pressed: bool = false;
static mut win_pressed: bool = false;
static mut alt_pressed: bool = false;

static DELEGATE_NAME: &'static [u8] = b"glutin_window_delegate\0";
static DELEGATE_THIS_IVAR: &'static [u8] = b"glutin_this";

struct InternalState {
    is_closed: AtomicBool,
}

impl InternalState {
    fn new() -> InternalState {
        InternalState {
            is_closed: AtomicBool::new(false),
        }
    }
}

pub struct Window {
    view: id,
    window: id,
    context: id,
    state: Box<InternalState>,
}

#[cfg(feature = "window")]
impl Window {
    pub fn new(builder: WindowBuilder) -> Result<Window, CreationError> {
        if builder.sharing.is_some() {
            unimplemented!()
        }

        Window::new_impl(builder.dimensions, builder.title.as_slice(), builder.monitor, builder.vsync, true)
    }
}

extern fn window_should_close(this: id, _: id) -> id {
    unsafe {
        let mut stored_value = ptr::null_mut();
        object_getInstanceVariable(this, DELEGATE_THIS_IVAR.as_ptr() as *const i8, &mut stored_value);
        let state = stored_value as *mut InternalState;
        (*state).is_closed.store(true, Relaxed);
    }
    0
}

impl Window {
    fn new_impl(dimensions: Option<(uint, uint)>, title: &str, monitor: Option<MonitorID>,
                vsync: bool, visible: bool) -> Result<Window, CreationError> {
        let app = match Window::create_app() {
            Some(app) => app,
            None      => { return Err(OsError(format!("Couldn't create NSApplication"))); },
        };
        let window = match Window::create_window(dimensions.unwrap_or((800, 600)), title, monitor) {
            Some(window) => window,
            None         => { return Err(OsError(format!("Couldn't create NSWindow"))); },
        };
        let view = match Window::create_view(window) {
            Some(view) => view,
            None       => { return Err(OsError(format!("Couldn't create NSView"))); },
        };

        let context = match Window::create_context(view, vsync) {
            Some(context) => context,
            None          => { return Err(OsError(format!("Couldn't create OpenGL context"))); },
        };

        unsafe {
            app.activateIgnoringOtherApps_(true);
            window.makeKeyAndOrderFront_(nil);
        }

        let window = Window {
            view: view,
            window: window,
            context: context,
            state: box InternalState::new(),
        };

        // Set up the window delegate to receive events
        let ptr_size = mem::size_of::<libc::intptr_t>() as u64;
        let ns_object = class("NSObject");

        unsafe {
            // Create a delegate class, add callback methods and store InternalState as user data.
            let delegate = objc_allocateClassPair(ns_object, DELEGATE_NAME.as_ptr() as *const i8, 0);
            class_addMethod(delegate, selector("windowShouldClose:"), window_should_close, "B@:@".to_c_str().as_ptr());
            class_addIvar(delegate, DELEGATE_THIS_IVAR.as_ptr() as *const i8, ptr_size, 3, "?".to_c_str().as_ptr());
            objc_registerClassPair(delegate);

            let del_obj = msg_send()(delegate, selector("alloc"));
            let del_obj: id = msg_send()(del_obj, selector("init"));
            object_setInstanceVariable(del_obj, DELEGATE_THIS_IVAR.as_ptr() as *const i8,
                                        &*window.state as *const InternalState as *mut libc::c_void);
            let _: id = msg_send()(window.window, selector("setDelegate:"), del_obj);
        }

        Ok(window)
    }

    fn create_app() -> Option<id> {
        unsafe {
            let app = NSApp();
            if app == nil {
                None
            } else {
                app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
                app.finishLaunching();
                Some(app)
            }
        }
    }

    fn create_window(dimensions: (uint, uint), title: &str, monitor: Option<MonitorID>) -> Option<id> {
        unsafe {
            let scr_frame = match monitor {
                Some(_) => {
                    let screen = NSScreen::mainScreen(nil);
                    NSScreen::frame(screen)
                }
                None    => {
                    let (width, height) = dimensions;
                    NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64))
                }
            };

             let masks = match monitor {
                Some(_) => NSBorderlessWindowMask as NSUInteger,
                None    => NSTitledWindowMask as NSUInteger |
                           NSClosableWindowMask as NSUInteger |
                           NSMiniaturizableWindowMask as NSUInteger |
                           NSResizableWindowMask as NSUInteger,
            };

            let window = NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
                scr_frame,
                masks,
                NSBackingStoreBuffered,
                false,
            );

            if window == nil {
                None
            } else {
                let title = NSString::alloc(nil).init_str(title);
                window.setTitle_(title);
                window.center();
                window.setAcceptsMouseMovedEvents_(true);
                if monitor.is_some() {
                    window.setLevel_(NSMainMenuWindowLevel as i64 + 1);
                }
                Some(window)
            }
        }
    }

    fn create_view(window: id) -> Option<id> {
        unsafe {
            let view = NSView::alloc(nil).init();
            if view == nil {
                None
            } else {
                view.setWantsBestResolutionOpenGLSurface_(true);
                window.setContentView_(view);
                Some(view)
            }
        }
    }

    fn create_context(view: id, vsync: bool) -> Option<id> {
        unsafe {
            let attributes = [
                NSOpenGLPFADoubleBuffer as uint,
                NSOpenGLPFAClosestPolicy as uint,
                NSOpenGLPFAColorSize as uint, 24,
                NSOpenGLPFAAlphaSize as uint, 8,
                NSOpenGLPFADepthSize as uint, 24,
                NSOpenGLPFAStencilSize as uint, 8,
                0
            ];

            let pixelformat = NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(&attributes);
            if pixelformat == nil {
                return None;
            }

            let context = NSOpenGLContext::alloc(nil).initWithFormat_shareContext_(pixelformat, nil);
            if context == nil {
                None
            } else {
                context.setView_(view);
                if vsync {
                    let value = 1;
                    context.setValues_forParameter_(&value, NSOpenGLCPSwapInterval);
                }
                Some(context)
            }
        }
    }

    pub fn is_closed(&self) -> bool {
        self.state.is_closed.load(Relaxed)
    }

    pub fn set_title(&self, title: &str) {
        unsafe {
            let title = NSString::alloc(nil).init_str(title);
            self.window.setTitle_(title);
        }
    }

    pub fn show(&self) {
    }

    pub fn hide(&self) {
    }

    pub fn get_position(&self) -> Option<(int, int)> {
        unimplemented!()
    }

    pub fn set_position(&self, _x: int, _y: int) {
        unimplemented!()
    }

    pub fn get_inner_size(&self) -> Option<(uint, uint)> {
        let rect = unsafe { NSView::frame(self.view) };
        Some((rect.size.width as uint, rect.size.height as uint))
    }

    pub fn get_outer_size(&self) -> Option<(uint, uint)> {
        unimplemented!()
    }

    pub fn set_inner_size(&self, _x: uint, _y: uint) {
        unimplemented!()
    }

    pub fn poll_events(&self) -> Vec<Event> {
        let mut events = Vec::new();

        loop {
            unsafe {
                let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
                    NSAnyEventMask as u64,
                    NSDate::distantPast(nil),
                    NSDefaultRunLoopMode,
                    true);
                if event == nil { break; }
                NSApp().sendEvent_(event);

                match event.get_type() {
                    NSLeftMouseDown         => { events.push(MouseInput(Pressed, LeftMouseButton)); },
                    NSLeftMouseUp           => { events.push(MouseInput(Released, LeftMouseButton)); },
                    NSRightMouseDown        => { events.push(MouseInput(Pressed, RightMouseButton)); },
                    NSRightMouseUp          => { events.push(MouseInput(Released, RightMouseButton)); },
                    NSMouseMoved            => {
                        let window_point = event.locationInWindow();
                        let view_point = self.view.convertPoint_fromView_(window_point, nil);
                        events.push(MouseMoved((view_point.x as int, view_point.y as int)));
                    },
                    NSKeyDown               => {
                        let received_str = CString::new(event.characters().UTF8String(), false);
                        for received_char in received_str.as_str().unwrap().chars() {
                            if received_char.is_ascii() {
                                events.push(ReceivedCharacter(received_char));
                            }
                        }

                        let vkey =  event::vkeycode_to_element(event.keycode());
                        events.push(KeyboardInput(Pressed, event.keycode() as u8, vkey));
                    },
                    NSKeyUp                 => {
                        let vkey =  event::vkeycode_to_element(event.keycode());
                        events.push(KeyboardInput(Released, event.keycode() as u8, vkey));
                    },
                    NSFlagsChanged          => {
                        let shift_modifier = Window::modifier_event(event, appkit::NSShiftKeyMask as u64, events::VirtualKeyCode::LShift, shift_pressed);
                        if shift_modifier.is_some() {
                            shift_pressed = !shift_pressed;
                            events.push(shift_modifier.unwrap());
                        }
                        let ctrl_modifier = Window::modifier_event(event, appkit::NSControlKeyMask as u64, events::VirtualKeyCode::LControl, ctrl_pressed);
                        if ctrl_modifier.is_some() {
                            ctrl_pressed = !ctrl_pressed;
                            events.push(ctrl_modifier.unwrap());
                        }
                        let win_modifier = Window::modifier_event(event, appkit::NSCommandKeyMask as u64, events::VirtualKeyCode::LWin, win_pressed);
                        if win_modifier.is_some() {
                            win_pressed = !win_pressed;
                            events.push(win_modifier.unwrap());
                        }
                        let alt_modifier = Window::modifier_event(event, appkit::NSAlternateKeyMask as u64, events::VirtualKeyCode::LAlt, alt_pressed);
                        if alt_modifier.is_some() {
                            alt_pressed = !alt_pressed;
                            events.push(alt_modifier.unwrap());
                        }
                    },
                    NSScrollWheel           => { },
                    NSOtherMouseDown        => { },
                    NSOtherMouseUp          => { },
                    NSOtherMouseDragged     => { },
                    _                       => { },
                }
            }
        }
        events
    }

    unsafe fn modifier_event(event: id, keymask: u64, key: events::VirtualKeyCode, key_pressed: bool) -> Option<Event> {
        if !key_pressed && Window::modifier_key_pressed(event, keymask) {
            return Some(KeyboardInput(Pressed, event.keycode() as u8, Some(key)));
        }
        else if key_pressed && !Window::modifier_key_pressed(event, keymask) {
            return Some(KeyboardInput(Released, event.keycode() as u8, Some(key)));
        }

        return None;
    }

    unsafe fn modifier_key_pressed(event: id, modifier: u64) -> bool {
        event.modifierFlags() & modifier != 0
    }

    pub fn wait_events(&self) -> Vec<Event> {
        unsafe {
            let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
                NSAnyEventMask as u64,
                NSDate::distantFuture(nil),
                NSDefaultRunLoopMode,
                false);
            NSApp().sendEvent_(event);

            self.poll_events()
        }
    }

    pub unsafe fn make_current(&self) {
        self.context.makeCurrentContext();
    }

    pub fn get_proc_address(&self, _addr: &str) -> *const () {
        let symbol_name: CFString = from_str(_addr).unwrap();
        let framework_name: CFString = from_str("com.apple.opengl").unwrap();
        let framework = unsafe {
            CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef())
        };
        let symbol = unsafe {
            CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef())
        };
        symbol as *const ()
    }

    pub fn swap_buffers(&self) {
        unsafe { self.context.flushBuffer(); }
    }

    pub fn platform_display(&self) -> *mut libc::c_void {
        unimplemented!()
    }
}
<commit_msg>Fixed issue with menu bar showing in fullscreen<commit_after>#[cfg(feature = "headless")]
pub use self::headless::HeadlessContext;

use {CreationError, Event};
use CreationError::OsError;
use libc;

#[cfg(feature = "window")]
use WindowBuilder;

use cocoa::base::{id, NSUInteger, nil, objc_allocateClassPair, class, objc_registerClassPair};
use cocoa::base::{selector, msg_send, class_addMethod, class_addIvar};
use cocoa::base::{object_setInstanceVariable, object_getInstanceVariable};
use cocoa::appkit;
use cocoa::appkit::*;

use core_foundation::base::TCFType;
use core_foundation::string::CFString;
use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};

use std::c_str::CString;
use std::mem;
use std::ptr;
use std::sync::atomic::{AtomicBool, Relaxed};

use events::Event::{MouseInput, MouseMoved, ReceivedCharacter, KeyboardInput};
use events::ElementState::{Pressed, Released};
use events::MouseButton::{LeftMouseButton, RightMouseButton};
use events;

pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};

mod monitor;
mod event;

#[cfg(feature = "headless")]
mod headless;

static mut shift_pressed: bool = false;
static mut ctrl_pressed: bool = false;
static mut win_pressed: bool = false;
static mut alt_pressed: bool = false;

static DELEGATE_NAME: &'static [u8] = b"glutin_window_delegate\0";
static DELEGATE_THIS_IVAR: &'static [u8] = b"glutin_this";

struct InternalState {
    is_closed: AtomicBool,
}

impl InternalState {
    fn new() -> InternalState {
        InternalState {
            is_closed: AtomicBool::new(false),
        }
    }
}

pub struct Window {
    view: id,
    window: id,
    context: id,
    state: Box<InternalState>,
}

#[cfg(feature = "window")]
impl Window {
    pub fn new(builder: WindowBuilder) -> Result<Window, CreationError> {
        if builder.sharing.is_some() {
            unimplemented!()
        }

        Window::new_impl(builder.dimensions, builder.title.as_slice(), builder.monitor, builder.vsync, true)
    }
}

extern fn window_should_close(this: id, _: id) -> id {
    unsafe {
        let mut stored_value = ptr::null_mut();
        object_getInstanceVariable(this, DELEGATE_THIS_IVAR.as_ptr() as *const i8, &mut stored_value);
        let state = stored_value as *mut InternalState;
        (*state).is_closed.store(true, Relaxed);
    }
    0
}

impl Window {
    fn new_impl(dimensions: Option<(uint, uint)>, title: &str, monitor: Option<MonitorID>,
                vsync: bool, visible: bool) -> Result<Window, CreationError> {
        let app = match Window::create_app() {
            Some(app) => app,
            None      => { return Err(OsError(format!("Couldn't create NSApplication"))); },
        };
        let window = match Window::create_window(dimensions.unwrap_or((800, 600)), title, monitor) {
            Some(window) => window,
            None         => { return Err(OsError(format!("Couldn't create NSWindow"))); },
        };
        let view = match Window::create_view(window) {
            Some(view) => view,
            None       => { return Err(OsError(format!("Couldn't create NSView"))); },
        };

        let context = match Window::create_context(view, vsync) {
            Some(context) => context,
            None          => { return Err(OsError(format!("Couldn't create OpenGL context"))); },
        };

        unsafe {
            app.activateIgnoringOtherApps_(true);
            window.makeKeyAndOrderFront_(nil);
        }

        let window = Window {
            view: view,
            window: window,
            context: context,
            state: box InternalState::new(),
        };

        // Set up the window delegate to receive events
        let ptr_size = mem::size_of::<libc::intptr_t>() as u64;
        let ns_object = class("NSObject");

        unsafe {
            // Create a delegate class, add callback methods and store InternalState as user data.
            let delegate = objc_allocateClassPair(ns_object, DELEGATE_NAME.as_ptr() as *const i8, 0);
            class_addMethod(delegate, selector("windowShouldClose:"), window_should_close, "B@:@".to_c_str().as_ptr());
            class_addIvar(delegate, DELEGATE_THIS_IVAR.as_ptr() as *const i8, ptr_size, 3, "?".to_c_str().as_ptr());
            objc_registerClassPair(delegate);

            let del_obj = msg_send()(delegate, selector("alloc"));
            let del_obj: id = msg_send()(del_obj, selector("init"));
            object_setInstanceVariable(del_obj, DELEGATE_THIS_IVAR.as_ptr() as *const i8,
                                        &*window.state as *const InternalState as *mut libc::c_void);
            let _: id = msg_send()(window.window, selector("setDelegate:"), del_obj);
        }

        Ok(window)
    }

    fn create_app() -> Option<id> {
        unsafe {
            let app = NSApp();
            if app == nil {
                None
            } else {
                app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
                app.finishLaunching();
                Some(app)
            }
        }
    }

    fn create_window(dimensions: (uint, uint), title: &str, monitor: Option<MonitorID>) -> Option<id> {
        unsafe {
            let scr_frame = match monitor {
                Some(_) => {
                    let screen = NSScreen::mainScreen(nil);
                    NSScreen::frame(screen)
                }
                None    => {
                    let (width, height) = dimensions;
                    NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64))
                }
            };

             let masks = match monitor {
                Some(_) => NSBorderlessWindowMask as NSUInteger,
                None    => NSTitledWindowMask as NSUInteger |
                           NSClosableWindowMask as NSUInteger |
                           NSMiniaturizableWindowMask as NSUInteger |
                           NSResizableWindowMask as NSUInteger,
            };

            let window = NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
                scr_frame,
                masks,
                NSBackingStoreBuffered,
                false,
            );

            if window == nil {
                None
            } else {
                let title = NSString::alloc(nil).init_str(title);
                window.setTitle_(title);
                window.setAcceptsMouseMovedEvents_(true);
                if monitor.is_some() {
                    window.setLevel_(NSMainMenuWindowLevel as i64 + 1);
                }
                else {
                    window.center();
                }
                Some(window)
            }
        }
    }

    fn create_view(window: id) -> Option<id> {
        unsafe {
            let view = NSView::alloc(nil).init();
            if view == nil {
                None
            } else {
                view.setWantsBestResolutionOpenGLSurface_(true);
                window.setContentView_(view);
                Some(view)
            }
        }
    }

    fn create_context(view: id, vsync: bool) -> Option<id> {
        unsafe {
            let attributes = [
                NSOpenGLPFADoubleBuffer as uint,
                NSOpenGLPFAClosestPolicy as uint,
                NSOpenGLPFAColorSize as uint, 24,
                NSOpenGLPFAAlphaSize as uint, 8,
                NSOpenGLPFADepthSize as uint, 24,
                NSOpenGLPFAStencilSize as uint, 8,
                0
            ];

            let pixelformat = NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(&attributes);
            if pixelformat == nil {
                return None;
            }

            let context = NSOpenGLContext::alloc(nil).initWithFormat_shareContext_(pixelformat, nil);
            if context == nil {
                None
            } else {
                context.setView_(view);
                if vsync {
                    let value = 1;
                    context.setValues_forParameter_(&value, NSOpenGLCPSwapInterval);
                }
                Some(context)
            }
        }
    }

    pub fn is_closed(&self) -> bool {
        self.state.is_closed.load(Relaxed)
    }

    pub fn set_title(&self, title: &str) {
        unsafe {
            let title = NSString::alloc(nil).init_str(title);
            self.window.setTitle_(title);
        }
    }

    pub fn show(&self) {
    }

    pub fn hide(&self) {
    }

    pub fn get_position(&self) -> Option<(int, int)> {
        unimplemented!()
    }

    pub fn set_position(&self, _x: int, _y: int) {
        unimplemented!()
    }

    pub fn get_inner_size(&self) -> Option<(uint, uint)> {
        let rect = unsafe { NSView::frame(self.view) };
        Some((rect.size.width as uint, rect.size.height as uint))
    }

    pub fn get_outer_size(&self) -> Option<(uint, uint)> {
        unimplemented!()
    }

    pub fn set_inner_size(&self, _x: uint, _y: uint) {
        unimplemented!()
    }

    pub fn poll_events(&self) -> Vec<Event> {
        let mut events = Vec::new();

        loop {
            unsafe {
                let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
                    NSAnyEventMask as u64,
                    NSDate::distantPast(nil),
                    NSDefaultRunLoopMode,
                    true);
                if event == nil { break; }
                NSApp().sendEvent_(event);

                match event.get_type() {
                    NSLeftMouseDown         => { events.push(MouseInput(Pressed, LeftMouseButton)); },
                    NSLeftMouseUp           => { events.push(MouseInput(Released, LeftMouseButton)); },
                    NSRightMouseDown        => { events.push(MouseInput(Pressed, RightMouseButton)); },
                    NSRightMouseUp          => { events.push(MouseInput(Released, RightMouseButton)); },
                    NSMouseMoved            => {
                        let window_point = event.locationInWindow();
                        let view_point = self.view.convertPoint_fromView_(window_point, nil);
                        events.push(MouseMoved((view_point.x as int, view_point.y as int)));
                    },
                    NSKeyDown               => {
                        let received_str = CString::new(event.characters().UTF8String(), false);
                        for received_char in received_str.as_str().unwrap().chars() {
                            if received_char.is_ascii() {
                                events.push(ReceivedCharacter(received_char));
                            }
                        }

                        let vkey =  event::vkeycode_to_element(event.keycode());
                        events.push(KeyboardInput(Pressed, event.keycode() as u8, vkey));
                    },
                    NSKeyUp                 => {
                        let vkey =  event::vkeycode_to_element(event.keycode());
                        events.push(KeyboardInput(Released, event.keycode() as u8, vkey));
                    },
                    NSFlagsChanged          => {
                        let shift_modifier = Window::modifier_event(event, appkit::NSShiftKeyMask as u64, events::VirtualKeyCode::LShift, shift_pressed);
                        if shift_modifier.is_some() {
                            shift_pressed = !shift_pressed;
                            events.push(shift_modifier.unwrap());
                        }
                        let ctrl_modifier = Window::modifier_event(event, appkit::NSControlKeyMask as u64, events::VirtualKeyCode::LControl, ctrl_pressed);
                        if ctrl_modifier.is_some() {
                            ctrl_pressed = !ctrl_pressed;
                            events.push(ctrl_modifier.unwrap());
                        }
                        let win_modifier = Window::modifier_event(event, appkit::NSCommandKeyMask as u64, events::VirtualKeyCode::LWin, win_pressed);
                        if win_modifier.is_some() {
                            win_pressed = !win_pressed;
                            events.push(win_modifier.unwrap());
                        }
                        let alt_modifier = Window::modifier_event(event, appkit::NSAlternateKeyMask as u64, events::VirtualKeyCode::LAlt, alt_pressed);
                        if alt_modifier.is_some() {
                            alt_pressed = !alt_pressed;
                            events.push(alt_modifier.unwrap());
                        }
                    },
                    NSScrollWheel           => { },
                    NSOtherMouseDown        => { },
                    NSOtherMouseUp          => { },
                    NSOtherMouseDragged     => { },
                    _                       => { },
                }
            }
        }
        events
    }

    unsafe fn modifier_event(event: id, keymask: u64, key: events::VirtualKeyCode, key_pressed: bool) -> Option<Event> {
        if !key_pressed && Window::modifier_key_pressed(event, keymask) {
            return Some(KeyboardInput(Pressed, event.keycode() as u8, Some(key)));
        }
        else if key_pressed && !Window::modifier_key_pressed(event, keymask) {
            return Some(KeyboardInput(Released, event.keycode() as u8, Some(key)));
        }

        return None;
    }

    unsafe fn modifier_key_pressed(event: id, modifier: u64) -> bool {
        event.modifierFlags() & modifier != 0
    }

    pub fn wait_events(&self) -> Vec<Event> {
        unsafe {
            let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
                NSAnyEventMask as u64,
                NSDate::distantFuture(nil),
                NSDefaultRunLoopMode,
                false);
            NSApp().sendEvent_(event);

            self.poll_events()
        }
    }

    pub unsafe fn make_current(&self) {
        self.context.makeCurrentContext();
    }

    pub fn get_proc_address(&self, _addr: &str) -> *const () {
        let symbol_name: CFString = from_str(_addr).unwrap();
        let framework_name: CFString = from_str("com.apple.opengl").unwrap();
        let framework = unsafe {
            CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef())
        };
        let symbol = unsafe {
            CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef())
        };
        symbol as *const ()
    }

    pub fn swap_buffers(&self) {
        unsafe { self.context.flushBuffer(); }
    }

    pub fn platform_display(&self) -> *mut libc::c_void {
        unimplemented!()
    }
}
<|endoftext|>