<commit_before>//! A collection of newtypes defining type-strong IDs.

use chrono::NaiveDateTime;
use internal::prelude::*;
use serde::de::{Deserialize, Deserializer};
use std::fmt::{Display, Formatter, Result as FmtResult};
use super::utils::U64Visitor;

macro_rules! id_u64 {
    ($($name:ident;)*) => {
        $(
            impl $name {
                /// Retrieves the time that the Id was created at.
                pub fn created_at(&self) -> NaiveDateTime {
                    let offset = (self.0 >> 22) / 1000;

                    NaiveDateTime::from_timestamp(1_420_070_400 + offset as i64, 0)
                }

                /// Immutably borrow inner Id.
                #[inline]
                pub fn as_u64(&self) -> &u64 {
                    &self.0
                }

                /// Mutably borrow inner Id.
                #[inline]
                pub fn as_mut_u64(&mut self) -> &mut u64 {
                    &mut self.0
                }
            }

            // This is a hack so functions can accept iterators that either:
            // 1. return the id itself (e.g: `MessageId`)
            // 2. return a reference to it (`&MessageId`).
            impl AsRef<$name> for $name {
                fn as_ref(&self) -> &Self {
                    self
                }
            }

            impl<'a> From<&'a $name> for $name {
                fn from(id: &'a $name) -> $name {
                    id.clone()
                }
            }

            impl From<u64> for $name {
                fn from(id_as_u64: u64) -> $name {
                    $name(id_as_u64)
                }
            }

            impl PartialEq for $name {
                fn eq(&self, other: &Self) -> bool {
                    self.0 == other.0
                }
            }

            impl PartialEq<u64> for $name {
                fn eq(&self, u: &u64) -> bool {
                    self.0 == *u
                }
            }

            impl Display for $name {
                fn fmt(&self, f: &mut Formatter) -> FmtResult {
                    Display::fmt(&self.0, f)
                }
            }

            impl<'de> Deserialize<'de> for $name {
                fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
                    deserializer.deserialize_any(U64Visitor).map($name)
                }
            }
        )*
    }
}

/// An identifier for an Application.
#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
#[allow(derive_hash_xor_eq)]
pub struct ApplicationId(pub u64);

/// An identifier for a Channel
#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
#[allow(derive_hash_xor_eq)]
pub struct ChannelId(pub u64);

/// An identifier for an Emoji
#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
#[allow(derive_hash_xor_eq)]
pub struct EmojiId(pub u64);

/// An identifier for a Guild
#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
#[allow(derive_hash_xor_eq)]
pub struct GuildId(pub u64);

/// An identifier for an Integration
#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
#[allow(derive_hash_xor_eq)]
pub struct IntegrationId(pub u64);

/// An identifier for a Message
#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
#[allow(derive_hash_xor_eq)]
pub struct MessageId(pub u64);

/// An identifier for a Role
#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
#[allow(derive_hash_xor_eq)]
pub struct RoleId(pub u64);

/// An identifier for a User
#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
#[allow(derive_hash_xor_eq)]
pub struct UserId(pub u64);

/// An identifier for a [`Webhook`](../webhook/struct.Webhook.html).
#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
#[allow(derive_hash_xor_eq)]
pub struct WebhookId(pub u64);

/// An identifier for an audit log entry.
#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
#[allow(derive_hash_xor_eq)]
pub struct AuditLogEntryId(pub u64);

id_u64! {
    ApplicationId;
    ChannelId;
    EmojiId;
    GuildId;
    IntegrationId;
    MessageId;
    RoleId;
    UserId;
    WebhookId;
    AuditLogEntryId;
}
<commit_msg>Implement `From<$id_struct>` for `u64` and `i64` to allow `into`'ing. (#468)<commit_after>//! A collection of newtypes defining type-strong IDs.

use chrono::NaiveDateTime;
use internal::prelude::*;
use serde::de::{Deserialize, Deserializer};
use std::fmt::{Display, Formatter, Result as FmtResult};
use super::utils::U64Visitor;

macro_rules! id_u64 {
    ($($name:ident;)*) => {
        $(
            impl $name {
                /// Retrieves the time that the Id was created at.
                pub fn created_at(&self) -> NaiveDateTime {
                    let offset = (self.0 >> 22) / 1000;

                    NaiveDateTime::from_timestamp(1_420_070_400 + offset as i64, 0)
                }

                /// Immutably borrow inner Id.
                #[inline]
                pub fn as_u64(&self) -> &u64 {
                    &self.0
                }

                /// Mutably borrow inner Id.
                #[inline]
                pub fn as_mut_u64(&mut self) -> &mut u64 {
                    &mut self.0
                }
            }

            // This is a hack so functions can accept iterators that either:
            // 1. return the id itself (e.g: `MessageId`)
            // 2. return a reference to it (`&MessageId`).
            impl AsRef<$name> for $name {
                fn as_ref(&self) -> &Self {
                    self
                }
            }

            impl<'a> From<&'a $name> for $name {
                fn from(id: &'a $name) -> $name {
                    id.clone()
                }
            }

            impl From<u64> for $name {
                fn from(id_as_u64: u64) -> $name {
                    $name(id_as_u64)
                }
            }

            impl PartialEq for $name {
                fn eq(&self, other: &Self) -> bool {
                    self.0 == other.0
                }
            }

            impl PartialEq<u64> for $name {
                fn eq(&self, u: &u64) -> bool {
                    self.0 == *u
                }
            }

            impl Display for $name {
                fn fmt(&self, f: &mut Formatter) -> FmtResult {
                    Display::fmt(&self.0, f)
                }
            }

            impl<'de> Deserialize<'de> for $name {
                fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
                    deserializer.deserialize_any(U64Visitor).map($name)
                }
            }

            impl From<$name> for u64 {
                fn from(id: $name) -> u64 {
                    id.0 as u64
                }
            }

            impl From<$name> for i64 {
                fn from(id: $name) -> i64 {
                    id.0 as i64
                }
            }
        )*
    }
}

/// An identifier for an Application.
#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
#[allow(derive_hash_xor_eq)]
pub struct ApplicationId(pub u64);

/// An identifier for a Channel
#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
#[allow(derive_hash_xor_eq)]
pub struct ChannelId(pub u64);

/// An identifier for an Emoji
#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
#[allow(derive_hash_xor_eq)]
pub struct EmojiId(pub u64);

/// An identifier for a Guild
#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
#[allow(derive_hash_xor_eq)]
pub struct GuildId(pub u64);

/// An identifier for an Integration
#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
#[allow(derive_hash_xor_eq)]
pub struct IntegrationId(pub u64);

/// An identifier for a Message
#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
#[allow(derive_hash_xor_eq)]
pub struct MessageId(pub u64);

/// An identifier for a Role
#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
#[allow(derive_hash_xor_eq)]
pub struct RoleId(pub u64);

/// An identifier for a User
#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
#[allow(derive_hash_xor_eq)]
pub struct UserId(pub u64);

/// An identifier for a [`Webhook`](../webhook/struct.Webhook.html).
#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
#[allow(derive_hash_xor_eq)]
pub struct WebhookId(pub u64);

/// An identifier for an audit log entry.
#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
#[allow(derive_hash_xor_eq)]
pub struct AuditLogEntryId(pub u64);

id_u64! {
    ApplicationId;
    ChannelId;
    EmojiId;
    GuildId;
    IntegrationId;
    MessageId;
    RoleId;
    UserId;
    WebhookId;
    AuditLogEntryId;
}
<|endoftext|>


<commit_before>#![allow(
    clippy::inherent_to_string,
    clippy::large_enum_variant,
    clippy::new_without_default,
    clippy::nonminimal_bool,
    clippy::or_fun_call,
    clippy::toplevel_ref_arg,
    clippy::useless_let_if_seq
)]

extern crate proc_macro;

mod derive;
mod expand;
mod syntax;
mod type_id;

use crate::syntax::file::Module;
use crate::syntax::namespace::Namespace;
use crate::syntax::qualified::QualifiedName;
use proc_macro::TokenStream;
use syn::parse::{Parse, ParseStream, Parser, Result};
use syn::parse_macro_input;

/// `#[cxx::bridge] mod ffi { ... }`
///
/// Refer to the crate-level documentation for the explanation of how this macro
/// is intended to be used.
///
/// The only additional thing to note here is namespace support — if the
/// types and functions on the `extern "C++"` side of our bridge are in a
/// namespace, specify that namespace as an argument of the cxx::bridge
/// attribute macro.
///
/// ```
/// #[cxx::bridge(namespace = "mycompany::rust")]
/// # mod ffi {}
/// ```
///
/// The types and functions from the `extern "Rust"` side of the bridge will be
/// placed into that same namespace in the generated C++ code.
#[proc_macro_attribute]
pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
    let _ = syntax::error::ERRORS;

    let namespace = match Namespace::parse_bridge_attr_namespace.parse(args) {
        Ok(namespace) => namespace,
        Err(err) => return err.to_compile_error().into(),
    };
    let mut ffi = parse_macro_input!(input as Module);
    ffi.namespace = namespace;

    expand::bridge(ffi)
        .unwrap_or_else(|err| err.to_compile_error())
        .into()
}

