<commit_before>//! Performs topological sorting.

#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

use std::collections::{HashMap, HashSet};
use std::collections::hash_map::Entry;
use std::hash::Hash;

struct Dependency<T> {
    num_prec: uint,
    succ: HashSet<T>
}

impl<T: Hash + Eq> Dependency<T> {
    fn new() -> Dependency<T> { Dependency { num_prec: 0, succ: HashSet::new() } }
}

/// Performs topological sorting.
pub struct TopologicalSort<T> {
    top: HashMap<T, Dependency<T>>
}

impl<T: Hash + Eq + Clone> TopologicalSort<T> {
    /// Creates new empty `TopologicalSort`.
    ///
    /// ```rust
    /// use tsort::TopologicalSort;
    /// let mut ts = TopologicalSort::new();
    /// ts.add_dependency("hello_world.o", "hello_world");
    /// ts.add_dependency("hello_world.c", "hello_world");
    /// ts.add_dependency("stdio.h", "hello_world.o");
    /// ts.add_dependency("glibc.so", "hello_world");
    /// assert_eq!(vec!["glibc.so", "hello_world.c", "stdio.h"],
    ///            { let mut v = ts.pop_all(); v.sort(); v });
    /// assert_eq!(vec!["hello_world.o"],
    ///            { let mut v = ts.pop_all(); v.sort(); v });
    /// assert_eq!(vec!["hello_world"],
    ///            { let mut v = ts.pop_all(); v.sort(); v });
    /// assert!(ts.pop_all().is_empty());
    /// ```
    #[inline]
    pub fn new() -> TopologicalSort<T> { TopologicalSort { top: HashMap::new() } }

    /// Returns the number of elements in the `TopologicalSort`.
    #[inline]
    pub fn len(&self) -> uint { self.top.len() }

    /// Returns true if the `TopologicalSort` contains no elements.
    #[inline]
    pub fn is_empty(&self) -> bool { self.top.is_empty() }

    /// Registers the two elements' dependency.
    ///
    /// # Arguments
    ///
    /// * `prec` - The element appears before `succ`. `prec` is depended on by `succ`.
    /// * `succ` - The element appears after `prec`. `succ` depends on `prec`.
    pub fn add_dependency(&mut self, prec: T, succ: T) {
        match self.top.entry(prec) {
            Entry::Vacant(e) => {
                let mut dep = Dependency::new();
                dep.succ.insert(succ.clone());
                let _ = e.set(dep);
            },
            Entry::Occupied(mut e) => {
                let mut p = e.get_mut();
                if !p.succ.insert(succ.clone()) { // Already registered
                    return
                }
            }
        }

        match self.top.entry(succ) {
            Entry::Vacant(e) => {
                let mut dep = Dependency::new();
                dep.num_prec += 1;
                let _ = e.set(dep);
            }
            Entry::Occupied(mut e) => {
                let s = e.get_mut();
                s.num_prec += 1;
            }
        }
    }

    /// Removes the item that is not depended on by any other items and returns it, or `None` if there is no such item.
    ///
    /// If `pop` returns `None` and `len` is not 0, there is cyclic dependencies.
    pub fn pop(&mut self) -> Option<T> {
        self.top
            .iter()
            .filter(|&(_, v)| v.num_prec == 0)
            .next()
            .map(|(k, _)| k.clone())
            .map(|key| {
                let _ = self.remove(&key);
                key
            })
    }

    /// Removes all items that are not depended on by any other items and returns it, or empty vector if there are no such items.
    ///
    /// If `pop_all` returns an empty vector and `len` is not 0, there is cyclic dependencies.
    pub fn pop_all(&mut self) -> Vec<T> {
        let keys = self.top
            .iter()
            .filter(|&(_, v)| v.num_prec == 0)
            .map(|(k, _)| k.clone())
            .collect::<Vec<_>>();
        for k in keys.iter() {
            let _ = self.remove(k);
        }
        keys
    }

    fn remove(&mut self, prec: &T) -> Option<Dependency<T>> {
        let result = self.top.remove(prec);
        if let Some(ref p) = result {
            for s in p.succ.iter() {
                if let Some(y) = self.top.get_mut(s) {
                    y.num_prec -= 1;
                }
            }
        }
        result
    }
}

impl<T: Hash + Eq + Clone> Iterator<T> for TopologicalSort<T> {
    fn next(&mut self) -> Option<T> { self.pop() }
}

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

    #[test]
    fn iter() {
        let mut ts = TopologicalSort::<uint>::new();
        ts.add_dependency(1, 2);
        ts.add_dependency(2, 3);
        ts.add_dependency(3, 4);
        assert_eq!(Some(1), ts.next());
        assert_eq!(Some(2), ts.next());
        assert_eq!(Some(3), ts.next());
        assert_eq!(Some(4), ts.next());
        assert_eq!(None, ts.next());
    }

    #[test]
    fn pop_all() {
        fn check(result: &[uint], ts: &mut TopologicalSort<uint>) {
            let l = ts.len();
            let mut v = ts.pop_all();
            v.sort();
            assert_eq!(result, v);
            assert_eq!(l - result.len(), ts.len());
        }

        let mut ts = TopologicalSort::<uint>::new();
        ts.add_dependency(7, 11);
        assert_eq!(2, ts.len());
        ts.add_dependency(7, 8);
        assert_eq!(3, ts.len());
        ts.add_dependency(5, 11);
        assert_eq!(4, ts.len());
        ts.add_dependency(3, 8);
        assert_eq!(5, ts.len());
        ts.add_dependency(3, 10);
        assert_eq!(6, ts.len());
        ts.add_dependency(11, 2);
        assert_eq!(7, ts.len());
        ts.add_dependency(11, 9);
        assert_eq!(8, ts.len());
        ts.add_dependency(11, 10);
        assert_eq!(8, ts.len());
        ts.add_dependency(8, 9);
        assert_eq!(8, ts.len());

        check(&[3, 5, 7], &mut ts);
        check(&[8, 11], &mut ts);
        check(&[2, 9, 10], &mut ts);
        check(&[], &mut ts);
    }
}

<commit_msg>tsort: Remove `uint` or `int` usage as general integer<commit_after>//! Performs topological sorting.

#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

use std::collections::{HashMap, HashSet};
use std::collections::hash_map::Entry;
use std::hash::Hash;

struct Dependency<T> {
    num_prec: uint,
    succ: HashSet<T>
}

impl<T: Hash + Eq> Dependency<T> {
    fn new() -> Dependency<T> { Dependency { num_prec: 0, succ: HashSet::new() } }
}

/// Performs topological sorting.
pub struct TopologicalSort<T> {
    top: HashMap<T, Dependency<T>>
}

impl<T: Hash + Eq + Clone> TopologicalSort<T> {
    /// Creates new empty `TopologicalSort`.
    ///
    /// ```rust
    /// use tsort::TopologicalSort;
    /// let mut ts = TopologicalSort::new();
    /// ts.add_dependency("hello_world.o", "hello_world");
    /// ts.add_dependency("hello_world.c", "hello_world");
    /// ts.add_dependency("stdio.h", "hello_world.o");
    /// ts.add_dependency("glibc.so", "hello_world");
    /// assert_eq!(vec!["glibc.so", "hello_world.c", "stdio.h"],
    ///            { let mut v = ts.pop_all(); v.sort(); v });
    /// assert_eq!(vec!["hello_world.o"],
    ///            { let mut v = ts.pop_all(); v.sort(); v });
    /// assert_eq!(vec!["hello_world"],
    ///            { let mut v = ts.pop_all(); v.sort(); v });
    /// assert!(ts.pop_all().is_empty());
    /// ```
    #[inline]
    pub fn new() -> TopologicalSort<T> { TopologicalSort { top: HashMap::new() } }

    /// Returns the number of elements in the `TopologicalSort`.
    #[inline]
    pub fn len(&self) -> uint { self.top.len() }

    /// Returns true if the `TopologicalSort` contains no elements.
    #[inline]
    pub fn is_empty(&self) -> bool { self.top.is_empty() }

    /// Registers the two elements' dependency.
    ///
    /// # Arguments
    ///
    /// * `prec` - The element appears before `succ`. `prec` is depended on by `succ`.
    /// * `succ` - The element appears after `prec`. `succ` depends on `prec`.
    pub fn add_dependency(&mut self, prec: T, succ: T) {
        match self.top.entry(prec) {
            Entry::Vacant(e) => {
                let mut dep = Dependency::new();
                dep.succ.insert(succ.clone());
                let _ = e.set(dep);
            },
            Entry::Occupied(mut e) => {
                let mut p = e.get_mut();
                if !p.succ.insert(succ.clone()) { // Already registered
                    return
                }
            }
        }

        match self.top.entry(succ) {
            Entry::Vacant(e) => {
                let mut dep = Dependency::new();
                dep.num_prec += 1;
                let _ = e.set(dep);
            }
            Entry::Occupied(mut e) => {
                let s = e.get_mut();
                s.num_prec += 1;
            }
        }
    }

    /// Removes the item that is not depended on by any other items and returns it, or `None` if there is no such item.
    ///
    /// If `pop` returns `None` and `len` is not 0, there is cyclic dependencies.
    pub fn pop(&mut self) -> Option<T> {
        self.top
            .iter()
            .filter(|&(_, v)| v.num_prec == 0)
            .next()
            .map(|(k, _)| k.clone())
            .map(|key| {
                let _ = self.remove(&key);
                key
            })
    }

    /// Removes all items that are not depended on by any other items and returns it, or empty vector if there are no such items.
    ///
    /// If `pop_all` returns an empty vector and `len` is not 0, there is cyclic dependencies.
    pub fn pop_all(&mut self) -> Vec<T> {
        let keys = self.top
            .iter()
            .filter(|&(_, v)| v.num_prec == 0)
            .map(|(k, _)| k.clone())
            .collect::<Vec<_>>();
        for k in keys.iter() {
            let _ = self.remove(k);
        }
        keys
    }

    fn remove(&mut self, prec: &T) -> Option<Dependency<T>> {
        let result = self.top.remove(prec);
        if let Some(ref p) = result {
            for s in p.succ.iter() {
                if let Some(y) = self.top.get_mut(s) {
                    y.num_prec -= 1;
                }
            }
        }
        result
    }
}

impl<T: Hash + Eq + Clone> Iterator<T> for TopologicalSort<T> {
    fn next(&mut self) -> Option<T> { self.pop() }
}

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

    #[test]
    fn iter() {
        let mut ts = TopologicalSort::<i32>::new();
        ts.add_dependency(1, 2);
        ts.add_dependency(2, 3);
        ts.add_dependency(3, 4);
        assert_eq!(Some(1), ts.next());
        assert_eq!(Some(2), ts.next());
        assert_eq!(Some(3), ts.next());
        assert_eq!(Some(4), ts.next());
        assert_eq!(None, ts.next());
    }

    #[test]
    fn pop_all() {
        fn check(result: &[i32], ts: &mut TopologicalSort<i32>) {
            let l = ts.len();
            let mut v = ts.pop_all();
            v.sort();
            assert_eq!(result, v);
            assert_eq!(l - result.len(), ts.len());
        }

        let mut ts = TopologicalSort::new();
        ts.add_dependency(7, 11);
        assert_eq!(2, ts.len());
        ts.add_dependency(7, 8);
        assert_eq!(3, ts.len());
        ts.add_dependency(5, 11);
        assert_eq!(4, ts.len());
        ts.add_dependency(3, 8);
        assert_eq!(5, ts.len());
        ts.add_dependency(3, 10);
        assert_eq!(6, ts.len());
        ts.add_dependency(11, 2);
        assert_eq!(7, ts.len());
        ts.add_dependency(11, 9);
        assert_eq!(8, ts.len());
        ts.add_dependency(11, 10);
        assert_eq!(8, ts.len());
        ts.add_dependency(8, 9);
        assert_eq!(8, ts.len());

        check(&[3, 5, 7], &mut ts);
        check(&[8, 11], &mut ts);
        check(&[2, 9, 10], &mut ts);
        check(&[], &mut ts);
    }
}

