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

use std::{cmp, ptr, usize};
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::ffi::CString;
use std::sync::Arc;
use std::time::Duration;

use libc::{c_char, c_int};
use grpc_sys::{self, GprTimespec, GrpcChannel, GrpcChannelArgs};

use CallOption;
use call::{Call, Method};
use credentials::ChannelCredentials;
use cq::CompletionQueue;
use env::Environment;

// hack: add a '\0' to be compatible with c string without extra allocation.
const OPT_DEFAULT_AUTHORITY: &'static [u8] = b"grpc.default_authority\0";
const OPT_MAX_CONCURRENT_STREAMS: &'static [u8] = b"grpc.max_concurrent_streams\0";
const OPT_MAX_RECEIVE_MESSAGE_LENGTH: &'static [u8] = b"grpc.max_receive_message_length\0";
const OPT_MAX_SEND_MESSAGE_LENGTH: &'static [u8] = b"grpc.max_send_message_length\0";
const OPT_MAX_RECONNECT_BACKOFF_MS: &'static [u8] = b"grpc.max_reconnect_backoff_ms\0";
const OPT_INITIAL_RECONNECT_BACKOFF_MS: &'static [u8] = b"grpc.initial_reconnect_backoff_ms\0";
const OPT_HTTP2_INITIAL_SEQUENCE_NUMBER: &'static [u8] = b"grpc.http2.initial_sequence_number\0";
const OPT_SO_REUSE_PORT: &'static [u8] = b"grpc.so_reuseport\0";
const OPT_SSL_TARGET_NAME_OVERRIDE: &'static [u8] = b"grpc.ssl_target_name_override\0";
const OPT_STREAM_INITIAL_WINDOW_SIZE: &'static [u8] = b"grpc.http2.lookahead_bytes\0";
const OPT_TCP_READ_CHUNK_SIZE: &'static [u8] = b"grpc.experimental.tcp_read_chunk_size\0";
const OPT_TCP_MIN_READ_CHUNK_SIZE: &'static [u8] = b"grpc.experimental.tcp_min_read_chunk_size\0";
const OPT_TCP_MAX_READ_CHUNK_SIZE: &'static [u8] = b"grpc.experimental.tcp_max_read_chunk_size\0";
const OPT_HTTP2_WRITE_BUFFER_SIZE: &'static [u8] = b"grpc.http2.write_buffer_size\0";
const PRIMARY_USER_AGENT_STRING: &'static [u8] = b"grpc.primary_user_agent\0";

/// Ref: http://www.grpc.io/docs/guides/wire.html#user-agents
fn format_user_agent_string(agent: &str) -> CString {
    let version = env!("CARGO_PKG_VERSION");
    let trimed_agent = agent.trim();
    let val = if trimed_agent.is_empty() {
        format!("grpc-rust/{}", version)
    } else {
        format!("{} grpc-rust/{}", trimed_agent, version)
    };
    CString::new(val).unwrap()
}

fn dur_to_ms(dur: Duration) -> usize {
    let millis = dur.as_secs() * 1000 + dur.subsec_nanos() as u64 / 1_000_000;
    cmp::min(usize::MAX as u64, millis) as usize
}

enum Options {
    Integer(usize),
    String(CString),
}

/// Channel configuration object.
pub struct ChannelBuilder {
    env: Arc<Environment>,
    options: HashMap<&'static [u8], Options>,
}

impl ChannelBuilder {
    pub fn new(env: Arc<Environment>) -> ChannelBuilder {
        ChannelBuilder {
            env: env,
            options: HashMap::new(),
        }
    }

    /// Default authority to pass if none specified on call construction.
    pub fn default_authority<S: Into<Vec<u8>>>(mut self, authority: S) -> ChannelBuilder {
        let authority = CString::new(authority).unwrap();
        self.options
            .insert(OPT_DEFAULT_AUTHORITY, Options::String(authority));
        self
    }

    /// Maximum number of concurrent incoming streams to allow on a http2 connection.
    pub fn max_concurrent_stream(mut self, num: usize) -> ChannelBuilder {
        self.options
            .insert(OPT_MAX_CONCURRENT_STREAMS, Options::Integer(num));
        self
    }

    /// Maximum message length that the channel can receive. usize::MAX means unlimited.
    pub fn max_receive_message_len(mut self, len: usize) -> ChannelBuilder {
        self.options
            .insert(OPT_MAX_RECEIVE_MESSAGE_LENGTH, Options::Integer(len));
        self
    }

    /// Maximum message length that the channel can send. -1 means unlimited.
    pub fn max_send_message_len(mut self, len: usize) -> ChannelBuilder {
        self.options
            .insert(OPT_MAX_SEND_MESSAGE_LENGTH, Options::Integer(len));
        self
    }

    /// The maximum time between subsequent connection attempts.
    pub fn max_reconnect_backoff(mut self, backoff: Duration) -> ChannelBuilder {
        self.options
            .insert(OPT_MAX_RECONNECT_BACKOFF_MS,
                    Options::Integer(dur_to_ms(backoff)));
        self
    }

    /// The time between the first and second connection attempts.
    pub fn initial_reconnect_backoff(mut self, backoff: Duration) -> ChannelBuilder {
        self.options
            .insert(OPT_INITIAL_RECONNECT_BACKOFF_MS,
                    Options::Integer(dur_to_ms(backoff)));
        self
    }

    /// Initial sequence number for http2 transports.
    pub fn https_initial_seq_number(mut self, number: usize) -> ChannelBuilder {
        self.options
            .insert(OPT_HTTP2_INITIAL_SEQUENCE_NUMBER, Options::Integer(number));
        self
    }

    /// Amount to read ahead on individual streams. Defaults to 64kb, larger
    /// values can help throughput on high-latency connections.
    pub fn stream_initial_window_size(mut self, window_size: usize) -> ChannelBuilder {
        self.options
            .insert(OPT_STREAM_INITIAL_WINDOW_SIZE,
                    Options::Integer(window_size));
        self
    }

    /// Primary user agent: goes at the start of the user-agent metadata sent on each request.
    pub fn primary_user_agent(mut self, agent: &str) -> ChannelBuilder {
        let agent_string = format_user_agent_string(agent);
        self.options
            .insert(PRIMARY_USER_AGENT_STRING, Options::String(agent_string));
        self
    }

    /// If enable, allow the use of SO_REUSEPORT if it's available (default true).
    pub fn reuse_port(mut self, reuse: bool) -> ChannelBuilder {
        let opt = if reuse { 1 } else { 0 };
        self.options
            .insert(OPT_SO_REUSE_PORT, Options::Integer(opt));
        self
    }

    /// The caller of the secure_channel_create functions may override the target name used for SSL
    /// host name checking using this channel argument. This *should* be used for testing only.
    pub fn override_ssl_target<S: Into<Vec<u8>>>(mut self, target: S) -> ChannelBuilder {
        let target = CString::new(target).unwrap();
        self.options
            .insert(OPT_SSL_TARGET_NAME_OVERRIDE, Options::String(target));
        self
    }

    /// How large a slice to try and read from the wire each time.
    pub fn tcp_read_chunk_size(mut self, bytes: usize) -> ChannelBuilder {
        self.options
            .insert(OPT_TCP_READ_CHUNK_SIZE, Options::Integer(bytes));
        self
    }

    /// How minimal large a slice to try and read from the wire each time.
    pub fn tcp_min_read_chunk_size(mut self, bytes: usize) -> ChannelBuilder {
        self.options
            .insert(OPT_TCP_MIN_READ_CHUNK_SIZE, Options::Integer(bytes));
        self
    }

    /// How maximal large a slice to try and read from the wire each time.
    pub fn tcp_max_read_chunk_size(mut self, bytes: usize) -> ChannelBuilder {
        self.options
            .insert(OPT_TCP_MAX_READ_CHUNK_SIZE, Options::Integer(bytes));
        self
    }

    /// How much data are we willing to queue up per stream if
    /// write_buffer_hint is set. This is an upper bound.
    pub fn http2_write_buffer_size(mut self, size: usize) -> ChannelBuilder {
        self.options
            .insert(OPT_HTTP2_WRITE_BUFFER_SIZE, Options::Integer(size));
        self
    }

    /// Build a channel args from the current configuration.
    pub fn build_args(&self) -> ChannelArgs {
        let args = unsafe { grpc_sys::grpcwrap_channel_args_create(self.options.len()) };
        for (i, (k, v)) in self.options.iter().enumerate() {
            let key = k.as_ptr() as *const c_char;
            match *v {
                Options::Integer(val) => unsafe {
                    grpc_sys::grpcwrap_channel_args_set_integer(args, i, key, val as c_int)
                },
                Options::String(ref val) => {
                    unsafe {
                        grpc_sys::grpcwrap_channel_args_set_string(args, i, key, val.as_ptr())
                    }
                }
            }
        }
        ChannelArgs { args: args }
    }

    /// Build an insure connection to the address.
    pub fn connect(self, addr: &str) -> Channel {
        self.connect_with_creds(addr, None)
    }

    fn connect_with_creds(mut self, addr: &str, creds: Option<ChannelCredentials>) -> Channel {
        let addr = CString::new(addr).unwrap();
        if let Entry::Vacant(e) = self.options.entry(PRIMARY_USER_AGENT_STRING) {
            e.insert(Options::String(format_user_agent_string("")));
        }
        let args = self.build_args();
        let addr_ptr = addr.as_ptr();
        let channel = unsafe {
            match creds {
                None => {
                    grpc_sys::grpc_insecure_channel_create(addr_ptr, args.args, ptr::null_mut())
                }
                Some(mut creds) => {
                    grpc_sys::grpc_secure_channel_create(creds.as_mut_ptr(),
                                                         addr_ptr,
                                                         args.args,
                                                         ptr::null_mut())
                }
            }
        };

        Channel {
            cq: self.env.pick_cq(),
            inner: Arc::new(ChannelInner {
                                _env: self.env,
                                channel: channel,
                            }),
        }
    }

    pub fn secure_connect(self, addr: &str, creds: ChannelCredentials) -> Channel {
        self.connect_with_creds(addr, Some(creds))
    }
}

pub struct ChannelArgs {
    args: *mut GrpcChannelArgs,
}

impl ChannelArgs {
    pub fn as_ptr(&self) -> *const GrpcChannelArgs {
        self.args
    }
}

impl Drop for ChannelArgs {
    fn drop(&mut self) {
        unsafe { grpc_sys::grpcwrap_channel_args_destroy(self.args) }
    }
}

struct ChannelInner {
    _env: Arc<Environment>,
    channel: *mut GrpcChannel,
}

impl Drop for ChannelInner {
    fn drop(&mut self) {
        unsafe {
            grpc_sys::grpc_channel_destroy(self.channel);
        }
    }
}

/// The Channel struct allows creation of Call objects.
#[derive(Clone)]
pub struct Channel {
    inner: Arc<ChannelInner>,
    cq: Arc<CompletionQueue>,
}

unsafe impl Send for Channel {}
unsafe impl Sync for Channel {}

impl Channel {
    /// Create a call using the method and option.
    pub fn create_call<P, Q>(&self, method: &Method<P, Q>, opt: &CallOption) -> Call {
        let raw_call = unsafe {
            let ch = self.inner.channel;
            let cq = self.cq.as_ptr();
            let method_ptr = method.name.as_ptr();
            let method_len = method.name.len();
            let timeout = opt.get_timeout()
                .map_or_else(GprTimespec::inf_future, GprTimespec::from);
            grpc_sys::grpcwrap_channel_create_call(ch,
                                                   ptr::null_mut(),
                                                   0,
                                                   cq,
                                                   method_ptr as *const _,
                                                   method_len,
                                                   ptr::null(),
                                                   0,
                                                   timeout,
                                                   ptr::null_mut())
        };

        unsafe { Call::from_raw(raw_call) }
    }