#[proc_macro]
pub fn type_id(input: TokenStream) -> TokenStream {
    struct TypeId(QualifiedName);

    impl Parse for TypeId {
        fn parse(input: ParseStream) -> Result<Self> {
            QualifiedName::parse_quoted_or_unquoted(input).map(TypeId)
        }
    }

    let arg = parse_macro_input!(input as TypeId);
    type_id::expand(arg.0).into()
}
<commit_msg>Suppress clippy single_match lint<commit_after>#![allow(
    clippy::inherent_to_string,
    clippy::large_enum_variant,
    clippy::new_without_default,
    clippy::nonminimal_bool,
    clippy::or_fun_call,
    clippy::single_match,
    clippy::toplevel_ref_arg,
    clippy::useless_let_if_seq
)]

extern crate proc_macro;

mod derive;
mod expand;
mod syntax;
mod type_id;

use crate::syntax::file::Module;
use crate::syntax::namespace::Namespace;
use crate::syntax::qualified::QualifiedName;
use proc_macro::TokenStream;
use syn::parse::{Parse, ParseStream, Parser, Result};
use syn::parse_macro_input;

/// `#[cxx::bridge] mod ffi { ... }`
///
/// Refer to the crate-level documentation for the explanation of how this macro
/// is intended to be used.
///
/// The only additional thing to note here is namespace support — if the
/// types and functions on the `extern "C++"` side of our bridge are in a
/// namespace, specify that namespace as an argument of the cxx::bridge
/// attribute macro.
///
/// ```
/// #[cxx::bridge(namespace = "mycompany::rust")]
/// # mod ffi {}
/// ```
///
/// The types and functions from the `extern "Rust"` side of the bridge will be
/// placed into that same namespace in the generated C++ code.
#[proc_macro_attribute]
pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
    let _ = syntax::error::ERRORS;

    let namespace = match Namespace::parse_bridge_attr_namespace.parse(args) {
        Ok(namespace) => namespace,
        Err(err) => return err.to_compile_error().into(),
    };
    let mut ffi = parse_macro_input!(input as Module);
    ffi.namespace = namespace;

    expand::bridge(ffi)
        .unwrap_or_else(|err| err.to_compile_error())
        .into()
}

#[proc_macro]
pub fn type_id(input: TokenStream) -> TokenStream {
    struct TypeId(QualifiedName);

    impl Parse for TypeId {
        fn parse(input: ParseStream) -> Result<Self> {
            QualifiedName::parse_quoted_or_unquoted(input).map(TypeId)
        }
    }

    let arg = parse_macro_input!(input as TypeId);
    type_id::expand(arg.0).into()
}
<|endoftext|>


<commit_before>extern crate core;

use std::mem;
use std::fmt::Debug;
use std::vec::Vec;
use std::boxed::Box;
use std::collections::HashMap;
use std::collections::hash_map::Values;
use self::core::ops::RangeFull;

#[derive(Debug)]
pub struct QuadTree<S, T: Debug> {
    root: Node<S, T>
}

#[derive(Debug)]
enum Child<S, T: Sized + Debug> {
    Inner(Box<Node<S, T>>),
    Leaf(S, Vec<T>)
}

impl<S, T: Debug> Child<S, T> {
    // fn visit(&self) {
    //     match self {
    //         &Child::Leaf(_, ref t) => {
    //             println!("{:?}", t);
    //         },
    //         &Child::Inner(ref b) => {
    //             b.as_ref().visit();
    //         }
    //     }
    // }
}

#[derive(Debug)]
struct Node<S, T: Sized + Debug> {
    span: S,
    children: HashMap<Dir, Child<S, T>>
}

impl<S: Span<S, T> + Debug, T: Debug + Clone + PartialEq> Node<S, T> {

    fn new(span: S) -> Node<S, T> {
        return Node {
            span: span,
            children: HashMap::new()
        };
    }

    // fn visit(&self) {
    //     // for i in 0..4 {
    //     //     match self.children.get(i) {
    //     //         Some(c) => c.visit(),
    //     //         None => println!("None")
    //     //     };
    //     // };
    // }

    fn add(&mut self, t: T) {
        let mut sub_spans = self.span.split();
        for (key, span) in sub_spans.drain() {
            if span.contains(&t) {
                if self.children.contains_key(&key) {
                    let child = self.children.remove(&key).unwrap();
                    let new_child: Child<S, T> = match child {
                        Child::Leaf(span, mut v) => {
                            if v.len() > 1 && self.span.can_split() {
                                let mut new_node = Node::new(span);
                                for old_t in v.drain(RangeFull) {
                                    new_node.add(old_t);
                                }
                                new_node.add(t);
                                Child::Inner(Box::new(new_node))
                            } else {
                                v.push(t);
                                Child::Leaf(span, v)
                            }
                        },
                        Child::Inner(mut b) => {
                            b.as_mut().add(t);
                            Child::Inner(b)
                        }
                    };
                    self.children.insert(key.clone(), new_child);
                } else {
                    self.children.insert(key.clone(), Child::Leaf(span, vec![t]));
                }
                return;
            }
        }
        unreachable!("Tried to add {:?} to node with span {:?}", t, self.span);
    }

    fn print(&self, depth: usize) {
        println!("Node {:?}", self.span);
        let indent = String::from_utf8(vec![b' '; 4 * depth]).unwrap();
        for (key, child) in self.children.iter() {
            print!("{}{:?}: ", indent, key);
            match child {
                &Child::Inner(ref b) => b.as_ref().print(depth + 1),
                &Child::Leaf(_, ref v) => println!("{:?}", v),
            };
        }
    }

    fn scan(&self, span: &S) -> Vec<T> {
        if !self.span.overlaps(span) {
            return Vec::new();
        }
        let mut result: Vec<T> = Vec::new();
        for (_, child) in &self.children {
            match child {
                &Child::Leaf(_, ref v) => {
                    for t in v.iter().filter(|t| span.contains(&t)) {
                        result.push(t.clone());
                    }
                },
                &Child::Inner(ref b) => {
                    for t in b.as_ref().scan(span) {
                        result.push(t.clone());
                    }
                }
            };
        }
        return result;
    }

    fn contains(&self, t: &T) -> bool {
        if !self.span.contains(t) {
            return false;
        }
        for (_, child) in &self.children {
            match child {
                &Child::Leaf(_, ref v) => {
                    if v.contains(t) {
                        return true;
                    }
                },
                &Child::Inner(ref b) => {
                    if b.as_ref().contains(t) {
                        return true;
                    }
                }
            };
        }
        return false;
    }
}

impl<S: Span<S, T> + Debug, T: Debug + Clone + PartialEq> QuadTree<S, T> {
    pub fn new(span: S) -> QuadTree<S, T> {
        return QuadTree { root: Node::new(span) };
    }

    pub fn add(&mut self, t: T) {
        self.ensure_contains(&t);
        self.root.add(t);
    }

    pub fn print(&self) {
        print!("root: ");
        self.root.print(1);
    }

    fn ensure_contains(&mut self, t: &T) {
        while !self.root.span.contains(&t) {
            let new_span = self.root.span.expand(&self.root.span.dir_of(&t).unwrap());
            let mut new_root = Node::new(new_span);
            for (dir, span) in new_root.span.split() {
                if span == self.root.span {
                    mem::swap(&mut self.root, &mut new_root);
                    self.root.children.insert(dir.clone(), Child::Inner(Box::new(new_root)));
                    break;
                }
                // unreachable!();
            }
        }
    }

    pub fn scan(&self, span: &S) -> Vec<T> {
        return self.root.scan(span);
    }

    pub fn contains(&self, t: &T) -> bool {
        return self.root.contains(t);
    }

    pub fn remove(&self, t: &T) -> bool {
        unimplemented!();
    }
}

#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum Dir { N, S, E, W, NE, NW, SE, SW }

pub trait Span<S: Span<S, T>, T>: Clone + Eq + PartialEq {

    /// The direction of `t` in relation to `self`, or `None` if
    /// `self` `contains` `t`.
    fn dir_of(&self, t: &T) -> Option<Dir>;

    /// The span of equal size to the north of `self`.
    fn north_span(&self) -> S;

    /// The span of equal size to the south of `self`.
    fn south_span(&self) -> S;

    /// The span of equal size to the east of `self`.
    fn east_span(&self) -> S;

    /// The span of equal size to the west of `self`.
    fn west_span(&self) -> S;

    /// Returns a new `S` with double the size of `self` expanded
    /// in the direction `dir`.
    fn expand(&self, dir: &Dir) -> S;

    /// Returns a partition of `self` with four blocks.
    /// The partition of the result of `expand` must contain the
    /// original `S`.
    fn split(&self) -> HashMap<Dir, S>;

    /// Returns true if the span can be split, e.g., if the span is
    /// represented by integers and the width and height is larger than `1`.
    fn can_split(&self) -> bool;

    /// Not implemented!
    fn merge(spans: Values<Dir, S>) -> S;

    /// Returns `true` if `self` overlaps with `other`, otherwise `false`.
    /// Used for `QuadTree.scan`.
    fn overlaps(&self, other: &S) -> bool;

    /// Returns `true` if `self` contains `t`, otherwise `false`.
    fn contains(&self, t: &T) -> bool {
        return self.dir_of(t) == None;
    }
}
<commit_msg>refactor<commit_after>extern crate core;

use std::mem;
use std::fmt::Debug;
use std::vec::Vec;
use std::boxed::Box;
use std::collections::HashMap;
use std::collections::hash_map::Values;
use self::core::ops::RangeFull;