<|endoftext|>


<commit_before>//! Library to read and write protocol buffers data.

// TODO: add docs
//#![deny(missing_docs)]

#[cfg(feature = "bytes")]
extern crate bytes;

pub use unknown::UnknownFields;
pub use unknown::UnknownFieldsIter;
pub use unknown::UnknownValue;
pub use unknown::UnknownValueRef;
pub use unknown::UnknownValues;
pub use unknown::UnknownValuesIter;
pub use repeated::RepeatedField;
pub use singular::SingularField;
pub use singular::SingularPtrField;
pub use clear::Clear;
pub use core::Message;
pub use core::ProtobufEnum;
pub use core::parse_from_bytes;
pub use core::parse_from_reader;
#[cfg(feature = "bytes")]
pub use core::parse_from_carllerche_bytes;
pub use core::parse_length_delimited_from;
pub use core::parse_length_delimited_from_reader;
pub use core::parse_length_delimited_from_bytes;
pub use stream::CodedInputStream;
pub use stream::CodedOutputStream;
pub use stream::wire_format;
pub use error::ProtobufResult;
pub use error::ProtobufError;
pub use cached_size::CachedSize;
#[cfg(feature = "bytes")]
pub use chars::Chars;

// generated
pub mod descriptor;
pub mod plugin;
pub mod rustproto;

mod core;
pub mod rt;
pub mod lazy;
pub mod compiler_plugin;
mod repeated;
mod singular;
mod clear;
pub mod reflect;
pub mod text_format;
pub mod stream;
pub mod error;
pub mod types;
pub mod well_known_types;
pub mod ext;

// used by test
#[cfg(test)]
#[path = "../../protobuf-test-common/src/hex.rs"]
mod hex;

// used by rust-grpc
pub mod descriptorx;

mod zigzag;
mod paginate;
mod unknown;
mod strx;
#[doc(hidden)] // used by codegen
pub mod rust;
mod cached_size;
mod varint;
#[cfg(feature = "bytes")]
pub mod chars; // TODO: make private

mod misc;

mod buf_read_iter;

// so `use protobuf::*` could work in mod descriptor and well_known_types
mod protobuf {
    pub use descriptor;
    pub use descriptorx;
    pub use reflect;
    pub use core::*;
    pub use error::*;
    pub use stream::*;
    pub use rt;
    pub use text_format;
    pub use types;
    pub use lazy;
    pub use well_known_types;
    pub use ext;
    pub use unknown::UnknownFields;
    pub use unknown::UnknownFieldsIter;
    pub use unknown::UnknownValue;
    pub use unknown::UnknownValueRef;
    pub use unknown::UnknownValues;
    pub use unknown::UnknownValuesIter;
    pub use repeated::RepeatedField;
    pub use singular::SingularField;
    pub use singular::SingularPtrField;
    pub use clear::Clear;
    pub use cached_size::CachedSize;
}
<commit_msg>Make protobuf::chars mod private<commit_after>//! Library to read and write protocol buffers data.

// TODO: add docs
//#![deny(missing_docs)]

#[cfg(feature = "bytes")]
extern crate bytes;

pub use unknown::UnknownFields;
pub use unknown::UnknownFieldsIter;
pub use unknown::UnknownValue;
pub use unknown::UnknownValueRef;
pub use unknown::UnknownValues;
pub use unknown::UnknownValuesIter;
pub use repeated::RepeatedField;
pub use singular::SingularField;
pub use singular::SingularPtrField;
pub use clear::Clear;
pub use core::Message;
pub use core::ProtobufEnum;
pub use core::parse_from_bytes;
pub use core::parse_from_reader;
#[cfg(feature = "bytes")]
pub use core::parse_from_carllerche_bytes;
pub use core::parse_length_delimited_from;
pub use core::parse_length_delimited_from_reader;
pub use core::parse_length_delimited_from_bytes;
pub use stream::CodedInputStream;
pub use stream::CodedOutputStream;
pub use stream::wire_format;
pub use error::ProtobufResult;
pub use error::ProtobufError;
pub use cached_size::CachedSize;
#[cfg(feature = "bytes")]
pub use chars::Chars;

// generated
pub mod descriptor;
pub mod plugin;
pub mod rustproto;

mod core;
pub mod rt;
pub mod lazy;
pub mod compiler_plugin;
mod repeated;
mod singular;
mod clear;
pub mod reflect;
pub mod text_format;
pub mod stream;
pub mod error;
pub mod types;
pub mod well_known_types;
pub mod ext;

// used by test
#[cfg(test)]
#[path = "../../protobuf-test-common/src/hex.rs"]
mod hex;

// used by rust-grpc
pub mod descriptorx;

mod zigzag;
mod paginate;
mod unknown;
mod strx;
#[doc(hidden)] // used by codegen
pub mod rust;
mod cached_size;
mod varint;
#[cfg(feature = "bytes")]
mod chars;

mod misc;

mod buf_read_iter;

// so `use protobuf::*` could work in mod descriptor and well_known_types
mod protobuf {
    pub use descriptor;
    pub use descriptorx;
    pub use reflect;
    pub use core::*;
    pub use error::*;
    pub use stream::*;
    pub use rt;
    pub use text_format;
    pub use types;
    pub use lazy;
    pub use well_known_types;
    pub use ext;
    pub use unknown::UnknownFields;
    pub use unknown::UnknownFieldsIter;
    pub use unknown::UnknownValue;
    pub use unknown::UnknownValueRef;
    pub use unknown::UnknownValues;
    pub use unknown::UnknownValuesIter;
    pub use repeated::RepeatedField;
    pub use singular::SingularField;
    pub use singular::SingularPtrField;
    pub use clear::Clear;
    pub use cached_size::CachedSize;
}
<|endoftext|>


<commit_before>//! Application, event loop and window event definitions and implementations.
//!
//! - [**Event**](./enum.Event.html) - the default application event type.
//! - [**winit::event::WindowEvent**](https://docs.rs/winit/0.22.1/winit/event/enum.WindowEvent.html) -
//!   events related to a single window.
//! - [**WindowEvent**](./enum.WindowEvent.html) - a stripped-back, simplified, newcomer-friendly
//!   version of the **raw**, low-level winit event.

use crate::geom::{self, Point2, Vector2};
use crate::window;
use crate::App;
use std::path::PathBuf;
use winit;

pub use winit::event::{
    ElementState, KeyboardInput, ModifiersState, MouseButton, MouseScrollDelta, TouchPhase,
    VirtualKeyCode as Key,
};

/// Event types that are compatible with the nannou app loop.
pub trait LoopEvent: 'static + From<Update> {
    /// Produce a loop event from the given winit event.
    fn from_winit_event<'a, T>(_: &winit::event::Event<'a, T>, _: &App) -> Option<Self>;
}

/// Update event, emitted on each pass of an application loop.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Update {
    /// The duration since the last update was emitted.
    ///
    /// The first update's delta will be the time since the given `model` function returned.
    pub since_last: std::time::Duration,
    /// The duration since the start of the app loop.
    ///
    /// Specifically, this is the duration of time since the given `model` function returned.
    pub since_start: std::time::Duration,
}

/// The default application **Event** type.
#[derive(Debug)]
pub enum Event {
    /// A window-specific event has occurred for the window with the given Id.
    ///
    /// The event is available as a **WindowEvent**, a more user-friendly form of
    /// **winit::event::WindowEvent**. Once
    /// [winit#1387](https://github.com/rust-windowing/winit/issues/1387) is fixed, its "raw" form
    /// will also be available.
    WindowEvent {
        id: window::Id,
        simple: Option<WindowEvent>,
        // TODO: Re-add this when winit#1387 is resolved.
        // raw: winit::event::WindowEvent,
    },

    /// A device-specific event has occurred for the device with the given Id.
    DeviceEvent(winit::event::DeviceId, winit::event::DeviceEvent),

    /// A timed update alongside the duration since the last update was emitted.
    ///
    /// The first update's delta will be the time since the `model` function returned.
    Update(Update),

    /// The application has been suspended or resumed.
    Suspended,
    /// The application has been awakened.
    Resumed,
}

/// The event associated with a touch at a single point.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct TouchEvent {
    /// The unique ID associated with this touch, e.g. useful for distinguishing between fingers.
    pub id: u64,
    /// The state of the touch.
    pub phase: TouchPhase,
    /// The position of the touch.
    pub position: Point2<geom::scalar::Default>,
}

/// Pressure on a touch pad.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct TouchpadPressure {
    /// The unique ID associated with the device that emitted this event.
    pub device_id: winit::event::DeviceId,
    /// The amount of pressure applied.
    pub pressure: f32,
    /// Integer representing the click level.
    pub stage: i64,
}

/// Motion along some axis of a device e.g. joystick or gamepad.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct AxisMotion {
    /// The unique ID of the device that emitted this event.
    pub device_id: winit::event::DeviceId,
    /// The axis on which motion occurred.
    pub axis: winit::event::AxisId,
    /// The motion value.
    pub value: geom::scalar::Default,
}

/// A simplified version of winit's `WindowEvent` type to make it easier to get started.
///
/// All co-ordinates and dimensions are DPI-agnostic scalar values.
///
/// Co-ordinates for each window are as follows:
///
/// - `(0.0, 0.0)` is the centre of the window.
/// - positive `x` points to the right, negative `x` points to the left.
/// - positive `y` points upwards, negative `y` points downwards.
/// - positive `z` points into the screen, negative `z` points out of the screen.
#[derive(Clone, Debug, PartialEq)]
pub enum WindowEvent {
    /// The window has been moved to a new position.
    Moved(Point2<geom::scalar::Default>),

    /// The given keyboard key was pressed.
    KeyPressed(Key),

    /// The given keyboard key was released.
    KeyReleased(Key),

    /// The mouse moved to the given x, y position.
    MouseMoved(Point2<geom::scalar::Default>),

    /// The given mouse button was pressed.
    MousePressed(MouseButton),

    /// The given mouse button was released.
    MouseReleased(MouseButton),

    /// The mouse entered the window.
    MouseEntered,

    /// The mouse exited the window.
    MouseExited,

    /// A mouse wheel movement or touchpad scroll occurred.
    MouseWheel(MouseScrollDelta, TouchPhase),

    /// The window was resized to the given dimensions (in DPI-agnostic points, not pixels).
    Resized(Vector2<geom::scalar::Default>),

    /// A file at the given path was hovered over the window.
    HoveredFile(PathBuf),

    /// A file at the given path was dropped onto the window.
    DroppedFile(PathBuf),

    /// A file at the given path that was hovered over the window was cancelled.
    HoveredFileCancelled,

    /// Received a touch event.
    Touch(TouchEvent),