    pub fn cq(&self) -> &CompletionQueue {
        self.cq.as_ref()
    }
}
<commit_msg>channel: add more http2 related options (#58)<commit_after>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{cmp, ptr, usize};
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::ffi::CString;
use std::sync::Arc;
use std::time::Duration;

use libc::{c_char, c_int};
use grpc_sys::{self, GprTimespec, GrpcChannel, GrpcChannelArgs};

use CallOption;
use call::{Call, Method};
use credentials::ChannelCredentials;
use cq::CompletionQueue;
use env::Environment;

// hack: add a '\0' to be compatible with c string without extra allocation.
const OPT_DEFAULT_AUTHORITY: &'static [u8] = b"grpc.default_authority\0";
const OPT_MAX_CONCURRENT_STREAMS: &'static [u8] = b"grpc.max_concurrent_streams\0";
const OPT_MAX_RECEIVE_MESSAGE_LENGTH: &'static [u8] = b"grpc.max_receive_message_length\0";
const OPT_MAX_SEND_MESSAGE_LENGTH: &'static [u8] = b"grpc.max_send_message_length\0";
const OPT_MAX_RECONNECT_BACKOFF_MS: &'static [u8] = b"grpc.max_reconnect_backoff_ms\0";
const OPT_INITIAL_RECONNECT_BACKOFF_MS: &'static [u8] = b"grpc.initial_reconnect_backoff_ms\0";
const OPT_HTTP2_INITIAL_SEQUENCE_NUMBER: &'static [u8] = b"grpc.http2.initial_sequence_number\0";
const OPT_SO_REUSE_PORT: &'static [u8] = b"grpc.so_reuseport\0";
const OPT_SSL_TARGET_NAME_OVERRIDE: &'static [u8] = b"grpc.ssl_target_name_override\0";
const OPT_STREAM_INITIAL_WINDOW_SIZE: &'static [u8] = b"grpc.http2.lookahead_bytes\0";
const OPT_TCP_READ_CHUNK_SIZE: &'static [u8] = b"grpc.experimental.tcp_read_chunk_size\0";
const OPT_TCP_MIN_READ_CHUNK_SIZE: &'static [u8] = b"grpc.experimental.tcp_min_read_chunk_size\0";
const OPT_TCP_MAX_READ_CHUNK_SIZE: &'static [u8] = b"grpc.experimental.tcp_max_read_chunk_size\0";
const OPT_HTTP2_WRITE_BUFFER_SIZE: &'static [u8] = b"grpc.http2.write_buffer_size\0";
const OPT_HTTP2_MAX_FRAME_SIZE: &'static [u8] = b"grpc.http2.max_frame_size\0";
const OPT_HTTP2_BDP_PROBE: &'static [u8] = b"grpc.http2.bdp_probe\0";
const PRIMARY_USER_AGENT_STRING: &'static [u8] = b"grpc.primary_user_agent\0";

/// Ref: http://www.grpc.io/docs/guides/wire.html#user-agents
fn format_user_agent_string(agent: &str) -> CString {
    let version = env!("CARGO_PKG_VERSION");
    let trimed_agent = agent.trim();
    let val = if trimed_agent.is_empty() {
        format!("grpc-rust/{}", version)
    } else {
        format!("{} grpc-rust/{}", trimed_agent, version)
    };
    CString::new(val).unwrap()
}

fn dur_to_ms(dur: Duration) -> usize {
    let millis = dur.as_secs() * 1000 + dur.subsec_nanos() as u64 / 1_000_000;
    cmp::min(usize::MAX as u64, millis) as usize
}

enum Options {
    Integer(usize),
    String(CString),
}

/// Channel configuration object.
pub struct ChannelBuilder {
    env: Arc<Environment>,
    options: HashMap<&'static [u8], Options>,
}

impl ChannelBuilder {
    pub fn new(env: Arc<Environment>) -> ChannelBuilder {
        ChannelBuilder {
            env: env,
            options: HashMap::new(),
        }
    }

    /// Default authority to pass if none specified on call construction.
    pub fn default_authority<S: Into<Vec<u8>>>(mut self, authority: S) -> ChannelBuilder {
        let authority = CString::new(authority).unwrap();
        self.options
            .insert(OPT_DEFAULT_AUTHORITY, Options::String(authority));
        self
    }

    /// Maximum number of concurrent incoming streams to allow on a http2 connection.
    pub fn max_concurrent_stream(mut self, num: usize) -> ChannelBuilder {
        self.options
            .insert(OPT_MAX_CONCURRENT_STREAMS, Options::Integer(num));
        self
    }

    /// Maximum message length that the channel can receive. usize::MAX means unlimited.
    pub fn max_receive_message_len(mut self, len: usize) -> ChannelBuilder {
        self.options
            .insert(OPT_MAX_RECEIVE_MESSAGE_LENGTH, Options::Integer(len));
        self
    }

    /// Maximum message length that the channel can send. -1 means unlimited.
    pub fn max_send_message_len(mut self, len: usize) -> ChannelBuilder {
        self.options
            .insert(OPT_MAX_SEND_MESSAGE_LENGTH, Options::Integer(len));
        self
    }

    /// The maximum time between subsequent connection attempts.
    pub fn max_reconnect_backoff(mut self, backoff: Duration) -> ChannelBuilder {
        self.options
            .insert(OPT_MAX_RECONNECT_BACKOFF_MS,
                    Options::Integer(dur_to_ms(backoff)));
        self
    }

    /// The time between the first and second connection attempts.
    pub fn initial_reconnect_backoff(mut self, backoff: Duration) -> ChannelBuilder {
        self.options
            .insert(OPT_INITIAL_RECONNECT_BACKOFF_MS,
                    Options::Integer(dur_to_ms(backoff)));
        self
    }

    /// Initial sequence number for http2 transports.
    pub fn https_initial_seq_number(mut self, number: usize) -> ChannelBuilder {
        self.options
            .insert(OPT_HTTP2_INITIAL_SEQUENCE_NUMBER, Options::Integer(number));
        self
    }

    /// Amount to read ahead on individual streams. Defaults to 64kb, larger
    /// values can help throughput on high-latency connections.
    pub fn stream_initial_window_size(mut self, window_size: usize) -> ChannelBuilder {
        self.options
            .insert(OPT_STREAM_INITIAL_WINDOW_SIZE,
                    Options::Integer(window_size));
        self
    }

    /// Primary user agent: goes at the start of the user-agent metadata sent on each request.
    pub fn primary_user_agent(mut self, agent: &str) -> ChannelBuilder {
        let agent_string = format_user_agent_string(agent);
        self.options
            .insert(PRIMARY_USER_AGENT_STRING, Options::String(agent_string));
        self
    }

    /// If enable, allow the use of SO_REUSEPORT if it's available (default true).
    pub fn reuse_port(mut self, reuse: bool) -> ChannelBuilder {
        let opt = if reuse { 1 } else { 0 };
        self.options
            .insert(OPT_SO_REUSE_PORT, Options::Integer(opt));
        self
    }

    /// The caller of the secure_channel_create functions may override the target name used for SSL
    /// host name checking using this channel argument. This *should* be used for testing only.
    pub fn override_ssl_target<S: Into<Vec<u8>>>(mut self, target: S) -> ChannelBuilder {
        let target = CString::new(target).unwrap();
        self.options
            .insert(OPT_SSL_TARGET_NAME_OVERRIDE, Options::String(target));
        self
    }

    /// How large a slice to try and read from the wire each time.
    pub fn tcp_read_chunk_size(mut self, bytes: usize) -> ChannelBuilder {
        self.options
            .insert(OPT_TCP_READ_CHUNK_SIZE, Options::Integer(bytes));
        self
    }

    /// How minimal large a slice to try and read from the wire each time.
    pub fn tcp_min_read_chunk_size(mut self, bytes: usize) -> ChannelBuilder {
        self.options
            .insert(OPT_TCP_MIN_READ_CHUNK_SIZE, Options::Integer(bytes));
        self
    }

    /// How maximal large a slice to try and read from the wire each time.
    pub fn tcp_max_read_chunk_size(mut self, bytes: usize) -> ChannelBuilder {
        self.options
            .insert(OPT_TCP_MAX_READ_CHUNK_SIZE, Options::Integer(bytes));
        self
    }

    /// How much data are we willing to queue up per stream if
    /// write_buffer_hint is set. This is an upper bound.
    pub fn http2_write_buffer_size(mut self, size: usize) -> ChannelBuilder {
        self.options
            .insert(OPT_HTTP2_WRITE_BUFFER_SIZE, Options::Integer(size));
        self
    }

    /// How big a frame are we willing to receive via HTTP2.
    /// Min 16384, max 16777215.
    /// Larger values give lower CPU usage for large messages, but more head of line
    /// blocking for small messages.
    pub fn http2_max_frame_size(mut self, size: usize) -> ChannelBuilder {
        self.options
            .insert(OPT_HTTP2_MAX_FRAME_SIZE, Options::Integer(size));
        self
    }

    /// Set BDP probing.
    pub fn http2_bdp_probe(mut self, enable: bool) -> ChannelBuilder {
        let enable_int = Options::Integer(if enable { 1 } else { 0 });
        self.options.insert(OPT_HTTP2_BDP_PROBE, enable_int);
        self
    }

    /// Build a channel args from the current configuration.
    pub fn build_args(&self) -> ChannelArgs {
        let args = unsafe { grpc_sys::grpcwrap_channel_args_create(self.options.len()) };
        for (i, (k, v)) in self.options.iter().enumerate() {
            let key = k.as_ptr() as *const c_char;
            match *v {
                Options::Integer(val) => unsafe {
                    grpc_sys::grpcwrap_channel_args_set_integer(args, i, key, val as c_int)
                },
                Options::String(ref val) => {
                    unsafe {
                        grpc_sys::grpcwrap_channel_args_set_string(args, i, key, val.as_ptr())
                    }
                }
            }
        }
        ChannelArgs { args: args }
    }

    /// Build an insure connection to the address.
    pub fn connect(self, addr: &str) -> Channel {
        self.connect_with_creds(addr, None)
    }

    fn connect_with_creds(mut self, addr: &str, creds: Option<ChannelCredentials>) -> Channel {
        let addr = CString::new(addr).unwrap();
        if let Entry::Vacant(e) = self.options.entry(PRIMARY_USER_AGENT_STRING) {
            e.insert(Options::String(format_user_agent_string("")));
        }
        let args = self.build_args();
        let addr_ptr = addr.as_ptr();
        let channel = unsafe {
            match creds {
                None => {
                    grpc_sys::grpc_insecure_channel_create(addr_ptr, args.args, ptr::null_mut())
                }
                Some(mut creds) => {
                    grpc_sys::grpc_secure_channel_create(creds.as_mut_ptr(),
                                                         addr_ptr,
                                                         args.args,
                                                         ptr::null_mut())
                }
            }
        };

        Channel {
            cq: self.env.pick_cq(),
            inner: Arc::new(ChannelInner {
                                _env: self.env,
                                channel: channel,
                            }),
        }
    }

    pub fn secure_connect(self, addr: &str, creds: ChannelCredentials) -> Channel {
        self.connect_with_creds(addr, Some(creds))
    }
}

pub struct ChannelArgs {
    args: *mut GrpcChannelArgs,
}

impl ChannelArgs {
    pub fn as_ptr(&self) -> *const GrpcChannelArgs {
        self.args
    }
}

impl Drop for ChannelArgs {
    fn drop(&mut self) {
        unsafe { grpc_sys::grpcwrap_channel_args_destroy(self.args) }
    }
}

struct ChannelInner {
    _env: Arc<Environment>,
    channel: *mut GrpcChannel,
}

impl Drop for ChannelInner {
    fn drop(&mut self) {
        unsafe {
            grpc_sys::grpc_channel_destroy(self.channel);
        }
    }
}

/// The Channel struct allows creation of Call objects.
#[derive(Clone)]
pub struct Channel {
    inner: Arc<ChannelInner>,
    cq: Arc<CompletionQueue>,
}

unsafe impl Send for Channel {}
unsafe impl Sync for Channel {}

impl Channel {
    /// Create a call using the method and option.
    pub fn create_call<P, Q>(&self, method: &Method<P, Q>, opt: &CallOption) -> Call {
        let raw_call = unsafe {
            let ch = self.inner.channel;
            let cq = self.cq.as_ptr();
            let method_ptr = method.name.as_ptr();
            let method_len = method.name.len();
            let timeout = opt.get_timeout()
                .map_or_else(GprTimespec::inf_future, GprTimespec::from);
            grpc_sys::grpcwrap_channel_create_call(ch,
                                                   ptr::null_mut(),
                                                   0,
                                                   cq,
                                                   method_ptr as *const _,
                                                   method_len,
                                                   ptr::null(),
                                                   0,
                                                   timeout,
                                                   ptr::null_mut())
        };

        unsafe { Call::from_raw(raw_call) }
    }

    pub fn cq(&self) -> &CompletionQueue {
        self.cq.as_ref()
    }
}
<|endoftext|>


<commit_before>use EnumMap;
use Internal;

use core::iter::Enumerate;
use core::marker::PhantomData;
use core::mem::ManuallyDrop;
use core::ptr;
use core::slice;

/// Immutable enum map iterator
///
/// This struct is created by `iter` method or `into_iter` on a reference
/// to `EnumMap`.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = enum_map! { Example::A => 3, _ => 0 };
///     assert_eq!(map[Example::A], 3);
///     for (key, &value) in &map {
///         assert_eq!(value, match key {
///             Example::A => 3,
///             _ => 0,
///         });
///     }
/// }
/// ```
#[derive(Debug)]
pub struct Iter<'a, K, V: 'a> {
    _phantom: PhantomData<fn() -> K>,
    iterator: Enumerate<slice::Iter<'a, V>>,
}

impl<'a, K: Internal<V>, V> Iterator for Iter<'a, K, V> {
    type Item = (K, &'a V);
    fn next(&mut self) -> Option<Self::Item> {
        self.iterator
            .next()
            .map(|(index, item)| (K::from_usize(index), item))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iterator.size_hint()
    }
}

impl<'a, K: Internal<V>, V> DoubleEndedIterator for Iter<'a, K, V> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iterator
            .next_back()
            .map(|(index, item)| (K::from_usize(index), item))
    }
}