#[derive(Debug)]
pub struct QuadTree<S, T: Debug> {
    root: Node<S, T>
}

impl<S: Span<S, T> + Debug, T: Debug + Clone + PartialEq> QuadTree<S, T> {
    pub fn new(span: S) -> QuadTree<S, T> {
        return QuadTree { root: Node::new(span) };
    }

    pub fn add(&mut self, t: T) {
        self.ensure_contains(&t);
        self.root.add(t);
    }

    pub fn print(&self) {
        print!("root: ");
        self.root.print(1);
    }

    fn ensure_contains(&mut self, t: &T) {
        while !self.root.span.contains(&t) {
            let new_span = self.root.span.expand(&self.root.span.dir_of(&t).unwrap());
            let mut new_root = Node::new(new_span);
            for (dir, span) in new_root.span.split() {
                if span == self.root.span {
                    mem::swap(&mut self.root, &mut new_root);
                    self.root.children.insert(dir.clone(), Child::Inner(Box::new(new_root)));
                    break;
                }
                // unreachable!();
            }
        }
    }

    pub fn scan(&self, span: &S) -> Vec<T> {
        return self.root.scan(span);
    }

    pub fn contains(&self, t: &T) -> bool {
        return self.root.contains(t);
    }

    pub fn remove(&self, t: &T) -> bool {
        unimplemented!();
    }
}

#[derive(Debug)]
struct Node<S, T: Sized + Debug> {
    span: S,
    children: HashMap<Dir, Child<S, T>>
}

impl<S: Span<S, T> + Debug, T: Debug + Clone + PartialEq> Node<S, T> {

    fn new(span: S) -> Node<S, T> {
        return Node {
            span: span,
            children: HashMap::new()
        };
    }

    fn add(&mut self, t: T) {
        let mut sub_spans = self.span.split();
        for (key, span) in sub_spans.drain() {
            if span.contains(&t) {
                let old_child = self.children.remove(&key);
                let new_child = self.new_child(span, old_child, t);
                self.children.insert(key, new_child);
                return;
            }
        }
        unreachable!("Tried to add {:?} to node with span {:?}", t, self.span);
    }

    fn new_child(&self, span: S, child: Option<Child<S, T>>, t: T) -> Child<S, T> {
        return match child {
            None => Child::Leaf(span, vec![t]),
            Some(c) => {
                match c {
                    Child::Leaf(span, mut v) => {
                        if v.len() > 1 && self.span.can_split() {
                            let mut new_node = Node::new(span);
                            for old_t in v.drain(RangeFull) {
                                new_node.add(old_t);
                            }
                            new_node.add(t);
                            Child::Inner(Box::new(new_node))
                        } else {
                            v.push(t);
                            Child::Leaf(span, v)
                        }
                    },
                    Child::Inner(mut b) => {
                        b.as_mut().add(t);
                        Child::Inner(b)
                    }
                }
            }
        };
    }

    fn print(&self, depth: usize) {
        println!("Node {:?}", self.span);
        let indent = String::from_utf8(vec![b' '; 4 * depth]).unwrap();
        for (key, child) in self.children.iter() {
            print!("{}{:?}: ", indent, key);
            match child {
                &Child::Inner(ref b) => b.as_ref().print(depth + 1),
                &Child::Leaf(_, ref v) => println!("{:?}", v),
            };
        }
    }

    fn scan(&self, span: &S) -> Vec<T> {
        if !self.span.overlaps(span) {
            return Vec::new();
        }
        let mut result: Vec<T> = Vec::new();
        for (_, child) in &self.children {
            match child {
                &Child::Leaf(_, ref v) => {
                    for t in v.iter().filter(|t| span.contains(&t)) {
                        result.push(t.clone());
                    }
                },
                &Child::Inner(ref b) => {
                    for t in b.as_ref().scan(span) {
                        result.push(t.clone());
                    }
                }
            };
        }
        return result;
    }

    fn contains(&self, t: &T) -> bool {
        if !self.span.contains(t) {
            return false;
        }
        for (_, child) in &self.children {
            match child {
                &Child::Leaf(_, ref v) => {
                    if v.contains(t) {
                        return true;
                    }
                },
                &Child::Inner(ref b) => {
                    if b.as_ref().contains(t) {
                        return true;
                    }
                }
            };
        }
        return false;
    }
}

#[derive(Debug)]
enum Child<S, T: Sized + Debug> {
    Inner(Box<Node<S, T>>),
    Leaf(S, Vec<T>)
}

#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum Dir { N, S, E, W, NE, NW, SE, SW }

pub trait Span<S: Span<S, T>, T>: Clone + Eq + PartialEq {

    /// The direction of `t` in relation to `self`, or `None` if
    /// `self` `contains` `t`.
    fn dir_of(&self, t: &T) -> Option<Dir>;

    /// The span of equal size to the north of `self`.
    fn north_span(&self) -> S;

    /// The span of equal size to the south of `self`.
    fn south_span(&self) -> S;

    /// The span of equal size to the east of `self`.
    fn east_span(&self) -> S;

    /// The span of equal size to the west of `self`.
    fn west_span(&self) -> S;

    /// Returns a new `S` with double the size of `self` expanded
    /// in the direction `dir`.
    fn expand(&self, dir: &Dir) -> S;

    /// Returns a partition of `self` with four blocks.
    /// The partition of the result of `expand` must contain the
    /// original `S`.
    fn split(&self) -> HashMap<Dir, S>;

    /// Returns true if the span can be split, e.g., if the span is
    /// represented by integers and the width and height is larger than `1`.
    fn can_split(&self) -> bool;

    /// Not implemented!
    fn merge(spans: Values<Dir, S>) -> S;

    /// Returns `true` if `self` overlaps with `other`, otherwise `false`.
    /// Used for `QuadTree.scan`.
    fn overlaps(&self, other: &S) -> bool;

    /// Returns `true` if `self` contains `t`, otherwise `false`.
    fn contains(&self, t: &T) -> bool {
        return self.dir_of(t) == None;
    }
}
<|endoftext|>


<commit_before>use std::fmt;

pub struct RawCodeItem {
    pub name: String,
    pub attributes: Vec<(String, String)>,
    pub children: Vec<RawCodeItem>
}

impl RawCodeItem {
    pub fn new(item_name: &str, item_attribs: Vec<(String, String)>) -> RawCodeItem {
        RawCodeItem {
            name: String::from(item_name),
            attributes: item_attribs,
            children: Vec::<RawCodeItem>::new()
        }
    }
}

pub struct RawCode {
    pub elements: Vec<RawCodeItem>
}

impl RawCode {
    pub fn new() -> RawCode {
        RawCode {
            elements: Vec::<RawCodeItem>::new()
        }
    }

    // convert raw data to cpp code
    pub fn to_cpp(&self) -> u8 {
        0
    }

    // convert raw data to Rust code
    pub fn to_rust(&self) -> u8 {
        0
    }

    // used by Display trait to print the tree of elements
    fn print_element(&self, e: &RawCodeItem, f: &mut fmt::Formatter, depth: u8, empty_spaces: &mut Vec<u8>) {
        // indentation
        for i in 0..depth {
            let idx = empty_spaces.binary_search(&i);
            let separator = match idx { Ok(_) => { " " }, _ => { "|" } };
            let _ = write!(f, "{}  ", separator);
        }

        let _ = write!(f, "|--{}", e.name);
        // print attributes
        if e.attributes.len() > 0 {
            let _ = write!(f, " [");
            for a in 0..e.attributes.len() {
                if a > 0 && a < e.attributes.len() {
                    let _ = write!(f, ", ");
                }
                let _ = write!(f, "{}:\"{}\"", e.attributes[a].0, e.attributes[a].1);
            }
            let _ = write!(f, "]");
        }
        let _ = write!(f, "\n");

        // child processing
        if e.children.len() > 0 {
            for c in 0..e.children.len() {
                if (e.children.len() - c) == 1 {
                    empty_spaces.push(depth+1);
                }
                else {
                    let idx = empty_spaces.binary_search(&(depth+1));
                    match idx { Ok(_) => { empty_spaces.remove(idx.unwrap()); }, _ => {} };
                }
                self.print_element(&e.children[c], f, depth+1, empty_spaces);
            }

            // reset space directory when topmost child is reached
            if depth == 1 {
                empty_spaces.clear();
            }
        }
    }
}

impl fmt::Display for RawCode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let _ = write!(f, "\n");
        for e in 0..self.elements.len() {
            let mut empty_spaces = Vec::<u8>::new();
            let _ = self.print_element(&self.elements[e], f, 0, &mut empty_spaces);
        }
        write!(f, "\n")
    }
}
<commit_msg>fixed bug with tree drawing<commit_after>use std::fmt;

pub struct RawCodeItem {
    pub name: String,
    pub attributes: Vec<(String, String)>,
    pub children: Vec<RawCodeItem>
}

impl RawCodeItem {
    pub fn new(item_name: &str, item_attribs: Vec<(String, String)>) -> RawCodeItem {
        RawCodeItem {
            name: String::from(item_name),
            attributes: item_attribs,
            children: Vec::<RawCodeItem>::new()
        }
    }
}

pub struct RawCode {
    pub elements: Vec<RawCodeItem>
}

impl RawCode {
    pub fn new() -> RawCode {
        RawCode {
            elements: Vec::<RawCodeItem>::new()
        }
    }