    /// Touchpad pressure event.
    ///
    /// At the moment, only supported on Apple forcetouch-capable macbooks.
    /// The parameters are: pressure level (value between 0 and 1 representing how hard the touchpad
    /// is being pressed) and stage (integer representing the click level).
    TouchPressure(TouchpadPressure),

    /// The window gained focus.
    Focused,

    /// The window lost focus.
    Unfocused,

    /// The window was closed and is no longer stored in the `App`.
    Closed,
}

impl WindowEvent {
    /// Produce a simplified, new-user-friendly version of the given `winit::event::WindowEvent`.
    ///
    /// This strips rarely needed technical information from the event type such as information
    /// about the source device, scancodes for keyboard events, etc to make the experience of
    /// pattern matching on window events nicer for new users.
    ///
    /// This also interprets the raw pixel positions and dimensions of the raw event into a
    /// dpi-agnostic scalar value where (0, 0, 0) is the centre of the screen with the `y` axis
    /// increasing in the upwards direction.
    ///
    /// If the user requires this extra information, they should use the `raw` field of the
    /// `WindowEvent` type rather than the `simple` one.
    pub fn from_winit_window_event(
        event: &winit::event::WindowEvent,
        win_w: f64,
        win_h: f64,
        scale_factor: f64,
    ) -> Option<Self> {
        use self::WindowEvent::*;

        // Translate the coordinates from top-left-origin-with-y-down to centre-origin-with-y-up.
        //
        // winit produces input events in pixels, so these positions need to be divided by the
        // width and height of the window in order to be DPI agnostic.
        let tw = |w: f64| w as geom::scalar::Default;
        let th = |h: f64| h as geom::scalar::Default;
        let tx = |x: f64| (x - win_w / 2.0) as geom::scalar::Default;
        let ty = |y: f64| (-(y - win_h / 2.0)) as geom::scalar::Default;

        let event = match event {
            winit::event::WindowEvent::Resized(new_size) => {
                let (new_w, new_h) = new_size.to_logical::<f64>(scale_factor).into();
                let x = tw(new_w);
                let y = th(new_h);
                Resized(Vector2 { x, y })
            }

            winit::event::WindowEvent::Moved(new_pos) => {
                let (new_x, new_y) = new_pos.to_logical::<f64>(scale_factor).into();
                let x = tx(new_x);
                let y = ty(new_y);
                Moved(Point2 { x, y })
            }

            // TODO: Should separate the behaviour of close requested and destroyed.
            winit::event::WindowEvent::CloseRequested | winit::event::WindowEvent::Destroyed => {
                Closed
            }

            winit::event::WindowEvent::DroppedFile(path) => DroppedFile(path.clone()),

            winit::event::WindowEvent::HoveredFile(path) => HoveredFile(path.clone()),

            winit::event::WindowEvent::HoveredFileCancelled => HoveredFileCancelled,

            winit::event::WindowEvent::Focused(b) => {
                if b.clone() {
                    Focused
                } else {
                    Unfocused
                }
            }

            winit::event::WindowEvent::CursorMoved { position, .. } => {
                let (x, y) = position.to_logical::<f64>(scale_factor).into();
                let x = tx(x);
                let y = ty(y);
                MouseMoved(Point2 { x, y })
            }

            winit::event::WindowEvent::CursorEntered { .. } => MouseEntered,

            winit::event::WindowEvent::CursorLeft { .. } => MouseExited,

            winit::event::WindowEvent::MouseWheel { delta, phase, .. } => {
                MouseWheel(delta.clone(), phase.clone())
            }

            winit::event::WindowEvent::MouseInput { state, button, .. } => match state {
                ElementState::Pressed => MousePressed(button.clone()),
                ElementState::Released => MouseReleased(button.clone()),
            },

            winit::event::WindowEvent::Touch(winit::event::Touch {
                phase,
                location,
                id,
                ..
            }) => {
                let (x, y) = location.to_logical::<f64>(scale_factor).into();
                let x = tx(x);
                let y = ty(y);
                let position = Point2 { x, y };
                let touch = TouchEvent {
                    phase: phase.clone(),
                    position,
                    id: id.clone(),
                };
                WindowEvent::Touch(touch)
            }

            winit::event::WindowEvent::TouchpadPressure {
                device_id,
                pressure,
                stage,
            } => TouchPressure(TouchpadPressure {
                device_id: device_id.clone(),
                pressure: pressure.clone(),
                stage: stage.clone(),
            }),

            winit::event::WindowEvent::KeyboardInput { input, .. } => match input.virtual_keycode {
                Some(key) => match input.state {
                    ElementState::Pressed => KeyPressed(key),
                    ElementState::Released => KeyReleased(key),
                },
                None => return None,
            },

            winit::event::WindowEvent::ModifiersChanged(_) => {
                return None;
            }

            winit::event::WindowEvent::AxisMotion { .. }
            | winit::event::WindowEvent::ReceivedCharacter(_)
            | winit::event::WindowEvent::ThemeChanged(_)
            | winit::event::WindowEvent::ScaleFactorChanged { .. } => {
                return None;
            }
        };

        Some(event)
    }
}

impl LoopEvent for Event {
    /// Convert the given `winit::event::Event` to a nannou `Event`.
    fn from_winit_event<'a, T>(event: &winit::event::Event<'a, T>, app: &App) -> Option<Self> {
        let event = match event {
            winit::event::Event::WindowEvent { window_id, event } => {
                let windows = app.windows.borrow();
                let (win_w, win_h, scale_factor) = match windows.get(&window_id) {
                    None => (0.0, 0.0, 1.0), // The window was likely closed, these will be ignored.
                    Some(window) => {
                        let sf = window.tracked_state.scale_factor;
                        let size = window.tracked_state.physical_size;
                        let (w, h) = size.to_logical::<f64>(sf).into();
                        (w, h, sf)
                    }
                };
                let simple =
                    WindowEvent::from_winit_window_event(event, win_w, win_h, scale_factor);
                Event::WindowEvent {
                    id: window_id.clone(),
                    simple,
                    // TODO: Re-add this when winit#1387 is resolved.
                    // raw,
                }
            }
            winit::event::Event::DeviceEvent { device_id, event } => {
                Event::DeviceEvent(device_id.clone(), event.clone())
            }
            winit::event::Event::Suspended => Event::Suspended,
            winit::event::Event::Resumed => Event::Resumed,
            winit::event::Event::NewEvents(_)
            | winit::event::Event::UserEvent(_)
            | winit::event::Event::MainEventsCleared
            | winit::event::Event::RedrawRequested(_)
            | winit::event::Event::RedrawEventsCleared
            | winit::event::Event::LoopDestroyed => return None,
        };
        Some(event)
    }
}

impl From<Update> for Event {
    fn from(update: Update) -> Self {
        Event::Update(update)
    }
}
<commit_msg>link to latest winit docs<commit_after>//! Application, event loop and window event definitions and implementations.
//!
//! - [**Event**](./enum.Event.html) - the default application event type.
//! - [**winit::event::WindowEvent**](https://docs.rs/winit/latest/winit/event/enum.WindowEvent.html) -
//!   events related to a single window.
//! - [**WindowEvent**](./enum.WindowEvent.html) - a stripped-back, simplified, newcomer-friendly
//!   version of the **raw**, low-level winit event.

use crate::geom::{self, Point2, Vector2};
use crate::window;
use crate::App;
use std::path::PathBuf;
use winit;

pub use winit::event::{
    ElementState, KeyboardInput, ModifiersState, MouseButton, MouseScrollDelta, TouchPhase,
    VirtualKeyCode as Key,
};

/// Event types that are compatible with the nannou app loop.
pub trait LoopEvent: 'static + From<Update> {
    /// Produce a loop event from the given winit event.
    fn from_winit_event<'a, T>(_: &winit::event::Event<'a, T>, _: &App) -> Option<Self>;
}

/// Update event, emitted on each pass of an application loop.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Update {
    /// The duration since the last update was emitted.
    ///
    /// The first update's delta will be the time since the given `model` function returned.
    pub since_last: std::time::Duration,
    /// The duration since the start of the app loop.
    ///
    /// Specifically, this is the duration of time since the given `model` function returned.
    pub since_start: std::time::Duration,
}

/// The default application **Event** type.
#[derive(Debug)]
pub enum Event {
    /// A window-specific event has occurred for the window with the given Id.
    ///
    /// The event is available as a **WindowEvent**, a more user-friendly form of
    /// **winit::event::WindowEvent**. Once
    /// [winit#1387](https://github.com/rust-windowing/winit/issues/1387) is fixed, its "raw" form
    /// will also be available.
    WindowEvent {
        id: window::Id,
        simple: Option<WindowEvent>,
        // TODO: Re-add this when winit#1387 is resolved.
        // raw: winit::event::WindowEvent,
    },

    /// A device-specific event has occurred for the device with the given Id.
    DeviceEvent(winit::event::DeviceId, winit::event::DeviceEvent),

    /// A timed update alongside the duration since the last update was emitted.
    ///
    /// The first update's delta will be the time since the `model` function returned.
    Update(Update),

    /// The application has been suspended or resumed.
    Suspended,
    /// The application has been awakened.
    Resumed,
}

/// The event associated with a touch at a single point.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct TouchEvent {
    /// The unique ID associated with this touch, e.g. useful for distinguishing between fingers.
    pub id: u64,
    /// The state of the touch.
    pub phase: TouchPhase,
    /// The position of the touch.
    pub position: Point2<geom::scalar::Default>,
}

/// Pressure on a touch pad.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct TouchpadPressure {
    /// The unique ID associated with the device that emitted this event.
    pub device_id: winit::event::DeviceId,
    /// The amount of pressure applied.
    pub pressure: f32,
    /// Integer representing the click level.
    pub stage: i64,
}

/// Motion along some axis of a device e.g. joystick or gamepad.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct AxisMotion {
    /// The unique ID of the device that emitted this event.
    pub device_id: winit::event::DeviceId,
    /// The axis on which motion occurred.
    pub axis: winit::event::AxisId,
    /// The motion value.
    pub value: geom::scalar::Default,
}

/// A simplified version of winit's `WindowEvent` type to make it easier to get started.
///
/// All co-ordinates and dimensions are DPI-agnostic scalar values.
///
/// Co-ordinates for each window are as follows:
///
/// - `(0.0, 0.0)` is the centre of the window.
/// - positive `x` points to the right, negative `x` points to the left.
/// - positive `y` points upwards, negative `y` points downwards.
/// - positive `z` points into the screen, negative `z` points out of the screen.
#[derive(Clone, Debug, PartialEq)]
pub enum WindowEvent {
    /// The window has been moved to a new position.
    Moved(Point2<geom::scalar::Default>),

    /// The given keyboard key was pressed.
    KeyPressed(Key),

    /// The given keyboard key was released.
    KeyReleased(Key),

    /// The mouse moved to the given x, y position.
    MouseMoved(Point2<geom::scalar::Default>),

    /// The given mouse button was pressed.
    MousePressed(MouseButton),

    /// The given mouse button was released.
    MouseReleased(MouseButton),

    /// The mouse entered the window.
    MouseEntered,

    /// The mouse exited the window.
    MouseExited,

    /// A mouse wheel movement or touchpad scroll occurred.
    MouseWheel(MouseScrollDelta, TouchPhase),