impl<'a, K: Internal<V>, V> ExactSizeIterator for Iter<'a, K, V> {}

impl<'a, K: Internal<V>, V> IntoIterator for &'a EnumMap<K, V> {
    type Item = (K, &'a V);
    type IntoIter = Iter<'a, K, V>;
    fn into_iter(self) -> Self::IntoIter {
        Iter {
            _phantom: PhantomData,
            iterator: self.as_slice().iter().enumerate(),
        }
    }
}

/// Mutable map iterator
///
/// This struct is created by `iter_mut` method or `into_iter` on a mutable
/// reference to `EnumMap`.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
///
/// #[derive(Debug, EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = enum_map! { Example::A => 3, _ => 0 };
///     for (_, value) in &mut map {
///         *value += 1;
///     }
///     assert_eq!(map, enum_map! { Example::A => 4, _ => 1 });
/// }
/// ```
#[derive(Debug)]
pub struct IterMut<'a, K, V: 'a> {
    _phantom: PhantomData<fn() -> K>,
    iterator: Enumerate<slice::IterMut<'a, V>>,
}

impl<'a, K: Internal<V>, V> Iterator for IterMut<'a, K, V> {
    type Item = (K, &'a mut V);
    fn next(&mut self) -> Option<Self::Item> {
        self.iterator
            .next()
            .map(|(index, item)| (K::from_usize(index), item))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iterator.size_hint()
    }
}

impl<'a, K: Internal<V>, V> DoubleEndedIterator for IterMut<'a, K, V> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iterator
            .next_back()
            .map(|(index, item)| (K::from_usize(index), item))
    }
}

impl<'a, K: Internal<V>, V> ExactSizeIterator for IterMut<'a, K, V> {}

impl<'a, K: Internal<V>, V> IntoIterator for &'a mut EnumMap<K, V> {
    type Item = (K, &'a mut V);
    type IntoIter = IterMut<'a, K, V>;
    fn into_iter(self) -> Self::IntoIter {
        IterMut {
            _phantom: PhantomData,
            iterator: self.as_mut_slice().iter_mut().enumerate(),
        }
    }
}

/// A map iterator that moves out of map.
///
/// This struct is created by `into_iter` on `EnumMap`.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
///
/// #[derive(Debug, EnumMap)]
/// enum Example {
///     A,
///     B,
/// }
///
/// fn main() {
///     let map = enum_map! { Example::A | Example::B => String::from("123") };
///     for (_, value) in map {
///         assert_eq!(value + "4", "1234");
///     }
/// }
/// ```
pub struct IntoIter<K: Internal<V>, V> {
    map: ManuallyDrop<EnumMap<K, V>>,
    position: usize,
}

impl<K: Internal<V>, V> Iterator for IntoIter<K, V> {
    type Item = (K, V);
    fn next(&mut self) -> Option<(K, V)> {
        let slice = self.map.as_slice();
        if self.position < slice.len() {
            let key = K::from_usize(self.position);
            let result = Some((key, unsafe { ptr::read(&slice[self.position]) }));
            self.position += 1;
            result
        } else {
            None
        }
    }
}

impl<K: Internal<V>, V> Drop for IntoIter<K, V> {
    fn drop(&mut self) {
        for _item in self {}
    }
}

impl<K: Internal<V>, V> IntoIterator for EnumMap<K, V> {
    type Item = (K, V);
    type IntoIter = IntoIter<K, V>;
    fn into_iter(self) -> Self::IntoIter {
        IntoIter {
            map: ManuallyDrop::new(self),
            position: 0,
        }
    }
}
<commit_msg>Implement FusedIterator for enum map iterators<commit_after>use EnumMap;
use Internal;

use core::iter::{Enumerate, FusedIterator};
use core::marker::PhantomData;
use core::mem::ManuallyDrop;
use core::ptr;
use core::slice;

/// Immutable enum map iterator
///
/// This struct is created by `iter` method or `into_iter` on a reference
/// to `EnumMap`.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = enum_map! { Example::A => 3, _ => 0 };
///     assert_eq!(map[Example::A], 3);
///     for (key, &value) in &map {
///         assert_eq!(value, match key {
///             Example::A => 3,
///             _ => 0,
///         });
///     }
/// }
/// ```
#[derive(Debug)]
pub struct Iter<'a, K, V: 'a> {
    _phantom: PhantomData<fn() -> K>,
    iterator: Enumerate<slice::Iter<'a, V>>,
}

impl<'a, K: Internal<V>, V> Iterator for Iter<'a, K, V> {
    type Item = (K, &'a V);
    fn next(&mut self) -> Option<Self::Item> {
        self.iterator
            .next()
            .map(|(index, item)| (K::from_usize(index), item))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iterator.size_hint()
    }
}

impl<'a, K: Internal<V>, V> DoubleEndedIterator for Iter<'a, K, V> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iterator
            .next_back()
            .map(|(index, item)| (K::from_usize(index), item))
    }
}

impl<'a, K: Internal<V>, V> ExactSizeIterator for Iter<'a, K, V> {}

impl<'a, K: Internal<V>, V> FusedIterator for Iter<'a, K, V> {}

impl<'a, K: Internal<V>, V> IntoIterator for &'a EnumMap<K, V> {
    type Item = (K, &'a V);
    type IntoIter = Iter<'a, K, V>;
    fn into_iter(self) -> Self::IntoIter {
        Iter {
            _phantom: PhantomData,
            iterator: self.as_slice().iter().enumerate(),
        }
    }
}

/// Mutable map iterator
///
/// This struct is created by `iter_mut` method or `into_iter` on a mutable
/// reference to `EnumMap`.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
///
/// #[derive(Debug, EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = enum_map! { Example::A => 3, _ => 0 };
///     for (_, value) in &mut map {
///         *value += 1;
///     }
///     assert_eq!(map, enum_map! { Example::A => 4, _ => 1 });
/// }
/// ```
#[derive(Debug)]
pub struct IterMut<'a, K, V: 'a> {
    _phantom: PhantomData<fn() -> K>,
    iterator: Enumerate<slice::IterMut<'a, V>>,
}

impl<'a, K: Internal<V>, V> Iterator for IterMut<'a, K, V> {
    type Item = (K, &'a mut V);
    fn next(&mut self) -> Option<Self::Item> {
        self.iterator
            .next()
            .map(|(index, item)| (K::from_usize(index), item))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iterator.size_hint()
    }
}

impl<'a, K: Internal<V>, V> DoubleEndedIterator for IterMut<'a, K, V> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iterator
            .next_back()
            .map(|(index, item)| (K::from_usize(index), item))
    }
}

impl<'a, K: Internal<V>, V> ExactSizeIterator for IterMut<'a, K, V> {}

impl<'a, K: Internal<V>, V> FusedIterator for IterMut<'a, K, V> {}