    // convert raw data to cpp code
    pub fn to_cpp(&self) -> u8 {
        0
    }

    // convert raw data to Rust code
    pub fn to_rust(&self) -> u8 {
        0
    }

    // used by Display trait to print the tree of elements
    fn print_element(&self, e: &RawCodeItem, f: &mut fmt::Formatter, depth: u8, empty_spaces: &mut Vec<u8>) {
        // indentation
        for i in 0..depth {
            let mut separator = "|";
            for j in empty_spaces.iter() {
                if i == *j {
                    separator = " ";
                    break;
                }
            }
            let _ = write!(f, "{}  ", separator);
        }

        let _ = write!(f, "|--{}", e.name);
        // print attributes
        if e.attributes.len() > 0 {
            let _ = write!(f, " [");
            for a in 0..e.attributes.len() {
                if a > 0 && a < e.attributes.len() {
                    let _ = write!(f, ", ");
                }
                let _ = write!(f, "{}:\"{}\"", e.attributes[a].0, e.attributes[a].1);
            }
            let _ = write!(f, "]");
        }
        let _ = write!(f, "\n");

        // child processing
        if e.children.len() > 0 {
            for c in 0..e.children.len() {
                if (e.children.len() - c) == 1 {
                    empty_spaces.push(depth+1);
                }
                else {
                    empty_spaces.sort();
                    let idx = empty_spaces.binary_search(&(depth+1));
                    match idx { Ok(_) => { empty_spaces.remove(idx.unwrap()); }, _ => {} };
                }
                self.print_element(&e.children[c], f, depth+1, empty_spaces);
            }

            // reset space directory when topmost child is reached
            if depth == 1 {
                empty_spaces.clear();
            }
        }
    }
}

impl fmt::Display for RawCode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let _ = write!(f, "\n");
        for e in 0..self.elements.len() {
            let mut empty_spaces = Vec::<u8>::new();
            let _ = self.print_element(&self.elements[e], f, 0, &mut empty_spaces);
        }
        write!(f, "\n")
    }
}
<|endoftext|>


<commit_before>#![deny(unsafe_op_in_unsafe_fn)]

use crate::sync::Once;
use crate::sys;
use crate::sys_common::thread_info;
use crate::thread::Thread;

// One-time runtime initialization.
// Runs before `main`.
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
#[cfg_attr(test, allow(dead_code))]
pub unsafe fn init(argc: isize, argv: *const *const u8) {
    unsafe {
        sys::init(argc, argv);

        let main_guard = sys::thread::guard::init();
        // Next, set up the current Thread with the guard information we just
        // created. Note that this isn't necessary in general for new threads,
        // but we just do this to name the main thread and to give it correct
        // info about the stack bounds.
        let thread = Thread::new(Some("main".to_owned()));
        thread_info::set(main_guard, thread);
    }
}

// One-time runtime cleanup.
// Runs after `main` or at program exit.
// NOTE: this is not guaranteed to run, for example when the program aborts.
#[cfg_attr(test, allow(dead_code))]
pub fn cleanup() {
    static CLEANUP: Once = Once::new();
    CLEANUP.call_once(|| unsafe {
        // Flush stdout and disable buffering.
        crate::io::cleanup();
        // SAFETY: Only called once during runtime cleanup.
        sys::cleanup();
    });
}

macro_rules! rtabort {
    ($($t:tt)*) => (crate::sys_common::util::abort(format_args!($($t)*)))
}

macro_rules! rtassert {
    ($e:expr) => {
        if !$e {
            rtabort!(concat!("assertion failed: ", stringify!($e)));
        }
    };
}

#[allow(unused_macros)] // not used on all platforms
macro_rules! rtunwrap {
    ($ok:ident, $e:expr) => {
        match $e {
            $ok(v) => v,
            ref err => {
                let err = err.as_ref().map(drop); // map Ok/Some which might not be Debug
                rtabort!(concat!("unwrap failed: ", stringify!($e), " = {:?}"), err)
            }
        }
    };
}
<commit_msg>Introduce `sys_common::rt::rterr!`<commit_after>#![deny(unsafe_op_in_unsafe_fn)]
#![allow(unused_macros)]

use crate::sync::Once;
use crate::sys;
use crate::sys_common::thread_info;
use crate::thread::Thread;

// One-time runtime initialization.
// Runs before `main`.
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
#[cfg_attr(test, allow(dead_code))]
pub unsafe fn init(argc: isize, argv: *const *const u8) {
    unsafe {
        sys::init(argc, argv);

        let main_guard = sys::thread::guard::init();
        // Next, set up the current Thread with the guard information we just
        // created. Note that this isn't necessary in general for new threads,
        // but we just do this to name the main thread and to give it correct
        // info about the stack bounds.
        let thread = Thread::new(Some("main".to_owned()));
        thread_info::set(main_guard, thread);
    }
}

// One-time runtime cleanup.
// Runs after `main` or at program exit.
// NOTE: this is not guaranteed to run, for example when the program aborts.
#[cfg_attr(test, allow(dead_code))]
pub fn cleanup() {
    static CLEANUP: Once = Once::new();
    CLEANUP.call_once(|| unsafe {
        // Flush stdout and disable buffering.
        crate::io::cleanup();
        // SAFETY: Only called once during runtime cleanup.
        sys::cleanup();
    });
}

macro_rules! rterr {
    ($($t:tt)*) => {
        if let Some(mut out) = crate::sys::stdio::panic_output() {
            let _ = crate::io::Write::write_fmt(&mut out, format_args!($($t)*));
        }
    }
}

macro_rules! rtabort {
    ($($t:tt)*) => (crate::sys_common::util::abort(format_args!($($t)*)))
}

macro_rules! rtassert {
    ($e:expr) => {
        if !$e {
            rtabort!(concat!("assertion failed: ", stringify!($e)));
        }
    };
}

macro_rules! rtunwrap {
    ($ok:ident, $e:expr) => {
        match $e {
            $ok(v) => v,
            ref err => {
                let err = err.as_ref().map(drop); // map Ok/Some which might not be Debug
                rtabort!(concat!("unwrap failed: ", stringify!($e), " = {:?}"), err)
            }
        }
    };
}
<|endoftext|>


<commit_before>use ::xflow::xfstruct::*;
// use ::xflow::errors::*;

pub struct ValidationError {
    pub code:    i32,
    pub message: String,
    pub paths:   Vec<String>,
}

impl ValidationError {
    /// Constructs a new `ValidationError`
    ///
    /// # Example
    /// ```
    /// use xfdocs::xflow::validation::{ValidationError};
    /// let err = ValidationError::new(1, "sample error".to_string(), Vec::<String>::new());
    /// println!("Validation error {}", err.message);
    /// ```
    pub fn new(code:i32, message:String, paths:Vec<String>) -> ValidationError {
        ValidationError {
            code:    code,
            message: message,
            paths:   paths
        }
    }
}

pub struct Validation {
    pub errors: Vec<ValidationError>,
}

impl Validation {

    pub fn new() -> Validation {
        Validation {
            errors: Vec::<ValidationError>::new()
        }
    }

   pub fn validate(&self, xflow:&XFlowStruct) {
       Validation::all_edges_have_nodes(xflow);
       Validation::has_one_entry_node(xflow);
       Validation::has_terminal_nodes(xflow);
   }

    pub fn all_edges_have_nodes(xflow:&XFlowStruct) -> Vec<ValidationError> {
        let mut errors = Vec::<ValidationError>::new();

        let mut node_ids = xflow.nodes.iter().map({|node|
            node.id.clone()
        }).collect::<Vec<i32>>();

        node_ids.sort();
        node_ids.dedup();

        for edge in xflow.edges.iter() {

            if !node_ids.contains(&edge.0) {
                errors.push(ValidationError {
                    code:    1,
                    message: format!("Edge {:?} has no connecting node {:?}", edge, edge.0),
                    paths:   vec![format!("/edges/{:?}", edge)],
                });
            };

            if !node_ids.contains(&edge.1) {
                errors.push(ValidationError {
                    code:    1,
                    message: format!("Edge {:?} has no connecting node {:?}", edge, edge.1),
                    paths:   vec![format!("/edges/{:?}", edge)],
                });
            };
        }

       errors
   }

    pub fn has_one_entry_node(xflow:&XFlowStruct) -> Vec<ValidationError> {
        let mut errors = Vec::<ValidationError>::new();

        let res = xflow.get_nodes_by("flow", "start");
        match res.len() {
            0 => {
                errors.push(ValidationError {
                    code:    1,
                    message: format!("XFlow has no entry nodes"),
                    paths:   vec![format!("/nodes")],
                });
            },
            1 => {},
            _ => {
                //
                // XXX: Add multiple paths
                //
                errors.push(ValidationError {
                    code:    1,
                    message: format!("XFlow has multiple entry nodes"),
                    paths:   vec!["/nodes".to_string()],
                });
            }
        }

        errors
    }

    pub fn has_terminal_nodes(xflow:&XFlowStruct) -> Vec<ValidationError> {
        let mut errors = Vec::<ValidationError>::new();

        let res = xflow.get_nodes_by("flow", "end");
        match res.len() {
            0 => {
                errors.push(ValidationError {
                    code:    1,
                    message: format!("XFlow has no terminal nodes"),
                    paths:   vec![format!("/nodes")],
                });
            }
            _ => {}
        }

        errors

    }

