<commit_before>use crate::BufGetBytes;
use bytes::Buf;
use bytes::Bytes;
use std::cmp;
use std::io::IoSlice;

/// Zeroes `Buf`
#[derive(Clone, Copy, Default)]
pub struct Zeroes(pub usize);

/// Padding length is up to 256 bytes, so this buffer is practically enough
static ZEROES: &[u8] = &[0; 256];

impl Buf for Zeroes {
    fn remaining(&self) -> usize {
        self.0
    }

    fn chunk(&self) -> &[u8] {
        let len = cmp::min(self.0, ZEROES.len());
        &ZEROES[..len]
    }

    fn chunks_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize {
        let mut c = self.clone();
        let mut n = 0;
        while c.0 != 0 && n != dst.len() {
            let len = c.chunk().len();
            dst[n] = IoSlice::new(&ZEROES[..len]);
            c.0 -= len;
            n += 1;
        }
        n
    }

    fn advance(&mut self, cnt: usize) {
        assert!(cnt <= self.0);
        self.0 -= cnt;
    }
}

impl BufGetBytes for Zeroes {
    fn get_bytes(&mut self, cnt: usize) -> Bytes {
        assert!(cnt <= self.remaining());
        if cnt <= ZEROES.len() {
            self.0 -= cnt;
            Bytes::from_static(&ZEROES[..cnt])
        } else {
            self.take(cnt).get_bytes(cnt)
        }
    }
}

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

    #[test]
    fn buf_small() {
        let mut z = Zeroes(5);
        assert_eq!(&[0, 0, 0, 0, 0], z.chunk());
        assert_eq!(5, z.remaining());
        z.advance(3);
        assert_eq!(2, z.remaining());
        assert_eq!(&[0, 0], z.chunk());
        z.advance(2);
        assert_eq!(0, z.remaining());
    }

    #[test]
    fn buf_large() {
        let mut z = Zeroes(10000);
        assert_eq!(ZEROES, z.chunk());
        z.advance(ZEROES.len());
        assert_eq!(10000 - ZEROES.len(), z.remaining());
    }

    #[test]
    fn buf_bytes_vectored_small() {
        let z = Zeroes(ZEROES.len() + 1);

        let mut s = [IoSlice::new(&[])];
        assert_eq!(1, z.chunks_vectored(&mut s));
        assert_eq!(ZEROES, &*s[0]);

        let mut s = [IoSlice::new(&[]), IoSlice::new(&[])];
        assert_eq!(2, z.chunks_vectored(&mut s));
        assert_eq!(ZEROES, &*s[0]);
        assert_eq!(&[0], &*s[1]);

        let mut s = [IoSlice::new(&[]), IoSlice::new(&[]), IoSlice::new(&[])];
        assert_eq!(2, z.chunks_vectored(&mut s));
        assert_eq!(ZEROES, &*s[0]);
        assert_eq!(&[0], &*s[1]);
    }

    #[test]
    fn buf_bytes_vectored_large() {
        let z = Zeroes(10000);

        let mut s = [IoSlice::new(&[])];
        assert_eq!(1, z.chunks_vectored(&mut s));
        assert_eq!(ZEROES, &*s[0]);

        let mut s = [IoSlice::new(&[]), IoSlice::new(&[])];
        assert_eq!(2, z.chunks_vectored(&mut s));
        assert_eq!(ZEROES, &*s[0]);
        assert_eq!(ZEROES, &*s[1]);
    }

    #[test]
    fn buf_get_bytes() {
        assert_eq!(ZEROES.as_ptr(), Zeroes(10).get_bytes(7).as_ptr());
        assert_eq!(&ZEROES[..7], Zeroes(10).get_bytes(7));
        assert_eq!(3, {
            let mut z = Zeroes(10);
            z.get_bytes(7);
            z.remaining()
        });

        assert_eq!(
            ZEROES.as_ptr(),
            Zeroes(ZEROES.len() * 2 + 1).get_bytes(7).as_ptr()
        );
        assert_eq!(&ZEROES[..7], Zeroes(ZEROES.len() * 2 + 1).get_bytes(7));

        assert_eq!(
            vec![0; ZEROES.len() + 2],
            Zeroes(ZEROES.len() * 2 + 1).get_bytes(ZEROES.len() + 2)
        );
    }
}
<commit_msg>Fix overflow<commit_after>use crate::BufGetBytes;
use bytes::Buf;
use bytes::BufMut;
use bytes::Bytes;
use bytes::BytesMut;
use std::cmp;
use std::io::IoSlice;

/// Zeroes `Buf`
#[derive(Clone, Copy, Default)]
pub struct Zeroes(pub usize);

/// Padding length is up to 256 bytes, so this buffer is practically enough
static ZEROES: &[u8] = &[0; 256];

impl Buf for Zeroes {
    fn remaining(&self) -> usize {
        self.0
    }

    fn chunk(&self) -> &[u8] {
        let len = cmp::min(self.0, ZEROES.len());
        &ZEROES[..len]
    }

    fn chunks_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize {
        let mut c = self.clone();
        let mut n = 0;
        while c.0 != 0 && n != dst.len() {
            let len = c.chunk().len();
            dst[n] = IoSlice::new(&ZEROES[..len]);
            c.0 -= len;
            n += 1;
        }
        n
    }

    fn advance(&mut self, cnt: usize) {
        assert!(cnt <= self.0);
        self.0 -= cnt;
    }
}

impl BufGetBytes for Zeroes {
    fn get_bytes(&mut self, cnt: usize) -> Bytes {
        assert!(cnt <= self.remaining());
        if cnt <= ZEROES.len() {
            self.0 -= cnt;
            Bytes::from_static(&ZEROES[..cnt])
        } else {
            let mut bytes_mut = BytesMut::with_capacity(cnt);
            while bytes_mut.len() < cnt {
                bytes_mut.put_slice(&ZEROES[..cmp::min(cnt - bytes_mut.len(), ZEROES.len())]);
            }
            bytes_mut.freeze()
        }
    }
}

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

    #[test]
    fn buf_small() {
        let mut z = Zeroes(5);
        assert_eq!(&[0, 0, 0, 0, 0], z.chunk());
        assert_eq!(5, z.remaining());
        z.advance(3);
        assert_eq!(2, z.remaining());
        assert_eq!(&[0, 0], z.chunk());
        z.advance(2);
        assert_eq!(0, z.remaining());
    }

    #[test]
    fn buf_large() {
        let mut z = Zeroes(10000);
        assert_eq!(ZEROES, z.chunk());
        z.advance(ZEROES.len());
        assert_eq!(10000 - ZEROES.len(), z.remaining());
    }

    #[test]
    fn buf_bytes_vectored_small() {
        let z = Zeroes(ZEROES.len() + 1);

        let mut s = [IoSlice::new(&[])];
        assert_eq!(1, z.chunks_vectored(&mut s));
        assert_eq!(ZEROES, &*s[0]);

        let mut s = [IoSlice::new(&[]), IoSlice::new(&[])];
        assert_eq!(2, z.chunks_vectored(&mut s));
        assert_eq!(ZEROES, &*s[0]);
        assert_eq!(&[0], &*s[1]);

        let mut s = [IoSlice::new(&[]), IoSlice::new(&[]), IoSlice::new(&[])];
        assert_eq!(2, z.chunks_vectored(&mut s));
        assert_eq!(ZEROES, &*s[0]);
        assert_eq!(&[0], &*s[1]);
    }

    #[test]
    fn buf_bytes_vectored_large() {
        let z = Zeroes(10000);

        let mut s = [IoSlice::new(&[])];
        assert_eq!(1, z.chunks_vectored(&mut s));
        assert_eq!(ZEROES, &*s[0]);

        let mut s = [IoSlice::new(&[]), IoSlice::new(&[])];
        assert_eq!(2, z.chunks_vectored(&mut s));
        assert_eq!(ZEROES, &*s[0]);
        assert_eq!(ZEROES, &*s[1]);
    }

    #[test]
    fn buf_get_bytes() {
        assert_eq!(ZEROES.as_ptr(), Zeroes(10).get_bytes(7).as_ptr());
        assert_eq!(&ZEROES[..7], Zeroes(10).get_bytes(7));
        assert_eq!(3, {
            let mut z = Zeroes(10);
            z.get_bytes(7);
            z.remaining()
        });

        assert_eq!(
            ZEROES.as_ptr(),
            Zeroes(ZEROES.len() * 2 + 1).get_bytes(7).as_ptr()
        );
        assert_eq!(&ZEROES[..7], Zeroes(ZEROES.len() * 2 + 1).get_bytes(7));

        assert_eq!(
            vec![0; ZEROES.len() + 2],
            Zeroes(ZEROES.len() * 2 + 1).get_bytes(ZEROES.len() + 2)
        );
    }
}
<|endoftext|>


<commit_before>
use std::io::Read;  // Trait providing read_to_string()

use hyper;
use rustc_serialize;

use projects;

pub const API_VERSION: u16 = 3;

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Version {
    pub version: String,
    pub revision: String,
}

#[derive(Debug)]
pub struct Pagination {
    pub page: u16,
    pub per_page: u16,
}

#[derive(Debug)]
pub struct GitLab {
    scheme: String,
    domain: String,
    port: u16,
    private_token: String,
    client: hyper::Client,
    pagination: Pagination,
}

impl GitLab {

    pub fn new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
        GitLab {
            scheme: scheme.to_string(),
            domain: domain.to_string(),
            port:   port,
            private_token: private_token.to_string(),
            client: hyper::Client::new(),
            pagination: Pagination {page: 1, per_page: 20},
        }
    }

    pub fn new_http(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("http", &domain, 80, &private_token)
    }

    pub fn new_https(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("https", &domain, 443, &private_token)
    }

    pub fn build_url(&self, command: &str) -> String {
        format!("{}://{}:{}/api/v{}/{}?private_token={}",
                                self.scheme,
                                self.domain,
                                self.port,
                                API_VERSION,
                                command,
                                self.private_token)
    }

    pub fn get(&self, command: &str) -> Result<hyper::client::Response, hyper::Error> {
        let url = self.build_url(&command);
        // Close connections after each GET.
        self.client.get(&url).header(hyper::header::Connection::close()).send()
    }

    pub fn set_pagination(&mut self, pagination: Pagination) {
        self.pagination = pagination;
    }

    pub fn attempt_connection(&self) -> Result<hyper::client::Response, hyper::Error> {
        self.get("version")
    }

    pub fn projects(&self) {
        let mut res: hyper::client::Response = self.get("projects").unwrap();
        println!("####################################################################");
        println!("res: {:?}", res);
        println!("####################################################################");
        println!("Response: {}", res.status);
        println!("####################################################################");
        println!("Headers:\n{}", res.headers);
        println!("####################################################################");

        // let fresh_request = Request::get(url);
        // let streaming_request = fresh_request.start();
        // let mut response = streaming_request.send();
        // Ok(response.read_to_string())

        // let mut body = Vec::new::<u8>();
        // body.resize(, 0);
        // let result = res.read_exact(&body);

        // println!("####################################################################");
        println!("----------------------------");
        let mut body = String::new();
        println!("----------------------------");
        res.read_to_string(&mut body).unwrap();
        // println!("####################################################################");
        // let result = res.read_to_string(&mut body);
        // println!("####################################################################");
        // println!("body:\n{}", body);

        let projects: projects::Projects = rustc_serialize::json::decode(body.as_str()).unwrap();
        println!("{}", projects.p[0].description);

    }

    // pub fn projects(&self) -> ProjectManager {
    //     ProjectManager()
    // }
}