impl<'a, K: Internal<V>, V> IntoIterator for &'a mut EnumMap<K, V> {
    type Item = (K, &'a mut V);
    type IntoIter = IterMut<'a, K, V>;
    fn into_iter(self) -> Self::IntoIter {
        IterMut {
            _phantom: PhantomData,
            iterator: self.as_mut_slice().iter_mut().enumerate(),
        }
    }
}

/// A map iterator that moves out of map.
///
/// This struct is created by `into_iter` on `EnumMap`.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
///
/// #[derive(Debug, EnumMap)]
/// enum Example {
///     A,
///     B,
/// }
///
/// fn main() {
///     let map = enum_map! { Example::A | Example::B => String::from("123") };
///     for (_, value) in map {
///         assert_eq!(value + "4", "1234");
///     }
/// }
/// ```
pub struct IntoIter<K: Internal<V>, V> {
    map: ManuallyDrop<EnumMap<K, V>>,
    position: usize,
}

impl<K: Internal<V>, V> Iterator for IntoIter<K, V> {
    type Item = (K, V);
    fn next(&mut self) -> Option<(K, V)> {
        let slice = self.map.as_slice();
        if self.position < slice.len() {
            let key = K::from_usize(self.position);
            let result = Some((key, unsafe { ptr::read(&slice[self.position]) }));
            self.position += 1;
            result
        } else {
            None
        }
    }
}

impl<K: Internal<V>, V> FusedIterator for IntoIter<K, V> {}

impl<K: Internal<V>, V> Drop for IntoIter<K, V> {
    fn drop(&mut self) {
        for _item in self {}
    }
}

impl<K: Internal<V>, V> IntoIterator for EnumMap<K, V> {
    type Item = (K, V);
    type IntoIter = IntoIter<K, V>;
    fn into_iter(self) -> Self::IntoIter {
        IntoIter {
            map: ManuallyDrop::new(self),
            position: 0,
        }
    }
}
<|endoftext|>


<commit_before>///! State machine composition macros

#[macro_export]
macro_rules! rotor_compose_state_machines {
    ($name: ident <$context:ty>  { $( $subname:ident($subtype:ty), )* }) => {
        enum $name {
            $( $subname($subtype) ),*
        }

        $(
            impl $crate::context::AsyncAddMachine<$subtype> for $context {
                fn async_add_machine(&mut self, m: $subtype) -> Result<(), $subtype> {
                    match self.async_add_machine($name::$subname(m)) {
                        Err($name::$subname(m)) => Err(m),
                        Err(_) => unreachable!(),
                        Ok(()) => Ok(())
                    }
                }
            }
        )*

        impl $crate::EventMachine<Context> for $name {
            fn ready(self, events: ::mio::EventSet, context: &mut Context)
                -> Option<Self>
            {
                match self {
                    $(
                        $name::$subname(m) => m.ready(events, context)
                                               .map($name::$subname),
                    )*
                }
            }
            fn register<H: ::mio::Handler>(&mut self,
                tok: ::mio::Token, eloop: &mut ::mio::EventLoop<H>)
                -> Result<(), ::std::io::Error>
            {
                match self {
                    $(
                        &mut $name::$subname(ref mut m)
                        => m.register(tok, eloop),
                    )*
                }
            }
        }
    };
}
<commit_msg>Fix composition macros<commit_after>///! State machine composition macros

#[macro_export]
macro_rules! rotor_compose_state_machines {
    (STRUCT_REPEAT $name:ident $context:ty [ $($name1:ident/$type1:ty)* ]
                               [ $($name2:ident/$type2:ty)* ]) => {
        mod scope {
            $(
                rotor_compose_state_machines!(SCOPE_STRUCT $name $name1);
            )*
        }
        rotor_compose_state_machines!(SCOPE_WRAPPER
            $name $context [ $({$name1 $type1})* ] [ $($name2/$type2)* ]);
    };
    (SCOPE_STRUCT $name:ident $cursub:ident) => {
        pub struct $cursub<'a, S: 'a>(pub &'a mut S);
    };
    (SCOPE_WRAPPER $name:ident $context:ty [ { $cursub:ident $curtyp:ty } ]
                               [ $($subname:ident / $subtype:ty)* ]) => {
        rotor_compose_state_machines!(SCOPE_IMPL
            $name $context { $cursub $curtyp } $($subname/$subtype)*);
    };
    (SCOPE_WRAPPER $name:ident $context:ty
        [ { $firstsub:ident $firsttyp:ty } $( { $tail:ident $tailtyp:ty } )* ]
        [ $($name2:ident/$type2:ty)* ]) => {
        rotor_compose_state_machines!(SCOPE_IMPL
            $name $context { $firstsub $firsttyp } $($name2/$type2)*);
        rotor_compose_state_machines!(SCOPE_WRAPPER
            $name $context [ $({ $tail $tailtyp })* ] [ $($name2/$type2)* ]);
    };
    (SCOPE_IMPL $name:ident $context:ty { $cursub:ident $curtyp:ty }
        $($subname:ident/$subtype:ty)*) => {
        impl<'a, S> $crate::Scope<$curtyp,
                    <$curtyp as $crate::EventMachine<$context>>::Timeout>
            for scope::$cursub<'a, S>
            where S: $crate::Scope<
                $name<$($subtype),*>,
                $name<$(<$subtype as $crate::EventMachine<$context>>::Timeout),*>> + 'a,
        {
            fn async_add_machine(&mut self, m: $curtyp) -> Result<(), $curtyp> {
                self.0.async_add_machine($name::$cursub(m))
                .map_err(|x| if let $name::$cursub(c) = x {
                    c
                } else {
                    unreachable!();
                })
            }
            fn add_timeout_ms(&mut self, delay: u64,
                t: <$curtyp as $crate::EventMachine<$context>>::Timeout)
                -> Result<::mio::Timeout, ::mio::TimerError>
            {
                self.0.add_timeout_ms(delay, $name::$cursub(t))
            }
            fn clear_timeout(&mut self, timeout: ::mio::Timeout) -> bool {
                self.0.clear_timeout(timeout)
            }
            fn register<E: ?Sized>(&mut self, io: &E,
                interest: ::mio::EventSet, opt: ::mio::PollOpt)
                -> Result<(), ::std::io::Error>
                where E: ::mio::Evented
            {
                self.0.register(io, interest, opt)
            }
        }
    };
    ($name: ident <$context:ty>  { $( $subname:ident($subtype:ty), )* }) => {
        pub enum $name<$($subname),*> {
            $( $subname($subname) ),*
        }

        rotor_compose_state_machines!(STRUCT_REPEAT $name $context
            [ $($subname / $subtype)* ] [ $($subname / $subtype)* ]);

        impl $crate::EventMachine<$context> for $name<$($subtype),*> {
            type Timeout = $name<$(
                <$subtype as rotor::EventMachine<$context>>::Timeout
            ),*>;
            fn ready<'x, S>(self, events: ::mio::EventSet,
                context: &mut $context, scope: &mut S)
                -> Option<Self>
                where S: 'x, S: $crate::Scope<Self, Self::Timeout>
            {
                match self {
                    $(
                        $name::$subname(m)
                        => m.ready(events, context, &mut scope::$subname(scope))
                                               .map($name::$subname),
                    )*
                }
            }
            fn register<'x, S>(&mut self, scope: &mut S)
                -> Result<(), ::std::io::Error>
                where S: 'x, S: $crate::Scope<Self, Self::Timeout>
            {
                match self {
                    $(
                        &mut $name::$subname(ref mut m)
                        => m.register(&mut scope::$subname(scope)),
                    )*
                }
            }
        }
    };
}
<|endoftext|>


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

use std::fmt;
use std::io;

use std::fmt::{Display, Formatter};
use std::fs::File;
use std::io::Write;
use std::sync::{Arc, Mutex};

use config::ApplicationConfig;

use svc_table::{Service, SharedServiceTableRef};

use net::raw::ether::MacAddr;

use scanner::ScanResult;

use timer::Timer;

use utils;

use utils::RuntimeError;

use utils::logger::{BoxedLogger, Severity};

use native_tls::TlsConnector;

use uuid::Uuid;

/// Arrow service connection state.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum ConnectionState {
    Connected,
    Disconnected,
    Unauthorized,
}

impl ConnectionState {
    /// Get string representation of the state.
    fn as_str(&self) -> &str {
        match self {
            &ConnectionState::Connected    => "connected",
            &ConnectionState::Disconnected => "disconnected",
            &ConnectionState::Unauthorized => "unauthorized",
        }
    }
}

impl Display for ConnectionState {
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}", self.as_str())
    }
}

/// Internal data of the application context.
struct ApplicationContextData {
    logger:      BoxedLogger,
    timer:       Timer,
    config:      ApplicationConfig,
    scanning:    bool,
    scan_result: ScanResult,
    conn_state:  ConnectionState,
}

impl ApplicationContextData {
    /// Take a given application config and create application context data.
    fn new(config: ApplicationConfig) -> ApplicationContextData {
        let timer = Timer::new(config.get_logger());

        ApplicationContextData {
            logger:      config.get_logger(),
            timer:       timer,
            config:      config,
            scanning:    false,
            scan_result: ScanResult::new(),
            conn_state:  ConnectionState::Disconnected,
        }
    }

    /// Get address of the remote Arrow Service.
    pub fn get_arrow_service_address(&self) -> String {
        self.config.get_arrow_service_address()
            .to_string()
    }

    /// Get Arrow Client UUID.
    fn get_arrow_uuid(&self) -> Uuid {
        self.config.get_uuid()
    }

    /// Get Arrow Client password.
    fn get_arrow_password(&self) -> Uuid {
        self.config.get_password()
    }

    /// Get Arrow Client MAC address.
    fn get_arrow_mac_address(&self) -> MacAddr {
        self.config.get_mac_address()
    }

    /// Get network discovery settings.
    pub fn get_discovery(&self) -> bool {
        self.config.get_discovery()
    }

    /// Check if the application is in the diagnostic mode.
    fn get_diagnostic_mode(&self) -> bool {
        self.config.get_diagnostic_mode()
    }

    /// Get path to a file containing RTSP paths for the network scanner.
    fn get_rtsp_paths_file(&self) -> String {
        self.config.get_rtsp_paths_file()
            .to_string()
    }

    /// Get path to a file containing MJPEG paths for the network scanner.
    fn get_mjpeg_paths_file(&self) -> String {
        self.config.get_mjpeg_paths_file()
            .to_string()
    }

    /// Get application logger.
    fn get_logger(&self) -> BoxedLogger {
        self.logger.clone()
    }

    /// Get application-wide instance of the Timer.
    fn get_timer(&self) -> Timer {
        self.timer.clone()
    }

    /// Get TLS connector.
    fn get_tls_connector(&self) -> Result<TlsConnector, RuntimeError> {
        self.config.get_tls_connector()
    }

    /// Set the state of the network scanner thread.
    fn set_scanning(&mut self, scanning: bool) {
        self.scanning = scanning;
    }

    /// Check if the network scanner thread is running right now.
    fn is_scanning(&self) -> bool {
        self.scanning
    }

    /// Get the last scan result.
    fn get_scan_result(&self) -> ScanResult {
        self.scan_result.clone()
    }

    /// Set last scan result.
    fn set_scan_result(&mut self, result: ScanResult) {
        self.scan_result = result;
    }

    /// Get read-only reference to the service table.
    fn get_service_table(&self) -> SharedServiceTableRef {
        self.config.get_service_table()
    }

    /// Update service table. Add all given services into the table and update active services.
    pub fn update_service_table<I>(&mut self, services: I)
        where I: IntoIterator<Item=Service> {
        self.config.update_service_table(services)
    }

    /// Reset service table.
    fn reset_service_table(&mut self) {
        self.config.reset_service_table()
    }

    /// Set connection state.
    fn set_connection_state(&mut self, state: ConnectionState) {
        self.conn_state = state;

        let res = self.save_connection_state();

        utils::result_or_log(
            &mut self.logger,
            Severity::WARN,
            "unable to save current connection state",
            res);
    }

    /// Save connection state into the file.
    fn save_connection_state(&self) -> Result<(), io::Error> {
        let mut file = File::create(self.config.get_connection_state_file())?;

        writeln!(&mut file, "{}", self.conn_state)?;

        Ok(())
    }
}

/// Application context.
#[derive(Clone)]
pub struct ApplicationContext {
    data: Arc<Mutex<ApplicationContextData>>,
}

impl ApplicationContext {
    /// Take a given application config and create a new application context.
    pub fn new(config: ApplicationConfig) -> ApplicationContext {
        ApplicationContext {
            data: Arc::new(Mutex::new(ApplicationContextData::new(config)))
        }
    }

    /// Get address of the remote Arrow Service.
    pub fn get_arrow_service_address(&self) -> String {
        self.data.lock()
            .unwrap()
            .get_arrow_service_address()
    }

    /// Get Arrow Client UUID.
    pub fn get_arrow_uuid(&self) -> Uuid {
        self.data.lock()
            .unwrap()
            .get_arrow_uuid()
    }

    /// Get Arrow Client password.
    pub fn get_arrow_password(&self) -> Uuid {
        self.data.lock()
            .unwrap()
            .get_arrow_password()
    }

    /// Get Arrow Client MAC address.
    pub fn get_arrow_mac_address(&self) -> MacAddr {
        self.data.lock()
            .unwrap()
            .get_arrow_mac_address()
    }

    /// Get network discovery settings.
    pub fn get_discovery(&self) -> bool {
        self.data.lock()
            .unwrap()
            .get_discovery()
    }

    /// Check if the application is in the diagnostic mode.
    pub fn get_diagnostic_mode(&self) -> bool {
        self.data.lock()
            .unwrap()
            .get_diagnostic_mode()
    }