    /// The window was resized to the given dimensions (in DPI-agnostic points, not pixels).
    Resized(Vector2<geom::scalar::Default>),

    /// A file at the given path was hovered over the window.
    HoveredFile(PathBuf),

    /// A file at the given path was dropped onto the window.
    DroppedFile(PathBuf),

    /// A file at the given path that was hovered over the window was cancelled.
    HoveredFileCancelled,

    /// Received a touch event.
    Touch(TouchEvent),

    /// Touchpad pressure event.
    ///
    /// At the moment, only supported on Apple forcetouch-capable macbooks.
    /// The parameters are: pressure level (value between 0 and 1 representing how hard the touchpad
    /// is being pressed) and stage (integer representing the click level).
    TouchPressure(TouchpadPressure),

    /// The window gained focus.
    Focused,

    /// The window lost focus.
    Unfocused,

    /// The window was closed and is no longer stored in the `App`.
    Closed,
}

impl WindowEvent {
    /// Produce a simplified, new-user-friendly version of the given `winit::event::WindowEvent`.
    ///
    /// This strips rarely needed technical information from the event type such as information
    /// about the source device, scancodes for keyboard events, etc to make the experience of
    /// pattern matching on window events nicer for new users.
    ///
    /// This also interprets the raw pixel positions and dimensions of the raw event into a
    /// dpi-agnostic scalar value where (0, 0, 0) is the centre of the screen with the `y` axis
    /// increasing in the upwards direction.
    ///
    /// If the user requires this extra information, they should use the `raw` field of the
    /// `WindowEvent` type rather than the `simple` one.
    pub fn from_winit_window_event(
        event: &winit::event::WindowEvent,
        win_w: f64,
        win_h: f64,
        scale_factor: f64,
    ) -> Option<Self> {
        use self::WindowEvent::*;

        // Translate the coordinates from top-left-origin-with-y-down to centre-origin-with-y-up.
        //
        // winit produces input events in pixels, so these positions need to be divided by the
        // width and height of the window in order to be DPI agnostic.
        let tw = |w: f64| w as geom::scalar::Default;
        let th = |h: f64| h as geom::scalar::Default;
        let tx = |x: f64| (x - win_w / 2.0) as geom::scalar::Default;
        let ty = |y: f64| (-(y - win_h / 2.0)) as geom::scalar::Default;

        let event = match event {
            winit::event::WindowEvent::Resized(new_size) => {
                let (new_w, new_h) = new_size.to_logical::<f64>(scale_factor).into();
                let x = tw(new_w);
                let y = th(new_h);
                Resized(Vector2 { x, y })
            }

            winit::event::WindowEvent::Moved(new_pos) => {
                let (new_x, new_y) = new_pos.to_logical::<f64>(scale_factor).into();
                let x = tx(new_x);
                let y = ty(new_y);
                Moved(Point2 { x, y })
            }

            // TODO: Should separate the behaviour of close requested and destroyed.
            winit::event::WindowEvent::CloseRequested | winit::event::WindowEvent::Destroyed => {
                Closed
            }

            winit::event::WindowEvent::DroppedFile(path) => DroppedFile(path.clone()),

            winit::event::WindowEvent::HoveredFile(path) => HoveredFile(path.clone()),

            winit::event::WindowEvent::HoveredFileCancelled => HoveredFileCancelled,

            winit::event::WindowEvent::Focused(b) => {
                if b.clone() {
                    Focused
                } else {
                    Unfocused
                }
            }

            winit::event::WindowEvent::CursorMoved { position, .. } => {
                let (x, y) = position.to_logical::<f64>(scale_factor).into();
                let x = tx(x);
                let y = ty(y);
                MouseMoved(Point2 { x, y })
            }

            winit::event::WindowEvent::CursorEntered { .. } => MouseEntered,

            winit::event::WindowEvent::CursorLeft { .. } => MouseExited,

            winit::event::WindowEvent::MouseWheel { delta, phase, .. } => {
                MouseWheel(delta.clone(), phase.clone())
            }

            winit::event::WindowEvent::MouseInput { state, button, .. } => match state {
                ElementState::Pressed => MousePressed(button.clone()),
                ElementState::Released => MouseReleased(button.clone()),
            },

            winit::event::WindowEvent::Touch(winit::event::Touch {
                phase,
                location,
                id,
                ..
            }) => {
                let (x, y) = location.to_logical::<f64>(scale_factor).into();
                let x = tx(x);
                let y = ty(y);
                let position = Point2 { x, y };
                let touch = TouchEvent {
                    phase: phase.clone(),
                    position,
                    id: id.clone(),
                };
                WindowEvent::Touch(touch)
            }

            winit::event::WindowEvent::TouchpadPressure {
                device_id,
                pressure,
                stage,
            } => TouchPressure(TouchpadPressure {
                device_id: device_id.clone(),
                pressure: pressure.clone(),
                stage: stage.clone(),
            }),

            winit::event::WindowEvent::KeyboardInput { input, .. } => match input.virtual_keycode {
                Some(key) => match input.state {
                    ElementState::Pressed => KeyPressed(key),
                    ElementState::Released => KeyReleased(key),
                },
                None => return None,
            },

            winit::event::WindowEvent::ModifiersChanged(_) => {
                return None;
            }

            winit::event::WindowEvent::AxisMotion { .. }
            | winit::event::WindowEvent::ReceivedCharacter(_)
            | winit::event::WindowEvent::ThemeChanged(_)
            | winit::event::WindowEvent::ScaleFactorChanged { .. } => {
                return None;
            }
        };

        Some(event)
    }
}

impl LoopEvent for Event {
    /// Convert the given `winit::event::Event` to a nannou `Event`.
    fn from_winit_event<'a, T>(event: &winit::event::Event<'a, T>, app: &App) -> Option<Self> {
        let event = match event {
            winit::event::Event::WindowEvent { window_id, event } => {
                let windows = app.windows.borrow();
                let (win_w, win_h, scale_factor) = match windows.get(&window_id) {
                    None => (0.0, 0.0, 1.0), // The window was likely closed, these will be ignored.
                    Some(window) => {
                        let sf = window.tracked_state.scale_factor;
                        let size = window.tracked_state.physical_size;
                        let (w, h) = size.to_logical::<f64>(sf).into();
                        (w, h, sf)
                    }
                };
                let simple =
                    WindowEvent::from_winit_window_event(event, win_w, win_h, scale_factor);
                Event::WindowEvent {
                    id: window_id.clone(),
                    simple,
                    // TODO: Re-add this when winit#1387 is resolved.
                    // raw,
                }
            }
            winit::event::Event::DeviceEvent { device_id, event } => {
                Event::DeviceEvent(device_id.clone(), event.clone())
            }
            winit::event::Event::Suspended => Event::Suspended,
            winit::event::Event::Resumed => Event::Resumed,
            winit::event::Event::NewEvents(_)
            | winit::event::Event::UserEvent(_)
            | winit::event::Event::MainEventsCleared
            | winit::event::Event::RedrawRequested(_)
            | winit::event::Event::RedrawEventsCleared
            | winit::event::Event::LoopDestroyed => return None,
        };
        Some(event)
    }
}

impl From<Update> for Event {
    fn from(update: Update) -> Self {
        Event::Update(update)
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 GFX developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use super::*;

use cocoa::foundation::NSUInteger;
use objc::runtime::{Class, YES, NO};
use objc_foundation::{INSString, NSString};

#[repr(u64)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum MTLMutability {
    Default = 0,
    Mutable = 1,
    Immutable = 2,
}

impl Default for MTLMutability {
    #[inline]
    fn default() -> Self {
        MTLMutability::Default
    }
}

#[repr(u64)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum MTLIndexType {
    UInt16 = 0,
    UInt32 = 1,
}

#[repr(u64)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum MTLAttributeFormat {
    Invalid = 0,
    UChar2 = 1,
    UChar3 = 2,
    UChar4 = 3,
    Char2 = 4,
    Char3 = 5,
    Char4 = 6,
    UChar2Normalized = 7,
    UChar3Normalized = 8,
    UChar4Normalized = 9,
    Char2Normalized = 10,
    Char3Normalized = 11,
    Char4Normalized = 12,
    UShort2 = 13,
    UShort3 = 14,
    UShort4 = 15,
    Short2 = 16,
    Short3 = 17,
    Short4 = 18,
    UShort2Normalized = 19,
    UShort3Normalized = 20,
    UShort4Normalized = 21,
    Short2Normalized = 22,
    Short3Normalized = 23,
    Short4Normalized = 24,
    Half2 = 25,
    Half3 = 26,
    Half4 = 27,
    Float = 28,
    Float2 = 29,
    Float3 = 30,
    Float4 = 31,
    Int = 32,
    Int2 = 33,
    Int3 = 34,
    Int4 = 35,
    UInt = 36,
    UInt2 = 37,
    UInt3 = 38,
    UInt4 = 39,
    Int1010102Normalized = 40,
    UInt1010102Normalized = 41,
}

#[repr(u64)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum MTLStepFunction {
    Constant = 0,
    PerInstance = 1,
    PerPatch = 2,
    PerPatchControlPoint = 3,
    PerVertex = 4,
    ThreadPositionInGridX = 5,
    ThreadPositionInGridXIndexed = 6,
    ThreadPositionInGridY = 7,
    ThreadPositionInGridYIndexed = 8,
}

pub enum MTLComputePipelineDescriptor {}

foreign_obj_type! {
    type CType = MTLComputePipelineDescriptor;
    pub struct ComputePipelineDescriptor;
    pub struct ComputePipelineDescriptorRef;
}

impl ComputePipelineDescriptor {
    pub fn new() -> Self {
        unsafe {
            let class = Class::get("MTLComputePipelineDescriptor").unwrap();
            msg_send![class, new]
        }
    }
}

impl ComputePipelineDescriptorRef {
    pub fn label(&self) -> &str {
        unsafe {
            let label: &NSString = msg_send![self, label];
            label.as_str()
        }
    }

    pub fn set_label(&self, label: &str) {
        unsafe {
            let nslabel = NSString::from_str(label);
            msg_send![self, setLabel:nslabel]
        }
    }

    pub fn compute_function(&self) -> Option<&FunctionRef> {
        unsafe {
            msg_send![self, computeFunction]
        }
    }

    pub fn set_compute_function(&self, function: Option<&FunctionRef>) {
        unsafe {
            msg_send![self, setComputeFunction:function]
        }
    }

    pub fn thread_group_size_is_multiple_of_thread_execution_width(&self) -> bool {
        unsafe {
            match msg_send![self, threadGroupSizeIsMultipleOfThreadExecutionWidth] {
                YES => true,
                NO => false,
                _ => unreachable!(),
            }
        }
    }

    pub fn set_thread_group_size_is_multiple_of_thread_execution_width(&self, size_is_multiple_of_width: bool) {
        unsafe {
            msg_send![self, setThreadGroupSizeIsMultipleOfThreadExecutionWidth:size_is_multiple_of_width]
        }
    }

    pub fn stage_input_descriptor(&self) -> Option<&StageInputOutputDescriptorRef> {
        unsafe {
            msg_send![self, stageInputDescriptor]
        }
    }

    pub fn set_stage_input_descriptor(&self, descriptor: Option<&StageInputOutputDescriptorRef>) {
        unsafe {
            msg_send![self, setStageInputDescriptor:descriptor]
        }
    }