#[cfg(test)]
mod tests {
    use std::env;
    use gitlab::GitLab;

    #[test]
    fn list_projects() {
        let token = match env::var("GITLAB_TOKEN") {
            Ok(val) => val,
            Err(_)  => panic!("Please set environment variable 'GITLAB_TOKEN'"),
        };

        let gl = GitLab::new_https("gitlab.com", &token);
        println!("gl: {:?}", gl);

        gl.projects();
        // assert_eq!(gl.attempt_connection().unwrap().status, hyper::Ok);

    }
}
<commit_msg>Add pagination to url<commit_after>
use std::io::Read;  // Trait providing read_to_string()

use hyper;
use rustc_serialize;

use projects;

pub const API_VERSION: u16 = 3;

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Version {
    pub version: String,
    pub revision: String,
}

#[derive(Debug)]
pub struct Pagination {
    pub page: u16,
    pub per_page: u16,
}

#[derive(Debug)]
pub struct GitLab {
    scheme: String,
    domain: String,
    port: u16,
    private_token: String,
    client: hyper::Client,
    pagination: Pagination,
}

impl GitLab {

    pub fn new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
        GitLab {
            scheme: scheme.to_string(),
            domain: domain.to_string(),
            port:   port,
            private_token: private_token.to_string(),
            client: hyper::Client::new(),
            pagination: Pagination {page: 1, per_page: 20},
        }
    }

    pub fn new_http(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("http", &domain, 80, &private_token)
    }

    pub fn new_https(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("https", &domain, 443, &private_token)
    }

    pub fn build_url(&self, command: &str) -> String {
        format!("{}://{}:{}/api/v{}/{}?private_token={}&page={}&per_page={}",
                                self.scheme,
                                self.domain,
                                self.port,
                                API_VERSION,
                                command,
                                self.private_token,
                                self.pagination.page,
                                self.pagination.per_page)
    }

    pub fn get(&self, command: &str) -> Result<hyper::client::Response, hyper::Error> {
        let url = self.build_url(&command);
        // Close connections after each GET.
        self.client.get(&url).header(hyper::header::Connection::close()).send()
    }

    pub fn set_pagination(&mut self, pagination: Pagination) {
        self.pagination = pagination;
    }

    pub fn attempt_connection(&self) -> Result<hyper::client::Response, hyper::Error> {
        self.get("version")
    }

    pub fn projects(&self) {
        let mut res: hyper::client::Response = self.get("projects").unwrap();
        println!("####################################################################");
        println!("res: {:?}", res);
        println!("####################################################################");
        println!("Response: {}", res.status);
        println!("####################################################################");
        println!("Headers:\n{}", res.headers);
        println!("####################################################################");

        // let fresh_request = Request::get(url);
        // let streaming_request = fresh_request.start();
        // let mut response = streaming_request.send();
        // Ok(response.read_to_string())

        // let mut body = Vec::new::<u8>();
        // body.resize(, 0);
        // let result = res.read_exact(&body);

        // println!("####################################################################");
        println!("----------------------------");
        let mut body = String::new();
        println!("----------------------------");
        res.read_to_string(&mut body).unwrap();
        // println!("####################################################################");
        // let result = res.read_to_string(&mut body);
        // println!("####################################################################");
        // println!("body:\n{}", body);

        let projects: projects::Projects = rustc_serialize::json::decode(body.as_str()).unwrap();
        println!("{}", projects.p[0].description);

    }

    // pub fn projects(&self) -> ProjectManager {
    //     ProjectManager()
    // }
}

#[cfg(test)]
mod tests {
    use std::env;
    use gitlab::GitLab;