    pub fn all_nodes_have_at_least_one_edge(xflow:&XFlowStruct) -> Vec<ValidationError> {
        let mut errors = Vec::<ValidationError>::new();

        for node in xflow.nodes.iter() {
            let res = xflow.edges.iter().filter({|edge|
                node.id == edge.0 ||
                    node.id == edge.1
            }).collect::<Vec<&XFlowEdge>>();

            if res.len() > 0 {
                //
                // XXX: Handle multiple
                //
                errors.push(ValidationError {
                    code:    1,
                    message: format!("XFlow node is not connected to an edge"),
                    paths:   vec![format!("/nodes")],
                });
            }
        }

        errors
    }

//     X  all_edges_have_nodes(flow),
//     X  has_one_entry_node(flow),
//     X  has_terminal_nodes(flow),
//        all_node_actions_have_matching_requirements(flow),
//        expressions_reference_known_variables(flow),
//        all_return_values_exist(flow),
//        variables_are_defined_only_once(flow),
//        all_nodes_have_at_least_one_edge(flow)
}
<commit_msg>Fix validation test, update error message<commit_after>use ::xflow::xfstruct::*;
// use ::xflow::errors::*;

pub struct ValidationError {
    pub code:    i32,
    pub message: String,
    pub paths:   Vec<String>,
}

impl ValidationError {
    /// Constructs a new `ValidationError`
    ///
    /// # Example
    /// ```
    /// use xfdocs::xflow::validation::{ValidationError};
    /// let err = ValidationError::new(1, "sample error".to_string(), Vec::<String>::new());
    /// println!("Validation error {}", err.message);
    /// ```
    pub fn new(code:i32, message:String, paths:Vec<String>) -> ValidationError {
        ValidationError {
            code:    code,
            message: message,
            paths:   paths
        }
    }
}

pub struct Validation {
    pub errors: Vec<ValidationError>,
}

impl Validation {

    pub fn new() -> Validation {
        Validation {
            errors: Vec::<ValidationError>::new()
        }
    }

   pub fn validate(&self, xflow:&XFlowStruct) {
       Validation::all_edges_have_nodes(xflow);
       Validation::has_one_entry_node(xflow);
       Validation::has_terminal_nodes(xflow);
   }

    pub fn all_edges_have_nodes(xflow:&XFlowStruct) -> Vec<ValidationError> {
        let mut errors = Vec::<ValidationError>::new();

        let mut node_ids = xflow.nodes.iter().map({|node|
            node.id.clone()
        }).collect::<Vec<i32>>();

        node_ids.sort();
        node_ids.dedup();

        for edge in xflow.edges.iter() {

            if !node_ids.contains(&edge.0) {
                errors.push(ValidationError {
                    code:    1,
                    message: format!("Edge {:?} has no connecting node {:?}", edge, edge.0),
                    paths:   vec![format!("/edges/{:?}", edge)],
                });
            };

            if !node_ids.contains(&edge.1) {
                errors.push(ValidationError {
                    code:    1,
                    message: format!("Edge {:?} has no connecting node {:?}", edge, edge.1),
                    paths:   vec![format!("/edges/{:?}", edge)],
                });
            };
        }

       errors
   }

    pub fn has_one_entry_node(xflow:&XFlowStruct) -> Vec<ValidationError> {
        let mut errors = Vec::<ValidationError>::new();

        let res = xflow.get_nodes_by("flow", "start");
        match res.len() {
            0 => {
                errors.push(ValidationError {
                    code:    1,
                    message: format!("XFlow has no entry nodes"),
                    paths:   vec![format!("/nodes")],
                });
            },
            1 => {},
            _ => {
                //
                // XXX: Add multiple paths
                //
                errors.push(ValidationError {
                    code:    1,
                    message: format!("XFlow has multiple entry nodes"),
                    paths:   vec!["/nodes".to_string()],
                });
            }
        }

        errors
    }

    pub fn has_terminal_nodes(xflow:&XFlowStruct) -> Vec<ValidationError> {
        let mut errors = Vec::<ValidationError>::new();

        let res = xflow.get_nodes_by("flow", "end");
        match res.len() {
            0 => {
                errors.push(ValidationError {
                    code:    1,
                    message: format!("XFlow has no terminal nodes"),
                    paths:   vec![format!("/nodes")],
                });
            }
            _ => {}
        }

        errors

    }

    pub fn all_nodes_have_at_least_one_edge(xflow:&XFlowStruct) -> Vec<ValidationError> {
        let mut errors = Vec::<ValidationError>::new();

        for node in xflow.nodes.iter() {
            let res = xflow.edges.iter().filter({|edge|
                node.id == edge.0 ||
                    node.id == edge.1
            }).collect::<Vec<&XFlowEdge>>();

            if res.len() == 0 {
                errors.push(ValidationError {
                    code:    1,
                    message: format!("XFlow node '{}' is not connected to an edge", node.id),
                    paths:   vec![format!("/nodes/{}", node.id)],
                });
            }
        }

        errors
    }

//     X  all_edges_have_nodes(flow),
//     X  has_one_entry_node(flow),
//     X  has_terminal_nodes(flow),
//        all_node_actions_have_matching_requirements(flow),
//        expressions_reference_known_variables(flow),
//        all_return_values_exist(flow),
//        variables_are_defined_only_once(flow),
//        all_nodes_have_at_least_one_edge(flow)
}
<|endoftext|>


<commit_before>//! Labels interface

use hyper::client::connect::Connect;

use self::super::{AuthenticationConstraint, Future, Github, MediaType};

pub struct App<C>
where
    C: Clone + Connect + 'static,
{
    github: Github<C>,
}

impl<C> App<C>
where
    C: Clone + Connect + 'static,
{
    #[doc(hidden)]
    pub(crate) fn new(github: Github<C>) -> Self {
        App { github: github }
    }

    fn path(&self, more: &str) -> String {
        format!("/app{}", more)
    }

    pub fn make_access_token(&self, installation_id: u64) -> Future<AccessToken> {
        self.github.post_media::<AccessToken>(
            &self.path(&format!("/installations/{}/access_tokens", installation_id)),
            Vec::new(),
            MediaType::Preview("machine-man"),
            AuthenticationConstraint::JWT,
        )
    }
}

// representations

#[derive(Debug, Deserialize)]
pub struct AccessToken {
    pub token: String,
    pub expires_at: String,
}
<commit_msg>Add App::find_repo_installation<commit_after>//! Labels interface

use hyper::client::connect::Connect;

use self::super::{AuthenticationConstraint, Future, Github, MediaType};

pub struct App<C>
where
    C: Clone + Connect + 'static,
{
    github: Github<C>,
}

impl<C> App<C>
where
    C: Clone + Connect + 'static,
{
    #[doc(hidden)]
    pub(crate) fn new(github: Github<C>) -> Self {
        App { github: github }
    }

    fn path(&self, more: &str) -> String {
        format!("/app{}", more)
    }

    pub fn make_access_token(&self, installation_id: u64) -> Future<AccessToken> {
        self.github.post_media::<AccessToken>(
            &self.path(&format!("/installations/{}/access_tokens", installation_id)),
            Vec::new(),
            MediaType::Preview("machine-man"),
            AuthenticationConstraint::JWT,
        )
    }

    pub fn find_repo_installation<O, R>(&self, owner: O, repo: R) -> Future<Installation>
    where
        O: Into<String>,
        R: Into<String> {
        self.github.get_media::<Installation>(
            &format!("/repos/{}/{}/installation", owner.into(), repo.into()),
            MediaType::Preview("machine-man"),
        )
    }
}

// representations

#[derive(Debug, Deserialize)]
pub struct AccessToken {
    pub token: String,
    pub expires_at: String,
}

#[derive(Debug, Deserialize)]
pub struct Installation {
    pub id: u64,
    // account: Account
    pub access_tokens_url: String,
    pub repositories_url: String,
    pub html_url: String,
    pub app_id: i32,
    pub target_id: i32,
    pub target_type: String,
    // permissions: Permissions
    pub events: Vec<String>,
    // created_at, updated_at
    pub single_file_name: Option<String>,
    pub repository_selection: String,
}
<|endoftext|>


<commit_before>
use std::ffi;
use std::path::Path;

use url::Url;

pub mod record;
pub mod header;

use htslib;
use bcf::header::{HeaderView, SampleSubset};

pub use bcf::header::Header;
pub use bcf::record::Record;

pub struct Reader {
    inner: *mut htslib::vcf::htsFile,
    pub header: HeaderView,
}

unsafe impl Send for Reader {}

impl Reader {

    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Self, BCFPathError> {
        match path.as_ref().to_str() {
            Some(p) if path.as_ref().exists() => {
                Ok(try!(Self::new(p.as_bytes())))
            },
            _ => {
                Err(BCFPathError::InvalidPath)
            }
        }
    }

    pub fn from_url(url: &Url) -> Result<Self, BCFError> {
        Self::new(url.as_str().as_bytes())
    }

    pub fn from_stdin() -> Result<Self, BCFError> {
        Self::new(b"-")
    }

    fn new(path: &[u8]) -> Result<Self, BCFError> {
        let htsfile = try!(bcf_open(path, b"r"));
        let header = unsafe { htslib::vcf::bcf_hdr_read(htsfile) };
        Ok(Reader { inner: htsfile, header: HeaderView::new(header) })
    }