    pub fn buffers(&self) -> Option<&PipelineBufferDescriptorArrayRef> {
        unsafe {
            msg_send![self, buffers]
        }
    }

    pub fn set_buffers(&self, buffers: Option<&PipelineBufferDescriptorArrayRef>) {
        unsafe {
            msg_send![self, setBuffers:buffers]
        }
    }

    pub fn reset(&self) {
        unsafe {
            msg_send![self, reset]
        }
    }
}

pub enum MTLComputePipelineState {}

foreign_obj_type! {
    type CType = MTLComputePipelineState;
    pub struct ComputePipelineState;
    pub struct ComputePipelineStateRef;
}

impl ComputePipelineStateRef {
    pub fn label(&self) -> &str {
        unsafe {
            let label: &NSString = msg_send![self, label];
            label.as_str()
        }
    }

    pub fn set_label(&self, label: &str) {
        unsafe {
            let nslabel = NSString::from_str(label);
            msg_send![self, setLabel:nslabel]
        }
    }
}

pub enum MTLPipelineBufferDescriptorArray {}

foreign_obj_type! {
    type CType = MTLPipelineBufferDescriptorArray;
    pub struct PipelineBufferDescriptorArray;
    pub struct PipelineBufferDescriptorArrayRef;
}

impl PipelineBufferDescriptorArrayRef {
    pub fn object_at(&self, index: usize) -> Option<&PipelineBufferDescriptorRef> {
        unsafe {
            msg_send![self, objectAtIndexedSubscript:index]
        }
    }

    pub fn set_object_at(&self, index: usize, buffer_desc: Option<&PipelineBufferDescriptorRef>) {
        unsafe {
            msg_send![self, setObject:buffer_desc atIndexedSubscript:index]
        }
    }
}

pub enum MTLPipelineBufferDescriptor {}

foreign_obj_type! {
    type CType = MTLPipelineBufferDescriptor;
    pub struct PipelineBufferDescriptor;
    pub struct PipelineBufferDescriptorRef;
}

impl PipelineBufferDescriptorRef {
    pub fn mutability(&self) -> MTLMutability {
        unsafe {
            msg_send![self, mutability]
        }
    }

    pub fn set_mutability(&self, new_mutability: MTLMutability) {
        unsafe {
            msg_send![self, setMutability:new_mutability]
        }
    }
}

pub enum MTLStageInputOutputDescriptor {}

foreign_obj_type! {
    type CType = MTLStageInputOutputDescriptor;
    pub struct StageInputOutputDescriptor;
    pub struct StageInputOutputDescriptorRef;
}

impl StageInputOutputDescriptor {
    pub fn new<'a>() -> &'a StageInputOutputDescriptorRef {
        unsafe {
            let class = Class::get("MTLStageInputOutputDescriptor").unwrap();
            msg_send![class, stageInputOutputDescriptor]
        }
    }
}

impl StageInputOutputDescriptorRef {
    pub fn attributes(&self) -> Option<&AttributeDescriptorArrayRef> {
        unsafe {
            msg_send![self, attributes]
        }
    }

    pub fn index_buffer_index(&self) -> NSUInteger {
        unsafe {
            msg_send![self, indexBufferIndex]
        }
    }

    pub fn set_index_buffer_index(&self, idx_buffer_idx: NSUInteger) {
        unsafe {
            msg_send![self, setIndexBufferIndex:idx_buffer_idx]
        }
    }

    pub fn index_type(&self) -> MTLIndexType {
        unsafe {
            msg_send![self, indexType]
        }
    }

    pub fn set_index_type(&self, index_ty: MTLIndexType) {
        unsafe {
            msg_send![self, setIndexType:index_ty]
        }
    }

    pub fn layouts(&self) -> Option<&BufferLayoutDescriptorArrayRef> {
        unsafe {
            msg_send![self, layouts]
        }
    }

    pub fn reset(&self) {
        unsafe {
            msg_send![self, reset]
        }
    }
}

pub enum MTLAttributeDescriptorArray {}

foreign_obj_type! {
    type CType = MTLAttributeDescriptorArray;
    pub struct AttributeDescriptorArray;
    pub struct AttributeDescriptorArrayRef;
}

impl AttributeDescriptorArrayRef {
    pub fn object_at(&self, index: usize) -> Option<&AttributeDescriptorRef> {
        unsafe {
            msg_send![self, objectAtIndexedSubscript:index]
        }
    }

    pub fn set_object_at(&self, index: usize, buffer_desc: Option<&AttributeDescriptorRef>) {
        unsafe {
            msg_send![self, setObject:buffer_desc atIndexedSubscript:index]
        }
    }
}

pub enum MTLAttributeDescriptor {}

foreign_obj_type! {
    type CType = MTLAttributeDescriptor;
    pub struct AttributeDescriptor;
    pub struct AttributeDescriptorRef;
}

impl AttributeDescriptorRef {
    pub fn buffer_index(&self) -> NSUInteger {
        unsafe {
            msg_send![self, bufferIndex]
        }
    }

    pub fn set_buffer_index(&self, buffer_index: NSUInteger) {
        unsafe {
            msg_send![self, setBufferIndex:buffer_index]
        }
    }

    pub fn format(&self) -> MTLAttributeFormat {
        unsafe {
            msg_send![self, format]
        }
    }

    pub fn set_format(&self, format: MTLAttributeFormat) {
        unsafe {
            msg_send![self, setFormat:format]
        }
    }

    pub fn offset(&self) -> NSUInteger {
        unsafe {
            msg_send![self, offset]
        }
    }

    pub fn set_offset(&self, offset: NSUInteger) {
        unsafe {
            msg_send![self, setOffset:offset]
        }
    }
}

pub enum MTLBufferLayoutDescriptorArray {}

foreign_obj_type! {
    type CType = MTLBufferLayoutDescriptorArray;
    pub struct BufferLayoutDescriptorArray;
    pub struct BufferLayoutDescriptorArrayRef;
}

impl BufferLayoutDescriptorArrayRef {
    pub fn object_at(&self, index: usize) -> Option<&BufferLayoutDescriptorRef> {
        unsafe {
            msg_send![self, objectAtIndexedSubscript:index]
        }
    }

    pub fn set_object_at(&self, index: usize, buffer_desc: Option<&BufferLayoutDescriptorRef>) {
        unsafe {
            msg_send![self, setObject:buffer_desc atIndexedSubscript:index]
        }
    }
}

pub enum MTLBufferLayoutDescriptor {}

foreign_obj_type! {
    type CType = MTLBufferLayoutDescriptor;
    pub struct BufferLayoutDescriptor;
    pub struct BufferLayoutDescriptorRef;
}

impl BufferLayoutDescriptorRef {
    pub fn step_function(&self) -> MTLStepFunction {
        unsafe {
            msg_send![self, stepFunction]
        }
    }

    pub fn set_step_function(&self, step_function: MTLStepFunction) {
        unsafe {
            msg_send![self, setStepFunction:step_function]
        }
    }

    pub fn step_rate(&self) -> NSUInteger {
        unsafe {
            msg_send![self, stepRate]
        }
    }

    pub fn set_step_rate(&self, step_rate: NSUInteger) {
        unsafe {
            msg_send![self, setStepRate:step_rate]
        }
    }

    pub fn stride(&self) -> NSUInteger {
        unsafe {
            msg_send![self, stride]
        }
    }

    pub fn set_stride(&self, stride: NSUInteger) {
        unsafe {
            msg_send![self, setStride:stride]
        }
    }
}
<commit_msg>Remove set_buffers on compute pipeline descriptor<commit_after>// Copyright 2017 GFX developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use super::*;

use cocoa::foundation::NSUInteger;
use objc::runtime::{Class, YES, NO};
use objc_foundation::{INSString, NSString};

#[repr(u64)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum MTLMutability {
    Default = 0,
    Mutable = 1,
    Immutable = 2,
}

impl Default for MTLMutability {
    #[inline]
    fn default() -> Self {
        MTLMutability::Default
    }
}

#[repr(u64)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum MTLIndexType {
    UInt16 = 0,
    UInt32 = 1,
}

#[repr(u64)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum MTLAttributeFormat {
    Invalid = 0,
    UChar2 = 1,
    UChar3 = 2,
    UChar4 = 3,
    Char2 = 4,
    Char3 = 5,
    Char4 = 6,
    UChar2Normalized = 7,
    UChar3Normalized = 8,
    UChar4Normalized = 9,
    Char2Normalized = 10,
    Char3Normalized = 11,
    Char4Normalized = 12,
    UShort2 = 13,
    UShort3 = 14,
    UShort4 = 15,
    Short2 = 16,
    Short3 = 17,
    Short4 = 18,
    UShort2Normalized = 19,
    UShort3Normalized = 20,
    UShort4Normalized = 21,
    Short2Normalized = 22,
    Short3Normalized = 23,
    Short4Normalized = 24,
    Half2 = 25,
    Half3 = 26,
    Half4 = 27,
    Float = 28,
    Float2 = 29,
    Float3 = 30,
    Float4 = 31,
    Int = 32,
    Int2 = 33,
    Int3 = 34,
    Int4 = 35,
    UInt = 36,
    UInt2 = 37,
    UInt3 = 38,
    UInt4 = 39,
    Int1010102Normalized = 40,
    UInt1010102Normalized = 41,
}

#[repr(u64)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum MTLStepFunction {
    Constant = 0,
    PerInstance = 1,
    PerPatch = 2,
    PerPatchControlPoint = 3,
    PerVertex = 4,
    ThreadPositionInGridX = 5,
    ThreadPositionInGridXIndexed = 6,
    ThreadPositionInGridY = 7,
    ThreadPositionInGridYIndexed = 8,
}

pub enum MTLComputePipelineDescriptor {}

foreign_obj_type! {
    type CType = MTLComputePipelineDescriptor;
    pub struct ComputePipelineDescriptor;
    pub struct ComputePipelineDescriptorRef;
}

impl ComputePipelineDescriptor {
    pub fn new() -> Self {
        unsafe {
            let class = Class::get("MTLComputePipelineDescriptor").unwrap();
            msg_send![class, new]
        }
    }
}

impl ComputePipelineDescriptorRef {
    pub fn label(&self) -> &str {
        unsafe {
            let label: &NSString = msg_send![self, label];
            label.as_str()
        }
    }

    pub fn set_label(&self, label: &str) {
        unsafe {
            let nslabel = NSString::from_str(label);
            msg_send![self, setLabel:nslabel]
        }
    }

    pub fn compute_function(&self) -> Option<&FunctionRef> {
        unsafe {
            msg_send![self, computeFunction]
        }
    }

    pub fn set_compute_function(&self, function: Option<&FunctionRef>) {
        unsafe {
            msg_send![self, setComputeFunction:function]
        }
    }

    pub fn thread_group_size_is_multiple_of_thread_execution_width(&self) -> bool {
        unsafe {
            match msg_send![self, threadGroupSizeIsMultipleOfThreadExecutionWidth] {
                YES => true,
                NO => false,
                _ => unreachable!(),
            }
        }
    }

    pub fn set_thread_group_size_is_multiple_of_thread_execution_width(&self, size_is_multiple_of_width: bool) {
        unsafe {
            msg_send![self, setThreadGroupSizeIsMultipleOfThreadExecutionWidth:size_is_multiple_of_width]
        }
    }