    #[test]
    fn list_projects() {
        let token = match env::var("GITLAB_TOKEN") {
            Ok(val) => val,
            Err(_)  => panic!("Please set environment variable 'GITLAB_TOKEN'"),
        };

        let gl = GitLab::new_https("gitlab.com", &token);
        println!("gl: {:?}", gl);

        gl.projects();
        // assert_eq!(gl.attempt_connection().unwrap().status, hyper::Ok);

    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::time::*;
use std::hash::Hash;

// A cache that allows for per-value timeout invalidation

pub enum LRUEntry<T> {
    Present(T),
    Expired,
    Vacant,
}

pub struct LRU<K: Hash + Eq, T> {
    cache: HashMap<K, (T, Instant, Duration)>,
}

impl<K, T> LRU<K, T>
    where K: Hash + Eq
{
    pub fn new() -> LRU<K, T> {
        LRU { cache: HashMap::new() }
    }

    pub fn insert(&mut self, key: K, val: T, lifespan: Duration) {
        self.cache.insert(key, (val, Instant::now(), lifespan));
    }

    pub fn get(&mut self, key: &K) -> LRUEntry<&T> {
        let (val, then, lifespan) = match self.cache.get(key) {
            Some(&(ref val, then, lifespan)) => (val as *const T, then, lifespan),
            None => return LRUEntry::Vacant,
        };

        if Self::is_timed_out(then, lifespan) {
            self.cache.remove(key);
            // self.cache.take(key)
            LRUEntry::Expired
        } else {
            LRUEntry::Present(unsafe { &*val })
        }
    }

    fn is_timed_out(then: Instant, dur: Duration) -> bool {
        let age = then.elapsed();
        if age >= dur {
            false
        } else {
            true
        }
    }
}
<commit_msg>Update lru.rs<commit_after>use std::time::*;
use std::hash::Hash;
use lru_cache::LruCache;

// A cache that allows for per-value timeout invalidation

pub enum LRUEntry<T> {
    Present(T),
    Expired,
    Vacant,
}

pub struct LRU<K: Hash + Eq, T> {
    cache: LruCache<K, (T, Instant, Duration)>,
}

impl<K, T> LRU<K, T>
    where K: Hash + Eq
{
    pub fn new(limit: usize) -> LRU<K, T> {
        LRU { cache: LruCache::new(limit) }
    }

    pub fn insert(&mut self, key: K, val: T, lifespan: Duration) {
        self.cache.insert(key, (val, Instant::now(), lifespan));
    }

    pub fn get(&mut self, key: &K) -> LRUEntry<&T> {
        let (val, then, lifespan) = match self.cache.get_mut(key) {
            Some(&mut (ref val, then, lifespan)) => (val as *const T, then, lifespan),
            None => return LRUEntry::Vacant,
        };

        if Self::is_timed_out(then, lifespan) {
            self.cache.remove(key);
            // self.cache.take(key)
            LRUEntry::Expired
        } else {
            LRUEntry::Present(unsafe { &*val })
        }
    }

    fn is_timed_out(then: Instant, dur: Duration) -> bool {
        let age = then.elapsed();
        if age >= dur {
            false
        } else {
            true
        }
    }
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2016, Boris Popov <popov@whitekefir.ru>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

extern crate syslog;
use logger::syslog::{Facility, Severity};

pub struct Logger {

    name:    &'static str,
    version: &'static str
}

impl Logger {
    /*
    pub fn start(&self) {
        //self.name = &NAME;
        //self.version = VERSION.to_string();

        //self.name = "MountAndExec";
        //
        //TODO
        //
        //return;
    }
    */
    pub fn new(n: &'static str,
               v: &'static str) -> Logger {

        match syslog::unix(Facility::LOG_USER) {
            Err(e)     => println!("impossible to connect to syslog: {:?}", e),
            Ok(writer) => {
                let r = writer.send(Severity::LOG_ALERT, "hello world");
                if r.is_err() {
                    println!("error sending the log {}", r.err().expect("got error"));
                }
            }
        }

        //
        //TODO make writer
        //
        Logger{name: n, version: v}
    }
}
<commit_msg>add syslog wrapper<commit_after>//
// Copyright (c) 2016, Boris Popov <popov@whitekefir.ru>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

extern crate syslog;
use self::syslog::{Facility, Severity};
use self::syslog::unix;
use std::io;

pub struct Logger {
    writer: Box<syslog::Logger>
}

impl Logger {
    pub fn new(name: &str) -> Logger {
        let res = unix(Facility::LOG_USER);
        if res.is_ok() {
            let mut w = res.unwrap();
            w.set_process_name(name.to_string());
            return Logger{writer: w};
        }
        panic!("Impossible to connect to syslog!");
    }

    pub fn info(&self, s: &str) {
        let res = self.writer.send_3164(Severity::LOG_INFO, s);
        if res.is_err() {
            self.to_console(res);
        }
    }

    pub fn error(&self, s: &str) {
        let res = self.writer.send_3164(Severity::LOG_ERR, s);
        if res.is_err() {
            self.to_console(res);
        }
    }

    fn to_console(&self, r: Result<usize, io::Error>) {
        println!("Impossible to write to syslog: {:?}", r);
    }
}
<|endoftext|>


<commit_before>//! Messaging primitives for discovering devices and services.

use std::io;
#[cfg(windows)]
use std::net;
use std::net::SocketAddr;

use net::connector::UdpConnector;
use net::IpVersionMode;

mod notify;
mod search;
mod ssdp;

pub use message::search::{SearchRequest, SearchResponse, SearchListener};
pub use message::notify::{NotifyMessage, NotifyListener};

#[cfg(not(windows))]
use ifaces;

/// Multicast Socket Information
const UPNP_MULTICAST_IPV4_ADDR: &'static str = "239.255.255.250";
const UPNP_MULTICAST_IPV6_LINK_LOCAL_ADDR: &'static str = "FF02::C";
pub const UPNP_MULTICAST_PORT: u16 = 1900;

/// Default TTL For Multicast
const UPNP_MULTICAST_TTL: u32 = 2;

/// Enumerates different types of SSDP messages.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub enum MessageType {
    /// A notify message.
    Notify,
    /// A search message.
    Search,
    /// A response to a search message.
    Response,
}

/// Generate `UdpConnector` objects for all local `IPv4` interfaces.
fn all_local_connectors(multicast_ttl: Option<u32>, filter: IpVersionMode) -> io::Result<Vec<UdpConnector>> {
    trace!("Fetching all local connectors");
    map_local(|&addr| match (&filter, addr) {
        (&IpVersionMode::V4Only, SocketAddr::V4(n)) |
        (&IpVersionMode::Any, SocketAddr::V4(n)) => {
            Ok(Some(try!(UdpConnector::new((*n.ip(), 0), multicast_ttl))))
        }
        (&IpVersionMode::V6Only, SocketAddr::V6(n)) |
        (&IpVersionMode::Any, SocketAddr::V6(n)) => Ok(Some(try!(UdpConnector::new(n, multicast_ttl)))),
        _ => Ok(None),
    })
}

fn map_local<F, R>(mut f: F) -> io::Result<Vec<R>>
    where F: FnMut(&SocketAddr) -> io::Result<Option<R>>
{
    let addrs_iter = try!(get_local_addrs());

    let mut obj_list = Vec::with_capacity(addrs_iter.len());

    for addr in addrs_iter {
        trace!("Found {}", addr);
        match addr {
            SocketAddr::V4(n) => {
                if !n.ip().is_loopback() {
                    if let Some(x) = try!(f(&addr)) {
                        obj_list.push(x);
                    }
                }
            }
            SocketAddr::V6(n) => {
                if !n.ip().is_loopback() {
                    if let Some(x) = try!(f(&addr)) {
                        obj_list.push(x);
                    }
                }
            }
        }
    }

    Ok(obj_list)
}

/// Generate a list of some object R constructed from all local `Ipv4Addr` objects.
///
/// If any of the `SocketAddr`'s fail to resolve, this function will not return an error.
#[cfg(windows)]
fn get_local_addrs() -> io::Result<Vec<SocketAddr>> {
    let host_iter = try!(net::lookup_host(""));
    Ok(host_iter.filter_map(|host| host.ok())
                .collect())
}

/// Generate a list of some object R constructed from all local `Ipv4Addr` objects.
///
/// If any of the `SocketAddr`'s fail to resolve, this function will not return an error.
#[cfg(not(windows))]
fn get_local_addrs() -> io::Result<Vec<SocketAddr>> {
    let iface_iter = try!(ifaces::Interface::get_all()).into_iter();
    Ok(iface_iter.filter(|iface| iface.kind != ifaces::Kind::Packet)
                 .filter_map(|iface| iface.addr)
                 .collect())
}
<commit_msg>Update Usage Of net::lookup_host On Windows For Latest Nightly<commit_after>//! Messaging primitives for discovering devices and services.

use std::io;
#[cfg(windows)]
use std::net;
use std::net::SocketAddr;

use net::connector::UdpConnector;
use net::IpVersionMode;

mod notify;
mod search;
mod ssdp;

pub use message::search::{SearchRequest, SearchResponse, SearchListener};
pub use message::notify::{NotifyMessage, NotifyListener};

#[cfg(not(windows))]
use ifaces;

/// Multicast Socket Information
const UPNP_MULTICAST_IPV4_ADDR: &'static str = "239.255.255.250";
const UPNP_MULTICAST_IPV6_LINK_LOCAL_ADDR: &'static str = "FF02::C";
pub const UPNP_MULTICAST_PORT: u16 = 1900;

/// Default TTL For Multicast
const UPNP_MULTICAST_TTL: u32 = 2;

/// Enumerates different types of SSDP messages.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub enum MessageType {
    /// A notify message.
    Notify,
    /// A search message.
    Search,
    /// A response to a search message.
    Response,
}

/// Generate `UdpConnector` objects for all local `IPv4` interfaces.
fn all_local_connectors(multicast_ttl: Option<u32>, filter: IpVersionMode) -> io::Result<Vec<UdpConnector>> {
    trace!("Fetching all local connectors");
    map_local(|&addr| match (&filter, addr) {
        (&IpVersionMode::V4Only, SocketAddr::V4(n)) |
        (&IpVersionMode::Any, SocketAddr::V4(n)) => {
            Ok(Some(try!(UdpConnector::new((*n.ip(), 0), multicast_ttl))))
        }
        (&IpVersionMode::V6Only, SocketAddr::V6(n)) |
        (&IpVersionMode::Any, SocketAddr::V6(n)) => Ok(Some(try!(UdpConnector::new(n, multicast_ttl)))),
        _ => Ok(None),
    })
}

fn map_local<F, R>(mut f: F) -> io::Result<Vec<R>>
    where F: FnMut(&SocketAddr) -> io::Result<Option<R>>
{
    let addrs_iter = try!(get_local_addrs());

    let mut obj_list = Vec::with_capacity(addrs_iter.len());

    for addr in addrs_iter {
        trace!("Found {}", addr);
        match addr {
            SocketAddr::V4(n) => {
                if !n.ip().is_loopback() {
                    if let Some(x) = try!(f(&addr)) {
                        obj_list.push(x);
                    }
                }
            }
            SocketAddr::V6(n) => {
                if !n.ip().is_loopback() {
                    if let Some(x) = try!(f(&addr)) {
                        obj_list.push(x);
                    }
                }
            }
        }
    }

    Ok(obj_list)
}

/// Generate a list of some object R constructed from all local `Ipv4Addr` objects.
///
/// If any of the `SocketAddr`'s fail to resolve, this function will not return an error.
#[cfg(windows)]
fn get_local_addrs() -> io::Result<Vec<SocketAddr>> {
    let host_iter = try!(net::lookup_host(""));
    Ok(host_iter.collect())
}

/// Generate a list of some object R constructed from all local `Ipv4Addr` objects.
///
/// If any of the `SocketAddr`'s fail to resolve, this function will not return an error.
#[cfg(not(windows))]
fn get_local_addrs() -> io::Result<Vec<SocketAddr>> {
    let iface_iter = try!(ifaces::Interface::get_all()).into_iter();
    Ok(iface_iter.filter(|iface| iface.kind != ifaces::Kind::Packet)
                 .filter_map(|iface| iface.addr)
                 .collect())
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use msg::constellation_msg::PipelineId;
use rustc_serialize::{json, Encoder, Encodable};
use std::cell::RefCell;
use std::collections::{HashMap, VecDeque};
use std::mem;
use std::net::TcpStream;
use std::sync::mpsc::channel;
use std::sync::{Arc, Mutex};
use std::thread::sleep_ms;

use actor::{Actor, ActorRegistry, ActorMessageStatus};
use actors::framerate::FramerateActor;
use actors::memory::{MemoryActor, TimelineMemoryReply};
use devtools_traits::DevtoolScriptControlMsg;
use devtools_traits::DevtoolScriptControlMsg::{SetTimelineMarkers, DropTimelineMarkers};
use devtools_traits::{PreciseTime, TimelineMarker, TracingMetadata, TimelineMarkerType};
use protocol::JsonPacketStream;
use util::task;

pub struct TimelineActor {
    name: String,
    script_sender: IpcSender<DevtoolScriptControlMsg>,
    marker_types: Vec<TimelineMarkerType>,
    pipeline: PipelineId,
    is_recording: Arc<Mutex<bool>>,
    stream: RefCell<Option<TcpStream>>,

    framerate_actor: RefCell<Option<String>>,
    memory_actor: RefCell<Option<String>>,
}

struct Emitter {
    from: String,
    stream: TcpStream,
    markers: Vec<TimelineMarkerReply>,
    registry: Arc<Mutex<ActorRegistry>>,
    start_stamp: PreciseTime,

    framerate_actor: Option<String>,
    memory_actor: Option<String>,
}

#[derive(RustcEncodable)]
struct IsRecordingReply {
    from: String,
    value: bool
}

#[derive(RustcEncodable)]
struct StartReply {
    from: String,
    value: HighResolutionStamp,
}

#[derive(RustcEncodable)]
struct StopReply {
    from: String,
    value: HighResolutionStamp,
}

#[derive(RustcEncodable)]
struct TimelineMarkerReply {
    name: String,
    start: HighResolutionStamp,
    end: HighResolutionStamp,
    stack: Option<Vec<()>>,
    endStack: Option<Vec<()>>,
}

#[derive(RustcEncodable)]
struct MarkersEmitterReply {
    __type__: String,
    markers: Vec<TimelineMarkerReply>,
    from: String,
    endTime: HighResolutionStamp,
}

#[derive(RustcEncodable)]
struct MemoryEmitterReply {
    __type__: String,
    from: String,
    delta: HighResolutionStamp,
    measurement: TimelineMemoryReply,
}

#[derive(RustcEncodable)]
struct FramerateEmitterReply {
    __type__: String,
    from: String,
    delta: HighResolutionStamp,
    timestamps: Vec<HighResolutionStamp>,
}

/// HighResolutionStamp is struct that contains duration in milliseconds
/// with accuracy to microsecond that shows how much time has passed since
/// actor registry inited
/// analog https://w3c.github.io/hr-time/#sec-DOMHighResTimeStamp
pub struct HighResolutionStamp(f64);

impl HighResolutionStamp {
    pub fn new(start_stamp: PreciseTime, time: PreciseTime) -> HighResolutionStamp {
        let duration = start_stamp.to(time).num_microseconds()
                                  .expect("Too big duration in microseconds");
        HighResolutionStamp(duration as f64 / 1000 as f64)
    }

    pub fn wrap(time: f64) -> HighResolutionStamp {
        HighResolutionStamp(time)
    }
}

impl Encodable for HighResolutionStamp {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        self.0.encode(s)
    }
}

static DEFAULT_TIMELINE_DATA_PULL_TIMEOUT: u32 = 200; //ms

impl TimelineActor {
    pub fn new(name: String,
               pipeline: PipelineId,
               script_sender: IpcSender<DevtoolScriptControlMsg>) -> TimelineActor {

        let marker_types = vec!(TimelineMarkerType::Reflow,
                                TimelineMarkerType::DOMEvent);

        TimelineActor {
            name: name,
            pipeline: pipeline,
            marker_types: marker_types,
            script_sender: script_sender,
            is_recording: Arc::new(Mutex::new(false)),
            stream: RefCell::new(None),

            framerate_actor: RefCell::new(None),
            memory_actor: RefCell::new(None),
        }
    }

    fn pull_timeline_data(&self, receiver: IpcReceiver<TimelineMarker>, mut emitter: Emitter) {
        let is_recording = self.is_recording.clone();

        if !*is_recording.lock().unwrap() {
            return;
        }

        /// Select root(with depth 0) TimelineMarker pair (IntervalStart + IntervalEnd)
        /// from queue and add marker to emitter
        /// Return true if closed (IntervalStart + IntervalEnd) pair was founded
        fn group(queue: &mut VecDeque<TimelineMarker>, depth: usize,
                 start_payload: Option<TimelineMarker>, emitter: &mut Emitter) -> bool {

            if let Some(start_payload) = start_payload {
                if start_payload.metadata != TracingMetadata::IntervalStart {
                    panic!("Start payload doesn't have metadata IntervalStart");
                }

                if let Some(end_payload) = queue.pop_front() {
                    match end_payload.metadata {
                        TracingMetadata::IntervalEnd => {
                            if depth == 0 {
                                // Emit TimelineMarkerReply, pair was found
                                emitter.add_marker(start_payload, end_payload);
                            }
                            return true;
                        }
                        TracingMetadata::IntervalStart => {
                            if group(queue, depth + 1, Some(end_payload), emitter) {
                                return group(queue, depth, Some(start_payload), emitter);
                            } else {
                                queue.push_front(start_payload);
                            }
                        }
                        _ => panic!("Unknown tracingMetadata")
                    }
                } else {
                    queue.push_front(start_payload);
                }
            }

            false
        }

        task::spawn_named("PullTimelineMarkers".to_string(), move || {
            let mut queues = HashMap::new();
            queues.insert("Reflow".to_string(), VecDeque::new());
            queues.insert("DOMEvent".to_string(), VecDeque::new());

            loop {
                if !*is_recording.lock().unwrap() {
                    break;
                }

                // Creating queues by marker.name
                loop {
                    match receiver.try_recv() {
                        Ok(marker) => {
                            if let Some(list) = queues.get_mut(&marker.name) {
                                list.push_back(marker);
                            }
                        }

                        Err(_) => break
                    }
                }

                // Emit all markers
                for (_, queue) in &mut queues {
                    let start_payload = queue.pop_front();
                    group(queue, 0, start_payload, &mut emitter);
                }
                emitter.send();

                sleep_ms(DEFAULT_TIMELINE_DATA_PULL_TIMEOUT);
            }
        });
    }
}

impl Actor for TimelineActor {
    fn name(&self) -> String {
        self.name.clone()
    }