    /// Get path to a file containing RTSP paths for the network scanner.
    pub fn get_rtsp_paths_file(&self) -> String {
        self.data.lock()
            .unwrap()
            .get_rtsp_paths_file()
    }

    /// Get path to a file containing MJPEG paths for the network scanner.
    pub fn get_mjpeg_paths_file(&self) -> String {
        self.data.lock()
            .unwrap()
            .get_mjpeg_paths_file()
    }

    /// Get application logger.
    pub fn get_logger(&self) -> BoxedLogger {
        self.data.lock()
            .unwrap()
            .get_logger()
    }

    /// Get application-wide instance of the Timer.
    pub fn get_timer(&self) -> Timer {
        self.data.lock()
            .unwrap()
            .get_timer()
    }

    /// Get TLS connector.
    pub fn get_tls_connector(&self) -> Result<TlsConnector, RuntimeError> {
        self.data.lock()
            .unwrap()
            .get_tls_connector()
    }

    /// Set the state of the network scanner thread.
    pub fn set_scanning(&mut self, scanning: bool) {
        self.data.lock()
            .unwrap()
            .set_scanning(scanning)
    }

    /// Check if the network scanner thread is running right now.
    pub fn is_scanning(&self) -> bool {
        self.data.lock()
            .unwrap()
            .is_scanning()
    }

    /// Get the last scan result.
    pub fn get_scan_result(&self) -> ScanResult {
        self.data.lock()
            .unwrap()
            .get_scan_result()
    }

    /// Set last scan result.
    pub fn set_scan_result(&mut self, result: ScanResult) {
        self.data.lock()
            .unwrap()
            .set_scan_result(result)
    }

    /// Get read-only reference to the service table.
    pub fn get_service_table(&self) -> SharedServiceTableRef {
        self.data.lock()
            .unwrap()
            .get_service_table()
    }

    /// Update service table. Add all given services into the table and update active services.
    pub fn update_service_table<I>(&mut self, services: I)
        where I: IntoIterator<Item=Service> {
        self.data.lock()
            .unwrap()
            .update_service_table(services)
    }

    /// Reset service table.
    pub fn reset_service_table(&mut self) {
        self.data.lock()
            .unwrap()
            .reset_service_table()
    }

    /// Set connection state.
    pub fn set_connection_state(&mut self, state: ConnectionState) {
        self.data.lock()
            .unwrap()
            .set_connection_state(state)
    }
}
<commit_msg>Remove unnecessary methods<commit_after>// Copyright 2017 click2stream, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::fmt;
use std::io;

use std::fmt::{Display, Formatter};
use std::fs::File;
use std::io::Write;
use std::sync::{Arc, Mutex};

use config::ApplicationConfig;

use svc_table::{Service, SharedServiceTableRef};

use net::raw::ether::MacAddr;

use scanner::ScanResult;

use timer::Timer;

use utils;

use utils::RuntimeError;

use utils::logger::{BoxedLogger, Severity};

use native_tls::TlsConnector;

use uuid::Uuid;

/// Arrow service connection state.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum ConnectionState {
    Connected,
    Disconnected,
    Unauthorized,
}

impl ConnectionState {
    /// Get string representation of the state.
    fn as_str(&self) -> &str {
        match self {
            &ConnectionState::Connected    => "connected",
            &ConnectionState::Disconnected => "disconnected",
            &ConnectionState::Unauthorized => "unauthorized",
        }
    }
}

impl Display for ConnectionState {
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}", self.as_str())
    }
}

/// Internal data of the application context.
struct ApplicationContextData {
    logger:      BoxedLogger,
    timer:       Timer,
    config:      ApplicationConfig,
    scanning:    bool,
    scan_result: ScanResult,
    conn_state:  ConnectionState,
}

impl ApplicationContextData {
    /// Take a given application config and create application context data.
    fn new(config: ApplicationConfig) -> ApplicationContextData {
        let timer = Timer::new(config.get_logger());

        ApplicationContextData {
            logger:      config.get_logger(),
            timer:       timer,
            config:      config,
            scanning:    false,
            scan_result: ScanResult::new(),
            conn_state:  ConnectionState::Disconnected,
        }
    }

    /// Get application config.
    fn get_config(&self) -> &ApplicationConfig {
        &self.config
    }

    /// Get application config.
    fn get_config_mut(&mut self) -> &mut ApplicationConfig {
        &mut self.config
    }

    /// Get application logger.
    fn get_logger(&self) -> BoxedLogger {
        self.logger.clone()
    }

    /// Get application-wide instance of the Timer.
    fn get_timer(&self) -> Timer {
        self.timer.clone()
    }

    /// Set the state of the network scanner thread.
    fn set_scanning(&mut self, scanning: bool) {
        self.scanning = scanning;
    }

    /// Check if the network scanner thread is running right now.
    fn is_scanning(&self) -> bool {
        self.scanning
    }

    /// Get the last scan result.
    fn get_scan_result(&self) -> ScanResult {
        self.scan_result.clone()
    }

    /// Set last scan result.
    fn set_scan_result(&mut self, result: ScanResult) {
        self.scan_result = result;
    }

    /// Set connection state.
    fn set_connection_state(&mut self, state: ConnectionState) {
        self.conn_state = state;

        let res = self.save_connection_state();

        utils::result_or_log(
            &mut self.logger,
            Severity::WARN,
            "unable to save current connection state",
            res);
    }

    /// Save connection state into the file.
    fn save_connection_state(&self) -> Result<(), io::Error> {
        let mut file = File::create(self.config.get_connection_state_file())?;

        writeln!(&mut file, "{}", self.conn_state)?;

        Ok(())
    }
}

/// Application context.
#[derive(Clone)]
pub struct ApplicationContext {
    data: Arc<Mutex<ApplicationContextData>>,
}

impl ApplicationContext {
    /// Take a given application config and create a new application context.
    pub fn new(config: ApplicationConfig) -> ApplicationContext {
        ApplicationContext {
            data: Arc::new(Mutex::new(ApplicationContextData::new(config)))
        }
    }

    /// Get address of the remote Arrow Service.
    pub fn get_arrow_service_address(&self) -> String {
        self.data.lock()
            .unwrap()
            .get_config()
            .get_arrow_service_address()
            .to_string()
    }

    /// Get Arrow Client UUID.
    pub fn get_arrow_uuid(&self) -> Uuid {
        self.data.lock()
            .unwrap()
            .get_config()
            .get_uuid()
    }

    /// Get Arrow Client password.
    pub fn get_arrow_password(&self) -> Uuid {
        self.data.lock()
            .unwrap()
            .get_config()
            .get_password()
    }

    /// Get Arrow Client MAC address.
    pub fn get_arrow_mac_address(&self) -> MacAddr {
        self.data.lock()
            .unwrap()
            .get_config()
            .get_mac_address()
    }

    /// Get network discovery settings.
    pub fn get_discovery(&self) -> bool {
        self.data.lock()
            .unwrap()
            .get_config()
            .get_discovery()
    }

    /// Check if the application is in the diagnostic mode.
    pub fn get_diagnostic_mode(&self) -> bool {
        self.data.lock()
            .unwrap()
            .get_config()
            .get_diagnostic_mode()
    }

    /// Get path to a file containing RTSP paths for the network scanner.
    pub fn get_rtsp_paths_file(&self) -> String {
        self.data.lock()
            .unwrap()
            .get_config()
            .get_rtsp_paths_file()
            .to_string()
    }

    /// Get path to a file containing MJPEG paths for the network scanner.
    pub fn get_mjpeg_paths_file(&self) -> String {
        self.data.lock()
            .unwrap()
            .get_config()
            .get_mjpeg_paths_file()
            .to_string()
    }

    /// Get application logger.
    pub fn get_logger(&self) -> BoxedLogger {
        self.data.lock()
            .unwrap()
            .get_logger()
    }

    /// Get application-wide instance of the Timer.
    pub fn get_timer(&self) -> Timer {
        self.data.lock()
            .unwrap()
            .get_timer()
    }

    /// Get TLS connector.
    pub fn get_tls_connector(&self) -> Result<TlsConnector, RuntimeError> {
        self.data.lock()
            .unwrap()
            .get_config()
            .get_tls_connector()
    }

    /// Set the state of the network scanner thread.
    pub fn set_scanning(&mut self, scanning: bool) {
        self.data.lock()
            .unwrap()
            .set_scanning(scanning)
    }

    /// Check if the network scanner thread is running right now.
    pub fn is_scanning(&self) -> bool {
        self.data.lock()
            .unwrap()
            .is_scanning()
    }

    /// Get the last scan result.
    pub fn get_scan_result(&self) -> ScanResult {
        self.data.lock()
            .unwrap()
            .get_scan_result()
    }

    /// Set last scan result.
    pub fn set_scan_result(&mut self, result: ScanResult) {
        self.data.lock()
            .unwrap()
            .set_scan_result(result)
    }

    /// Get read-only reference to the service table.
    pub fn get_service_table(&self) -> SharedServiceTableRef {
        self.data.lock()
            .unwrap()
            .get_config()
            .get_service_table()
    }

    /// Update service table. Add all given services into the table and update active services.
    pub fn update_service_table<I>(&mut self, services: I)
        where I: IntoIterator<Item=Service> {
        self.data.lock()
            .unwrap()
            .get_config_mut()
            .update_service_table(services)
    }

    /// Reset service table.
    pub fn reset_service_table(&mut self) {
        self.data.lock()
            .unwrap()
            .get_config_mut()
            .reset_service_table()
    }

    /// Set connection state.
    pub fn set_connection_state(&mut self, state: ConnectionState) {
        self.data.lock()
            .unwrap()
            .set_connection_state(state)
    }
}
<|endoftext|>


<commit_before>#[cfg(target_arch = "x86_64")]
pub use self::x64::*;

#[cfg(target_arch = "x86_64")]
pub mod x64;

#[cfg(target_arch = "arm")]
pub use self::arm::*;

#[cfg(target_arch = "arm")]
pub mod arm;
<commit_msg>remove usage of arm module<commit_after>#[cfg(target_arch = "x86_64")]
pub use self::x64::*;

#[cfg(target_arch = "x86_64")]
pub mod x64;
<|endoftext|>


<commit_before>//! The initializer module parses arguments and verfies commands are valid
//! The creator module handles creating the muxed directory and project files.
#![allow(experimental)]

use std::io::File;
use std::path::posix::Path;
use editor;
use root;

#[cfg(test)] use std::finally::Finally;
#[cfg(test)] use test_helper::{random_name,cleanup_file};

static TEMPLATE: &'static str = include_str!("creator/template.toml");
static DEFAULT_MUXED_DIR: &'static str = "muxed";

pub fn new(name: &str) {
    let muxed_dir = match root::muxed_dir_exists(&DEFAULT_MUXED_DIR.to_string()) {
        true  => Path::new(format!("{}/.{}/", root::homedir_string(), &DEFAULT_MUXED_DIR.to_string())),
        false => root::create_muxed_dir(&DEFAULT_MUXED_DIR.to_string())
    };

    let path = &Path::new(format!("{}/{}.toml", muxed_dir.display(), name));
    if !path.exists() {
        create_project_file(path);

        match editor::default_editor_set() {
            true  => editor::open_project_file(path),
            false => println!("Default editor is not set. Please define $EDITOR in your ~/.bashrc or similar file.")
        }
    } else {
        println!("Project already exists.");
    }
}

/// Copy and create the new project file from a template.
fn create_project_file(path: &Path) {
    let filename = project_filename(path);
    match File::create(path).write(modified_template(TEMPLATE, filename.as_slice()).as_bytes()) {
        Ok(())  => (),
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }
}