    pub fn stage_input_descriptor(&self) -> Option<&StageInputOutputDescriptorRef> {
        unsafe {
            msg_send![self, stageInputDescriptor]
        }
    }

    pub fn set_stage_input_descriptor(&self, descriptor: Option<&StageInputOutputDescriptorRef>) {
        unsafe {
            msg_send![self, setStageInputDescriptor:descriptor]
        }
    }

    pub fn buffers(&self) -> Option<&PipelineBufferDescriptorArrayRef> {
        unsafe {
            msg_send![self, buffers]
        }
    }

    pub fn reset(&self) {
        unsafe {
            msg_send![self, reset]
        }
    }
}

pub enum MTLComputePipelineState {}

foreign_obj_type! {
    type CType = MTLComputePipelineState;
    pub struct ComputePipelineState;
    pub struct ComputePipelineStateRef;
}

impl ComputePipelineStateRef {
    pub fn label(&self) -> &str {
        unsafe {
            let label: &NSString = msg_send![self, label];
            label.as_str()
        }
    }

    pub fn set_label(&self, label: &str) {
        unsafe {
            let nslabel = NSString::from_str(label);
            msg_send![self, setLabel:nslabel]
        }
    }
}

pub enum MTLPipelineBufferDescriptorArray {}

foreign_obj_type! {
    type CType = MTLPipelineBufferDescriptorArray;
    pub struct PipelineBufferDescriptorArray;
    pub struct PipelineBufferDescriptorArrayRef;
}

impl PipelineBufferDescriptorArrayRef {
    pub fn object_at(&self, index: usize) -> Option<&PipelineBufferDescriptorRef> {
        unsafe {
            msg_send![self, objectAtIndexedSubscript:index]
        }
    }

    pub fn set_object_at(&self, index: usize, buffer_desc: Option<&PipelineBufferDescriptorRef>) {
        unsafe {
            msg_send![self, setObject:buffer_desc atIndexedSubscript:index]
        }
    }
}

pub enum MTLPipelineBufferDescriptor {}

foreign_obj_type! {
    type CType = MTLPipelineBufferDescriptor;
    pub struct PipelineBufferDescriptor;
    pub struct PipelineBufferDescriptorRef;
}

impl PipelineBufferDescriptorRef {
    pub fn mutability(&self) -> MTLMutability {
        unsafe {
            msg_send![self, mutability]
        }
    }

    pub fn set_mutability(&self, new_mutability: MTLMutability) {
        unsafe {
            msg_send![self, setMutability:new_mutability]
        }
    }
}

pub enum MTLStageInputOutputDescriptor {}

foreign_obj_type! {
    type CType = MTLStageInputOutputDescriptor;
    pub struct StageInputOutputDescriptor;
    pub struct StageInputOutputDescriptorRef;
}

impl StageInputOutputDescriptor {
    pub fn new<'a>() -> &'a StageInputOutputDescriptorRef {
        unsafe {
            let class = Class::get("MTLStageInputOutputDescriptor").unwrap();
            msg_send![class, stageInputOutputDescriptor]
        }
    }
}

impl StageInputOutputDescriptorRef {
    pub fn attributes(&self) -> Option<&AttributeDescriptorArrayRef> {
        unsafe {
            msg_send![self, attributes]
        }
    }

    pub fn index_buffer_index(&self) -> NSUInteger {
        unsafe {
            msg_send![self, indexBufferIndex]
        }
    }

    pub fn set_index_buffer_index(&self, idx_buffer_idx: NSUInteger) {
        unsafe {
            msg_send![self, setIndexBufferIndex:idx_buffer_idx]
        }
    }

    pub fn index_type(&self) -> MTLIndexType {
        unsafe {
            msg_send![self, indexType]
        }
    }

    pub fn set_index_type(&self, index_ty: MTLIndexType) {
        unsafe {
            msg_send![self, setIndexType:index_ty]
        }
    }

    pub fn layouts(&self) -> Option<&BufferLayoutDescriptorArrayRef> {
        unsafe {
            msg_send![self, layouts]
        }
    }

    pub fn reset(&self) {
        unsafe {
            msg_send![self, reset]
        }
    }
}

pub enum MTLAttributeDescriptorArray {}

foreign_obj_type! {
    type CType = MTLAttributeDescriptorArray;
    pub struct AttributeDescriptorArray;
    pub struct AttributeDescriptorArrayRef;
}

impl AttributeDescriptorArrayRef {
    pub fn object_at(&self, index: usize) -> Option<&AttributeDescriptorRef> {
        unsafe {
            msg_send![self, objectAtIndexedSubscript:index]
        }
    }

    pub fn set_object_at(&self, index: usize, buffer_desc: Option<&AttributeDescriptorRef>) {
        unsafe {
            msg_send![self, setObject:buffer_desc atIndexedSubscript:index]
        }
    }
}

pub enum MTLAttributeDescriptor {}

foreign_obj_type! {
    type CType = MTLAttributeDescriptor;
    pub struct AttributeDescriptor;
    pub struct AttributeDescriptorRef;
}

impl AttributeDescriptorRef {
    pub fn buffer_index(&self) -> NSUInteger {
        unsafe {
            msg_send![self, bufferIndex]
        }
    }

    pub fn set_buffer_index(&self, buffer_index: NSUInteger) {
        unsafe {
            msg_send![self, setBufferIndex:buffer_index]
        }
    }

    pub fn format(&self) -> MTLAttributeFormat {
        unsafe {
            msg_send![self, format]
        }
    }

    pub fn set_format(&self, format: MTLAttributeFormat) {
        unsafe {
            msg_send![self, setFormat:format]
        }
    }

    pub fn offset(&self) -> NSUInteger {
        unsafe {
            msg_send![self, offset]
        }
    }

    pub fn set_offset(&self, offset: NSUInteger) {
        unsafe {
            msg_send![self, setOffset:offset]
        }
    }
}

pub enum MTLBufferLayoutDescriptorArray {}

foreign_obj_type! {
    type CType = MTLBufferLayoutDescriptorArray;
    pub struct BufferLayoutDescriptorArray;
    pub struct BufferLayoutDescriptorArrayRef;
}

impl BufferLayoutDescriptorArrayRef {
    pub fn object_at(&self, index: usize) -> Option<&BufferLayoutDescriptorRef> {
        unsafe {
            msg_send![self, objectAtIndexedSubscript:index]
        }
    }

    pub fn set_object_at(&self, index: usize, buffer_desc: Option<&BufferLayoutDescriptorRef>) {
        unsafe {
            msg_send![self, setObject:buffer_desc atIndexedSubscript:index]
        }
    }
}

pub enum MTLBufferLayoutDescriptor {}

foreign_obj_type! {
    type CType = MTLBufferLayoutDescriptor;
    pub struct BufferLayoutDescriptor;
    pub struct BufferLayoutDescriptorRef;
}

impl BufferLayoutDescriptorRef {
    pub fn step_function(&self) -> MTLStepFunction {
        unsafe {
            msg_send![self, stepFunction]
        }
    }

    pub fn set_step_function(&self, step_function: MTLStepFunction) {
        unsafe {
            msg_send![self, setStepFunction:step_function]
        }
    }

    pub fn step_rate(&self) -> NSUInteger {
        unsafe {
            msg_send![self, stepRate]
        }
    }

    pub fn set_step_rate(&self, step_rate: NSUInteger) {
        unsafe {
            msg_send![self, setStepRate:step_rate]
        }
    }

    pub fn stride(&self) -> NSUInteger {
        unsafe {
            msg_send![self, stride]
        }
    }