    fn handle_message(&self,
                      registry: &ActorRegistry,
                      msg_type: &str,
                      msg: &json::Object,
                      stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> {
        Ok(match msg_type {
            "start" => {
                **self.is_recording.lock().as_mut().unwrap() = true;

                let (tx, rx) = ipc::channel::<TimelineMarker>().unwrap();
                self.script_sender.send(SetTimelineMarkers(self.pipeline,
                                                           self.marker_types.clone(),
                                                           tx)).unwrap();

                *self.stream.borrow_mut() = stream.try_clone().ok();

                // init memory actor
                if let Some(with_memory) = msg.get("withMemory") {
                    if let Some(true) = with_memory.as_boolean() {
                        *self.memory_actor.borrow_mut() = Some(MemoryActor::create(registry));
                    }
                }

                // init framerate actor
                if let Some(with_ticks) = msg.get("withTicks") {
                    if let Some(true) = with_ticks.as_boolean() {
                        let framerate_actor = Some(FramerateActor::create(
                                registry,
                                self.pipeline.clone(),
                                self.script_sender.clone()));
                        *self.framerate_actor.borrow_mut() = framerate_actor;
                    }
                }

                let emitter = Emitter::new(self.name(), registry.get_shareable(),
                                           registry.start_stamp(),
                                           stream.try_clone().unwrap(),
                                           self.memory_actor.borrow().clone(),
                                           self.framerate_actor.borrow().clone());

                self.pull_timeline_data(rx, emitter);

                let msg = StartReply {
                    from: self.name(),
                    value: HighResolutionStamp::new(registry.start_stamp(), PreciseTime::now()),
                };
                stream.write_json_packet(&msg);
                ActorMessageStatus::Processed
            }

            "stop" => {
                let msg = StopReply {
                    from: self.name(),
                    value: HighResolutionStamp::new(registry.start_stamp(), PreciseTime::now()),
                };

                stream.write_json_packet(&msg);
                self.script_sender.send(DropTimelineMarkers(self.pipeline, self.marker_types.clone())).unwrap();

                if let Some(ref actor_name) = *self.framerate_actor.borrow() {
                    registry.drop_actor_later(actor_name.clone());
                }

                if let Some(ref actor_name) = *self.memory_actor.borrow() {
                    registry.drop_actor_later(actor_name.clone());
                }

                **self.is_recording.lock().as_mut().unwrap() = false;
                self.stream.borrow_mut().take();
                ActorMessageStatus::Processed
            }

            "isRecording" => {
                let msg = IsRecordingReply {
                    from: self.name(),
                    value: self.is_recording.lock().unwrap().clone()
                };

                stream.write_json_packet(&msg);
                ActorMessageStatus::Processed
            }

            _ => {
                ActorMessageStatus::Ignored
            }
        })
    }
}

impl Emitter {
    pub fn new(name: String,
               registry: Arc<Mutex<ActorRegistry>>,
               start_stamp: PreciseTime,
               stream: TcpStream,
               memory_actor_name: Option<String>,
               framerate_actor_name: Option<String>) -> Emitter {

        Emitter {
            from: name,
            stream: stream,
            markers: Vec::new(),
            registry: registry,
            start_stamp: start_stamp,

            framerate_actor: framerate_actor_name,
            memory_actor: memory_actor_name,
        }
    }

    fn add_marker(&mut self, start_payload: TimelineMarker, end_payload: TimelineMarker) -> () {
        self.markers.push(TimelineMarkerReply {
            name: start_payload.name,
            start: HighResolutionStamp::new(self.start_stamp, start_payload.time),
            end: HighResolutionStamp::new(self.start_stamp, end_payload.time),
            stack: start_payload.stack,
            endStack: end_payload.stack,
        });
    }

    fn send(&mut self) -> () {
        let end_time = PreciseTime::now();
        let reply = MarkersEmitterReply {
            __type__: "markers".to_string(),
            markers: mem::replace(&mut self.markers, Vec::new()),
            from: self.from.clone(),
            endTime: HighResolutionStamp::new(self.start_stamp, end_time),
        };
        self.stream.write_json_packet(&reply);

        if let Some(ref actor_name) = self.framerate_actor {
            let mut lock = self.registry.lock();
            let registry = lock.as_mut().unwrap();
            let framerate_actor = registry.find_mut::<FramerateActor>(actor_name);
            let framerateReply = FramerateEmitterReply {
                __type__: "framerate".to_string(),
                from: framerate_actor.name(),
                delta: HighResolutionStamp::new(self.start_stamp, end_time),
                timestamps: framerate_actor.take_pending_ticks(),
            };
            self.stream.write_json_packet(&framerateReply);
        }

        if let Some(ref actor_name) = self.memory_actor {
            let registry = self.registry.lock().unwrap();
            let memory_actor = registry.find::<MemoryActor>(actor_name);
            let memoryReply = MemoryEmitterReply {
                __type__: "memory".to_string(),
                from: memory_actor.name(),
                delta: HighResolutionStamp::new(self.start_stamp, end_time),
                measurement: memory_actor.measure(),
            };
            self.stream.write_json_packet(&memoryReply);
        }
    }
}
<commit_msg>Auto merge of #7386 - Ms2ger:emitter, r=jdm<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use msg::constellation_msg::PipelineId;
use rustc_serialize::{json, Encoder, Encodable};
use std::cell::RefCell;
use std::collections::{HashMap, VecDeque};
use std::net::TcpStream;
use std::sync::mpsc::channel;
use std::sync::{Arc, Mutex};
use std::thread::sleep_ms;

use actor::{Actor, ActorRegistry, ActorMessageStatus};
use actors::framerate::FramerateActor;
use actors::memory::{MemoryActor, TimelineMemoryReply};
use devtools_traits::DevtoolScriptControlMsg;
use devtools_traits::DevtoolScriptControlMsg::{SetTimelineMarkers, DropTimelineMarkers};
use devtools_traits::{PreciseTime, TimelineMarker, TracingMetadata, TimelineMarkerType};
use protocol::JsonPacketStream;
use util::task;

pub struct TimelineActor {
    name: String,
    script_sender: IpcSender<DevtoolScriptControlMsg>,
    marker_types: Vec<TimelineMarkerType>,
    pipeline: PipelineId,
    is_recording: Arc<Mutex<bool>>,
    stream: RefCell<Option<TcpStream>>,

    framerate_actor: RefCell<Option<String>>,
    memory_actor: RefCell<Option<String>>,
}

struct Emitter {
    from: String,
    stream: TcpStream,
    registry: Arc<Mutex<ActorRegistry>>,
    start_stamp: PreciseTime,

    framerate_actor: Option<String>,
    memory_actor: Option<String>,
}

#[derive(RustcEncodable)]
struct IsRecordingReply {
    from: String,
    value: bool
}

#[derive(RustcEncodable)]
struct StartReply {
    from: String,
    value: HighResolutionStamp,
}

#[derive(RustcEncodable)]
struct StopReply {
    from: String,
    value: HighResolutionStamp,
}

#[derive(RustcEncodable)]
struct TimelineMarkerReply {
    name: String,
    start: HighResolutionStamp,
    end: HighResolutionStamp,
    stack: Option<Vec<()>>,
    endStack: Option<Vec<()>>,
}

#[derive(RustcEncodable)]
struct MarkersEmitterReply {
    __type__: String,
    markers: Vec<TimelineMarkerReply>,
    from: String,
    endTime: HighResolutionStamp,
}

#[derive(RustcEncodable)]
struct MemoryEmitterReply {
    __type__: String,
    from: String,
    delta: HighResolutionStamp,
    measurement: TimelineMemoryReply,
}

#[derive(RustcEncodable)]
struct FramerateEmitterReply {
    __type__: String,
    from: String,
    delta: HighResolutionStamp,
    timestamps: Vec<HighResolutionStamp>,
}

/// HighResolutionStamp is struct that contains duration in milliseconds
/// with accuracy to microsecond that shows how much time has passed since
/// actor registry inited
/// analog https://w3c.github.io/hr-time/#sec-DOMHighResTimeStamp
pub struct HighResolutionStamp(f64);

impl HighResolutionStamp {
    pub fn new(start_stamp: PreciseTime, time: PreciseTime) -> HighResolutionStamp {
        let duration = start_stamp.to(time).num_microseconds()
                                  .expect("Too big duration in microseconds");
        HighResolutionStamp(duration as f64 / 1000 as f64)
    }

    pub fn wrap(time: f64) -> HighResolutionStamp {
        HighResolutionStamp(time)
    }
}

impl Encodable for HighResolutionStamp {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        self.0.encode(s)
    }
}

static DEFAULT_TIMELINE_DATA_PULL_TIMEOUT: u32 = 200; //ms

impl TimelineActor {
    pub fn new(name: String,
               pipeline: PipelineId,
               script_sender: IpcSender<DevtoolScriptControlMsg>) -> TimelineActor {

        let marker_types = vec!(TimelineMarkerType::Reflow,
                                TimelineMarkerType::DOMEvent);

        TimelineActor {
            name: name,
            pipeline: pipeline,
            marker_types: marker_types,
            script_sender: script_sender,
            is_recording: Arc::new(Mutex::new(false)),
            stream: RefCell::new(None),

            framerate_actor: RefCell::new(None),
            memory_actor: RefCell::new(None),
        }
    }