    pub fn read(&self, record: &mut record::Record) -> Result<(), ReadError> {
        match unsafe { htslib::vcf::bcf_read(self.inner, self.header.inner, record.inner) } {
            0  => {
                record.header = self.header.inner;
                Ok(())
            },
            -1 => Err(ReadError::NoMoreRecord),
            _  => Err(ReadError::Invalid),
        }
    }

    pub fn records(&self) -> Records {
        Records { reader: self }
    }
}

impl Drop for Reader {
    fn drop(&mut self) {
        unsafe {
            htslib::vcf::bcf_hdr_destroy(self.header.inner);
            htslib::vcf::hts_close(self.inner);
        }
    }
}

pub struct Writer {
    inner: *mut htslib::vcf::htsFile,
    pub header: HeaderView,
    subset: Option<SampleSubset>,
}

unsafe impl Send for Writer {}

impl Writer {
    pub fn from_path<P: AsRef<Path>>(path: P, header: &Header, uncompressed: bool, vcf: bool) -> Result<Self, BCFPathError> {
        if let Some(p) = path.as_ref().to_str() {
            Ok(try!(Self::new(p.as_bytes(), header, uncompressed, vcf)))
        } else {
            Err(BCFPathError::InvalidPath)
        }
    }

    pub fn from_url(url: &Url, header: &Header, uncompressed: bool, vcf: bool) -> Result<Self, BCFError> {
        Self::new(url.as_str().as_bytes(), header, uncompressed, vcf)
    }

    pub fn from_stdin(header: &Header, uncompressed: bool, vcf: bool) -> Result<Self, BCFError> {
        Self::new(b"-", header, uncompressed, vcf)
    }

    fn new(path: &[u8], header: &Header, uncompressed: bool, vcf: bool) -> Result<Self, BCFError> {
        let mode: &[u8] = match (uncompressed, vcf) {
            (true, true)   => b"w",
            (false, true)  => b"wz",
            (true, false)  => b"wu",
            (false, false) => b"wb",
        };

        let htsfile = try!(bcf_open(path, mode));
        unsafe { htslib::vcf::bcf_hdr_write(htsfile, header.inner) };
        Ok(Writer {
            inner: htsfile,
            header: HeaderView::new(unsafe { htslib::vcf::bcf_hdr_dup(header.inner) }),
            subset: header.subset.clone()
        })
    }

    /// Translate record to header of this writer.
    pub fn translate(&mut self, record: &mut record::Record) {
        unsafe {
            htslib::vcf::bcf_translate(self.header.inner, record.header, record.inner);
        }
        record.header = self.header.inner;
    }

    /// Subset samples of record to match header of this writer.
    pub fn subset(&mut self, record: &mut record::Record) {
        match self.subset {
            Some(ref mut subset) => unsafe {
                htslib::vcf::bcf_subset(self.header.inner, record.inner, subset.len() as i32, subset.as_mut_ptr());
            },
            None         => ()
        }
    }

    pub fn write(&mut self, record: &record::Record) -> Result<(), WriteError> {
        if unsafe { htslib::vcf::bcf_write(self.inner, self.header.inner, record.inner) } == -1 {
            Err(WriteError::WriteError)
        }
        else {
            Ok(())
        }
    }
}

impl Drop for Writer {
    fn drop(&mut self) {
        unsafe {
            htslib::vcf::bcf_hdr_destroy(self.header.inner);
            htslib::vcf::hts_close(self.inner);
        }
    }
}

pub struct Records<'a> {
    reader: &'a Reader,
}

impl<'a> Iterator for Records<'a> {
    type Item = Result<record::Record, ReadError>;