fn modified_template(template: &str, project_name: &str) -> String {
    template.replace("{file_name}", project_name)
}

fn project_filename(path: &Path) -> String {
    String::from_utf8(path.filename().unwrap().to_vec()).unwrap().replace(".toml", "")
}

#[test]
fn populates_template_values() {
    let value = modified_template(TEMPLATE, "muxed project");
    let result = value.as_slice().contains("muxed project");
    assert!(result);
}

#[test]
fn replaces_template_values() {
    let value = modified_template(TEMPLATE, "muxed project");
    let result = !value.as_slice().contains("{file_name}");
    assert!(result);
}

#[test]
fn creates_project_file() {
    let path = &Path::new(format!("{}/.muxed/{}.toml", root::homedir_string(), random_name()));
    create_project_file(path);
    assert!(path.exists());

    cleanup_file(path);
}

#[test]
fn errors_when_creating_project_file() {
    //assert!(false);
}

#[test]
fn create_copies_the_template_file() {
    let path = &Path::new(format!("{}/.muxed/{}.toml", root::homedir_string(), random_name()));
    let filename = project_filename(path);
    create_project_file(path);
    let data = File::open(path).read_to_end().unwrap();
    let template_expectation = modified_template(TEMPLATE, filename.as_slice());
    assert_eq!(data.as_slice(), template_expectation.as_bytes());

    cleanup_file(path);
}

#[test]
fn new_writes_file_to_muxed_dir() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}.toml", root::homedir_string(), name));
    new(name.as_slice());
    assert!(path.exists());

    cleanup_file(path);
}
<commit_msg>Remove unused import. The test using finally was creating lingering test files.<commit_after>//! The initializer module parses arguments and verfies commands are valid
//! The creator module handles creating the muxed directory and project files.
#![allow(experimental)]

use std::io::File;
use std::path::posix::Path;
use editor;
use root;

#[cfg(test)] use test_helper::{random_name,cleanup_file};

static TEMPLATE: &'static str = include_str!("creator/template.toml");
static DEFAULT_MUXED_DIR: &'static str = "muxed";

pub fn new(name: &str) {
    let muxed_dir = match root::muxed_dir_exists(&DEFAULT_MUXED_DIR.to_string()) {
        true  => Path::new(format!("{}/.{}/", root::homedir_string(), &DEFAULT_MUXED_DIR.to_string())),
        false => root::create_muxed_dir(&DEFAULT_MUXED_DIR.to_string())
    };

    let path = &Path::new(format!("{}/{}.toml", muxed_dir.display(), name));
    if !path.exists() {
        create_project_file(path);

        match editor::default_editor_set() {
            true  => editor::open_project_file(path),
            false => println!("Default editor is not set. Please define $EDITOR in your ~/.bashrc or similar file.")
        }
    } else {
        println!("Project already exists.");
    }
}

/// Copy and create the new project file from a template.
fn create_project_file(path: &Path) {
    let filename = project_filename(path);
    match File::create(path).write(modified_template(TEMPLATE, filename.as_slice()).as_bytes()) {
        Ok(())  => (),
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }
}

fn modified_template(template: &str, project_name: &str) -> String {
    template.replace("{file_name}", project_name)
}

fn project_filename(path: &Path) -> String {
    String::from_utf8(path.filename().unwrap().to_vec()).unwrap().replace(".toml", "")
}

#[test]
fn populates_template_values() {
    let value = modified_template(TEMPLATE, "muxed project");
    let result = value.as_slice().contains("muxed project");
    assert!(result);
}

#[test]
fn replaces_template_values() {
    let value = modified_template(TEMPLATE, "muxed project");
    let result = !value.as_slice().contains("{file_name}");
    assert!(result);
}

#[test]
fn creates_project_file() {
    let path = &Path::new(format!("{}/.muxed/{}.toml", root::homedir_string(), random_name()));
    create_project_file(path);
    assert!(path.exists());

    cleanup_file(path);
}

#[test]
fn errors_when_creating_project_file() {
    //assert!(false);
}

#[test]
fn create_copies_the_template_file() {
    let path = &Path::new(format!("{}/.muxed/{}.toml", root::homedir_string(), random_name()));
    let filename = project_filename(path);
    create_project_file(path);
    let data = File::open(path).read_to_end().unwrap();
    let template_expectation = modified_template(TEMPLATE, filename.as_slice());
    assert_eq!(data.as_slice(), template_expectation.as_bytes());

    cleanup_file(path);
}

#[test]
fn new_writes_file_to_muxed_dir() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}.toml", root::homedir_string(), name));
    new(name.as_slice());
    assert!(path.exists());

    cleanup_file(path);
}
<|endoftext|>


<commit_before>//! Implementation of the fast sweeping method.

/// Computes the solution of the eikonal equation in 3D using the fast sweeping algorithm.
///
/// `d` should be initialized to a large value at the unknown nodes.
///
/// `inv_dual_norm(d, [d1, d2, d3], [s1, s2, s3]) -> t` needs to solve the "inverse problem" for the norm:
/// Given values `d_i` at points `-s_i e_i`, find the largest value `t ≤ d` at the origin such that
/// `||p|| ≤ 1`, where `p_i = (s_i (t - d_i))_+` and `||p||` is the __dual__ anisotropic norm.
pub fn fast_sweep_3d<F>(
    d: &mut [f64],
    dim: (usize, usize, usize),
    mut inv_dual_norm: F,
) where
    F: FnMut(f64, [f64; 3], [f64; 3]) -> f64,
{
    let (nx, ny, nz) = dim;
    assert_eq!(nx * ny * nz, d.len());
    let (sx, sy, sz) = (ny * nz, nz, 1);
    // sweep in 8 directions
    for m in 0..8 {
        for p in 1..nx {
            let (i, ip, isign) = if m & 0b001 == 0 {
                (nx - 1 - p, nx - 1 - p + 1, -1.)
            } else {
                (p, p - 1, 1.)
            };
            for q in 1..ny {
                let (j, jp, jsign) = if m & 0b010 == 0 {
                    (ny - 1 - q, ny - 1 - q + 1, -1.)
                } else {
                    (q, q - 1, 1.)
                };

                if m & 0b100 == 0 {
                    let ksign = -1.;
                    for k in (0..nz - 1).rev() {
                        let kp = k + 1;
                        let s = i * sx + j * sy + k * sz;

                        d[s] = inv_dual_norm(
                            d[s],
                            [
                                d[ip * sx + j * sy + k * sz],
                                d[i * sx + jp * sy + k * sz],
                                d[i * sx + j * sy + kp * sz],
                            ],
                            [isign, jsign, ksign],
                        );
                    }
                } else {
                    let ksign = 1.;
                    for k in 1..nz {
                        let kp = k - 1;
                        let s = i * sx + j * sy + k * sz;

                        d[s] = inv_dual_norm(
                            d[s],
                            [
                                d[ip * sx + j * sy + k * sz],
                                d[i * sx + jp * sy + k * sz],
                                d[i * sx + j * sy + kp * sz],
                            ],
                            [isign, jsign, ksign],
                        );
                    }
                }
            }
        }
    }
}

/// Computes the solution of the eikonal equation in 2D using the fast sweeping algorithm.
///
/// `inv_dual_norm(d, [d1, d2], [s1, s2]) -> t` needs to solve the "inverse problem" for the norm:
/// Given values `d_i` at points `-s_i e_i`, find the largest value `t ≤ d` at the origin such that
/// `||p|| ≤ 1`, where `p_i = (s_i (t - d_i))_+` and `||p||` is the __dual__ anisotropic norm.
pub fn fast_sweep_2d<F>(d: &mut [f64], dim: (usize, usize), mut inv_dual_norm: F)
where
    F: FnMut(f64, [f64; 2], [f64; 2]) -> f64,
{
    let (nx, ny) = dim;
    let (sx, _sy) = (ny, 1);
    assert_eq!(nx * ny, d.len());
    // sweep in 4 directions
    // for m in 0..4 {
    //     for p in 1..nx {
    //         let (i, ip, isign) = if m & 0b001 == 0 {
    //             (nx - 1 - p, nx - 1 - p + 1, -1.)
    //         } else {
    //             (p, p - 1, 1.)
    //         };
    //         for q in 1..ny {
    //             let (j, jp, jsign) = if m & 0b010 == 0 {
    //                 (ny - 1 - q, ny - 1 - q + 1, -1.)
    //             } else {
    //                 (q, q - 1, 1.)
    //             };
    //
    //             let s = i * sx + j * sy;
    //
    //             d[s] = inv_dual_norm(
    //                 d[s],
    //                 [d[ip * sx + j * sy], d[i * sx + jp * sy]],
    //                 [isign, jsign],
    //             );
    //         }
    //     }
    // }

    // sweep in 4 directions
    // try to avoid bounds checks and impove cache locality (about 45% faster than the above version)
    for p in 1..nx {
        let (di, dj) = d.split_at_mut(p * sx);
        let di = &di[(p - 1) * sx..][..ny];
        let dj = &mut dj[..ny];
        for q in 1..ny {
            let j = q;
            // Two independent computations (both forward and reversed sweep at once). Instruction
            // level parallelism! Major performance gain.
            dj[j] = inv_dual_norm(dj[j], [di[j], dj[j - 1]], [1., 1.]);
            // rust 1.30 cannot optimize away 2 bounds checks here :(
            let j = ny - 1 - q;
            dj[j] = inv_dual_norm(dj[j], [di[j], dj[j + 1]], [1., -1.]);
        }
        // The following code avoids bounds checks, but cannot exploit instruction level parallelism in the
        // above loop.
        // let mut prev = dj[0];
        // for (dj, di) in (&mut dj[1..]).into_iter().zip(di[1..].into_iter()) {
        //     prev = inv_dual_norm(*dj, [*di, prev], [1., 1.]);
        //     *dj = prev;
        // }
        // let mut prev = dj[ny - 1];
        // for (dj, di) in (&mut dj[..ny-1]).into_iter().zip(di[..ny-1].into_iter()).rev() {
        //     prev = inv_dual_norm(*dj, [*di, prev], [1., -1.]);
        //     *dj = prev;
        // }
    }
    for p in (0..nx - 1).rev() {
        let (dj, di) = d.split_at_mut((p + 1) * sx);
        let di = &di[..ny];
        let dj = &mut dj[p * sx..][..ny];
        for q in 1..ny {
            let j = q;
            dj[j] = inv_dual_norm(dj[j], [di[j], dj[j - 1]], [-1., 1.]);
            let j = ny - 1 - q;
            dj[j] = inv_dual_norm(dj[j], [di[j], dj[j + 1]], [-1., -1.]);
        }
    }
}
<commit_msg>More docs<commit_after>//! The fast sweeping method for the eikonal equation.
//!
//! This is an implementation of the fast sweeping method proposed by Zhao (2004). It solves the
//! eikonal equation
//!
//! ‖∇u‖ = 1,
//!
//! where ‖.‖ denotes a norm, by performing 2^N Gauss-Seidel sweeps in alternating directions. Here
//! N is the dimension. Zhao showed that the accuracy for the Euclidean norm is O(h log h).