    fn pull_timeline_data(&self, receiver: IpcReceiver<TimelineMarker>, mut emitter: Emitter) {
        let is_recording = self.is_recording.clone();

        if !*is_recording.lock().unwrap() {
            return;
        }

        /// Select root(with depth 0) TimelineMarker pair (IntervalStart + IntervalEnd)
        /// from queue and add marker to emitter
        /// Return true if closed (IntervalStart + IntervalEnd) pair was founded
        fn group(queue: &mut VecDeque<TimelineMarker>, depth: usize,
                 start_payload: Option<TimelineMarker>, emitter: &Emitter,
                 markers: &mut Vec<TimelineMarkerReply>) -> bool {

            if let Some(start_payload) = start_payload {
                if start_payload.metadata != TracingMetadata::IntervalStart {
                    panic!("Start payload doesn't have metadata IntervalStart");
                }

                if let Some(end_payload) = queue.pop_front() {
                    match end_payload.metadata {
                        TracingMetadata::IntervalEnd => {
                            if depth == 0 {
                                // Emit TimelineMarkerReply, pair was found
                                markers.push(emitter.marker(start_payload, end_payload));
                            }
                            return true;
                        }
                        TracingMetadata::IntervalStart => {
                            if group(queue, depth + 1, Some(end_payload), emitter, markers) {
                                return group(queue, depth, Some(start_payload), emitter, markers);
                            } else {
                                queue.push_front(start_payload);
                            }
                        }
                        _ => panic!("Unknown tracingMetadata")
                    }
                } else {
                    queue.push_front(start_payload);
                }
            }

            false
        }

        task::spawn_named("PullTimelineMarkers".to_string(), move || {
            let mut queues = HashMap::new();
            queues.insert("Reflow".to_string(), VecDeque::new());
            queues.insert("DOMEvent".to_string(), VecDeque::new());

            loop {
                if !*is_recording.lock().unwrap() {
                    break;
                }

                // Creating queues by marker.name
                loop {
                    match receiver.try_recv() {
                        Ok(marker) => {
                            if let Some(list) = queues.get_mut(&marker.name) {
                                list.push_back(marker);
                            }
                        }

                        Err(_) => break
                    }
                }

                // Emit all markers
                let mut markers = vec![];
                for (_, queue) in &mut queues {
                    let start_payload = queue.pop_front();
                    group(queue, 0, start_payload, &emitter, &mut markers);
                }
                emitter.send(markers);

                sleep_ms(DEFAULT_TIMELINE_DATA_PULL_TIMEOUT);
            }
        });
    }
}

impl Actor for TimelineActor {
    fn name(&self) -> String {
        self.name.clone()
    }

    fn handle_message(&self,
                      registry: &ActorRegistry,
                      msg_type: &str,
                      msg: &json::Object,
                      stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> {
        Ok(match msg_type {
            "start" => {
                **self.is_recording.lock().as_mut().unwrap() = true;

                let (tx, rx) = ipc::channel::<TimelineMarker>().unwrap();
                self.script_sender.send(SetTimelineMarkers(self.pipeline,
                                                           self.marker_types.clone(),
                                                           tx)).unwrap();

                *self.stream.borrow_mut() = stream.try_clone().ok();

                // init memory actor
                if let Some(with_memory) = msg.get("withMemory") {
                    if let Some(true) = with_memory.as_boolean() {
                        *self.memory_actor.borrow_mut() = Some(MemoryActor::create(registry));
                    }
                }

                // init framerate actor
                if let Some(with_ticks) = msg.get("withTicks") {
                    if let Some(true) = with_ticks.as_boolean() {
                        let framerate_actor = Some(FramerateActor::create(
                                registry,
                                self.pipeline.clone(),
                                self.script_sender.clone()));
                        *self.framerate_actor.borrow_mut() = framerate_actor;
                    }
                }

                let emitter = Emitter::new(self.name(), registry.get_shareable(),
                                           registry.start_stamp(),
                                           stream.try_clone().unwrap(),
                                           self.memory_actor.borrow().clone(),
                                           self.framerate_actor.borrow().clone());

                self.pull_timeline_data(rx, emitter);

                let msg = StartReply {
                    from: self.name(),
                    value: HighResolutionStamp::new(registry.start_stamp(), PreciseTime::now()),
                };
                stream.write_json_packet(&msg);
                ActorMessageStatus::Processed
            }

            "stop" => {
                let msg = StopReply {
                    from: self.name(),
                    value: HighResolutionStamp::new(registry.start_stamp(), PreciseTime::now()),
                };

                stream.write_json_packet(&msg);
                self.script_sender.send(DropTimelineMarkers(self.pipeline, self.marker_types.clone())).unwrap();

                if let Some(ref actor_name) = *self.framerate_actor.borrow() {
                    registry.drop_actor_later(actor_name.clone());
                }

                if let Some(ref actor_name) = *self.memory_actor.borrow() {
                    registry.drop_actor_later(actor_name.clone());
                }

                **self.is_recording.lock().as_mut().unwrap() = false;
                self.stream.borrow_mut().take();
                ActorMessageStatus::Processed
            }

            "isRecording" => {
                let msg = IsRecordingReply {
                    from: self.name(),
                    value: self.is_recording.lock().unwrap().clone()
                };

                stream.write_json_packet(&msg);
                ActorMessageStatus::Processed
            }

            _ => {
                ActorMessageStatus::Ignored
            }
        })
    }
}

impl Emitter {
    pub fn new(name: String,
               registry: Arc<Mutex<ActorRegistry>>,
               start_stamp: PreciseTime,
               stream: TcpStream,
               memory_actor_name: Option<String>,
               framerate_actor_name: Option<String>) -> Emitter {

        Emitter {
            from: name,
            stream: stream,
            registry: registry,
            start_stamp: start_stamp,

            framerate_actor: framerate_actor_name,
            memory_actor: memory_actor_name,
        }
    }

    fn marker(&self, start_payload: TimelineMarker, end_payload: TimelineMarker)
              -> TimelineMarkerReply {
        TimelineMarkerReply {
            name: start_payload.name,
            start: HighResolutionStamp::new(self.start_stamp, start_payload.time),
            end: HighResolutionStamp::new(self.start_stamp, end_payload.time),
            stack: start_payload.stack,
            endStack: end_payload.stack,
        }
    }