    fn next(&mut self) -> Option<Result<record::Record, ReadError>> {
        let mut record = record::Record::new();
        match self.reader.read(&mut record) {
            Err(ReadError::NoMoreRecord) => None,
            Err(e)                       => Some(Err(e)),
            Ok(())                       => Some(Ok(record)),
        }
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum BCFError {
        Some {
            description("error reading BCF/VCF file")
        }
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum BCFPathError {
        InvalidPath {
            description("invalid path")
        }
        BCFError(err: BCFError) {
            from()
        }
    }
}

/// Wrapper for opening a BCF file.
fn bcf_open(path: &[u8], mode: &[u8]) -> Result<*mut htslib::vcf::htsFile, BCFError> {
    let p = ffi::CString::new(path).unwrap();
    let ret = unsafe {
        htslib::vcf::hts_open(
            p.as_ptr(),
            ffi::CString::new(mode).unwrap().as_ptr()
        )
    };
    if ret.is_null() {
        Err(BCFError::Some)
    } else {
        Ok(ret)
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum ReadError {
        Invalid {
            description("invalid record")
        }
        NoMoreRecord {
            description("no more record")
        }
    }
}

impl ReadError {
    /// Returns true if no record has been read because the end of the file was reached.
    pub fn is_eof(&self) -> bool {
        match self {
            &ReadError::NoMoreRecord => true,
            _ => false
        }
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum WriteError {
        WriteError {
            description("failed to write record")
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate tempdir;
    use super::*;
    use std::path::Path;
    use bcf::record::Numeric;

    fn _test_read<P: AsRef<Path>>(path: &P) {
        let bcf = Reader::from_path(path).ok().expect("Error opening file.");
        assert_eq!(bcf.header.samples(), [b"NA12878.subsample-0.25-0"]);

        for (i, rec) in bcf.records().enumerate() {
            let mut record = rec.ok().expect("Error reading record.");
            assert_eq!(record.sample_count(), 1);

            assert_eq!(record.rid().expect("Error reading rid."), 0);
            assert_eq!(record.pos(), 10021 + i as u32);
            assert_eq!(record.qual(), 0f32);
            assert_eq!(record.info(b"MQ0F").float().ok().expect("Error reading info.").expect("Missing tag"), [1.0]);
            if i == 59 {
                assert_eq!(record.info(b"SGB").float().ok().expect("Error reading info.").expect("Missing tag"), [-0.379885]);
            }
            // the artificial "not observed" allele is present in each record.
            assert_eq!(record.alleles().iter().last().unwrap(), b"<X>");

            let mut fmt = record.format(b"PL");
            let pl = fmt.integer().ok().expect("Error reading format.");
            assert_eq!(pl.len(), 1);
            if i == 59 {
                assert_eq!(pl[0].len(), 6);
            }
            else {
                assert_eq!(pl[0].len(), 3);
            }
        }
    }

    #[test]
    fn test_read() {
        _test_read(&"test/test.bcf");
    }

    #[test]
    fn test_write() {
        let bcf = Reader::from_path(&"test/test_multi.bcf").ok().expect("Error opening file.");
        let tmp = tempdir::TempDir::new("rust-htslib").ok().expect("Cannot create temp dir");
        let bcfpath = tmp.path().join("test.bcf");
        println!("{:?}", bcfpath);
        {
            let header = Header::subset_template(&bcf.header, &[b"NA12878.subsample-0.25-0"]).ok().expect("Error subsetting samples.");
            let mut writer = Writer::from_path(&bcfpath, &header, false, false).ok().expect("Error opening file.");
            for rec in bcf.records() {
                let mut record = rec.ok().expect("Error reading record.");
                writer.translate(&mut record);
                writer.subset(&mut record);
                record.trim_alleles().ok().expect("Error trimming alleles.");
                writer.write(&record).ok().expect("Error writing record");
            }
        }
        {
            _test_read(&bcfpath);
        }
        tmp.close().ok().expect("Failed to delete temp dir");
    }

    #[test]
    fn test_strings() {
        let vcf = Reader::from_path(&"test/test_string.vcf").ok().expect("Error opening file.");
        let fs1 = [&b"LongString1"[..], &b"LongString2"[..], &b"."[..], &b"LongString4"[..], &b"evenlength"[..], &b"ss6"[..]];
        for (i, rec) in vcf.records().enumerate() {
            println!("record {}", i);
            let mut record = rec.ok().expect("Error reading record.");
            assert_eq!(record.info(b"S1").string().ok().expect("Error reading string.").expect("Missing tag")[0], format!("string{}", i + 1).as_bytes());
            println!("{}", String::from_utf8_lossy(record.format(b"FS1").string().ok().expect("Error reading string.")[0]));
            assert_eq!(record.format(b"FS1").string().ok().expect("Error reading string.")[0], fs1[i]);
        }
    }

    #[test]
    fn test_missing() {
        let vcf = Reader::from_path(&"test/test_missing.vcf").ok().expect("Error opening file.");
        let fn4 = [&[i32::missing(), i32::missing(), i32::missing(), i32::missing()][..], &[i32::missing()][..]];
        let f1 = [false, true];
        for (i, rec) in vcf.records().enumerate() {
            let mut record = rec.ok().expect("Error reading record.");
            assert_eq!(record.info(b"F1").float().ok().expect("Error reading float.").expect("Missing tag")[0].is_nan(), f1[i]);
            assert_eq!(record.format(b"FN4").integer().ok().expect("Error reading integer.")[1], fn4[i]);
            assert!(record.format(b"FF4").float().ok().expect("Error reading float.")[1].iter().all(|&v| v.is_missing()));
        }
    }

    #[test]
    fn test_genotypes() {
        let vcf = Reader::from_path(&"test/test_string.vcf").ok().expect("Error opening file.");
        let expected = ["./1", "1|1", "0/1", "0|1", "1|.", "1/1"];
        for (rec, exp_gt) in vcf.records().zip(expected.into_iter()) {
            let mut rec = rec.ok().expect("Error reading record.");
            let genotypes = rec.genotypes().expect("Error reading genotypes");
            assert_eq!(&format!("{}", genotypes.get(0)), exp_gt);
        }
    }
}
<commit_msg>Fix constructor name.<commit_after>
use std::ffi;
use std::path::Path;

use url::Url;

pub mod record;
pub mod header;

use htslib;
use bcf::header::{HeaderView, SampleSubset};

pub use bcf::header::Header;
pub use bcf::record::Record;

pub struct Reader {
    inner: *mut htslib::vcf::htsFile,
    pub header: HeaderView,
}

unsafe impl Send for Reader {}

impl Reader {

    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Self, BCFPathError> {
        match path.as_ref().to_str() {
            Some(p) if path.as_ref().exists() => {
                Ok(try!(Self::new(p.as_bytes())))
            },
            _ => {
                Err(BCFPathError::InvalidPath)
            }
        }
    }

    pub fn from_url(url: &Url) -> Result<Self, BCFError> {
        Self::new(url.as_str().as_bytes())
    }

    pub fn from_stdin() -> Result<Self, BCFError> {
        Self::new(b"-")
    }

    fn new(path: &[u8]) -> Result<Self, BCFError> {
        let htsfile = try!(bcf_open(path, b"r"));
        let header = unsafe { htslib::vcf::bcf_hdr_read(htsfile) };
        Ok(Reader { inner: htsfile, header: HeaderView::new(header) })
    }

    pub fn read(&self, record: &mut record::Record) -> Result<(), ReadError> {
        match unsafe { htslib::vcf::bcf_read(self.inner, self.header.inner, record.inner) } {
            0  => {
                record.header = self.header.inner;
                Ok(())
            },
            -1 => Err(ReadError::NoMoreRecord),
            _  => Err(ReadError::Invalid),
        }
    }

    pub fn records(&self) -> Records {
        Records { reader: self }
    }
}

impl Drop for Reader {
    fn drop(&mut self) {
        unsafe {
            htslib::vcf::bcf_hdr_destroy(self.header.inner);
            htslib::vcf::hts_close(self.inner);
        }
    }
}

pub struct Writer {
    inner: *mut htslib::vcf::htsFile,
    pub header: HeaderView,
    subset: Option<SampleSubset>,
}

unsafe impl Send for Writer {}

impl Writer {
    pub fn from_path<P: AsRef<Path>>(path: P, header: &Header, uncompressed: bool, vcf: bool) -> Result<Self, BCFPathError> {
        if let Some(p) = path.as_ref().to_str() {
            Ok(try!(Self::new(p.as_bytes(), header, uncompressed, vcf)))
        } else {
            Err(BCFPathError::InvalidPath)
        }
    }

    pub fn from_url(url: &Url, header: &Header, uncompressed: bool, vcf: bool) -> Result<Self, BCFError> {
        Self::new(url.as_str().as_bytes(), header, uncompressed, vcf)
    }

    pub fn from_stdout(header: &Header, uncompressed: bool, vcf: bool) -> Result<Self, BCFError> {
        Self::new(b"-", header, uncompressed, vcf)
    }

    fn new(path: &[u8], header: &Header, uncompressed: bool, vcf: bool) -> Result<Self, BCFError> {
        let mode: &[u8] = match (uncompressed, vcf) {
            (true, true)   => b"w",
            (false, true)  => b"wz",
            (true, false)  => b"wu",
            (false, false) => b"wb",
        };

        let htsfile = try!(bcf_open(path, mode));
        unsafe { htslib::vcf::bcf_hdr_write(htsfile, header.inner) };
        Ok(Writer {
            inner: htsfile,
            header: HeaderView::new(unsafe { htslib::vcf::bcf_hdr_dup(header.inner) }),
            subset: header.subset.clone()
        })
    }

    /// Translate record to header of this writer.
    pub fn translate(&mut self, record: &mut record::Record) {
        unsafe {
            htslib::vcf::bcf_translate(self.header.inner, record.header, record.inner);
        }
        record.header = self.header.inner;
    }

    /// Subset samples of record to match header of this writer.
    pub fn subset(&mut self, record: &mut record::Record) {
        match self.subset {
            Some(ref mut subset) => unsafe {
                htslib::vcf::bcf_subset(self.header.inner, record.inner, subset.len() as i32, subset.as_mut_ptr());
            },
            None         => ()
        }
    }

    pub fn write(&mut self, record: &record::Record) -> Result<(), WriteError> {
        if unsafe { htslib::vcf::bcf_write(self.inner, self.header.inner, record.inner) } == -1 {
            Err(WriteError::WriteError)
        }
        else {
            Ok(())
        }
    }
}

impl Drop for Writer {
    fn drop(&mut self) {
        unsafe {
            htslib::vcf::bcf_hdr_destroy(self.header.inner);
            htslib::vcf::hts_close(self.inner);
        }
    }
}

pub struct Records<'a> {
    reader: &'a Reader,
}

impl<'a> Iterator for Records<'a> {
    type Item = Result<record::Record, ReadError>;

    fn next(&mut self) -> Option<Result<record::Record, ReadError>> {
        let mut record = record::Record::new();
        match self.reader.read(&mut record) {
            Err(ReadError::NoMoreRecord) => None,
            Err(e)                       => Some(Err(e)),
            Ok(())                       => Some(Ok(record)),
        }
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum BCFError {
        Some {
            description("error reading BCF/VCF file")
        }
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum BCFPathError {
        InvalidPath {
            description("invalid path")
        }
        BCFError(err: BCFError) {
            from()
        }
    }
}

/// Wrapper for opening a BCF file.
fn bcf_open(path: &[u8], mode: &[u8]) -> Result<*mut htslib::vcf::htsFile, BCFError> {
    let p = ffi::CString::new(path).unwrap();
    let ret = unsafe {
        htslib::vcf::hts_open(
            p.as_ptr(),
            ffi::CString::new(mode).unwrap().as_ptr()
        )
    };
    if ret.is_null() {
        Err(BCFError::Some)
    } else {
        Ok(ret)
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum ReadError {
        Invalid {
            description("invalid record")
        }
        NoMoreRecord {
            description("no more record")
        }
    }
}

impl ReadError {
    /// Returns true if no record has been read because the end of the file was reached.
    pub fn is_eof(&self) -> bool {
        match self {
            &ReadError::NoMoreRecord => true,
            _ => false
        }
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum WriteError {
        WriteError {
            description("failed to write record")
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate tempdir;
    use super::*;
    use std::path::Path;
    use bcf::record::Numeric;

    fn _test_read<P: AsRef<Path>>(path: &P) {
        let bcf = Reader::from_path(path).ok().expect("Error opening file.");
        assert_eq!(bcf.header.samples(), [b"NA12878.subsample-0.25-0"]);

        for (i, rec) in bcf.records().enumerate() {
            let mut record = rec.ok().expect("Error reading record.");
            assert_eq!(record.sample_count(), 1);

            assert_eq!(record.rid().expect("Error reading rid."), 0);
            assert_eq!(record.pos(), 10021 + i as u32);
            assert_eq!(record.qual(), 0f32);
            assert_eq!(record.info(b"MQ0F").float().ok().expect("Error reading info.").expect("Missing tag"), [1.0]);
            if i == 59 {
                assert_eq!(record.info(b"SGB").float().ok().expect("Error reading info.").expect("Missing tag"), [-0.379885]);
            }
            // the artificial "not observed" allele is present in each record.
            assert_eq!(record.alleles().iter().last().unwrap(), b"<X>");

            let mut fmt = record.format(b"PL");
            let pl = fmt.integer().ok().expect("Error reading format.");
            assert_eq!(pl.len(), 1);
            if i == 59 {
                assert_eq!(pl[0].len(), 6);
            }
            else {
                assert_eq!(pl[0].len(), 3);
            }
        }
    }

    #[test]
    fn test_read() {
        _test_read(&"test/test.bcf");
    }

    #[test]
    fn test_write() {
        let bcf = Reader::from_path(&"test/test_multi.bcf").ok().expect("Error opening file.");
        let tmp = tempdir::TempDir::new("rust-htslib").ok().expect("Cannot create temp dir");
        let bcfpath = tmp.path().join("test.bcf");
        println!("{:?}", bcfpath);
        {
            let header = Header::subset_template(&bcf.header, &[b"NA12878.subsample-0.25-0"]).ok().expect("Error subsetting samples.");
            let mut writer = Writer::from_path(&bcfpath, &header, false, false).ok().expect("Error opening file.");
            for rec in bcf.records() {
                let mut record = rec.ok().expect("Error reading record.");
                writer.translate(&mut record);
                writer.subset(&mut record);
                record.trim_alleles().ok().expect("Error trimming alleles.");
                writer.write(&record).ok().expect("Error writing record");
            }
        }
        {
            _test_read(&bcfpath);
        }
        tmp.close().ok().expect("Failed to delete temp dir");
    }

    #[test]
    fn test_strings() {
        let vcf = Reader::from_path(&"test/test_string.vcf").ok().expect("Error opening file.");
        let fs1 = [&b"LongString1"[..], &b"LongString2"[..], &b"."[..], &b"LongString4"[..], &b"evenlength"[..], &b"ss6"[..]];
        for (i, rec) in vcf.records().enumerate() {
            println!("record {}", i);
            let mut record = rec.ok().expect("Error reading record.");
            assert_eq!(record.info(b"S1").string().ok().expect("Error reading string.").expect("Missing tag")[0], format!("string{}", i + 1).as_bytes());
            println!("{}", String::from_utf8_lossy(record.format(b"FS1").string().ok().expect("Error reading string.")[0]));
            assert_eq!(record.format(b"FS1").string().ok().expect("Error reading string.")[0], fs1[i]);
        }
    }

    #[test]
    fn test_missing() {
        let vcf = Reader::from_path(&"test/test_missing.vcf").ok().expect("Error opening file.");
        let fn4 = [&[i32::missing(), i32::missing(), i32::missing(), i32::missing()][..], &[i32::missing()][..]];
        let f1 = [false, true];
        for (i, rec) in vcf.records().enumerate() {
            let mut record = rec.ok().expect("Error reading record.");
            assert_eq!(record.info(b"F1").float().ok().expect("Error reading float.").expect("Missing tag")[0].is_nan(), f1[i]);
            assert_eq!(record.format(b"FN4").integer().ok().expect("Error reading integer.")[1], fn4[i]);
            assert!(record.format(b"FF4").float().ok().expect("Error reading float.")[1].iter().all(|&v| v.is_missing()));
        }
    }

    #[test]
    fn test_genotypes() {
        let vcf = Reader::from_path(&"test/test_string.vcf").ok().expect("Error opening file.");
        let expected = ["./1", "1|1", "0/1", "0|1", "1|.", "1/1"];
        for (rec, exp_gt) in vcf.records().zip(expected.into_iter()) {
            let mut rec = rec.ok().expect("Error reading record.");
            let genotypes = rec.genotypes().expect("Error reading genotypes");
            assert_eq!(&format!("{}", genotypes.get(0)), exp_gt);
        }
    }
}
<|endoftext|>


<commit_before>use crate::beacon_chain::BeaconChain;
use crate::error;
use crate::messages::NodeMessage;
use crate::service::NetworkMessage;
use crate::sync::SimpleSync;
use crossbeam_channel::{unbounded as channel, Sender};
use futures::future;
use futures::prelude::*;
use libp2p::{PeerId, RPCEvent};
use slog::debug;
use std::collections::HashMap;
use std::sync::Arc;
use std::time::{Duration, Instant};
use types::Hash256;

/// Timeout for establishing a HELLO handshake.
const HELLO_TIMEOUT: Duration = Duration::from_secs(30);

/// Handles messages received from the network and client and organises syncing.
pub struct MessageHandler {
    /// Currently loaded and initialised beacon chain.
    chain: Arc<BeaconChain>,
    /// The syncing framework.
    sync: SimpleSync,
    /// The network channel to relay messages to the Network service.
    network_send: crossbeam_channel::Sender<NetworkMessage>,
    /// A mapping of peers we have sent a HELLO rpc request to.
    hello_requests: HashMap<PeerId, Instant>,
    /// The `MessageHandler` logger.
    log: slog::Logger,
}

/// Types of messages the handler can receive.
#[derive(Debug, Clone)]
pub enum HandlerMessage {
    /// We have initiated a connection to a new peer.
    PeerDialed(PeerId),
    /// Peer has disconnected,
    PeerDisconnected(PeerId),
    /// A Node message has been received.
    Message(PeerId, NodeMessage),
    /// An RPC response/request has been received.
    RPC(RPCEvent),
}

impl MessageHandler {
    /// Initializes and runs the MessageHandler.
    pub fn new(
        beacon_chain: Arc<BeaconChain>,
        network_send: crossbeam_channel::Sender<NetworkMessage>,
        executor: &tokio::runtime::TaskExecutor,
        log: slog::Logger,
    ) -> error::Result<Sender<HandlerMessage>> {
        debug!(log, "Service starting");

        let (handler_send, handler_recv) = channel();

        // Initialise sync and begin processing in thread
        // generate the Message handler
        let sync = SimpleSync::new(beacon_chain.clone());

        let mut handler = MessageHandler {
            // TODO: The handler may not need a chain, perhaps only sync?
            chain: beacon_chain.clone(),
            sync,
            network_send,
            hello_requests: HashMap::new(),
            log: log.clone(),
        };

        // spawn handler task
        // TODO: Handle manual termination of thread
        executor.spawn(future::poll_fn(move || -> Result<_, _> {
            loop {
                handler.handle_message(handler_recv.recv().map_err(|_| {
                    debug!(log, "Network message handler terminated.");
                })?);
            }
        }));

        Ok(handler_send)
    }

    fn handle_message(&mut self, message: HandlerMessage) {
        match message {
            HandlerMessage::PeerDialed(peer_id) => {
                // register RPC request
                self.hello_requests.insert(peer_id.clone(), Instant::now());
                self.send_hello(peer_id);
            }
            //TODO: Handle all messages
            _ => {}
        }
    }

    /// Sends a HELLO RPC request to a newly connected peer.
    fn send_hello(&self, peer_id: PeerId) {
        // send the hello request to the network
        //sync.hello()
    }
}
<commit_msg>Adds RPC request send framework in message handler<commit_after>use crate::beacon_chain::BeaconChain;
use crate::error;
use crate::messages::NodeMessage;
use crate::service::NetworkMessage;
use crate::sync::SimpleSync;
use crossbeam_channel::{unbounded as channel, Sender};
use futures::future;
use futures::prelude::*;
use libp2p::{
    rpc::{RPCRequest, RPCResponse},
    PeerId, RPCEvent,
};
use slog::debug;
use std::collections::HashMap;
use std::sync::Arc;
use std::time::{Duration, Instant};
use types::Hash256;

/// Timeout for RPC requests.
const REQUEST_TIMEOUT: Duration = Duration::from_secs(30);

/// Handles messages received from the network and client and organises syncing.
pub struct MessageHandler {
    /// Currently loaded and initialised beacon chain.
    chain: Arc<BeaconChain>,
    /// The syncing framework.
    sync: SimpleSync,
    /// The network channel to relay messages to the Network service.
    network_send: crossbeam_channel::Sender<NetworkMessage>,
    /// A mapping of peers we have sent an RPC request to.
    requests: HashMap<PeerId, Vec<RPCRequestInfo>>,
    /// A counter of request id for each peer.
    request_ids: HashMap<PeerId, u16>,
    /// The `MessageHandler` logger.
    log: slog::Logger,
}

/// RPC request information
pub struct RPCRequestInfo {
    /// The id of the request
    id: u16,
    /// The time the request was sent, to check ttl.
    request_time: Instant,
}

/// Types of messages the handler can receive.
#[derive(Debug, Clone)]
pub enum HandlerMessage {
    /// We have initiated a connection to a new peer.
    PeerDialed(PeerId),
    /// Peer has disconnected,
    PeerDisconnected(PeerId),
    /// A Node message has been received.
    Message(PeerId, NodeMessage),
    /// An RPC response/request has been received.
    RPC(RPCEvent),
}

impl MessageHandler {
    /// Initializes and runs the MessageHandler.
    pub fn new(
        beacon_chain: Arc<BeaconChain>,
        network_send: crossbeam_channel::Sender<NetworkMessage>,
        executor: &tokio::runtime::TaskExecutor,
        log: slog::Logger,
    ) -> error::Result<Sender<HandlerMessage>> {
        debug!(log, "Service starting");

        let (handler_send, handler_recv) = channel();

        // Initialise sync and begin processing in thread
        // generate the Message handler
        let sync = SimpleSync::new(beacon_chain.clone());

        let mut handler = MessageHandler {
            // TODO: The handler may not need a chain, perhaps only sync?
            chain: beacon_chain.clone(),
            sync,
            network_send,
            requests: HashMap::new(),
            request_ids: HashMap::new(),
            log: log.clone(),
        };

        // spawn handler task
        // TODO: Handle manual termination of thread
        executor.spawn(future::poll_fn(move || -> Result<_, _> {
            loop {
                handler.handle_message(handler_recv.recv().map_err(|_| {
                    debug!(log, "Network message handler terminated.");
                })?);
            }
        }));

        Ok(handler_send)
    }

    fn handle_message(&mut self, message: HandlerMessage) {
        match message {
            HandlerMessage::PeerDialed(peer_id) => {
                self.send_hello(peer_id);
            }
            //TODO: Handle all messages
            _ => {}
        }
    }

    /// Sends a HELLO RPC request to a newly connected peer.
    fn send_hello(&mut self, peer_id: PeerId) {
        // generate a unique id for the peer
        let id = {
            let borrowed_id = self.request_ids.entry(peer_id.clone()).or_insert_with(|| 0);
            let id = borrowed_id.clone();
            //increment the counter
            *borrowed_id += 1;
            id
        };
        // register RPC request
        {
            let requests = self.requests.entry(peer_id).or_insert_with(|| vec![]);
            requests.push(RPCRequestInfo {
                id: id.clone(),
                request_time: Instant::now(),
            });
        }
        // send the hello request to the network
        self.send_rpc_request(id, RPCResponse::Hello(self.sync.generate_hello()));
    }

    /// Sends and RPC response
    fn send_rpc_request(&self, request_id: u16, response: RPCResponse) {}
}
<|endoftext|>