/// Computes the solution of the eikonal equation in 3D using the fast sweeping algorithm.
///
/// `d` should be initialized to a large value at the unknown nodes.
///
/// `inv_dual_norm(d, [d1, d2, d3], [s1, s2, s3]) -> t` needs to solve the "inverse problem" for the norm:
/// Given values `d_i` at points `-s_i e_i`, find the largest value `t ≤ d` at the origin such that
/// `||p|| ≤ 1`, where `p_i = (s_i (t - d_i))_+` and `||p||` is the __dual__ anisotropic norm.
pub fn fast_sweep_3d<F>(
    d: &mut [f64],
    dim: (usize, usize, usize),
    mut inv_dual_norm: F,
) where
    F: FnMut(f64, [f64; 3], [f64; 3]) -> f64,
{
    let (nx, ny, nz) = dim;
    assert_eq!(nx * ny * nz, d.len());
    let (sx, sy, sz) = (ny * nz, nz, 1);
    // sweep in 8 directions
    for m in 0..8 {
        for p in 1..nx {
            let (i, ip, isign) = if m & 0b001 == 0 {
                (nx - 1 - p, nx - 1 - p + 1, -1.)
            } else {
                (p, p - 1, 1.)
            };
            for q in 1..ny {
                let (j, jp, jsign) = if m & 0b010 == 0 {
                    (ny - 1 - q, ny - 1 - q + 1, -1.)
                } else {
                    (q, q - 1, 1.)
                };

                if m & 0b100 == 0 {
                    let ksign = -1.;
                    for k in (0..nz - 1).rev() {
                        let kp = k + 1;
                        let s = i * sx + j * sy + k * sz;

                        d[s] = inv_dual_norm(
                            d[s],
                            [
                                d[ip * sx + j * sy + k * sz],
                                d[i * sx + jp * sy + k * sz],
                                d[i * sx + j * sy + kp * sz],
                            ],
                            [isign, jsign, ksign],
                        );
                    }
                } else {
                    let ksign = 1.;
                    for k in 1..nz {
                        let kp = k - 1;
                        let s = i * sx + j * sy + k * sz;

                        d[s] = inv_dual_norm(
                            d[s],
                            [
                                d[ip * sx + j * sy + k * sz],
                                d[i * sx + jp * sy + k * sz],
                                d[i * sx + j * sy + kp * sz],
                            ],
                            [isign, jsign, ksign],
                        );
                    }
                }
            }
        }
    }
}

/// Computes the solution of the eikonal equation in 2D using the fast sweeping algorithm.
///
/// `inv_dual_norm(d, [d1, d2], [s1, s2]) -> t` needs to solve the "inverse problem" for the norm:
/// Given values `d_i` at points `-s_i e_i`, find the largest value `t ≤ d` at the origin such that
/// `||p|| ≤ 1`, where `p_i = (s_i (t - d_i))_+` and `||p||` is the __dual__ anisotropic norm.
pub fn fast_sweep_2d<F>(d: &mut [f64], dim: (usize, usize), mut inv_dual_norm: F)
where
    F: FnMut(f64, [f64; 2], [f64; 2]) -> f64,
{
    let (nx, ny) = dim;
    let (sx, _sy) = (ny, 1);
    assert_eq!(nx * ny, d.len());
    // sweep in 4 directions
    // for m in 0..4 {
    //     for p in 1..nx {
    //         let (i, ip, isign) = if m & 0b001 == 0 {
    //             (nx - 1 - p, nx - 1 - p + 1, -1.)
    //         } else {
    //             (p, p - 1, 1.)
    //         };
    //         for q in 1..ny {
    //             let (j, jp, jsign) = if m & 0b010 == 0 {
    //                 (ny - 1 - q, ny - 1 - q + 1, -1.)
    //             } else {
    //                 (q, q - 1, 1.)
    //             };
    //
    //             let s = i * sx + j * sy;
    //
    //             d[s] = inv_dual_norm(
    //                 d[s],
    //                 [d[ip * sx + j * sy], d[i * sx + jp * sy]],
    //                 [isign, jsign],
    //             );
    //         }
    //     }
    // }

    // sweep in 4 directions
    // try to avoid bounds checks and impove cache locality (about 45% faster than the above version)
    for p in 1..nx {
        let (di, dj) = d.split_at_mut(p * sx);
        let di = &di[(p - 1) * sx..][..ny];
        let dj = &mut dj[..ny];
        for q in 1..ny {
            let j = q;
            // Two independent computations (both forward and reversed sweep at once). Instruction
            // level parallelism! Major performance gain.
            dj[j] = inv_dual_norm(dj[j], [di[j], dj[j - 1]], [1., 1.]);
            // rust 1.30 cannot optimize away 2 bounds checks here :(
            let j = ny - 1 - q;
            dj[j] = inv_dual_norm(dj[j], [di[j], dj[j + 1]], [1., -1.]);
        }
        // The following code avoids bounds checks, but cannot exploit instruction level parallelism in the
        // above loop.
        // let mut prev = dj[0];
        // for (dj, di) in (&mut dj[1..]).into_iter().zip(di[1..].into_iter()) {
        //     prev = inv_dual_norm(*dj, [*di, prev], [1., 1.]);
        //     *dj = prev;
        // }
        // let mut prev = dj[ny - 1];
        // for (dj, di) in (&mut dj[..ny-1]).into_iter().zip(di[..ny-1].into_iter()).rev() {
        //     prev = inv_dual_norm(*dj, [*di, prev], [1., -1.]);
        //     *dj = prev;
        // }
    }
    for p in (0..nx - 1).rev() {
        let (dj, di) = d.split_at_mut((p + 1) * sx);
        let di = &di[..ny];
        let dj = &mut dj[p * sx..][..ny];
        for q in 1..ny {
            let j = q;
            dj[j] = inv_dual_norm(dj[j], [di[j], dj[j - 1]], [-1., 1.]);
            let j = ny - 1 - q;
            dj[j] = inv_dual_norm(dj[j], [di[j], dj[j + 1]], [-1., -1.]);
        }
    }
}
<|endoftext|>


<commit_before>//! Draw ellipse

pub use rectangle::centered;
pub use rectangle::centered_square as circle;

use current::{ Get, Modifier, Set };
use internal;
use triangulation;
use BackEnd;
use Context;
use ImageSize;
use Color;

/// Ellipse border
pub struct Border {
    /// The border color
    pub color: internal::Color,
    /// The border radius
    pub radius: internal::Radius,
}

/// Wrapper trait for `Get<Border>`
pub trait GetBorder: Get<Border> {
    /// Get border
    #[inline(always)]
    fn get_border(&self) -> Border {
        self.get()
    }
}

impl<T: Get<Border>> GetBorder for T {}

/// Wrapper trait for `Set<Border>`
pub trait SetBorder: Set<Border> {
    /// Set border
    #[inline(always)]
    fn set_border(&mut self, val: Border) {
        self.set_mut(val);
    }
}

impl<T: Set<Border>> SetBorder for T {}

/// Maybe border property
pub struct MaybeBorder(pub Option<Border>);

/// Wrapper trait for `Get<MaybeBorder>`
pub trait GetMaybeBorder: Get<MaybeBorder> {
    /// Get maybe border
    #[inline(always)]
    fn get_maybe_border(&self) -> MaybeBorder {
        self.get()
    }
}

impl<T: Get<MaybeBorder>> GetMaybeBorder for T {}

/// Wrapper trait for `Set<MaybeBorder>`
pub trait SetMaybeBorder: Set<MaybeBorder> {
    /// Set maybe border
    #[inline(always)]
    fn set_maybe_border(&mut self, val: MaybeBorder) {
        self.set_mut(val);
    }
}

impl<T: Set<MaybeBorder>> SetMaybeBorder for T {}

/// An ellipse with filled color
#[deriving(Copy)]
pub struct Ellipse {
    /// The ellipse color
    pub color: internal::Color,
    /// The ellipse border
    pub border: Option<Border>,
}

impl Ellipse {
    /// Creates a new ellipse
    pub fn new(color: internal::Color) -> Ellipse {
        Ellipse {
            color: color,
            border: None
        }
    }

    /// Draws the ellipse.
    pub fn draw<B: BackEnd<I>, I: ImageSize>(
        &self,
        rectangle: internal::Rectangle,
        c: &Context,
        back_end: &mut B
    ) {
        if self.color[3] != 0.0 {
            back_end.color(self.color);
            triangulation::with_ellipse_tri_list(
                128,
                c.transform,
                rectangle,
                |vertices| {
                    back_end.tri_list(vertices)
                }
            );
        }

        if let Some(Border { color, radius: border_radius }) = self.border {
            if color[3] == 0.0 { return; }
            back_end.color(self.color);
            triangulation::with_ellipse_border_tri_list(
                128,
                c.transform,
                rectangle,
                border_radius,
                |vertices| back_end.tri_list(vertices)
            );
        }
    }
}

impl Modifier<Ellipse> for Color {
    #[inline(always)]
    fn modify(self, e: &mut Ellipse) {
        let Color(val) = self;
        e.color = val;
    }
}

impl Get<Color> for Ellipse {
    #[inline(always)]
    fn get(&self) -> Color {
        Color(self.color)
    }
}

impl Modifier<Ellipse> for Border {
    #[inline(always)]
    fn modify(self, e: &mut Ellipse) {
        e.border = Some(self);
    }
}

impl Modifier<Ellipse> for MaybeBorder {
    #[inline(always)]
    fn modify(self, e: &mut Ellipse) {
        let MaybeBorder(val) = self;
        e.border = val;
    }
}

impl Get<MaybeBorder> for Ellipse {
    #[inline(always)]
    fn get(&self) -> MaybeBorder {
        MaybeBorder(self.border)
    }
}

#[cfg(test)]
mod test {
    use super::Ellipse;
    use super::Border;
    use Color;
    use current::Set;

    #[test]
    fn test_ellipse() {
        let _ellipse = Ellipse::new([1.0, ..4])
            .set(Color([0.0, ..4]))
            .set(Border { color: [1.0, ..4], radius: 3.0 });
    }
}

<commit_msg>Added border constructor for Ellipse<commit_after>//! Draw ellipse

pub use rectangle::centered;
pub use rectangle::centered_square as circle;

use current::{ Get, Modifier, Set };
use internal;
use triangulation;
use BackEnd;
use Context;
use ImageSize;
use Color;

/// Ellipse border
pub struct Border {
    /// The border color
    pub color: internal::Color,
    /// The border radius
    pub radius: internal::Radius,
}

/// Wrapper trait for `Get<Border>`
pub trait GetBorder: Get<Border> {
    /// Get border
    #[inline(always)]
    fn get_border(&self) -> Border {
        self.get()
    }
}

impl<T: Get<Border>> GetBorder for T {}

/// Wrapper trait for `Set<Border>`
pub trait SetBorder: Set<Border> {
    /// Set border
    #[inline(always)]
    fn set_border(&mut self, val: Border) {
        self.set_mut(val);
    }
}

impl<T: Set<Border>> SetBorder for T {}

/// Maybe border property
pub struct MaybeBorder(pub Option<Border>);

/// Wrapper trait for `Get<MaybeBorder>`
pub trait GetMaybeBorder: Get<MaybeBorder> {
    /// Get maybe border
    #[inline(always)]
    fn get_maybe_border(&self) -> MaybeBorder {
        self.get()
    }
}

impl<T: Get<MaybeBorder>> GetMaybeBorder for T {}

/// Wrapper trait for `Set<MaybeBorder>`
pub trait SetMaybeBorder: Set<MaybeBorder> {
    /// Set maybe border
    #[inline(always)]
    fn set_maybe_border(&mut self, val: MaybeBorder) {
        self.set_mut(val);
    }
}

impl<T: Set<MaybeBorder>> SetMaybeBorder for T {}

/// An ellipse with filled color
#[deriving(Copy)]
pub struct Ellipse {
    /// The ellipse color
    pub color: internal::Color,
    /// The ellipse border
    pub border: Option<Border>,
}

impl Ellipse {
    /// Creates a new ellipse
    pub fn new(color: internal::Color) -> Ellipse {
        Ellipse {
            color: color,
            border: None
        }
    }