    fn send(&mut self, markers: Vec<TimelineMarkerReply>) -> () {
        let end_time = PreciseTime::now();
        let reply = MarkersEmitterReply {
            __type__: "markers".to_string(),
            markers: markers,
            from: self.from.clone(),
            endTime: HighResolutionStamp::new(self.start_stamp, end_time),
        };
        self.stream.write_json_packet(&reply);

        if let Some(ref actor_name) = self.framerate_actor {
            let mut lock = self.registry.lock();
            let registry = lock.as_mut().unwrap();
            let framerate_actor = registry.find_mut::<FramerateActor>(actor_name);
            let framerateReply = FramerateEmitterReply {
                __type__: "framerate".to_string(),
                from: framerate_actor.name(),
                delta: HighResolutionStamp::new(self.start_stamp, end_time),
                timestamps: framerate_actor.take_pending_ticks(),
            };
            self.stream.write_json_packet(&framerateReply);
        }

        if let Some(ref actor_name) = self.memory_actor {
            let registry = self.registry.lock().unwrap();
            let memory_actor = registry.find::<MemoryActor>(actor_name);
            let memoryReply = MemoryEmitterReply {
                __type__: "memory".to_string(),
                from: memory_actor.name(),
                delta: HighResolutionStamp::new(self.start_stamp, end_time),
                measurement: memory_actor.measure(),
            };
            self.stream.write_json_packet(&memoryReply);
        }
    }
}
<|endoftext|>


<commit_before>// Vector/Point macros
macro_rules! n_pointvector {
    (ops $lhs:ident; $rhs:ident {$($field:ident),*}) => {
        impl<F: $crate::traitdefs::Float> ::std::ops::Add<$rhs<F>> for $lhs<F> {
            type Output = $lhs<F>;

            fn add(self, rhs: $rhs<F>) -> $lhs<F> {
                $lhs {
                    $($field: self.$field + rhs.$field),*
                }
            }
        }

        impl<F: $crate::traitdefs::Float> ::std::ops::Sub<$rhs<F>> for $lhs<F> {
            type Output = $lhs<F>;

            fn sub(self, rhs: $rhs<F>) -> $lhs<F> {
                $lhs {
                    $($field: self.$field - rhs.$field),*
                }
            }
        }
    };

    (float ops $name:ident {$($field:ident),+}) => {
        impl<F: $crate::traitdefs::Float> ::std::ops::Mul<F> for $name<F> {
            type Output = $name<F>;

            fn mul(self, rhs: F) -> $name<F> {
                $name {
                    $($field: self.$field * rhs),+
                }
            }
        }

        impl<F: $crate::traitdefs::Float> ::std::ops::Div<F> for $name<F> {
            type Output = $name<F>;

            fn div(self, rhs: F) -> $name<F> {
                $name {
                    $($field: self.$field / rhs),+
                }
            }
        }

        impl<F: $crate::traitdefs::Float> ::std::ops::Neg for $name<F> {
            type Output = $name<F>;

            fn neg(self) -> $name<F> {
                $name {
                    $($field: -self.$field),+
                }
            }
        }
    };

    (struct $dims:expr; $name:ident {$($field:ident: $f_ty:ident),+} $sibling:ident) => {
        #[derive(Debug, Clone, Copy)]
        pub struct $name<F: $crate::traitdefs::Float> {
            $(pub $field: F),+
        }

        impl<F: $crate::traitdefs::Float> $name<F> {
            pub fn new($($field: F),+) -> $name<F> {
                $name {
                    $($field: $field),+
                }
            }
        }

        impl<'a, F: $crate::traitdefs::Float> ::std::convert::From<&'a [F]> for $name<F> {
            fn from(slice: &'a [F]) -> $name<F> {
                assert_eq!(slice.len(), count!($($field),+));
                let mut index = -1;
                $name{$($field: {
                    index += 1;
                    slice[index as usize]
                }),+}
            }
        }

        impl<F: $crate::traitdefs::Float> ::std::convert::Into<[F; $dims]> for $name<F> {
            fn into(self) -> [F; $dims] {
                [$(self.$field),*]
            }
        }

        impl<F: $crate::traitdefs::Float> ::std::convert::Into<($($f_ty),*)> for $name<F> {
            fn into(self) -> ($($f_ty),*) {
                ($(self.$field),*)
            }
        }

        impl<F: $crate::traitdefs::Float> ::std::convert::From<$sibling<F>> for $name<F> {
            fn from(sib: $sibling<F>) -> $name<F> {
                $name {
                    $($field: sib.$field),*
                }
            }
        }

        impl<F: $crate::traitdefs::Float> ::std::convert::AsRef<[F]> for $name<F> {
            fn as_ref(&self) -> &[F] {
                use std::slice;
                unsafe {
                    slice::from_raw_parts(self as *const $name<F> as *const F, $dims)
                }
            }
        }

        impl<F: $crate::traitdefs::Float> ::std::convert::AsMut<[F]> for $name<F> {
            fn as_mut(&mut self) -> &mut [F] {
                use std::slice;
                unsafe {
                    slice::from_raw_parts_mut(self as *mut $name<F> as *mut F, $dims)
                }
            }
        }

        n_pointvector!(ops $name; $sibling {$($field),+});
        n_pointvector!(ops $name; $name {$($field),+});
        n_pointvector!(float ops $name {$($field),+});
    };

    ($dims:expr; $p_name:ident, $v_name:ident {$($field:ident),+}) => {
        n_pointvector!(struct $dims; $p_name {$($field: F),+} $v_name);
        n_pointvector!(struct $dims; $v_name {$($field: F),+} $p_name);

        impl<F: $crate::traitdefs::Float> $v_name<F> {
            pub fn len(self) -> F {
                ($(self.$field.powi(2) +)+ F::from_f32(0.0).unwrap()).sqrt()
            }

            pub fn normalize(self) -> $v_name<F> {
                self / self.len()
            }
        }
    }
}

macro_rules! check_t_bounds {
    ($t: expr) => {{
        let zero = F::from_f32(0.0).unwrap();
        let one  = F::from_f32(1.0).unwrap();
        if !(zero <= $t && $t <= one) {
            return None;
        }
    }}
}

// Polynomial Macros
macro_rules! count {
    ($idc:tt) => (1);
    ($($element:tt),*) => {{$(count!($element) +)* 0}};
}

macro_rules! n_bezier {
    ($name:ident {
        $($field:ident: $weight:expr),+
    } derived {
        $($dleft:ident - $dright:ident: $dweight:expr),+
    } elevated $elevated:ident<$($est:ty),+> {
        $estart:ident;
        $($eleft:ident + $eright:ident),+;
        $eend:ident;
    }) => {
        #[derive(Debug, Clone, Copy)]
        pub struct $name<F> where F: $crate::traitdefs::Float {
            $(pub $field: F),+
        }

        impl<F> $name<F> where F: $crate::traitdefs::Float {
            pub fn new($($field: F),+) -> $name<F> {
                $name {
                    $($field: $field),+
                }
            }
        }

        impl<F> $crate::BezCurve<F> for $name<F>
                where F: $crate::traitdefs::Float
        {
            type Point = F;
            type Vector = F;
            type Elevated = $elevated<$($est),+>;

            fn from_slice(slice: &[F]) -> Option<$name<F>> {
                use $crate::OrderStatic;
                if slice.len() - 1 != $name::<F>::order_static() {
                    None
                } else {
                    let mut index = -1;
                    Some($name {$($field: {
                        index += 1;
                        slice[index as usize]
                    }),+})
                }
            }

            fn interp_unbounded(&self, t: F) -> F {
                let t1 = F::from_f32(1.0).unwrap() - t;
                const COUNT: i32 = count!($($field),+) - 1;
                let mut factor = COUNT + 1;

                $(
                    factor -= 1;
                    let $field =
                        t1.powi(factor) *
                        t.powi(COUNT-factor) *
                        self.$field *
                        F::from_i32($weight).unwrap();
                )+
                $($field +)+ F::from_f32(0.0).unwrap()
            }

            fn slope_unbounded(&self, t: F) -> F {
                let t1 = F::from_f32(1.0).unwrap() - t;
                const COUNT: i32 = count!($($dleft),+) - 1;
                let mut factor = COUNT + 1;

                $(
                    factor -= 1;
                    let $dleft =
                        t1.powi(factor) *
                        t.powi(COUNT-factor) *
                        (self.$dleft - self.$dright) *
                        F::from_i32($dweight * (COUNT + 1)).unwrap();
                )+
                $($dleft +)+ F::from_f32(0.0).unwrap()
            }

            fn elevate(&self) -> $elevated<$($est),+> {
                let mut factor = 0.0;
                let order = F::from_usize(self.order() + 1).unwrap();
                $elevated::from([self.$estart,
                    $({
                        factor += 1.0;
                        let factor = F::from_f32(factor).unwrap();
                        (self.$eleft * factor +
                        self.$eright * (order - factor)) / order
                    },)+
                    self.$eend])
            }

            fn order(&self) -> usize {
                use $crate::OrderStatic;
                $name::<F>::order_static()
            }
        }

        impl<F> $crate::OrderStatic for $name<F>
                where F: $crate::traitdefs::Float
        {
            fn order_static() -> usize {
                count!($($field),+)-1
            }
        }

        impl<F> ::std::convert::From<[F; count!($($field),+)]> for $name<F>
                where F: $crate::traitdefs::Float
        {
            fn from(array: [F; count!($($field),+)]) -> $name<F> {
                use $crate::BezCurve;
                $name::from_slice(&array[..]).unwrap()
            }
        }

        impl<F> ::std::convert::AsRef<[F]> for $name<F>
                where F: $crate::traitdefs::Float
        {
            fn as_ref(&self) -> &[F] {
                use std::slice;
                unsafe {
                    slice::from_raw_parts(self as *const $name<F> as *const F, count!($($field),+))
                }
            }
        }

        impl<F> ::std::convert::AsMut<[F]> for $name<F>
                where F: $crate::traitdefs::Float
        {
            fn as_mut(&mut self) -> &mut [F] {
                use std::slice;
                unsafe {
                    slice::from_raw_parts_mut(self as *mut $name<F> as *mut F, count!($($field),+))
                }
            }
        }
    }
}

macro_rules! bez_composite {
    ($name:ident<$poly:ident> {
        $($field:ident: $($n_field:ident),+;)+
    } -> <$point:ident; $vector:ident> {
        $($dim:ident = $($dfield:ident),+;)+
    } elevated $elevated:ident<$($est:ty),+> {
        $($eindex:expr => $($edim:ident),+;)+
    } chained $chain:ident) =>
    {
        #[derive(Debug, Clone, Copy)]
        pub struct $name<F: $crate::traitdefs::Float> {
            $(pub $field: $point<F>),+
        }

        impl<F: $crate::traitdefs::Float> $name<F> {
            pub fn new($($($n_field: F),+),+) -> $name<F> {
                $name {
                    $($field: $point::new($($n_field),+)),+
                }
            }

            $(
                pub fn $dim(&self) -> $poly<F> {
                    $poly::new($(self.$dfield.$dim),+)
                }
            )+
        }

        impl<F> $crate::BezCurve<F> for $name<F>
                where F: $crate::traitdefs::Float
        {
            type Point = $point<F>;
            type Vector = $vector<F>;
            type Elevated = $elevated<$($est),+>;

            fn from_slice(slice: &[$point<F>]) -> Option<$name<F>> {
                use $crate::OrderStatic;
                if slice.len() - 1 != $name::<F>::order_static() {
                    None
                } else {
                    let mut index = -1;
                    Some($name {$($field: {
                        index += 1;
                        slice[index as usize]
                    }),+})
                }
            }

            fn interp_unbounded(&self, t: F) -> $point<F> {
                use $crate::BezCurve;

                $point::new($(self.$dim().interp_unbounded(t)),+)
            }

            fn slope_unbounded(&self, t: F) -> $vector<F> {
                use $crate::BezCurve;

                $vector::new($(self.$dim().slope_unbounded(t)),+)
            }

            fn elevate(&self) -> $elevated<$($est),+> {
                use $crate::BezCurve;

                $(let $dim = self.$dim().elevate();)+
                $elevated::from([$($point::new($($edim.as_ref()[$eindex]),+)),+])
            }

            fn order(&self) -> usize {
                use $crate::OrderStatic;
                $poly::<F>::order_static()
            }
        }

        impl<F> $crate::OrderStatic for $name<F>
                where F: $crate::traitdefs::Float
        {
            #[inline]
            fn order_static() -> usize {
                use $crate::OrderStatic;
                $poly::<F>::order_static()
            }
        }

        impl<F> ::std::convert::From<[$point<F>; count!($($field),+)]> for $name<F>
                where F: $crate::traitdefs::Float
        {
            fn from(array: [$point<F>; count!($($field),+)]) -> $name<F> {
                use $crate::BezCurve;
                $name::from_slice(&array[..]).unwrap()
            }
        }

        impl<F> ::std::convert::AsRef<[$point<F>]> for $name<F>
                where F: $crate::traitdefs::Float
        {
            fn as_ref(&self) -> &[$point<F>] {
                use std::slice;
                unsafe {
                    slice::from_raw_parts(self as *const $name<F> as *const $point<F>, count!($($field),+))
                }
            }
        }

        impl<F> ::std::convert::AsMut<[$point<F>]> for $name<F>
                where F: $crate::traitdefs::Float
        {
            fn as_mut(&mut self) -> &mut [$point<F>] {
                use std::slice;
                unsafe {
                    slice::from_raw_parts_mut(self as *mut $name<F> as *mut $point<F>, count!($($field),+))
                }
            }
        }

        #[derive(Clone, Copy)]
        pub struct $chain<F, C>
                where F: $crate::traitdefs::Float,
                      C: AsRef<[$point<F>]>
        {
            points: C,
            phantom: ::std::marker::PhantomData<F>
        }

        impl<F, C> $crate::BezChain<F, C> for $chain<F, C>
                where F: $crate::traitdefs::Float,
                      C: AsRef<[$point<F>]>
        {
            type Curve = $name<F>;

            fn from_container(container: C) -> $chain<F, C> {
                $chain {
                    points: container,
                    phantom: ::std::marker::PhantomData
                }
            }

            fn get(&self, index: usize) -> $name<F> {
                use $crate::{BezCurve, OrderStatic};

                let order = $name::<F>::order_static();
                let curve_index = index * order;
                $name::from_slice(&self.points.as_ref()[curve_index..curve_index + order + 1]).unwrap()
            }

            fn iter(&self) -> $crate::BezIter<F, $name<F>> {
                use $crate::OrderStatic;

                $crate::BezIter {
                    points: self.points.as_ref().as_ptr(),
                    len: self.points.as_ref().len(),
                    order: $name::<F>::order_static()
                }
            }

            fn unwrap(self) -> C {
                self.points
            }
        }

        impl<F, C> AsRef<C> for $chain<F, C>
                where F: Float,
                      C: AsRef<[$point<F>]>
        {
            fn as_ref(&self) -> &C {
                &self.points
            }
        }

        impl<F, C> AsMut<C> for $chain<F, C>
                where F: Float,
                      C: AsRef<[$point<F>]>
        {
            fn as_mut(&mut self) -> &mut C {
                &mut self.points
            }
        }
    };
}<commit_msg><commit_after>// Vector/Point macros
macro_rules! n_pointvector {
    (ops $lhs:ident; $rhs:ident {$($field:ident),*}) => {
        impl<F: $crate::traitdefs::Float> ::std::ops::Add<$rhs<F>> for $lhs<F> {
            type Output = $lhs<F>;

            fn add(self, rhs: $rhs<F>) -> $lhs<F> {
                $lhs {
                    $($field: self.$field + rhs.$field),*
                }
            }
        }

        impl<F: $crate::traitdefs::Float> ::std::ops::Sub<$rhs<F>> for $lhs<F> {
            type Output = $lhs<F>;

            fn sub(self, rhs: $rhs<F>) -> $lhs<F> {
                $lhs {
                    $($field: self.$field - rhs.$field),*
                }
            }
        }
    };

    (float ops $name:ident {$($field:ident),+}) => {
        impl<F: $crate::traitdefs::Float> ::std::ops::Mul<F> for $name<F> {
            type Output = $name<F>;

            fn mul(self, rhs: F) -> $name<F> {
                $name {
                    $($field: self.$field * rhs),+
                }
            }
        }

        impl<F: $crate::traitdefs::Float> ::std::ops::Div<F> for $name<F> {
            type Output = $name<F>;

            fn div(self, rhs: F) -> $name<F> {
                $name {
                    $($field: self.$field / rhs),+
                }
            }
        }

        impl<F: $crate::traitdefs::Float> ::std::ops::Neg for $name<F> {
            type Output = $name<F>;

            fn neg(self) -> $name<F> {
                $name {
                    $($field: -self.$field),+
                }
            }
        }
    };

    (struct $dims:expr; $name:ident {$($field:ident: $f_ty:ident),+} $sibling:ident) => {
        #[derive(Debug, Clone, Copy)]
        pub struct $name<F: $crate::traitdefs::Float> {
            $(pub $field: F),+
        }

        impl<F: $crate::traitdefs::Float> $name<F> {
            pub fn new($($field: F),+) -> $name<F> {
                $name {
                    $($field: $field),+
                }
            }
        }

        impl<F: $crate::traitdefs::Float> ::std::convert::From<[F; $dims]> for $name<F> {
            fn from(array: [F; $dims]) -> $name<F> {
                let mut index = -1;
                $name{$($field: {
                    index += 1;
                    array[index as usize]
                }),+}
            }
        }

        impl<F: $crate::traitdefs::Float> ::std::convert::Into<[F; $dims]> for $name<F> {
            fn into(self) -> [F; $dims] {
                [$(self.$field),*]
            }
        }

        impl<F: $crate::traitdefs::Float> ::std::convert::Into<($($f_ty),*)> for $name<F> {
            fn into(self) -> ($($f_ty),*) {
                ($(self.$field),*)
            }
        }

        impl<F: $crate::traitdefs::Float> ::std::convert::From<$sibling<F>> for $name<F> {
            fn from(sib: $sibling<F>) -> $name<F> {
                $name {
                    $($field: sib.$field),*
                }
            }
        }

        impl<F: $crate::traitdefs::Float> ::std::convert::AsRef<[F]> for $name<F> {
            fn as_ref(&self) -> &[F] {
                use std::slice;
                unsafe {
                    slice::from_raw_parts(self as *const $name<F> as *const F, $dims)
                }
            }
        }

        impl<F: $crate::traitdefs::Float> ::std::convert::AsMut<[F]> for $name<F> {
            fn as_mut(&mut self) -> &mut [F] {
                use std::slice;
                unsafe {
                    slice::from_raw_parts_mut(self as *mut $name<F> as *mut F, $dims)
                }
            }
        }

        n_pointvector!(ops $name; $sibling {$($field),+});
        n_pointvector!(ops $name; $name {$($field),+});
        n_pointvector!(float ops $name {$($field),+});
    };

    ($dims:expr; $p_name:ident, $v_name:ident {$($field:ident),+}) => {
        n_pointvector!(struct $dims; $p_name {$($field: F),+} $v_name);
        n_pointvector!(struct $dims; $v_name {$($field: F),+} $p_name);

        impl<F: $crate::traitdefs::Float> $v_name<F> {
            pub fn len(self) -> F {
                ($(self.$field.powi(2) +)+ F::from_f32(0.0).unwrap()).sqrt()
            }

            pub fn normalize(self) -> $v_name<F> {
                self / self.len()
            }
        }
    }
}

macro_rules! check_t_bounds {
    ($t: expr) => {{
        let zero = F::from_f32(0.0).unwrap();
        let one  = F::from_f32(1.0).unwrap();
        if !(zero <= $t && $t <= one) {
            return None;
        }
    }}
}

// Polynomial Macros
macro_rules! count {
    ($idc:tt) => (1);
    ($($element:tt),*) => {{$(count!($element) +)* 0}};
}

macro_rules! n_bezier {
    ($name:ident {
        $($field:ident: $weight:expr),+
    } derived {
        $($dleft:ident - $dright:ident: $dweight:expr),+
    } elevated $elevated:ident<$($est:ty),+> {
        $estart:ident;
        $($eleft:ident + $eright:ident),+;
        $eend:ident;
    }) => {
        #[derive(Debug, Clone, Copy)]
        pub struct $name<F> where F: $crate::traitdefs::Float {
            $(pub $field: F),+
        }

        impl<F> $name<F> where F: $crate::traitdefs::Float {
            pub fn new($($field: F),+) -> $name<F> {
                $name {
                    $($field: $field),+
                }
            }
        }

        impl<F> $crate::BezCurve<F> for $name<F>
                where F: $crate::traitdefs::Float
        {
            type Point = F;
            type Vector = F;
            type Elevated = $elevated<$($est),+>;

            fn from_slice(slice: &[F]) -> Option<$name<F>> {
                use $crate::OrderStatic;
                if slice.len() - 1 != $name::<F>::order_static() {
                    None
                } else {
                    let mut index = -1;
                    Some($name {$($field: {
                        index += 1;
                        slice[index as usize]
                    }),+})
                }
            }

            fn interp_unbounded(&self, t: F) -> F {
                let t1 = F::from_f32(1.0).unwrap() - t;
                const COUNT: i32 = count!($($field),+) - 1;
                let mut factor = COUNT + 1;

                $(
                    factor -= 1;
                    let $field =
                        t1.powi(factor) *
                        t.powi(COUNT-factor) *
                        self.$field *
                        F::from_i32($weight).unwrap();
                )+
                $($field +)+ F::from_f32(0.0).unwrap()
            }

            fn slope_unbounded(&self, t: F) -> F {
                let t1 = F::from_f32(1.0).unwrap() - t;
                const COUNT: i32 = count!($($dleft),+) - 1;
                let mut factor = COUNT + 1;

                $(
                    factor -= 1;
                    let $dleft =
                        t1.powi(factor) *
                        t.powi(COUNT-factor) *
                        (self.$dleft - self.$dright) *
                        F::from_i32($dweight * (COUNT + 1)).unwrap();
                )+
                $($dleft +)+ F::from_f32(0.0).unwrap()
            }

            fn elevate(&self) -> $elevated<$($est),+> {
                let mut factor = 0.0;
                let order = F::from_usize(self.order() + 1).unwrap();
                $elevated::from([self.$estart,
                    $({
                        factor += 1.0;
                        let factor = F::from_f32(factor).unwrap();
                        (self.$eleft * factor +
                        self.$eright * (order - factor)) / order
                    },)+
                    self.$eend])
            }

            fn order(&self) -> usize {
                use $crate::OrderStatic;
                $name::<F>::order_static()
            }
        }

        impl<F> $crate::OrderStatic for $name<F>
                where F: $crate::traitdefs::Float
        {
            fn order_static() -> usize {
                count!($($field),+)-1
            }
        }

        impl<F> ::std::convert::From<[F; count!($($field),+)]> for $name<F>
                where F: $crate::traitdefs::Float
        {
            fn from(array: [F; count!($($field),+)]) -> $name<F> {
                use $crate::BezCurve;
                $name::from_slice(&array[..]).unwrap()
            }
        }

        impl<F> ::std::convert::AsRef<[F]> for $name<F>
                where F: $crate::traitdefs::Float
        {
            fn as_ref(&self) -> &[F] {
                use std::slice;
                unsafe {
                    slice::from_raw_parts(self as *const $name<F> as *const F, count!($($field),+))
                }
            }
        }

        impl<F> ::std::convert::AsMut<[F]> for $name<F>
                where F: $crate::traitdefs::Float
        {
            fn as_mut(&mut self) -> &mut [F] {
                use std::slice;
                unsafe {
                    slice::from_raw_parts_mut(self as *mut $name<F> as *mut F, count!($($field),+))
                }
            }
        }
    }
}

macro_rules! bez_composite {
    ($name:ident<$poly:ident> {
        $($field:ident: $($n_field:ident),+;)+
    } -> <$point:ident; $vector:ident> {
        $($dim:ident = $($dfield:ident),+;)+
    } elevated $elevated:ident<$($est:ty),+> {
        $($eindex:expr => $($edim:ident),+;)+
    } chained $chain:ident) =>
    {
        #[derive(Debug, Clone, Copy)]
        pub struct $name<F: $crate::traitdefs::Float> {
            $(pub $field: $point<F>),+
        }

        impl<F: $crate::traitdefs::Float> $name<F> {
            pub fn new($($($n_field: F),+),+) -> $name<F> {
                $name {
                    $($field: $point::new($($n_field),+)),+
                }
            }

            $(
                pub fn $dim(&self) -> $poly<F> {
                    $poly::new($(self.$dfield.$dim),+)
                }
            )+
        }

        impl<F> $crate::BezCurve<F> for $name<F>
                where F: $crate::traitdefs::Float
        {
            type Point = $point<F>;
            type Vector = $vector<F>;
            type Elevated = $elevated<$($est),+>;

            fn from_slice(slice: &[$point<F>]) -> Option<$name<F>> {
                use $crate::OrderStatic;
                if slice.len() - 1 != $name::<F>::order_static() {
                    None
                } else {
                    let mut index = -1;
                    Some($name {$($field: {
                        index += 1;
                        slice[index as usize]
                    }),+})
                }
            }

            fn interp_unbounded(&self, t: F) -> $point<F> {
                use $crate::BezCurve;

                $point::new($(self.$dim().interp_unbounded(t)),+)
            }

            fn slope_unbounded(&self, t: F) -> $vector<F> {
                use $crate::BezCurve;

                $vector::new($(self.$dim().slope_unbounded(t)),+)
            }

            fn elevate(&self) -> $elevated<$($est),+> {
                use $crate::BezCurve;

                $(let $dim = self.$dim().elevate();)+
                $elevated::from([$($point::new($($edim.as_ref()[$eindex]),+)),+])
            }

            fn order(&self) -> usize {
                use $crate::OrderStatic;
                $poly::<F>::order_static()
            }
        }

        impl<F> $crate::OrderStatic for $name<F>
                where F: $crate::traitdefs::Float
        {
            #[inline]
            fn order_static() -> usize {
                use $crate::OrderStatic;
                $poly::<F>::order_static()
            }
        }

        impl<F> ::std::convert::From<[$point<F>; count!($($field),+)]> for $name<F>
                where F: $crate::traitdefs::Float
        {
            fn from(array: [$point<F>; count!($($field),+)]) -> $name<F> {
                use $crate::BezCurve;
                $name::from_slice(&array[..]).unwrap()
            }
        }

        impl<F> ::std::convert::AsRef<[$point<F>]> for $name<F>
                where F: $crate::traitdefs::Float
        {
            fn as_ref(&self) -> &[$point<F>] {
                use std::slice;
                unsafe {
                    slice::from_raw_parts(self as *const $name<F> as *const $point<F>, count!($($field),+))
                }
            }
        }

        impl<F> ::std::convert::AsMut<[$point<F>]> for $name<F>
                where F: $crate::traitdefs::Float
        {
            fn as_mut(&mut self) -> &mut [$point<F>] {
                use std::slice;
                unsafe {
                    slice::from_raw_parts_mut(self as *mut $name<F> as *mut $point<F>, count!($($field),+))
                }
            }
        }

        #[derive(Clone, Copy)]
        pub struct $chain<F, C>
                where F: $crate::traitdefs::Float,
                      C: AsRef<[$point<F>]>
        {
            points: C,
            phantom: ::std::marker::PhantomData<F>
        }

        impl<F, C> $crate::BezChain<F, C> for $chain<F, C>
                where F: $crate::traitdefs::Float,
                      C: AsRef<[$point<F>]>
        {
            type Curve = $name<F>;

            fn from_container(container: C) -> $chain<F, C> {
                $chain {
                    points: container,
                    phantom: ::std::marker::PhantomData
                }
            }

            fn get(&self, index: usize) -> $name<F> {
                use $crate::{BezCurve, OrderStatic};

                let order = $name::<F>::order_static();
                let curve_index = index * order;
                $name::from_slice(&self.points.as_ref()[curve_index..curve_index + order + 1]).unwrap()
            }

            fn iter(&self) -> $crate::BezIter<F, $name<F>> {
                use $crate::OrderStatic;

                $crate::BezIter {
                    points: self.points.as_ref().as_ptr(),
                    len: self.points.as_ref().len(),
                    order: $name::<F>::order_static()
                }
            }

            fn unwrap(self) -> C {
                self.points
            }
        }

        impl<F, C> AsRef<C> for $chain<F, C>
                where F: Float,
                      C: AsRef<[$point<F>]>
        {
            fn as_ref(&self) -> &C {
                &self.points
            }
        }

        impl<F, C> AsMut<C> for $chain<F, C>
                where F: Float,
                      C: AsRef<[$point<F>]>
        {
            fn as_mut(&mut self) -> &mut C {
                &mut self.points
            }
        }
    };
}<|endoftext|>


<commit_before>use crate::decoder::{decode, decode_regular, decode_slice};
use crate::encoder::Encodable;
use crate::errors::{Error, Result};
use crate::jsontypes::FacebookScopeMapping;
use crate::jsontypes::RawSourceMap;
use crate::types::{DecodedMap, SourceMap};
use crate::vlq::parse_vlq_segment;
use std::cmp::Ordering;
use std::io::Read;
use std::ops::{Deref, DerefMut};

/// These are starting locations of scopes.
/// The `name_index` represents the index into the `HermesFunctionMap.names` vec,
/// which represents the function names/scopes.
pub struct HermesScopeOffset {
    line: u32,
    column: u32,
    name_index: u32,
}

pub struct HermesFunctionMap {
    names: Vec<String>,
    mappings: Vec<HermesScopeOffset>,
}

pub struct SourceMapHermes {
    pub(crate) sm: SourceMap,
    // There should be one `HermesFunctionMap` per each `sources` entry in the main SourceMap.
    function_maps: Vec<Option<HermesFunctionMap>>,
}

impl Deref for SourceMapHermes {
    type Target = SourceMap;