    pub fn set_stride(&self, stride: NSUInteger) {
        unsafe {
            msg_send![self, setStride:stride]
        }
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::vec::Vec;
use std::ops::Deref;

use util::*;
use classfile::attr::Attributes;
use classfile::constant_pool as cp;

const ACC_PUBLIC: u16 = 0x0001;
const ACC_PRIVATE: u16 = 0x0002;
const ACC_PROTECTED: u16 = 0x0004;
const ACC_STATIC: u16 = 0x0008;
const ACC_FINAL: u16 = 0x0010;
const ACC_VOLATILE: u16 = 0x0040;
const ACC_TRANSIENT: u16 = 0x0080;
const ACC_SYNTHETIC: u16 = 0x1000;
const ACC_ENUM: u16 = 0x4000;

#[derive(Debug)]
pub struct FieldAccessFlags {
    access_flags: u16
}

impl FieldAccessFlags {
    fn new(access_flags: u16) -> FieldAccessFlags {
        FieldAccessFlags {
            access_flags: access_flags
        }
    }

    pub fn is_public(&self) -> bool {
        (self.access_flags & ACC_PUBLIC) != 0
    }

    pub fn is_private(&self) -> bool {
        (self.access_flags & ACC_PRIVATE) != 0
    }

    pub fn is_protected(&self) -> bool {
        (self.access_flags & ACC_PROTECTED) != 0
    }

    pub fn is_static(&self) -> bool {
        (self.access_flags & ACC_STATIC) != 0
    }

    pub fn is_final(&self) -> bool {
        (self.access_flags & ACC_FINAL) != 0
    }

    pub fn is_volatile(&self) -> bool {
        (self.access_flags & ACC_VOLATILE) != 0
    }

    pub fn is_transient(&self) -> bool {
        (self.access_flags & ACC_TRANSIENT) != 0
    }

    pub fn is_synthetic(&self) -> bool {
        (self.access_flags & ACC_SYNTHETIC) != 0
    }

    pub fn is_enum(&self) -> bool {
        (self.access_flags & ACC_ENUM) != 0
    }
}

#[derive(Debug)]
pub struct Fields {
    fields: Vec<FieldInfo>
}

impl Fields {
    pub fn read<T: io::Read>(rdr: &mut T, constant_pool: &cp::ConstantPool) -> io::Result<Fields> {
        let fields_count = try!(read_u16(rdr));
        let mut fields: Vec<FieldInfo> = vec![];
        for _ in 0..fields_count {
            let entry = try!(FieldInfo::read(rdr, constant_pool));
            fields.push(entry);
        }
        Ok(Fields {
            fields: fields
        })
    }
}

impl Deref for Fields {
    type Target = Vec<FieldInfo>;

    fn deref(&self) -> &Vec<FieldInfo> {
        &self.fields
    }
}

#[derive(Debug)]
pub struct FieldInfo {
    pub access_flags: FieldAccessFlags,
    pub name_index: u16,
    pub descriptor_index: u16,
    pub attributes: Attributes
}

impl FieldInfo {
    pub fn read<T: io::Read>(rdr: &mut T, constant_pool: &cp::ConstantPool) -> io::Result<FieldInfo> {
        let access_flags = try!(read_u16(rdr));
        let name_index = try!(read_u16(rdr));
        let descriptor_index = try!(read_u16(rdr));
        let attributes: Attributes = try!(Attributes::read(rdr, constant_pool));
        Ok(FieldInfo {
            access_flags: FieldAccessFlags::new(access_flags),
            name_index: name_index,
            descriptor_index: descriptor_index,
            attributes: attributes
        })
    }
}
<commit_msg>Add some documentation to fields.rs<commit_after>use std::io;
use std::vec::Vec;
use std::ops::Deref;

use util::*;
use classfile::attr::Attributes;
use classfile::constant_pool as cp;

const ACC_PUBLIC: u16 = 0x0001;
const ACC_PRIVATE: u16 = 0x0002;
const ACC_PROTECTED: u16 = 0x0004;
const ACC_STATIC: u16 = 0x0008;
const ACC_FINAL: u16 = 0x0010;
const ACC_VOLATILE: u16 = 0x0040;
const ACC_TRANSIENT: u16 = 0x0080;
const ACC_SYNTHETIC: u16 = 0x1000;
const ACC_ENUM: u16 = 0x4000;

/// Holds the [`access_flags`](https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.5-200-A.1) value from a `FieldInfo` structure.
#[derive(Debug)]
pub struct FieldAccessFlags {
    access_flags: u16
}

impl FieldAccessFlags {
    fn new(access_flags: u16) -> FieldAccessFlags {
        FieldAccessFlags {
            access_flags: access_flags
        }
    }

    pub fn is_public(&self) -> bool {
        self.read_flag(ACC_PUBLIC)
    }

    pub fn is_private(&self) -> bool {
        self.read_flag(ACC_PRIVATE)
    }

    pub fn is_protected(&self) -> bool {
        self.read_flag(ACC_PROTECTED)
    }

    pub fn is_static(&self) -> bool {
        self.read_flag(ACC_STATIC)
    }

    pub fn is_final(&self) -> bool {
        self.read_flag(ACC_FINAL)
    }

    pub fn is_volatile(&self) -> bool {
        self.read_flag(ACC_VOLATILE)
    }

    pub fn is_transient(&self) -> bool {
        self.read_flag(ACC_TRANSIENT)
    }

    pub fn is_synthetic(&self) -> bool {
        self.read_flag(ACC_SYNTHETIC)
    }

    pub fn is_enum(&self) -> bool {
        self.read_flag(ACC_ENUM)
    }

    fn read_flag(&self, mask: u16) -> bool {
        (self.access_flags & mask) != 0
    }
}

/// Wrapper around a `Vec<FieldInfo>`.
#[derive(Debug)]
pub struct Fields {
    fields: Vec<FieldInfo>
}

impl Fields {
    /// Reads in a list of `FieldInfo` structures. The reader should be positioned such that
    /// the next 2 byte define the number of entries, followed immediately by the
    /// `FieldInfo` structures.
    pub fn read<T: io::Read>(rdr: &mut T, constant_pool: &cp::ConstantPool) -> io::Result<Fields> {
        let fields_count = try!(read_u16(rdr));
        let mut fields: Vec<FieldInfo> = vec![];
        for _ in 0..fields_count {
            let entry = try!(FieldInfo::read(rdr, constant_pool));
            fields.push(entry);
        }
        Ok(Fields {
            fields: fields
        })
    }
}

impl Deref for Fields {
    type Target = Vec<FieldInfo>;

    fn deref(&self) -> &Vec<FieldInfo> {
        &self.fields
    }
}

/// Metadata about a field in a class file.
#[derive(Debug)]
pub struct FieldInfo {
    /// Metadata about this field.
    pub access_flags: FieldAccessFlags,
    /// The name of this field.
    pub name_index: u16,
    /// A [field descriptor string](https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.3.2).
    pub descriptor_index: u16,
    /// Collection of attributes that are associated with this field.
    pub attributes: Attributes
}

impl FieldInfo {
    /// Constructs a [`FieldInfo`](https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.5)
    /// structure from a byte stream containing classfile data.
    pub fn read<T: io::Read>(rdr: &mut T, constant_pool: &cp::ConstantPool) -> io::Result<FieldInfo> {
        let access_flags = try!(read_u16(rdr));
        let name_index = try!(read_u16(rdr));
        let descriptor_index = try!(read_u16(rdr));
        let attributes: Attributes = try!(Attributes::read(rdr, constant_pool));
        Ok(FieldInfo {
            access_flags: FieldAccessFlags::new(access_flags),
            name_index: name_index,
            descriptor_index: descriptor_index,
            attributes: attributes
        })
    }
}
<|endoftext|>


<commit_before>mod config;
mod run;

use clap::{App, Arg, SubCommand};
use config::get_configs;
use env_logger::{Builder, Env};
use slog::{crit, o, warn, Drain, Level};

pub const DEFAULT_DATA_DIR: &str = ".lighthouse";
pub const CLIENT_CONFIG_FILENAME: &str = "beacon-node.toml";
pub const ETH2_CONFIG_FILENAME: &str = "eth2-spec.toml";
pub const TESTNET_CONFIG_FILENAME: &str = "testnet.toml";

fn main() {
    // debugging output for libp2p and external crates
    Builder::from_env(Env::default()).init();

    let matches = App::new("Lighthouse")
        .version(version::version().as_str())
        .author("Sigma Prime <contact@sigmaprime.io>")
        .about("Eth 2.0 Client")
        /*
         * Configuration directory locations.
         */
        .arg(
            Arg::with_name("datadir")
                .long("datadir")
                .value_name("DIR")
                .help("Data directory for keys and databases.")
                .takes_value(true)
                .global(true)
        )
        .arg(
            Arg::with_name("logfile")
                .long("logfile")
                .value_name("logfile")
                .help("File path where output will be written.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("network-dir")
                .long("network-dir")
                .value_name("NETWORK-DIR")
                .help("Data directory for network keys.")
                .takes_value(true)
                .global(true)
        )
        /*
         * Network parameters.
         */
        .arg(
            Arg::with_name("listen-address")
                .long("listen-address")
                .value_name("ADDRESS")
                .help("The address lighthouse will listen for UDP and TCP connections. (default 127.0.0.1).")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("port")
                .long("port")
                .value_name("PORT")
                .help("The TCP/UDP port to listen on. The UDP port can be modified by the --discovery-port flag.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("maxpeers")
                .long("maxpeers")
                .help("The maximum number of peers (default 10).")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("boot-nodes")
                .long("boot-nodes")
                .allow_hyphen_values(true)
                .value_name("BOOTNODES")
                .help("One or more comma-delimited base64-encoded ENR's to bootstrap the p2p network.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("discovery-port")
                .long("disc-port")
                .value_name("PORT")
                .help("The discovery UDP port.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("discovery-address")
                .long("discovery-address")
                .value_name("ADDRESS")
                .help("The IP address to broadcast to other peers on how to reach this node.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("topics")
                .long("topics")
                .value_name("STRING")
                .help("One or more comma-delimited gossipsub topic strings to subscribe to.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("libp2p-addresses")
                .long("libp2p-addresses")
                .value_name("MULTIADDR")
                .help("One or more comma-delimited multiaddrs to manually connect to a libp2p peer without an ENR.")
                .takes_value(true),
        )
        /*
         * gRPC parameters.
         */
        .arg(
            Arg::with_name("rpc")
                .long("rpc")
                .value_name("RPC")
                .help("Enable the RPC server.")
                .takes_value(false),
        )
        .arg(
            Arg::with_name("rpc-address")
                .long("rpc-address")
                .value_name("Address")
                .help("Listen address for RPC endpoint.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("rpc-port")
                .long("rpc-port")
                .help("Listen port for RPC endpoint.")
                .takes_value(true),
        )
        /* Client related arguments */
        .arg(
            Arg::with_name("api")
                .long("api")
                .value_name("API")
                .help("Enable the RESTful HTTP API server.")
                .takes_value(false),
        )
        .arg(
            Arg::with_name("api-address")
                .long("api-address")
                .value_name("APIADDRESS")
                .help("Set the listen address for the RESTful HTTP API server.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("api-port")
                .long("api-port")
                .value_name("APIPORT")
                .help("Set the listen TCP port for the RESTful HTTP API server.")
                .takes_value(true),
        )

        /*
         * Database parameters.
         */
        .arg(
            Arg::with_name("db")
                .long("db")
                .value_name("DB")
                .help("Type of database to use.")
                .takes_value(true)
                .possible_values(&["disk", "memory"])
                .default_value("disk"),
        )
        /*
         * Logging.
         */
        .arg(
            Arg::with_name("debug-level")
                .long("debug-level")
                .value_name("LEVEL")
                .help("The title of the spec constants for chain config.")
                .takes_value(true)
                .possible_values(&["info", "debug", "trace", "warn", "error", "crit"])
                .default_value("trace"),
        )
        .arg(
            Arg::with_name("verbosity")
                .short("v")
                .multiple(true)
                .help("Sets the verbosity level")
                .takes_value(true),
        )
        /*
<<<<<<< HEAD
         * The "testnet" sub-command.
         *
         * Allows for creating a new datadir with testnet-specific configs.
         */
        .subcommand(SubCommand::with_name("testnet")
            .about("Create a new Lighthouse datadir using a testnet strategy.")
            .arg(
                Arg::with_name("spec")
                    .short("s")
                    .long("spec")
                    .value_name("TITLE")
                    .help("Specifies the default eth2 spec type. Only effective when creating a new datadir.")
                    .takes_value(true)
                    .required(true)
                    .possible_values(&["mainnet", "minimal", "interop"])
                    .default_value("minimal")
            )
            .arg(
                Arg::with_name("eth2-config")
                    .long("eth2-config")
                    .value_name("TOML_FILE")
                    .help("A existing eth2_spec TOML file (e.g., eth2_spec.toml).")
                    .takes_value(true)
                    .conflicts_with("spec")
            )
            .arg(
                Arg::with_name("client-config")
                    .long("client-config")
                    .value_name("TOML_FILE")
                    .help("An existing beacon_node TOML file (e.g., beacon_node.toml).")
                    .takes_value(true)
            )
            .arg(
                Arg::with_name("random-datadir")
                    .long("random-datadir")
                    .short("r")
                    .help("If present, append a random string to the datadir path. Useful for fast development \
                          iteration.")
            )
            .arg(
                Arg::with_name("force")
                    .long("force")
                    .short("f")
                    .help("If present, will create new config and database files and move the any existing to a \
                           backup directory.")
                    .conflicts_with("random-datadir")
            )
            /*
             * Testnet sub-commands.
             *
             * `boostrap`
             *
             * Start a new node by downloading genesis and network info from another node via the
             * HTTP API.
             */
            .subcommand(SubCommand::with_name("bootstrap")
                .about("Connects to the given HTTP server, downloads a genesis state and attempts to peer with it.")
                .arg(Arg::with_name("server")
                    .value_name("HTTP_SERVER")
                    .required(true)
                    .help("A HTTP server, with a http:// prefix"))
                .arg(Arg::with_name("libp2p-port")
                    .short("p")
                    .long("port")
                    .value_name("TCP_PORT")
                    .help("A libp2p listen port used to peer with the bootstrap server. This flag is useful \
                           when port-fowarding is used: you may connect using a different port than \
                           the one the server is immediately listening on."))
            )
            /*
             * `recent`
             *
             * Start a new node, with a specified number of validators with a genesis time in the last
             * 30-minutes.
             */
            .subcommand(SubCommand::with_name("recent")
                .about("Creates a new genesis state where the genesis time was at the previous \
                       30-minute boundary (e.g., 12:00, 12:30, 13:00, etc.)")
                .arg(Arg::with_name("validator_count")
                    .value_name("VALIDATOR_COUNT")
                    .required(true)
                    .help("The number of validators in the genesis state"))
            )
            .subcommand(SubCommand::with_name("yaml-genesis-state")
                .about("Creates a new datadir where the genesis state is read from YAML. Will fail to parse \
                       a YAML state that was generated to a different spec than that specified by --spec.")
                .arg(Arg::with_name("file")
                    .value_name("YAML_FILE")
                    .required(true)
                    .help("A YAML file from which to read the state"))
            )
        )
        .get_matches();

    // build the initial logger
    let decorator = slog_term::TermDecorator::new().build();
    let decorator = logging::AlignedTermDecorator::new(decorator, logging::MAX_MESSAGE_WIDTH);
    let drain = slog_term::FullFormat::new(decorator).build().fuse();
    let drain = slog_async::Async::new(drain).build();

    let drain = match matches.value_of("debug-level") {
        Some("info") => drain.filter_level(Level::Info),
        Some("debug") => drain.filter_level(Level::Debug),
        Some("trace") => drain.filter_level(Level::Trace),
        Some("warn") => drain.filter_level(Level::Warning),
        Some("error") => drain.filter_level(Level::Error),
        Some("crit") => drain.filter_level(Level::Critical),
        _ => unreachable!("guarded by clap"),
    };

    let drain = match matches.occurrences_of("verbosity") {
        0 => drain.filter_level(Level::Info),
        1 => drain.filter_level(Level::Debug),
        2 => drain.filter_level(Level::Trace),
        _ => drain.filter_level(Level::Trace),
    };

    let log = slog::Logger::root(drain.fuse(), o!());

    warn!(
        log,
        "Ethereum 2.0 is pre-release. This software is experimental."
    );

    // Load the process-wide configuration.
    //
    // May load this from disk or create a new configuration, depending on the CLI flags supplied.
    let (client_config, eth2_config) = match get_configs(&matches, &log) {
        Ok(configs) => configs,
        Err(e) => {
            crit!(log, "Failed to load configuration"; "error" => e);
            return;
        }
    };

    // Start the node using a `tokio` executor.
    match run::run_beacon_node(client_config, eth2_config, &log) {
        Ok(_) => {}
        Err(e) => crit!(log, "Beacon node failed to start"; "reason" => format!("{:}", e)),
    }
}
<commit_msg>Remove old git merge relic<commit_after>mod config;
mod run;

use clap::{App, Arg, SubCommand};
use config::get_configs;
use env_logger::{Builder, Env};
use slog::{crit, o, warn, Drain, Level};

pub const DEFAULT_DATA_DIR: &str = ".lighthouse";
pub const CLIENT_CONFIG_FILENAME: &str = "beacon-node.toml";
pub const ETH2_CONFIG_FILENAME: &str = "eth2-spec.toml";
pub const TESTNET_CONFIG_FILENAME: &str = "testnet.toml";

fn main() {
    // debugging output for libp2p and external crates
    Builder::from_env(Env::default()).init();

    let matches = App::new("Lighthouse")
        .version(version::version().as_str())
        .author("Sigma Prime <contact@sigmaprime.io>")
        .about("Eth 2.0 Client")
        /*
         * Configuration directory locations.
         */
        .arg(
            Arg::with_name("datadir")
                .long("datadir")
                .value_name("DIR")
                .help("Data directory for keys and databases.")
                .takes_value(true)
                .global(true)
        )
        .arg(
            Arg::with_name("logfile")
                .long("logfile")
                .value_name("logfile")
                .help("File path where output will be written.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("network-dir")
                .long("network-dir")
                .value_name("NETWORK-DIR")
                .help("Data directory for network keys.")
                .takes_value(true)
                .global(true)
        )
        /*
         * Network parameters.
         */
        .arg(
            Arg::with_name("listen-address")
                .long("listen-address")
                .value_name("ADDRESS")
                .help("The address lighthouse will listen for UDP and TCP connections. (default 127.0.0.1).")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("port")
                .long("port")
                .value_name("PORT")
                .help("The TCP/UDP port to listen on. The UDP port can be modified by the --discovery-port flag.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("maxpeers")
                .long("maxpeers")
                .help("The maximum number of peers (default 10).")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("boot-nodes")
                .long("boot-nodes")
                .allow_hyphen_values(true)
                .value_name("BOOTNODES")
                .help("One or more comma-delimited base64-encoded ENR's to bootstrap the p2p network.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("discovery-port")
                .long("disc-port")
                .value_name("PORT")
                .help("The discovery UDP port.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("discovery-address")
                .long("discovery-address")
                .value_name("ADDRESS")
                .help("The IP address to broadcast to other peers on how to reach this node.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("topics")
                .long("topics")
                .value_name("STRING")
                .help("One or more comma-delimited gossipsub topic strings to subscribe to.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("libp2p-addresses")
                .long("libp2p-addresses")
                .value_name("MULTIADDR")
                .help("One or more comma-delimited multiaddrs to manually connect to a libp2p peer without an ENR.")
                .takes_value(true),
        )
        /*
         * gRPC parameters.
         */
        .arg(
            Arg::with_name("rpc")
                .long("rpc")
                .value_name("RPC")
                .help("Enable the RPC server.")
                .takes_value(false),
        )
        .arg(
            Arg::with_name("rpc-address")
                .long("rpc-address")
                .value_name("Address")
                .help("Listen address for RPC endpoint.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("rpc-port")
                .long("rpc-port")
                .help("Listen port for RPC endpoint.")
                .takes_value(true),
        )
        /* Client related arguments */
        .arg(
            Arg::with_name("api")
                .long("api")
                .value_name("API")
                .help("Enable the RESTful HTTP API server.")
                .takes_value(false),
        )
        .arg(
            Arg::with_name("api-address")
                .long("api-address")
                .value_name("APIADDRESS")
                .help("Set the listen address for the RESTful HTTP API server.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("api-port")
                .long("api-port")
                .value_name("APIPORT")
                .help("Set the listen TCP port for the RESTful HTTP API server.")
                .takes_value(true),
        )

        /*
         * Database parameters.
         */
        .arg(
            Arg::with_name("db")
                .long("db")
                .value_name("DB")
                .help("Type of database to use.")
                .takes_value(true)
                .possible_values(&["disk", "memory"])
                .default_value("disk"),
        )
        /*
         * Logging.
         */
        .arg(
            Arg::with_name("debug-level")
                .long("debug-level")
                .value_name("LEVEL")
                .help("The title of the spec constants for chain config.")
                .takes_value(true)
                .possible_values(&["info", "debug", "trace", "warn", "error", "crit"])
                .default_value("trace"),
        )
        .arg(
            Arg::with_name("verbosity")
                .short("v")
                .multiple(true)
                .help("Sets the verbosity level")
                .takes_value(true),
        )
        /*
         * The "testnet" sub-command.
         *
         * Allows for creating a new datadir with testnet-specific configs.
         */
        .subcommand(SubCommand::with_name("testnet")
            .about("Create a new Lighthouse datadir using a testnet strategy.")
            .arg(
                Arg::with_name("spec")
                    .short("s")
                    .long("spec")
                    .value_name("TITLE")
                    .help("Specifies the default eth2 spec type. Only effective when creating a new datadir.")
                    .takes_value(true)
                    .required(true)
                    .possible_values(&["mainnet", "minimal", "interop"])
                    .default_value("minimal")
            )
            .arg(
                Arg::with_name("eth2-config")
                    .long("eth2-config")
                    .value_name("TOML_FILE")
                    .help("A existing eth2_spec TOML file (e.g., eth2_spec.toml).")
                    .takes_value(true)
                    .conflicts_with("spec")
            )
            .arg(
                Arg::with_name("client-config")
                    .long("client-config")
                    .value_name("TOML_FILE")
                    .help("An existing beacon_node TOML file (e.g., beacon_node.toml).")
                    .takes_value(true)
            )
            .arg(
                Arg::with_name("random-datadir")
                    .long("random-datadir")
                    .short("r")
                    .help("If present, append a random string to the datadir path. Useful for fast development \
                          iteration.")
            )
            .arg(
                Arg::with_name("force")
                    .long("force")
                    .short("f")
                    .help("If present, will create new config and database files and move the any existing to a \
                           backup directory.")
                    .conflicts_with("random-datadir")
            )
            /*
             * Testnet sub-commands.
             *
             * `boostrap`
             *
             * Start a new node by downloading genesis and network info from another node via the
             * HTTP API.
             */
            .subcommand(SubCommand::with_name("bootstrap")
                .about("Connects to the given HTTP server, downloads a genesis state and attempts to peer with it.")
                .arg(Arg::with_name("server")
                    .value_name("HTTP_SERVER")
                    .required(true)
                    .help("A HTTP server, with a http:// prefix"))
                .arg(Arg::with_name("libp2p-port")
                    .short("p")
                    .long("port")
                    .value_name("TCP_PORT")
                    .help("A libp2p listen port used to peer with the bootstrap server. This flag is useful \
                           when port-fowarding is used: you may connect using a different port than \
                           the one the server is immediately listening on."))
            )
            /*
             * `recent`
             *
             * Start a new node, with a specified number of validators with a genesis time in the last
             * 30-minutes.
             */
            .subcommand(SubCommand::with_name("recent")
                .about("Creates a new genesis state where the genesis time was at the previous \
                       30-minute boundary (e.g., 12:00, 12:30, 13:00, etc.)")
                .arg(Arg::with_name("validator_count")
                    .value_name("VALIDATOR_COUNT")
                    .required(true)
                    .help("The number of validators in the genesis state"))
            )
            .subcommand(SubCommand::with_name("yaml-genesis-state")
                .about("Creates a new datadir where the genesis state is read from YAML. Will fail to parse \
                       a YAML state that was generated to a different spec than that specified by --spec.")
                .arg(Arg::with_name("file")
                    .value_name("YAML_FILE")
                    .required(true)
                    .help("A YAML file from which to read the state"))
            )
        )
        .get_matches();

    // build the initial logger
    let decorator = slog_term::TermDecorator::new().build();
    let decorator = logging::AlignedTermDecorator::new(decorator, logging::MAX_MESSAGE_WIDTH);
    let drain = slog_term::FullFormat::new(decorator).build().fuse();
    let drain = slog_async::Async::new(drain).build();

    let drain = match matches.value_of("debug-level") {
        Some("info") => drain.filter_level(Level::Info),
        Some("debug") => drain.filter_level(Level::Debug),
        Some("trace") => drain.filter_level(Level::Trace),
        Some("warn") => drain.filter_level(Level::Warning),
        Some("error") => drain.filter_level(Level::Error),
        Some("crit") => drain.filter_level(Level::Critical),
        _ => unreachable!("guarded by clap"),
    };

    let drain = match matches.occurrences_of("verbosity") {
        0 => drain.filter_level(Level::Info),
        1 => drain.filter_level(Level::Debug),
        2 => drain.filter_level(Level::Trace),
        _ => drain.filter_level(Level::Trace),
    };

    let log = slog::Logger::root(drain.fuse(), o!());

    warn!(
        log,
        "Ethereum 2.0 is pre-release. This software is experimental."
    );

    // Load the process-wide configuration.
    //
    // May load this from disk or create a new configuration, depending on the CLI flags supplied.
    let (client_config, eth2_config) = match get_configs(&matches, &log) {
        Ok(configs) => configs,
        Err(e) => {
            crit!(log, "Failed to load configuration"; "error" => e);
            return;
        }
    };

    // Start the node using a `tokio` executor.
    match run::run_beacon_node(client_config, eth2_config, &log) {
        Ok(_) => {}
        Err(e) => crit!(log, "Beacon node failed to start"; "reason" => format!("{:}", e)),
    }
}
<|endoftext|>