    /// Creates a new ellipse border
    pub fn border(
        color: internal::Color,
        radius: internal::Radius
    ) -> Ellipse {
        Ellipse {
            color: [0.0, ..4],
            border: Some(Border {
                    color: color,
                    radius: radius,
                })
        }
    }

    /// Draws the ellipse.
    pub fn draw<B: BackEnd<I>, I: ImageSize>(
        &self,
        rectangle: internal::Rectangle,
        c: &Context,
        back_end: &mut B
    ) {
        if self.color[3] != 0.0 {
            back_end.color(self.color);
            triangulation::with_ellipse_tri_list(
                128,
                c.transform,
                rectangle,
                |vertices| {
                    back_end.tri_list(vertices)
                }
            );
        }

        if let Some(Border { color, radius: border_radius }) = self.border {
            if color[3] == 0.0 { return; }
            back_end.color(self.color);
            triangulation::with_ellipse_border_tri_list(
                128,
                c.transform,
                rectangle,
                border_radius,
                |vertices| back_end.tri_list(vertices)
            );
        }
    }
}

impl Modifier<Ellipse> for Color {
    #[inline(always)]
    fn modify(self, e: &mut Ellipse) {
        let Color(val) = self;
        e.color = val;
    }
}

impl Get<Color> for Ellipse {
    #[inline(always)]
    fn get(&self) -> Color {
        Color(self.color)
    }
}

impl Modifier<Ellipse> for Border {
    #[inline(always)]
    fn modify(self, e: &mut Ellipse) {
        e.border = Some(self);
    }
}

impl Modifier<Ellipse> for MaybeBorder {
    #[inline(always)]
    fn modify(self, e: &mut Ellipse) {
        let MaybeBorder(val) = self;
        e.border = val;
    }
}

impl Get<MaybeBorder> for Ellipse {
    #[inline(always)]
    fn get(&self) -> MaybeBorder {
        MaybeBorder(self.border)
    }
}

#[cfg(test)]
mod test {
    use super::Ellipse;
    use super::Border;
    use Color;
    use current::Set;

    #[test]
    fn test_ellipse() {
        let _ellipse = Ellipse::new([1.0, ..4])
            .set(Color([0.0, ..4]))
            .set(Border { color: [1.0, ..4], radius: 3.0 });
    }
}

<|endoftext|>


<commit_before>//! Starts a timely dataflow execution from configuration information and per-worker logic.

use timely_communication::{initialize, Configuration, Allocator, WorkerGuards};
use dataflow::scopes::{Root, Child, Scope};

/// Executes a single-threaded timely dataflow computation.
///
/// The `example` method takes a closure on a `Scope` which it executes to initialize and run a
/// timely dataflow computation on a single thread. This method is intended for use in examples,
/// rather than programs that may need to run across multiple workers.
///
/// #Examples
/// ```
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// timely::example(|scope| {
///     (0..10).to_stream(scope)
///            .inspect(|x| println!("seen: {:?}", x));
/// }).unwrap();
/// ```
pub fn example<F>(func: F)
where F: Fn(&mut Child<Root<Allocator>, u64>)+Send+Sync+'static {
    initialize(Configuration::Thread, move |allocator| {
        let mut root = Root::new(allocator);
        root.scoped::<u64,_,_>(|x| func(x));
        while root.step() { }
    }).unwrap();
}

/// Executes a timely dataflow from a configuration and per-communicator logic.
///
/// The `execute` method takes a `Configuration` and spins up some number of
/// workers threads, each of which execute the supplied closure to construct and run a timely
/// dataflow computation.
///
/// #Examples
/// ```
/// use timely::dataflow::Scope;
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using three worker threads.
/// timely::execute(timely::Configuration::Process(3), |root| {
///     root.scoped::<u64,_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// }).unwrap();
/// ```
pub fn execute<T:Send+'static, F>(config: Configuration, func: F) -> Result<WorkerGuards<T>,String>
where F: Fn(&mut Root<Allocator>)->T+Send+Sync+'static {
    initialize(config, move |allocator| {
        let mut root = Root::new(allocator);
        let result = func(&mut root);
        while root.step() { }
        result
    })
}

/// Executes a timely dataflow from supplied arguments and per-communicator logic.
///
/// The `execute` method takes arguments (typically `std::env::args()`) and spins up some number of
/// workers threads, each of which execute the supplied closure to construct and run a timely
/// dataflow computation.
///
/// The arguments `execute` currently understands are:
///
/// `-w, --workers`: number of per-process worker threads.
///
/// `-n, --processes`: number of processes involved in the computation.
///
/// `-p, --process`: identity of this process; from 0 to n-1.
///
/// `-h, --hostfile`: a text file whose lines are "hostname:port" in order of process identity.
/// If not specified, `localhost` will be used, with port numbers increasing from 2101 (chosen
/// arbitrarily).
///
/// #Examples
/// ```
/// use timely::dataflow::*;
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using command line parameters
/// timely::execute_from_args(std::env::args(), |root| {
///     root.scoped::<u64,_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// }).unwrap();
/// ```
/// ```ignore
/// host0% cargo run -- -w 2 -n 4 -h hosts.txt -p 0
/// host1% cargo run -- -w 2 -n 4 -h hosts.txt -p 1
/// host2% cargo run -- -w 2 -n 4 -h hosts.txt -p 2
/// host3% cargo run -- -w 2 -n 4 -h hosts.txt -p 3
/// ```
/// ```ignore
/// % cat hosts.txt
/// host0:port
/// host1:port
/// host2:port
/// host3:port
/// ```
pub fn execute_from_args<I, T:Send+'static, F>(iter: I, func: F) -> Result<WorkerGuards<T>,String>
    where I: Iterator<Item=String>,
          F: Fn(&mut Root<Allocator>)->T+Send+Sync+'static, {
    execute(try!(Configuration::from_args(iter)), func)
 }
<commit_msg>screwed up doc example<commit_after>//! Starts a timely dataflow execution from configuration information and per-worker logic.

use timely_communication::{initialize, Configuration, Allocator, WorkerGuards};
use dataflow::scopes::{Root, Child, Scope};

/// Executes a single-threaded timely dataflow computation.
///
/// The `example` method takes a closure on a `Scope` which it executes to initialize and run a
/// timely dataflow computation on a single thread. This method is intended for use in examples,
/// rather than programs that may need to run across multiple workers.
///
/// #Examples
/// ```
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// timely::example(|scope| {
///     (0..10).to_stream(scope)
///            .inspect(|x| println!("seen: {:?}", x));
/// });
/// ```
pub fn example<F>(func: F)
where F: Fn(&mut Child<Root<Allocator>, u64>)+Send+Sync+'static {
    initialize(Configuration::Thread, move |allocator| {
        let mut root = Root::new(allocator);
        root.scoped::<u64,_,_>(|x| func(x));
        while root.step() { }
    }).unwrap();
}

/// Executes a timely dataflow from a configuration and per-communicator logic.
///
/// The `execute` method takes a `Configuration` and spins up some number of
/// workers threads, each of which execute the supplied closure to construct and run a timely
/// dataflow computation.
///
/// #Examples
/// ```
/// use timely::dataflow::Scope;
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using three worker threads.
/// timely::execute(timely::Configuration::Process(3), |root| {
///     root.scoped::<u64,_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// }).unwrap();
/// ```
pub fn execute<T:Send+'static, F>(config: Configuration, func: F) -> Result<WorkerGuards<T>,String>
where F: Fn(&mut Root<Allocator>)->T+Send+Sync+'static {
    initialize(config, move |allocator| {
        let mut root = Root::new(allocator);
        let result = func(&mut root);
        while root.step() { }
        result
    })
}

/// Executes a timely dataflow from supplied arguments and per-communicator logic.
///
/// The `execute` method takes arguments (typically `std::env::args()`) and spins up some number of
/// workers threads, each of which execute the supplied closure to construct and run a timely
/// dataflow computation.
///
/// The arguments `execute` currently understands are:
///
/// `-w, --workers`: number of per-process worker threads.
///
/// `-n, --processes`: number of processes involved in the computation.
///
/// `-p, --process`: identity of this process; from 0 to n-1.
///
/// `-h, --hostfile`: a text file whose lines are "hostname:port" in order of process identity.
/// If not specified, `localhost` will be used, with port numbers increasing from 2101 (chosen
/// arbitrarily).
///
/// #Examples
/// ```
/// use timely::dataflow::*;
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using command line parameters
/// timely::execute_from_args(std::env::args(), |root| {
///     root.scoped::<u64,_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// }).unwrap();
/// ```
/// ```ignore
/// host0% cargo run -- -w 2 -n 4 -h hosts.txt -p 0
/// host1% cargo run -- -w 2 -n 4 -h hosts.txt -p 1
/// host2% cargo run -- -w 2 -n 4 -h hosts.txt -p 2
/// host3% cargo run -- -w 2 -n 4 -h hosts.txt -p 3
/// ```
/// ```ignore
/// % cat hosts.txt
/// host0:port
/// host1:port
/// host2:port
/// host3:port
/// ```
pub fn execute_from_args<I, T:Send+'static, F>(iter: I, func: F) -> Result<WorkerGuards<T>,String>
    where I: Iterator<Item=String>,
          F: Fn(&mut Root<Allocator>)->T+Send+Sync+'static, {
    execute(try!(Configuration::from_args(iter)), func)
 }
<|endoftext|>


<commit_before>use path_parsing::SEP;
use std::str;

struct ExtnameCoords {
  word: bool,
  pred: bool,
  dot: bool,
  start: usize,
  end: usize,
}

impl ExtnameCoords {
  pub fn dec(&mut self) {
    self.start -= 1;
    if !self.word {
      self.end -= 1;
    }
  }
}

pub fn extname(pth: &str) -> &str {
  let path = pth.as_bytes();
  let mut extname = ExtnameCoords {
    word: false,
    pred: false,
    dot: false,
    start: path.len(),
    end: path.len(),
  };

  for &item in path.iter().rev() {
    if (item == b'.' && !extname.dot) || item == SEP {
      if item == SEP && extname.word {
        return ""
      }

      if !extname.pred {
        extname.dec();
      }

      if extname.word {
        extname.dot = true;
      }
    } else {
      if extname.dot {
        extname.pred = true;
        break;
      } else {
        extname.word = true;
      }

      if !extname.pred {
        extname.dec()
      }
    }
  }

  if !extname.dot || !extname.pred {
    return "";
  }

  str::from_utf8(&path[extname.start..extname.end]).unwrap_or("")
}
<commit_msg>minor refactor<commit_after>use path_parsing::SEP;
use std::str;

struct ExtnameCoords {
  word: bool,
  pred: bool,
  dot: bool,
  start: usize,
  end: usize,
}

impl ExtnameCoords {
  pub fn dec(&mut self) {
    self.start -= 1;
    if !self.word {
      self.end -= 1;
    }
  }
}

pub fn extname(pth: &str) -> &str {
  let path = pth.as_bytes();
  let mut extname = ExtnameCoords {
    word: false,
    pred: false,
    dot: false,
    start: path.len(),
    end: path.len(),
  };

  for &item in path.iter().rev() {
    if (item == b'.' && !extname.dot) || item == SEP {
      if item == SEP && extname.word {
        return ""
      }

      if !extname.pred {
        extname.dec();
      }

      if extname.word {
        extname.dot = true;
      }
    } else {
      if extname.dot {
        extname.pred = true;
        break;
      } else {
        extname.word = true;
      }

      if !extname.pred {
        extname.dec()
      }
    }
  }

  if !extname.pred {
    return "";
  }

  str::from_utf8(&path[extname.start..extname.end]).unwrap_or("")
}
<|endoftext|>