    fn deref(&self) -> &Self::Target {
        &self.sm
    }
}

impl DerefMut for SourceMapHermes {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.sm
    }
}

impl Encodable for SourceMapHermes {
    fn as_raw_sourcemap(&self) -> RawSourceMap {
        let rsm = self.sm.as_raw_sourcemap();
        // TODO: need to serialize the `HermesFunctionMap` mappings
        rsm
    }
}

impl SourceMapHermes {
    pub fn from_reader<R: Read>(rdr: R) -> Result<Self> {
        match decode(rdr)? {
            DecodedMap::Hermes(sm) => Ok(sm),
            _ => Err(Error::IndexedSourcemap),
        }
    }

    pub fn from_slice(slice: &[u8]) -> Result<Self> {
        match decode_slice(slice)? {
            DecodedMap::Hermes(sm) => Ok(sm),
            _ => Err(Error::IndexedSourcemap),
        }
    }

    pub fn get_original_function_name(&self, bytecode_offset: u32) -> Option<&str> {
        let token = self.sm.lookup_token(0, bytecode_offset)?;

        let function_map = &self.function_maps[token.get_src_id() as usize].as_ref()?;

        // Find the closest mapping, just like here:
        // https://github.com/facebook/metro/blob/63b523eb20e7bdf62018aeaf195bb5a3a1a67f36/packages/metro-symbolicate/src/SourceMetadataMapConsumer.js#L204-L231
        let mapping =
            function_map
                .mappings
                .binary_search_by(|o| match o.line.cmp(&token.get_src_line()) {
                    Ordering::Equal => o.column.cmp(&token.get_src_col()),
                    x => x,
                });
        let name_index = function_map.mappings[match mapping {
            Ok(a) => a,
            Err(a) => a.saturating_sub(1),
        }]
        .name_index;

        function_map
            .names
            .get(name_index as usize)
            .map(|n| n.as_str())
    }
}

pub fn decode_hermes(mut rsm: RawSourceMap) -> Result<SourceMapHermes> {
    let x_facebook_sources = rsm
        .x_facebook_sources
        .take()
        .expect("expected x_facebook_sources");

    // This is basically the logic from here:
    // https://github.com/facebook/metro/blob/63b523eb20e7bdf62018aeaf195bb5a3a1a67f36/packages/metro-symbolicate/src/SourceMetadataMapConsumer.js#L182-L202

    let function_maps = x_facebook_sources
        .into_iter()
        .map(|v| {
            let FacebookScopeMapping {
                names,
                mappings: raw_mappings,
            } = v.into_iter().next()?;

            let mut mappings = vec![];
            let mut line = 1;
            let mut name_index = 0;

            for line_mapping in raw_mappings.split(';') {
                if line_mapping.is_empty() {
                    continue;
                }

                let mut column = 0;

                for mapping in line_mapping.split(',') {
                    if mapping.is_empty() {
                        continue;
                    }

                    let mut nums = parse_vlq_segment(mapping).ok()?.into_iter();

                    column = (i64::from(column) + nums.next()?) as u32;
                    name_index = (i64::from(name_index) + nums.next().unwrap_or(0)) as u32;
                    line = (i64::from(line) + nums.next().unwrap_or(0)) as u32;
                    mappings.push(HermesScopeOffset {
                        column,
                        line,
                        name_index,
                    });
                }
            }
            Some(HermesFunctionMap { names, mappings })
        })
        .collect();

    let sm = decode_regular(rsm)?;
    Ok(SourceMapHermes { sm, function_maps })
}
<commit_msg>make clippy happy<commit_after>use crate::decoder::{decode, decode_regular, decode_slice};
use crate::encoder::Encodable;
use crate::errors::{Error, Result};
use crate::jsontypes::FacebookScopeMapping;
use crate::jsontypes::RawSourceMap;
use crate::types::{DecodedMap, SourceMap};
use crate::vlq::parse_vlq_segment;
use std::cmp::Ordering;
use std::io::Read;
use std::ops::{Deref, DerefMut};

/// These are starting locations of scopes.
/// The `name_index` represents the index into the `HermesFunctionMap.names` vec,
/// which represents the function names/scopes.
pub struct HermesScopeOffset {
    line: u32,
    column: u32,
    name_index: u32,
}

pub struct HermesFunctionMap {
    names: Vec<String>,
    mappings: Vec<HermesScopeOffset>,
}

pub struct SourceMapHermes {
    pub(crate) sm: SourceMap,
    // There should be one `HermesFunctionMap` per each `sources` entry in the main SourceMap.
    function_maps: Vec<Option<HermesFunctionMap>>,
}

impl Deref for SourceMapHermes {
    type Target = SourceMap;

    fn deref(&self) -> &Self::Target {
        &self.sm
    }
}

impl DerefMut for SourceMapHermes {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.sm
    }
}

impl Encodable for SourceMapHermes {
    fn as_raw_sourcemap(&self) -> RawSourceMap {
        // TODO: need to serialize the `HermesFunctionMap` mappings
        self.sm.as_raw_sourcemap()
    }
}

impl SourceMapHermes {
    pub fn from_reader<R: Read>(rdr: R) -> Result<Self> {
        match decode(rdr)? {
            DecodedMap::Hermes(sm) => Ok(sm),
            _ => Err(Error::IndexedSourcemap),
        }
    }

    pub fn from_slice(slice: &[u8]) -> Result<Self> {
        match decode_slice(slice)? {
            DecodedMap::Hermes(sm) => Ok(sm),
            _ => Err(Error::IndexedSourcemap),
        }
    }

    pub fn get_original_function_name(&self, bytecode_offset: u32) -> Option<&str> {
        let token = self.sm.lookup_token(0, bytecode_offset)?;

        let function_map = &self.function_maps[token.get_src_id() as usize].as_ref()?;

        // Find the closest mapping, just like here:
        // https://github.com/facebook/metro/blob/63b523eb20e7bdf62018aeaf195bb5a3a1a67f36/packages/metro-symbolicate/src/SourceMetadataMapConsumer.js#L204-L231
        let mapping =
            function_map
                .mappings
                .binary_search_by(|o| match o.line.cmp(&token.get_src_line()) {
                    Ordering::Equal => o.column.cmp(&token.get_src_col()),
                    x => x,
                });
        let name_index = function_map.mappings[match mapping {
            Ok(a) => a,
            Err(a) => a.saturating_sub(1),
        }]
        .name_index;

        function_map
            .names
            .get(name_index as usize)
            .map(|n| n.as_str())
    }
}

pub fn decode_hermes(mut rsm: RawSourceMap) -> Result<SourceMapHermes> {
    let x_facebook_sources = rsm
        .x_facebook_sources
        .take()
        .expect("expected x_facebook_sources");

    // This is basically the logic from here:
    // https://github.com/facebook/metro/blob/63b523eb20e7bdf62018aeaf195bb5a3a1a67f36/packages/metro-symbolicate/src/SourceMetadataMapConsumer.js#L182-L202

    let function_maps = x_facebook_sources
        .into_iter()
        .map(|v| {
            let FacebookScopeMapping {
                names,
                mappings: raw_mappings,
            } = v.into_iter().next()?;

            let mut mappings = vec![];
            let mut line = 1;
            let mut name_index = 0;

            for line_mapping in raw_mappings.split(';') {
                if line_mapping.is_empty() {
                    continue;
                }

                let mut column = 0;

                for mapping in line_mapping.split(',') {
                    if mapping.is_empty() {
                        continue;
                    }

                    let mut nums = parse_vlq_segment(mapping).ok()?.into_iter();

                    column = (i64::from(column) + nums.next()?) as u32;
                    name_index = (i64::from(name_index) + nums.next().unwrap_or(0)) as u32;
                    line = (i64::from(line) + nums.next().unwrap_or(0)) as u32;
                    mappings.push(HermesScopeOffset {
                        column,
                        line,
                        name_index,
                    });
                }
            }
            Some(HermesFunctionMap { names, mappings })
        })
        .collect();

    let sm = decode_regular(rsm)?;
    Ok(SourceMapHermes { sm, function_maps })
}
<|endoftext|>