<commit_before>use clap::{App, Arg};
use luminance_glfw::{self, open_window};
pub use luminance_glfw::{Action, DeviceError, Key, MouseButton, WindowDim, WindowEvent, WindowOpt};
use std::cell::RefCell;
use std::rc::Rc;
use std::thread;
use std::time::{Duration, Instant};

use camera::{Camera, Freefly};
use linear::V3;

type Time = f64;

/// Signals events can pass up back to their handlers to notify them how they have processed an
/// event. They’re three kinds of signals:
///
/// - `EventSig::Ignored`:  the event should be passed to other handlers the parents knows about –
///    if any – because it wasn’t handled (ignored);
///
/// - `EventSig::Handled`: the event has been correctly handled;
///
/// - `EventSig::Focused`: the event has been correctly handled, and the parent should consider that
///    the this handler has now an exclusive focus on that event;
///
/// - `EventSig::Aborted`: the event has been correctly handled and the parent handler should be
///    aborted. This signal is typically used to kill all the handlers chain and thus quit the
///    application.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum EventSig {
  Ignored,
  Handled,
  Focused,
  Aborted
}

/// Class of event handlers.
///
/// All functions return a special object of type `EventSig`. An event report gives information
/// about how a handler has handled the event. See the documentation of `EventSig` for further
/// information.
///
/// All functions’ implementations default to `EventSig::Ignored`.
pub trait EventHandler {
  /// Implement this function if you want to react to key strokes.
  fn on_key(&mut self, _: Key, _: Action) -> EventSig { EventSig::Ignored }
  /// Implement this function if you want to react to mouse button events.
  fn on_mouse_button(&mut self, _: MouseButton, _: Action) -> EventSig { EventSig::Ignored }
  /// Implement this function if you want to react to cursor moves.
  fn on_cursor_move(&mut self, _: [f32; 2]) -> EventSig { EventSig::Ignored }
  /// Implement this function if you want to react to scroll events.
  fn on_scroll(&mut self, _: [f32; 2]) -> EventSig { EventSig::Ignored }
}

/// Empty handler.
///
/// This handler will just let pass all events without doing anything. It’s only useful for debug
/// purposes when you don’t want to bother with interaction – it doesn’t even let you close the
/// application!
#[derive(Clone, Copy, Eq, Debug, PartialEq)]
pub struct Unhandled;

impl EventHandler for Unhandled {}

/// Device object.
///
/// Upon bootstrapping, this type is created to add interaction and context handling.
pub struct Device {
  raw: luminance_glfw::Device,
  /// Some kind of epoch start the application started at.
  start_time: Instant
}

impl Device {
  /// Entry point.
  ///
  /// This function is the first one you have to call before anything else related to this crate.
  ///
  /// > Note: see `bootstrap!` macro for a better usage.
  pub fn new(def_width: u32,
             def_height: u32,
             version: &str,
             author: &str,
             title: &str,
             win_opt: WindowOpt)
             -> Result<Self, DeviceError> {
    let options = App::new(title)
      .version(version)
      .author(author)
      .arg(Arg::with_name("width")
           .short("w")
           .long("width")
           .value_name("WIDTH")
           .help("Sets the width of the viewport used for render")
           .takes_value(true))
      .arg(Arg::with_name("height")
           .short("h")
           .long("height")
           .value_name("HEIGHT")
           .help("Sets the height of the viewport used for render")
           .takes_value(true))
      .arg(Arg::with_name("fullscreen")
           .short("f")
           .long("fullscreen")
           .value_name("FULLSCREEN")
           .help("Sets the viewport to be displayed in fullscreen mode")
           .takes_value(false))
      .get_matches();

    let width = options.value_of("width").map(|s| s.parse().unwrap_or(def_width)).unwrap_or(def_width);
    let height = options.value_of("height").map(|s| s.parse().unwrap_or(def_height)).unwrap_or(def_height);
    let fullscreen = options.is_present("fullscreen");

    // build the WindowDim
    let win_dim = if fullscreen {
      if options.is_present("width") && options.is_present("height") {
        WindowDim::FullscreenRestricted(width, height)
      } else {
        WindowDim::Fullscreen
      }
    } else {
      WindowDim::Windowed(width, height)
    };

    info!("{} starting", title);
    info!("window mode: {:?}", win_dim);
    info!("window options: {:?}", win_opt);

    let dev = open_window(win_dim, title, win_opt)?;

    info!("bootstrapping finished");

    Ok(Device {
      raw: dev,
      start_time: Instant::now()
    })
  }

  /// Width of the attached window.
  #[inline]
  pub fn width(&self) -> u32 {
    self.raw.width()
  }

  /// Height of the attached window.
  #[inline]
  pub fn height(&self) -> u32 {
    self.raw.height()
  }

  /// Current time, starting from the beginning of the creation of that object.
  pub fn time(&self) -> f64 {
    let elapsed = Instant::now() - self.start_time;
    elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 * 1e-9
  }

  /// Dispatch events to a handler.
  pub fn dispatch_events<H>(&mut self, handler: &mut H) -> bool where H: EventHandler {
    for (_, event) in self.raw.events() {
      match event {
        WindowEvent::Key(key, _, action, _) => if handler.on_key(key, action) == EventSig::Aborted {
          return false;
        },
        WindowEvent::MouseButton(button, action, _) => if handler.on_mouse_button(button, action) == EventSig::Aborted {
          return false;
        },
        WindowEvent::CursorPos(x, y) => if handler.on_cursor_move([x as f32, y as f32]) == EventSig::Aborted {
          return false;
        },
        WindowEvent::Scroll(x, y) => if handler.on_scroll([x as f32, y as f32]) == EventSig::Aborted {
          return false;
        },
        _ => ()
      }
    }

    true
  }

  /// Step function.
  ///
  /// This function provides two features:
  ///
  /// - it runs a *drawer* function, responsible of rendering a single frame, by passing it the
  ///   current time
  /// - it performs process idleing if you have requested a certain *framerate* – frame per second.
  ///
  /// The second feature is very neat because it lets you handle the scheduler off your application
  /// and then contribute to better CPU usage.
  ///
  /// > Note: if you pass `None`, no idleing will take place. However, you might be blocked by the
  /// *VSync* if enabled in your driver.
  pub fn step<FPS, R>(&mut self, fps: FPS, mut draw_frame: R) -> bool where FPS: Into<Option<u32>>, R: FnMut(Time) {
    let t = self.time();

    self.raw.draw(|| {
      draw_frame(t);
    });

    // wait for next frame according to the wished FPS
    if let Some(fps) = fps.into() {
      let fps = fps as f64;
      let max_time = 1. / fps;
      let elapsed_time = self.time() - t;

      if elapsed_time < max_time {
        let sleep_time = max_time - elapsed_time;
        thread::sleep(Duration::from_millis((sleep_time * 1e3) as u64));
      }
    }

    true
  }
}

#[macro_export]
macro_rules! bootstrap {
  ($def_width:expr, $def_height:expr, $win_opt:expr) => {{
    $crate::bootstrap::Device::new($def_width,
                                   $def_height,
                                   crate_version!(),
                                   crate_authors!(),
                                   crate_name!(),
                                   $win_opt)
  }}
}

/// Freefly handler.
///
/// This handler is very neat as it provides freefly interaction.
pub struct FreeflyHandler {
  camera: Rc<RefCell<Camera<Freefly>>>,
  left_down: bool,
  right_down: bool,
  last_cursor: [f32; 2]
}

impl FreeflyHandler {
  pub fn new(camera: Rc<RefCell<Camera<Freefly>>>) -> Self {
    FreeflyHandler {
      camera: camera,
      left_down: false,
      right_down: false,
      last_cursor: [0., 0.]
    }
  }

  fn move_camera_on_event(&mut self, key: Key) {
    let camera = &mut self.camera.borrow_mut();

    match key {
      Key::W => camera.mv(V3::new(0., 0., 1.)),
      Key::S => camera.mv(V3::new(0., 0., -1.)),
      Key::A => camera.mv(V3::new(1., 0., 0.)),
      Key::D => camera.mv(V3::new(-1., 0., 0.)),
      Key::Q => camera.mv(V3::new(0., -1., 0.)),
      Key::E => camera.mv(V3::new(0., 1., 0.)),
      _ => ()
    }
  }

  fn orient_camera_on_event(&mut self, cursor: [f32; 2]) {
    let camera = &mut self.camera.borrow_mut();

    if self.left_down {
      let (dx, dy) = (cursor[0] - self.last_cursor[0], cursor[1] - self.last_cursor[1]);
      camera.look_around(V3::new(dy, dx, 0.));
    } else if self.right_down {
      let (dx, _) = (cursor[0] - self.last_cursor[0], cursor[1] - self.last_cursor[1]);
      camera.look_around(V3::new(0., 0., dx));
    }

    self.last_cursor = cursor;
  }
}

impl EventHandler for FreeflyHandler {
  fn on_key(&mut self, key: Key, action: Action) -> EventSig {
    match action {
      Action::Press | Action::Repeat => self.move_camera_on_event(key),
      Action::Release => if key == Key::Escape { return EventSig::Aborted }
    }

    EventSig::Handled
  }

  fn on_mouse_button(&mut self, button: MouseButton, action: Action) -> EventSig {
    match (button, action) {
      (MouseButton::Button1, Action::Press) => {
        self.left_down = true;
      },
      (MouseButton::Button1, Action::Release) => {
        self.left_down = false;
      },
      (MouseButton::Button2, Action::Press) => {
        self.right_down = true;
      },
      (MouseButton::Button2, Action::Release) => {
        self.right_down = false;
      },
      _ => ()
    }

    EventSig::Handled
  }

  fn on_cursor_move(&mut self, dir: [f32; 2]) -> EventSig {
    self.orient_camera_on_event(dir);
    EventSig::Handled
  }
}
<commit_msg>Implement a better Device::size function (for hidpi displays).<commit_after>use clap::{App, Arg};
use luminance_glfw::{self, open_window};
pub use luminance_glfw::{Action, DeviceError, Key, MouseButton, WindowDim, WindowEvent, WindowOpt};
use std::cell::RefCell;
use std::rc::Rc;
use std::thread;
use std::time::{Duration, Instant};

use camera::{Camera, Freefly};
use linear::V3;

type Time = f64;

/// Signals events can pass up back to their handlers to notify them how they have processed an
/// event. They’re three kinds of signals:
///
/// - `EventSig::Ignored`:  the event should be passed to other handlers the parents knows about –
///    if any – because it wasn’t handled (ignored);
///
/// - `EventSig::Handled`: the event has been correctly handled;
///
/// - `EventSig::Focused`: the event has been correctly handled, and the parent should consider that
///    the this handler has now an exclusive focus on that event;
///
/// - `EventSig::Aborted`: the event has been correctly handled and the parent handler should be
///    aborted. This signal is typically used to kill all the handlers chain and thus quit the
///    application.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum EventSig {
  Ignored,
  Handled,
  Focused,
  Aborted
}

/// Class of event handlers.
///
/// All functions return a special object of type `EventSig`. An event report gives information
/// about how a handler has handled the event. See the documentation of `EventSig` for further
/// information.
///
/// All functions’ implementations default to `EventSig::Ignored`.
pub trait EventHandler {
  /// Implement this function if you want to react to key strokes.
  fn on_key(&mut self, _: Key, _: Action) -> EventSig { EventSig::Ignored }
  /// Implement this function if you want to react to mouse button events.
  fn on_mouse_button(&mut self, _: MouseButton, _: Action) -> EventSig { EventSig::Ignored }
  /// Implement this function if you want to react to cursor moves.
  fn on_cursor_move(&mut self, _: [f32; 2]) -> EventSig { EventSig::Ignored }
  /// Implement this function if you want to react to scroll events.
  fn on_scroll(&mut self, _: [f32; 2]) -> EventSig { EventSig::Ignored }
  /// Implement this function if you want to react to size events.
  fn on_resize(&mut self, _: [u32; 2]) -> EventSig { EventSig::Ignored }
}

/// Empty handler.
///
/// This handler will just let pass all events without doing anything. It’s only useful for debug
/// purposes when you don’t want to bother with interaction – it doesn’t even let you close the
/// application!
#[derive(Clone, Copy, Eq, Debug, PartialEq)]
pub struct Unhandled;

impl EventHandler for Unhandled {}

/// Device object.
///
/// Upon bootstrapping, this type is created to add interaction and context handling.
pub struct Device {
  raw: luminance_glfw::Device,
  /// Some kind of epoch start the application started at.
  start_time: Instant
}

impl Device {
  /// Entry point.
  ///
  /// This function is the first one you have to call before anything else related to this crate.
  ///
  /// > Note: see `bootstrap!` macro for a better usage.
  pub fn new(def_width: u32,
             def_height: u32,
             version: &str,
             author: &str,
             title: &str,
             win_opt: WindowOpt)
             -> Result<Self, DeviceError> {
    let options = App::new(title)
      .version(version)
      .author(author)
      .arg(Arg::with_name("width")
           .short("w")
           .long("width")
           .value_name("WIDTH")
           .help("Sets the width of the viewport used for render")
           .takes_value(true))
      .arg(Arg::with_name("height")
           .short("h")
           .long("height")
           .value_name("HEIGHT")
           .help("Sets the height of the viewport used for render")
           .takes_value(true))
      .arg(Arg::with_name("fullscreen")
           .short("f")
           .long("fullscreen")
           .value_name("FULLSCREEN")
           .help("Sets the viewport to be displayed in fullscreen mode")
           .takes_value(false))
      .get_matches();

    let width = options.value_of("width").map(|s| s.parse().unwrap_or(def_width)).unwrap_or(def_width);
    let height = options.value_of("height").map(|s| s.parse().unwrap_or(def_height)).unwrap_or(def_height);
    let fullscreen = options.is_present("fullscreen");

    // build the WindowDim
    let win_dim = if fullscreen {
      if options.is_present("width") && options.is_present("height") {
        WindowDim::FullscreenRestricted(width, height)
      } else {
        WindowDim::Fullscreen
      }
    } else {
      WindowDim::Windowed(width, height)
    };

    info!("{} starting", title);
    info!("window mode: {:?}", win_dim);
    info!("window options: {:?}", win_opt);

    let dev = open_window(win_dim, title, win_opt)?;

    info!("bootstrapping finished");

    Ok(Device {
      raw: dev,
      start_time: Instant::now()
    })
  }

  /// Size of the attached window.
  #[inline]
  pub fn size(&self) -> [u32; 2] {
    self.raw.size()
  }

  /// Current time, starting from the beginning of the creation of that object.
  pub fn time(&self) -> f64 {
    let elapsed = Instant::now() - self.start_time;
    elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 * 1e-9
  }

  /// Dispatch events to a handler.
  pub fn dispatch_events<H>(&mut self, handler: &mut H) -> bool where H: EventHandler {
    for (_, event) in self.raw.events() {
      match event {
        WindowEvent::Key(key, _, action, _) => if handler.on_key(key, action) == EventSig::Aborted {
          return false;
        },
        WindowEvent::MouseButton(button, action, _) => if handler.on_mouse_button(button, action) == EventSig::Aborted {
          return false;
        },
        WindowEvent::CursorPos(x, y) => if handler.on_cursor_move([x as f32, y as f32]) == EventSig::Aborted {
          return false;
        },
        WindowEvent::Scroll(x, y) => if handler.on_scroll([x as f32, y as f32]) == EventSig::Aborted {
          return false;
        },
        WindowEvent::FramebufferSize(w, h) => if handler.on_resize([w as u32, h as u32]) == EventSig::Aborted {
          return false;
        },
        _ => ()
      }
    }

    true
  }

  /// Step function.
  ///
  /// This function provides two features:
  ///
  /// - it runs a *drawer* function, responsible of rendering a single frame, by passing it the
  ///   current time
  /// - it performs process idleing if you have requested a certain *framerate* – frame per second.
  ///
  /// The second feature is very neat because it lets you handle the scheduler off your application
  /// and then contribute to better CPU usage.
  ///
  /// > Note: if you pass `None`, no idleing will take place. However, you might be blocked by the
  /// *VSync* if enabled in your driver.
  pub fn step<FPS, R>(&mut self, fps: FPS, mut draw_frame: R) -> bool where FPS: Into<Option<u32>>, R: FnMut(Time) {
    let t = self.time();

    self.raw.draw(|| {
      draw_frame(t);
    });

    // wait for next frame according to the wished FPS
    if let Some(fps) = fps.into() {
      let fps = fps as f64;
      let max_time = 1. / fps;
      let elapsed_time = self.time() - t;

      if elapsed_time < max_time {
        let sleep_time = max_time - elapsed_time;
        thread::sleep(Duration::from_millis((sleep_time * 1e3) as u64));
      }
    }

    true
  }
}

#[macro_export]
macro_rules! bootstrap {
  ($def_width:expr, $def_height:expr, $win_opt:expr) => {{
    $crate::bootstrap::Device::new($def_width,
                                   $def_height,
                                   crate_version!(),
                                   crate_authors!(),
                                   crate_name!(),
                                   $win_opt)
  }}
}

/// Freefly handler.
///
/// This handler is very neat as it provides freefly interaction.
pub struct FreeflyHandler {
  camera: Rc<RefCell<Camera<Freefly>>>,
  left_down: bool,
  right_down: bool,
  last_cursor: [f32; 2]
}

impl FreeflyHandler {
  pub fn new(camera: Rc<RefCell<Camera<Freefly>>>) -> Self {
    FreeflyHandler {
      camera: camera,
      left_down: false,
      right_down: false,
      last_cursor: [0., 0.]
    }
  }

  fn move_camera_on_event(&mut self, key: Key) {
    let camera = &mut self.camera.borrow_mut();

    match key {
      Key::W => camera.mv(V3::new(0., 0., 1.)),
      Key::S => camera.mv(V3::new(0., 0., -1.)),
      Key::A => camera.mv(V3::new(1., 0., 0.)),
      Key::D => camera.mv(V3::new(-1., 0., 0.)),
      Key::Q => camera.mv(V3::new(0., -1., 0.)),
      Key::E => camera.mv(V3::new(0., 1., 0.)),
      _ => ()
    }
  }

  fn orient_camera_on_event(&mut self, cursor: [f32; 2]) {
    let camera = &mut self.camera.borrow_mut();

    if self.left_down {
      let (dx, dy) = (cursor[0] - self.last_cursor[0], cursor[1] - self.last_cursor[1]);
      camera.look_around(V3::new(dy, dx, 0.));
    } else if self.right_down {
      let (dx, _) = (cursor[0] - self.last_cursor[0], cursor[1] - self.last_cursor[1]);
      camera.look_around(V3::new(0., 0., dx));
    }

    self.last_cursor = cursor;
  }
}

impl EventHandler for FreeflyHandler {
  fn on_key(&mut self, key: Key, action: Action) -> EventSig {
    match action {
      Action::Press | Action::Repeat => self.move_camera_on_event(key),
      Action::Release => if key == Key::Escape { return EventSig::Aborted }
    }

    EventSig::Handled
  }

  fn on_mouse_button(&mut self, button: MouseButton, action: Action) -> EventSig {
    match (button, action) {
      (MouseButton::Button1, Action::Press) => {
        self.left_down = true;
      },
      (MouseButton::Button1, Action::Release) => {
        self.left_down = false;
      },
      (MouseButton::Button2, Action::Press) => {
        self.right_down = true;
      },
      (MouseButton::Button2, Action::Release) => {
        self.right_down = false;
      },
      _ => ()
    }

    EventSig::Handled
  }

  fn on_cursor_move(&mut self, dir: [f32; 2]) -> EventSig {
    self.orient_camera_on_event(dir);
    EventSig::Handled
  }
}
<|endoftext|>


<commit_before>use gl;
use glfw::{self, Context, CursorMode, SwapInterval, Window};
pub use glfw::{Action, Key, MouseButton};
use std::cell::RefCell;
use std::os::raw::c_void;
use std::rc::Rc;
use std::sync::mpsc;
use std::thread;
use std::time::{Duration, Instant};

use camera::{Camera, Freefly};
use linear::Translation;

type Time = f64;

/// Dimension of the window to create.
#[derive(Clone, Copy, Debug)]
pub enum WindowDim {
  Windowed(u32, u32),
  FullScreen,
  FullScreenRestricted(u32, u32)
}

type Keyboard = mpsc::Receiver<(Key, Action)>;
type Mouse = mpsc::Receiver<(MouseButton, Action)>;
type MouseMove = mpsc::Receiver<[f32; 2]>;
type Scroll = mpsc::Receiver<[f32; 2]>;

/// Signals events can pass up back to their handlers to notify them how they have processed an
/// event. They’re three kinds of signals:

/// - `EventSig::Ignored`:  the event should be passed to other handlers the parents knows about –
///    if any – because it wasn’t handled (ignored);
///
/// - `EventSig::Handled`: the event has been correctly handled;
///
/// - `EventSig::Focused`: the event has been correctly handled, and the parent should consider that
///    the this handler has now an exclusive focus on that event;
///
/// - `EventSig::Aborted`: the event has been correctly handled and the parent handler should be
///    aborted. This signal is typically used to kill all the handlers chain and thus quit the
///    application.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum EventSig {
  Ignored,
  Handled,
  Focused,
  Aborted
}

/// Class of event handlers.
///
/// All functions return a special object of type `EventSig`. An event report gives information
/// about how a handler has handled the event. See the documentation of `EventSig` for further
/// information.
///
/// All functions’ implementations default to `EventSig::Ignored`.
pub trait EventHandler {
  /// Implement this function if you want to react to key strokes.
  fn on_key(&mut self, _: Key, _: Action) -> EventSig { EventSig::Ignored }
  /// Implement this function if you want to react to mouse button events.
  fn on_mouse_button(&mut self, _: MouseButton, _: Action) -> EventSig { EventSig::Ignored }
  /// Implement this function if you want to react to cursor moves.
  fn on_cursor_move(&mut self, _: [f32; 2]) -> EventSig { EventSig::Ignored }
  /// Implement this function if you want to react to scroll events.
  fn on_scroll(&mut self, _: [f32; 2]) -> EventSig { EventSig::Ignored }
}

/// Empty handler.
///
/// This handler will just let pass all events without doing anything. It’s only useful for debug
/// purposes when you don’t want to bother with interaction – it doesn’t even let you close the
/// application!
#[derive(Clone, Copy, Eq, Debug, PartialEq)]
pub struct Unhandled;

impl EventHandler for Unhandled {}

/// Device object.
///
/// Upon bootstrapping, this type is created to add interaction and context handling.
pub struct Device {
  /// Width of the window.
  w: u32,
  /// Height of the window.
  h: u32,
  /// Some kind of epoch start the application started at.
  start_time: Instant,
  /// Keyboard receiver.
  kbd: Keyboard,
  /// Mouse receiver.
  mouse: Mouse,
  /// Cursor receiver.
  cursor: MouseMove,
  /// Scroll receiver.
  scroll: Scroll,
  /// Window.
  window: Window,
  /// Event thread join handle. Unused and keep around until death.
  #[allow(dead_code)]
  event_thread: thread::JoinHandle<()>
}

impl Device {
  /// Entry point.
  ///
  /// This function is the first one you have to call before anything else related to this crate.
  ///
  /// # Arguments
  ///
  /// - `dim`: dimension of the window to create
  /// - `title`: title to give to the window
  pub fn bootstrap(dim: WindowDim, title: &'static str) -> Self {
    info!("{} starting", title);
    info!("window mode: {:?}", dim);

    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    // OpenGL hints
    glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
    glfw.window_hint(glfw::WindowHint::ContextVersionMajor(3));
    glfw.window_hint(glfw::WindowHint::ContextVersionMinor(3));

    // open a window in windowed or fullscreen mode
    let (mut window, events, w, h) = match dim {
      WindowDim::Windowed(w, h) => {
        let (window, events) = glfw.create_window(w, h, title, glfw::WindowMode::Windowed).expect("Failed to create GLFW window.");
        (window, events, w, h)
      },
      WindowDim::FullScreen => {
        glfw.with_primary_monitor(|glfw, monitor| {
          let monitor = monitor.unwrap();
          let vmode = monitor.get_video_mode().expect("primary monitor’s video mode");
          let (w, h) = (vmode.width, vmode.height);

          let (window, events) = glfw.create_window(w, h, title, glfw::WindowMode::FullScreen(monitor)).expect("Failed to create GLFW window.");
          (window, events, w, h)
        })
      },
      WindowDim::FullScreenRestricted(w, h) => {
        glfw.with_primary_monitor(|glfw, monitor| {
          let monitor = monitor.unwrap();

          let (window, events) = glfw.create_window(w, h, title, glfw::WindowMode::FullScreen(monitor)).expect("Failed to create GLFW window.");
          (window, events, w, h)
        })
      }
    };

    deb!("opened window");

    window.make_current();

    // FIXME: use a target instead
    if cfg!(feature = "release") {
      deb!("hiding cursor");
      window.set_cursor_mode(CursorMode::Disabled);
    }

    window.set_key_polling(true);
    window.set_cursor_pos_polling(true);
    window.set_mouse_button_polling(true);
    window.set_scroll_polling(true);
    glfw.set_swap_interval(SwapInterval::Sync(1));

    deb!("initializing OpenGL pointers");

    // init OpenGL
    gl::load_with(|s| window.get_proc_address(s) as *const c_void);

    // create channels to stream keyboard and mouse events
    let (kbd_snd, kbd_rcv) = mpsc::channel();
    let (mouse_snd, mouse_rcv) = mpsc::channel();
    let (cursor_snd, cursor_rcv) = mpsc::channel();
    let (scroll_snd, scroll_rcv) = mpsc::channel();

    deb!("spawning the event thread");
    let event_thread = thread::spawn(move || {
      loop {
        glfw.wait_events();

        for (_, event) in glfw::flush_messages(&events) {
          match event {
            glfw::WindowEvent::Key(key, _, action, _) => {
              let _ = kbd_snd.send((key, action));
            },
            glfw::WindowEvent::MouseButton(button, action, _) => {
              let _ = mouse_snd.send((button, action));
            },
            glfw::WindowEvent::CursorPos(x, y) => {
              let _ = cursor_snd.send([x as f32, y as f32]);
            },
            glfw::WindowEvent::Scroll(x, y) => {
              let _ = scroll_snd.send([x as f32, y as f32]);
            },
            _ => {},
          }
        }
      }
    });

    deb!("bootstrapping finished");

    Device {
      w: w,
      h: h,
      start_time: Instant::now(),
      kbd: kbd_rcv,
      mouse: mouse_rcv,
      cursor: cursor_rcv,
      scroll: scroll_rcv,
      window: window,
      event_thread: event_thread
    }
  }

  /// Width of the attached window.
  #[inline]
  pub fn width(&self) -> u32 {
    self.w
  }

  /// Height of the attached window.
  #[inline]
  pub fn height(&self) -> u32 {
    self.h
  }

  /// Current time, starting from the beginning of the creation of that object.
  pub fn time(&self) -> f64 {
    let elapsed = Instant::now() - self.start_time;
    elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 * 1e-9
  }

  /// Dispatch events to a handler.
  pub fn dispatch_events<H>(&self, handler: &mut H) -> bool where H: EventHandler {
    while let Ok((key, action)) = self.kbd.try_recv() {
      if handler.on_key(key, action) == EventSig::Aborted {
        return false;
      }
    }

    while let Ok((button, action)) = self.mouse.try_recv() {
      if handler.on_mouse_button(button, action) == EventSig::Aborted {
        return false;
      }
    }

    while let Ok(xy) = self.cursor.try_recv() {
      if handler.on_cursor_move(xy) == EventSig::Aborted {
        return false;
      }
    }

    while let Ok(xy) = self.scroll.try_recv() {
      if handler.on_scroll(xy) == EventSig::Aborted {
        return false;
      }
    }

    true
  }

  /// Step function.
  ///
  /// This function provides two features:
  ///
  /// - it runs a *drawer* function, responsible of rendering a single frame, by passing it the
  ///   current time
  /// - it performs process idleing if you have requested a certain *framerate* – frame per second.
  ///
  /// The second feature is very neat because it lets you handle the scheduler off your application
  /// and then contribute to better CPU usage.
  ///
  /// > Note: if you pass `None`, no idleing will take place. However, you might be blocked by the
  /// *VSync* if enabled in your driver.
  pub fn step<FPS, R>(&mut self, fps: FPS, mut draw_frame: R) -> bool where FPS: Into<Option<u32>>, R: FnMut(Time) {
    if self.window.should_close() {
      return false;
    }

    let t = self.time();

    draw_frame(t);
    self.window.swap_buffers();

    // wait for next frame according to the wished FPS
    if let Some(fps) = fps.into() {
      let fps = fps as f64;
      let max_time = 1. / fps;
      let elapsed_time = self.time() - t;

      if elapsed_time < max_time {
        let sleep_time = max_time - elapsed_time;
        thread::sleep(Duration::from_millis((sleep_time * 1e3) as u64));
      }
    }

    true
  }
}

/// Freefly handler.
///
/// This handler is very neat as it provides freefly interaction.
pub struct FreeflyHandler {
  camera: Rc<RefCell<Camera<Freefly>>>,
  left_down: bool,
  right_down: bool,
  last_cursor: [f32; 2]
}

impl FreeflyHandler {
  pub fn new(camera: Rc<RefCell<Camera<Freefly>>>) -> Self {
    FreeflyHandler {
      camera: camera,
      left_down: false,
      right_down: false,
      last_cursor: [0., 0.]
    }
  }

  fn move_camera_on_event(&mut self, key: Key) {
    let camera = &mut self.camera.borrow_mut();

    match key {
      Key::W => camera.mv(Translation::new(0., 0., 1.)),
      Key::S => camera.mv(Translation::new(0., 0., -1.)),
      Key::A => camera.mv(Translation::new(1., 0., 0.)),
      Key::D => camera.mv(Translation::new(-1., 0., 0.)),
      Key::Q => camera.mv(Translation::new(0., -1., 0.)),
      Key::E => camera.mv(Translation::new(0., 1., 0.)),
      _ => ()
    }
  }

  fn orient_camera_on_event(&mut self, cursor: [f32; 2]) {
    let camera = &mut self.camera.borrow_mut();

    if self.left_down {
      let (dx, dy) = (cursor[0] - self.last_cursor[0], cursor[1] - self.last_cursor[1]);
      camera.look_around(Translation::new(dy, dx, 0.));
    } else if self.right_down {
      let (dx, _) = (cursor[0] - self.last_cursor[0], cursor[1] - self.last_cursor[1]);
      camera.look_around(Translation::new(0., 0., dx));
    }

    self.last_cursor = cursor;
  }
}

impl EventHandler for FreeflyHandler {
  fn on_key(&mut self, key: Key, action: Action) -> EventSig {
    match action {
      Action::Press | Action::Repeat => self.move_camera_on_event(key),
      Action::Release => if key == Key::Escape { return EventSig::Aborted }
    }

    EventSig::Handled
  }

  fn on_mouse_button(&mut self, button: MouseButton, action: Action) -> EventSig {
    match (button, action) {
      (MouseButton::Button1, Action::Press) => {
        self.left_down = true;
      },
      (MouseButton::Button1, Action::Release) => {
        self.left_down = false;
      },
      (MouseButton::Button2, Action::Press) => {
        self.right_down = true;
      },
      (MouseButton::Button2, Action::Release) => {
        self.right_down = false;
      },
      _ => ()
    }

    EventSig::Handled
  }

  fn on_cursor_move(&mut self, dir: [f32; 2]) -> EventSig {
    self.orient_camera_on_event(dir);
    EventSig::Handled
  }
}
<commit_msg>Fixed format for EventSig documentation.<commit_after>use gl;
use glfw::{self, Context, CursorMode, SwapInterval, Window};
pub use glfw::{Action, Key, MouseButton};
use std::cell::RefCell;
use std::os::raw::c_void;
use std::rc::Rc;
use std::sync::mpsc;
use std::thread;
use std::time::{Duration, Instant};

use camera::{Camera, Freefly};
use linear::Translation;

type Time = f64;

/// Dimension of the window to create.
#[derive(Clone, Copy, Debug)]
pub enum WindowDim {
  Windowed(u32, u32),
  FullScreen,
  FullScreenRestricted(u32, u32)
}

type Keyboard = mpsc::Receiver<(Key, Action)>;
type Mouse = mpsc::Receiver<(MouseButton, Action)>;
type MouseMove = mpsc::Receiver<[f32; 2]>;
type Scroll = mpsc::Receiver<[f32; 2]>;

/// Signals events can pass up back to their handlers to notify them how they have processed an
/// event. They’re three kinds of signals:
///
/// - `EventSig::Ignored`:  the event should be passed to other handlers the parents knows about –
///    if any – because it wasn’t handled (ignored);
///
/// - `EventSig::Handled`: the event has been correctly handled;
///
/// - `EventSig::Focused`: the event has been correctly handled, and the parent should consider that
///    the this handler has now an exclusive focus on that event;
///
/// - `EventSig::Aborted`: the event has been correctly handled and the parent handler should be
///    aborted. This signal is typically used to kill all the handlers chain and thus quit the
///    application.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum EventSig {
  Ignored,
  Handled,
  Focused,
  Aborted
}

/// Class of event handlers.
///
/// All functions return a special object of type `EventSig`. An event report gives information
/// about how a handler has handled the event. See the documentation of `EventSig` for further
/// information.
///
/// All functions’ implementations default to `EventSig::Ignored`.
pub trait EventHandler {
  /// Implement this function if you want to react to key strokes.
  fn on_key(&mut self, _: Key, _: Action) -> EventSig { EventSig::Ignored }
  /// Implement this function if you want to react to mouse button events.
  fn on_mouse_button(&mut self, _: MouseButton, _: Action) -> EventSig { EventSig::Ignored }
  /// Implement this function if you want to react to cursor moves.
  fn on_cursor_move(&mut self, _: [f32; 2]) -> EventSig { EventSig::Ignored }
  /// Implement this function if you want to react to scroll events.
  fn on_scroll(&mut self, _: [f32; 2]) -> EventSig { EventSig::Ignored }
}

/// Empty handler.
///
/// This handler will just let pass all events without doing anything. It’s only useful for debug
/// purposes when you don’t want to bother with interaction – it doesn’t even let you close the
/// application!
#[derive(Clone, Copy, Eq, Debug, PartialEq)]
pub struct Unhandled;

impl EventHandler for Unhandled {}

/// Device object.
///
/// Upon bootstrapping, this type is created to add interaction and context handling.
pub struct Device {
  /// Width of the window.
  w: u32,
  /// Height of the window.
  h: u32,
  /// Some kind of epoch start the application started at.
  start_time: Instant,
  /// Keyboard receiver.
  kbd: Keyboard,
  /// Mouse receiver.
  mouse: Mouse,
  /// Cursor receiver.
  cursor: MouseMove,
  /// Scroll receiver.
  scroll: Scroll,
  /// Window.
  window: Window,
  /// Event thread join handle. Unused and keep around until death.
  #[allow(dead_code)]
  event_thread: thread::JoinHandle<()>
}

impl Device {
  /// Entry point.
  ///
  /// This function is the first one you have to call before anything else related to this crate.
  ///
  /// # Arguments
  ///
  /// - `dim`: dimension of the window to create
  /// - `title`: title to give to the window
  pub fn bootstrap(dim: WindowDim, title: &'static str) -> Self {
    info!("{} starting", title);
    info!("window mode: {:?}", dim);

    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    // OpenGL hints
    glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
    glfw.window_hint(glfw::WindowHint::ContextVersionMajor(3));
    glfw.window_hint(glfw::WindowHint::ContextVersionMinor(3));

    // open a window in windowed or fullscreen mode
    let (mut window, events, w, h) = match dim {
      WindowDim::Windowed(w, h) => {
        let (window, events) = glfw.create_window(w, h, title, glfw::WindowMode::Windowed).expect("Failed to create GLFW window.");
        (window, events, w, h)
      },
      WindowDim::FullScreen => {
        glfw.with_primary_monitor(|glfw, monitor| {
          let monitor = monitor.unwrap();
          let vmode = monitor.get_video_mode().expect("primary monitor’s video mode");
          let (w, h) = (vmode.width, vmode.height);

          let (window, events) = glfw.create_window(w, h, title, glfw::WindowMode::FullScreen(monitor)).expect("Failed to create GLFW window.");
          (window, events, w, h)
        })
      },
      WindowDim::FullScreenRestricted(w, h) => {
        glfw.with_primary_monitor(|glfw, monitor| {
          let monitor = monitor.unwrap();

          let (window, events) = glfw.create_window(w, h, title, glfw::WindowMode::FullScreen(monitor)).expect("Failed to create GLFW window.");
          (window, events, w, h)
        })
      }
    };

    deb!("opened window");

    window.make_current();

    // FIXME: use a target instead
    if cfg!(feature = "release") {
      deb!("hiding cursor");
      window.set_cursor_mode(CursorMode::Disabled);
    }

    window.set_key_polling(true);
    window.set_cursor_pos_polling(true);
    window.set_mouse_button_polling(true);
    window.set_scroll_polling(true);
    glfw.set_swap_interval(SwapInterval::Sync(1));

    deb!("initializing OpenGL pointers");

    // init OpenGL
    gl::load_with(|s| window.get_proc_address(s) as *const c_void);

    // create channels to stream keyboard and mouse events
    let (kbd_snd, kbd_rcv) = mpsc::channel();
    let (mouse_snd, mouse_rcv) = mpsc::channel();
    let (cursor_snd, cursor_rcv) = mpsc::channel();
    let (scroll_snd, scroll_rcv) = mpsc::channel();

    deb!("spawning the event thread");
    let event_thread = thread::spawn(move || {
      loop {
        glfw.wait_events();

        for (_, event) in glfw::flush_messages(&events) {
          match event {
            glfw::WindowEvent::Key(key, _, action, _) => {
              let _ = kbd_snd.send((key, action));
            },
            glfw::WindowEvent::MouseButton(button, action, _) => {
              let _ = mouse_snd.send((button, action));
            },
            glfw::WindowEvent::CursorPos(x, y) => {
              let _ = cursor_snd.send([x as f32, y as f32]);
            },
            glfw::WindowEvent::Scroll(x, y) => {
              let _ = scroll_snd.send([x as f32, y as f32]);
            },
            _ => {},
          }
        }
      }
    });

    deb!("bootstrapping finished");

    Device {
      w: w,
      h: h,
      start_time: Instant::now(),
      kbd: kbd_rcv,
      mouse: mouse_rcv,
      cursor: cursor_rcv,
      scroll: scroll_rcv,
      window: window,
      event_thread: event_thread
    }
  }

  /// Width of the attached window.
  #[inline]
  pub fn width(&self) -> u32 {
    self.w
  }

  /// Height of the attached window.
  #[inline]
  pub fn height(&self) -> u32 {
    self.h
  }

  /// Current time, starting from the beginning of the creation of that object.
  pub fn time(&self) -> f64 {
    let elapsed = Instant::now() - self.start_time;
    elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 * 1e-9
  }

  /// Dispatch events to a handler.
  pub fn dispatch_events<H>(&self, handler: &mut H) -> bool where H: EventHandler {
    while let Ok((key, action)) = self.kbd.try_recv() {
      if handler.on_key(key, action) == EventSig::Aborted {
        return false;
      }
    }

    while let Ok((button, action)) = self.mouse.try_recv() {
      if handler.on_mouse_button(button, action) == EventSig::Aborted {
        return false;
      }
    }

    while let Ok(xy) = self.cursor.try_recv() {
      if handler.on_cursor_move(xy) == EventSig::Aborted {
        return false;
      }
    }

    while let Ok(xy) = self.scroll.try_recv() {
      if handler.on_scroll(xy) == EventSig::Aborted {
        return false;
      }
    }

    true
  }

  /// Step function.
  ///
  /// This function provides two features:
  ///
  /// - it runs a *drawer* function, responsible of rendering a single frame, by passing it the
  ///   current time
  /// - it performs process idleing if you have requested a certain *framerate* – frame per second.
  ///
  /// The second feature is very neat because it lets you handle the scheduler off your application
  /// and then contribute to better CPU usage.
  ///
  /// > Note: if you pass `None`, no idleing will take place. However, you might be blocked by the
  /// *VSync* if enabled in your driver.
  pub fn step<FPS, R>(&mut self, fps: FPS, mut draw_frame: R) -> bool where FPS: Into<Option<u32>>, R: FnMut(Time) {
    if self.window.should_close() {
      return false;
    }

    let t = self.time();

    draw_frame(t);
    self.window.swap_buffers();

    // wait for next frame according to the wished FPS
    if let Some(fps) = fps.into() {
      let fps = fps as f64;
      let max_time = 1. / fps;
      let elapsed_time = self.time() - t;

      if elapsed_time < max_time {
        let sleep_time = max_time - elapsed_time;
        thread::sleep(Duration::from_millis((sleep_time * 1e3) as u64));
      }
    }

    true
  }
}

/// Freefly handler.
///
/// This handler is very neat as it provides freefly interaction.
pub struct FreeflyHandler {
  camera: Rc<RefCell<Camera<Freefly>>>,
  left_down: bool,
  right_down: bool,
  last_cursor: [f32; 2]
}

impl FreeflyHandler {
  pub fn new(camera: Rc<RefCell<Camera<Freefly>>>) -> Self {
    FreeflyHandler {
      camera: camera,
      left_down: false,
      right_down: false,
      last_cursor: [0., 0.]
    }
  }

  fn move_camera_on_event(&mut self, key: Key) {
    let camera = &mut self.camera.borrow_mut();

    match key {
      Key::W => camera.mv(Translation::new(0., 0., 1.)),
      Key::S => camera.mv(Translation::new(0., 0., -1.)),
      Key::A => camera.mv(Translation::new(1., 0., 0.)),
      Key::D => camera.mv(Translation::new(-1., 0., 0.)),
      Key::Q => camera.mv(Translation::new(0., -1., 0.)),
      Key::E => camera.mv(Translation::new(0., 1., 0.)),
      _ => ()
    }
  }

  fn orient_camera_on_event(&mut self, cursor: [f32; 2]) {
    let camera = &mut self.camera.borrow_mut();

    if self.left_down {
      let (dx, dy) = (cursor[0] - self.last_cursor[0], cursor[1] - self.last_cursor[1]);
      camera.look_around(Translation::new(dy, dx, 0.));
    } else if self.right_down {
      let (dx, _) = (cursor[0] - self.last_cursor[0], cursor[1] - self.last_cursor[1]);
      camera.look_around(Translation::new(0., 0., dx));
    }

    self.last_cursor = cursor;
  }
}

impl EventHandler for FreeflyHandler {
  fn on_key(&mut self, key: Key, action: Action) -> EventSig {
    match action {
      Action::Press | Action::Repeat => self.move_camera_on_event(key),
      Action::Release => if key == Key::Escape { return EventSig::Aborted }
    }

    EventSig::Handled
  }

  fn on_mouse_button(&mut self, button: MouseButton, action: Action) -> EventSig {
    match (button, action) {
      (MouseButton::Button1, Action::Press) => {
        self.left_down = true;
      },
      (MouseButton::Button1, Action::Release) => {
        self.left_down = false;
      },
      (MouseButton::Button2, Action::Press) => {
        self.right_down = true;
      },
      (MouseButton::Button2, Action::Release) => {
        self.right_down = false;
      },
      _ => ()
    }

    EventSig::Handled
  }

  fn on_cursor_move(&mut self, dir: [f32; 2]) -> EventSig {
    self.orient_camera_on_event(dir);
    EventSig::Handled
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013-2014, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

#![feature(globs)]
#![feature(macro_rules)]
#![feature(phase)]
#![allow(experimental)]
#![feature(unsafe_destructor)]

#![crate_name="capnp"]
#![crate_type = "lib"]

// import logging macros
#[phase(plugin, link)] extern crate log;
extern crate libc;

// reexports
pub use blob::{text, data};
pub use common::{MessageSize};
pub use list::{primitive_list, enum_list, struct_list, text_list, data_list, list_list};
pub use message::{MessageBuilder, BuilderOptions, MessageReader, ReaderOptions};
pub use message::MallocMessageBuilder;
pub use serialize::OwnedSpaceMessageReader;

pub mod any_pointer;
pub mod arena;
pub mod blob;
pub mod capability;
pub mod common;
pub mod endian;
pub mod io;
pub mod layout;
pub mod list;
pub mod mask;
pub mod message;
pub mod serialize;
pub mod serialize_packed;

#[cfg(test)]
pub mod layout_test;
#[cfg(test)]
pub mod serialize_packed_test;

<commit_msg>a tiny bit of rustdoc<commit_after>/*
 * Copyright (c) 2013-2014, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

//! # Cap'n Proto Runtime Library
//!
//! [Cap'n Proto](http://kentonv.github.io/capnproto/) is an extremely
//! efficient protocol for sharing data and capabilities.
//!
//! Hosted on Github [here](https://github.com/dwrensha/capnproto-rust).
//!
//! [capnpc-rust](https://github.com/dwrensha/capnpc-rust)
//!
//! [capnp-rpc-rust](https://github.com/dwrensha/capnp-rpc-rust)
//!

#![feature(globs)]
#![feature(macro_rules)]
#![feature(phase)]
#![allow(experimental)]
#![feature(unsafe_destructor)]

#![crate_name="capnp"]
#![crate_type = "lib"]

// import logging macros
#[phase(plugin, link)] extern crate log;
extern crate libc;

// reexports
pub use blob::{text, data};
pub use common::{MessageSize};
pub use list::{primitive_list, enum_list, struct_list, text_list, data_list, list_list};
pub use message::{MessageBuilder, BuilderOptions, MessageReader, ReaderOptions};
pub use message::MallocMessageBuilder;
pub use serialize::OwnedSpaceMessageReader;

pub mod any_pointer;
pub mod arena;
pub mod blob;
pub mod capability;
pub mod common;
pub mod endian;
pub mod io;
pub mod layout;
pub mod list;
pub mod mask;
pub mod message;
pub mod serialize;
pub mod serialize_packed;

#[cfg(test)]
pub mod layout_test;
#[cfg(test)]
pub mod serialize_packed_test;

<|endoftext|>


<commit_before>mod sys;

extern crate getopts;
#[macro_use] extern crate log;
extern crate simplelog;
extern crate daemonize;

use std::env;
use std::fs::{File, OpenOptions};
use getopts::Options;
use simplelog::*;
use daemonize::Daemonize;

const STDOUT_FILE: &str = "./stdout.txt";
const STDERR_FILE: &str = "./stderr.txt";
const PID_FILE: &str = "./rshanghai.pid";
const LOG_FILE: &str = "./rshanghai.log";

/// stdout, stderr をリダイレクトし、デーモン化する。
/// ファイルオープンに失敗したら exit(1) する。
/// デーモン化に失敗したら exit(1) する。
/// 成功した場合は元の親プロセスは正常終了し、子プロセスが以降の処理を続行する。
fn daemon() {
    let stdout = match File::create(STDOUT_FILE) {
        Ok(f) => f,
        Err(e) => {
            eprintln!("Open {} error: {}", STDOUT_FILE, e);
            std::process::exit(1);
        }
    };
    let stderr = match File::create(STDERR_FILE) {
        Ok(f) => f,
        Err(e) => {
            eprintln!("Open {} error: {}", STDERR_FILE, e);
            std::process::exit(1);
        }
    };

    let daemonize = Daemonize::new()
        .pid_file(PID_FILE)
        //.chown_pid_file(true)
        .working_directory(".")
        //.user("nobody")
        //.group("daemon")
        .stdout(stdout)
        .stderr(stderr);

    if let Err(e) = daemonize.start() {
        eprintln!("Daemonize error: {}", e);
        std::process::exit(1);
    }
}

/// ロギングシステムを有効化する。
fn init_log(is_daemon: bool) {
    let config = ConfigBuilder::new()
        .set_time_format_custom(format_description!("[year]-[month]-[day] [hour]:[minute]:[second]"))
        .build();
    let file = OpenOptions::new()
        .append(true)
        .create(true)
        .open(LOG_FILE)
        .unwrap();

    // filter = Off, Error, Warn, Info, Debug, Trace
    let loggers: Vec<Box<dyn SharedLogger>> = if is_daemon {
        vec![
            WriteLogger::new(LevelFilter::Info, config.clone(), file),
        ]
    }
    else {
        vec![
            TermLogger::new(LevelFilter::Trace, config.clone(), TerminalMode::Stdout, ColorChoice::Never),
            WriteLogger::new(LevelFilter::Info, config.clone(), file),
        ]
    };
    CombinedLogger::init(loggers).unwrap();

    error!("Error test");
    warn!("Warn test");
    info!("Info test");
    debug!("Debug test");
    trace!("Trace test");
}

/// システムメイン処理。
/// コマンドラインとデーモン化の後に入る。
fn system_main() {
    // TODO
    sys::config::init_and_load("{}", "{}");
}

fn print_help(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    // コマンドライン引数のパース
    let args: Vec<String> = env::args().collect();
    let program = &args[0];

    let mut opts = Options::new();
    opts.optflag("h", "help", "Print this help");
    opts.optflag("d", "daemon", "Run as daemon");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(fail) => {
            eprintln!("{}", fail);
            std::process::exit(1);
        }
    };

    // --help がある場合は出力して終了
    if matches.opt_present("h") {
        print_help(&program, opts);
        std::process::exit(0);
    }

    if matches.opt_present("d") {
        daemon();
        init_log(true);
    }
    else {
        init_log(false);
    }

    system_main();
}
<commit_msg>clippy 対応<commit_after>mod sys;

extern crate getopts;
#[macro_use] extern crate log;
extern crate simplelog;
extern crate daemonize;

use std::env;
use std::fs::{File, OpenOptions};
use getopts::Options;
use simplelog::*;
use daemonize::Daemonize;

const STDOUT_FILE: &str = "./stdout.txt";
const STDERR_FILE: &str = "./stderr.txt";
const PID_FILE: &str = "./rshanghai.pid";
const LOG_FILE: &str = "./rshanghai.log";

/// stdout, stderr をリダイレクトし、デーモン化する。
/// ファイルオープンに失敗したら exit(1) する。
/// デーモン化に失敗したら exit(1) する。
/// 成功した場合は元の親プロセスは正常終了し、子プロセスが以降の処理を続行する。
fn daemon() {
    let stdout = match File::create(STDOUT_FILE) {
        Ok(f) => f,
        Err(e) => {
            eprintln!("Open {} error: {}", STDOUT_FILE, e);
            std::process::exit(1);
        }
    };
    let stderr = match File::create(STDERR_FILE) {
        Ok(f) => f,
        Err(e) => {
            eprintln!("Open {} error: {}", STDERR_FILE, e);
            std::process::exit(1);
        }
    };

    let daemonize = Daemonize::new()
        .pid_file(PID_FILE)
        //.chown_pid_file(true)
        .working_directory(".")
        //.user("nobody")
        //.group("daemon")
        .stdout(stdout)
        .stderr(stderr);

    if let Err(e) = daemonize.start() {
        eprintln!("Daemonize error: {}", e);
        std::process::exit(1);
    }
}

/// ロギングシステムを有効化する。
fn init_log(is_daemon: bool) {
    let config = ConfigBuilder::new()
        .set_time_format_custom(format_description!("[year]-[month]-[day] [hour]:[minute]:[second]"))
        .build();
    let file = OpenOptions::new()
        .append(true)
        .create(true)
        .open(LOG_FILE)
        .unwrap();

    // filter = Off, Error, Warn, Info, Debug, Trace
    let loggers: Vec<Box<dyn SharedLogger>> = if is_daemon {
        vec![
            WriteLogger::new(LevelFilter::Info, config, file),
        ]
    }
    else {
        vec![
            TermLogger::new(LevelFilter::Trace, config.clone(), TerminalMode::Stdout, ColorChoice::Never),
            WriteLogger::new(LevelFilter::Info, config, file),
        ]
    };
    CombinedLogger::init(loggers).unwrap();

    error!("Error test");
    warn!("Warn test");
    info!("Info test");
    debug!("Debug test");
    trace!("Trace test");
}

/// システムメイン処理。
/// コマンドラインとデーモン化の後に入る。
fn system_main() {
    // TODO
    sys::config::init_and_load("{}", "{}")
        .expect("Json parse error");
}

fn print_help(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    // コマンドライン引数のパース
    let args: Vec<String> = env::args().collect();
    let program = &args[0];

    let mut opts = Options::new();
    opts.optflag("h", "help", "Print this help");
    opts.optflag("d", "daemon", "Run as daemon");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(fail) => {
            eprintln!("{}", fail);
            std::process::exit(1);
        }
    };

    // --help がある場合は出力して終了
    if matches.opt_present("h") {
        print_help(program, opts);
        std::process::exit(0);
    }

    if matches.opt_present("d") {
        daemon();
        init_log(true);
    }
    else {
        init_log(false);
    }

    system_main();
}
<|endoftext|>


<commit_before>// Bitcoin secp256k1 bindings
// Written in 2014 by
//   Dawid Ciężarkiewicz
//   Andrew Poelstra
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # Constants
//! Constants related to the API and the underlying curve

/// The size (in bytes) of a message
pub const MESSAGE_SIZE: usize = 32;

/// The size (in bytes) of a secret key
pub const SECRET_KEY_SIZE: usize = 32;

/// The size (in bytes) of a serialized public key.
pub const PUBLIC_KEY_SIZE: usize = 33;

/// The size (in bytes) of an serialized uncompressed public key
pub const UNCOMPRESSED_PUBLIC_KEY_SIZE: usize = 65;

/// The maximum size of a signature
pub const MAX_SIGNATURE_SIZE: usize = 72;

/// The maximum size of a compact signature
pub const COMPACT_SIGNATURE_SIZE: usize = 64;

/// The order of the secp256k1 curve
pub const CURVE_ORDER: [u8; 32] = [
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
    0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b,
    0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41
];

/// The X coordinate of the generator
pub const GENERATOR_X: [u8; 32] = [
    0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac,
    0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07,
    0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9,
    0x59, 0xf2, 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98
];

/// The Y coordinate of the generator
pub const GENERATOR_Y: [u8; 32] = [
    0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65,
    0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8,
    0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19,
    0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8
];

<commit_msg>Add constant of the prime of the curve field.<commit_after>// Bitcoin secp256k1 bindings
// Written in 2014 by
//   Dawid Ciężarkiewicz
//   Andrew Poelstra
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # Constants
//! Constants related to the API and the underlying curve

/// The size (in bytes) of a message
pub const MESSAGE_SIZE: usize = 32;

/// The size (in bytes) of a secret key
pub const SECRET_KEY_SIZE: usize = 32;

/// The size (in bytes) of a serialized public key.
pub const PUBLIC_KEY_SIZE: usize = 33;

/// The size (in bytes) of an serialized uncompressed public key
pub const UNCOMPRESSED_PUBLIC_KEY_SIZE: usize = 65;

/// The maximum size of a signature
pub const MAX_SIGNATURE_SIZE: usize = 72;

/// The maximum size of a compact signature
pub const COMPACT_SIGNATURE_SIZE: usize = 64;

/// The Prime for the secp256k1 field element.
pub const FIELD_SIZE: [u8; 32] = [
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f
];

/// The order of the secp256k1 curve
pub const CURVE_ORDER: [u8; 32] = [
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
    0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b,
    0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41
];

/// The X coordinate of the generator
pub const GENERATOR_X: [u8; 32] = [
    0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac,
    0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07,
    0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9,
    0x59, 0xf2, 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98
];

/// The Y coordinate of the generator
pub const GENERATOR_Y: [u8; 32] = [
    0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65,
    0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8,
    0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19,
    0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8
];

<|endoftext|>


<commit_before>use errors::Error;
use guards::{ReadGuard, WriteGuard};
use methods::Method;
use reflect;

use downcast::Downcast;

use std::any::Any;
use std::collections::BTreeMap;
use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard, TryLockError};

fn type_name<T: ::std::marker::Reflect>() -> &'static str {
    unsafe { ::std::intrinsics::type_name::<T>() }
}

pub struct Container<Key, SvcBase: ?Sized> {
    services: BTreeMap<Key, RwLock<Box<SvcBase>>>,
}

impl<Key, SvcBase: ?Sized> Container<Key, SvcBase>
    where Key: reflect::Key, SvcBase: Any
{
    pub fn new() -> Self {
        Container{ services: BTreeMap::new() }
    }

    pub fn register_service(&mut self, key: Key, svc: Box<SvcBase>) -> &mut Self {
        self.services.insert(key, RwLock::new(svc));
        self
    }

    /// NOTE: The `Box<Svc>: Into<Box<Base>>`-clause is needed due to rusts lack of
    /// HKT or a `Coercible`-trait (to name two solutions).
    pub fn register<Svc>(&mut self, svc: Svc) -> &mut Self
    where
        Svc: reflect::Service<Key = Key>,
        Box<Svc>: Into<Box<SvcBase>>,
    {
        self.register_service(Svc::key().clone(), Box::new(svc).into())
    }

    pub fn services(&self) -> &BTreeMap<Key, RwLock<Box<SvcBase>>> {
        &self.services
    }

    pub fn get_service(&self, key: &Key) -> Option<&RwLock<Box<SvcBase>>> {
        self.services.get(key)
    }

    pub fn read_service_base<'a>(
        &'a self,
        key: &'a Key
    ) -> Result<RwLockReadGuard<Box<SvcBase>>, Error<'a, Key>> {
        match self.get_service(key) {
            Some(service) => match service.read() {
                Ok(r) => Ok(r),
                Err(_) => Err(Error::Poisoned{ key: key })
            },
            None => Err(Error::NotFound{ key: key })
        }
    }

    pub fn write_service_base<'a>(
        &'a self,
        key: &'a Key
    ) -> Result<RwLockWriteGuard<Box<SvcBase>>, Error<'a, Key>> {
        match self.get_service(key) {
            Some(service) => match service.write() {
                Ok(r) => Ok(r),
                Err(_) => Err(Error::Poisoned{ key: key })
            },
            None => Err(Error::NotFound{ key: key })
        }
    }

    pub fn read_service<'a, Svc>(
        &'a self,
        key: &'a Key
    ) -> Result<ReadGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: Any, SvcBase: Downcast<Svc>
    {
        let base = try!{self.read_service_base(key)};
        if !base.is_type() {
            return Err(Error::MismatchedType{
                key: key,
                expected: type_name::<Svc>(),
                found: type_name::<Svc>(),
            })
        };
        Ok(ReadGuard::new(base))
    }

    pub fn write_service<'a, Svc>(
        &'a self,
        key: &'a Key
    ) -> Result<WriteGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: Any, SvcBase: Downcast<Svc>
    {
        let base = try!{self.write_service_base(key)};
        if !base.is_type() {
            return Err(Error::MismatchedType{
                key: key,
                expected: type_name::<Svc>(),
                found: type_name::<Svc>(),
            })
        };
        Ok(WriteGuard::new(base))
    }

    pub fn read<'a, Svc>(
        &'a self
    ) -> Result<ReadGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: reflect::Service<Key = Key>, SvcBase: Downcast<Svc>
    {
        self.read_service(Svc::key())
    }

    pub fn write<'a, Svc>(
        &'a self
    ) -> Result<WriteGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: reflect::Service<Key = Key>, SvcBase: Downcast<Svc>
    {
        self.write_service(Svc::key())
    }

    pub fn try_read_service_base<'a>(
        &'a self,
        key: &'a Key
    ) -> Result<RwLockReadGuard<Box<SvcBase>>, Error<'a, Key>> {
        match self.get_service(key) {
            Some(service) => match service.try_read() {
                Ok(r) => Ok(r),
                Err(TryLockError::Poisoned(_)) => Err(Error::Poisoned{ key: key }),
                Err(TryLockError::WouldBlock) => Err(Error::WouldBlock{ key: key })
            },
            None => Err(Error::NotFound{ key: key })
        }
    }

    pub fn try_write_service_base<'a>(
        &'a self,
        key: &'a Key
    ) -> Result<RwLockWriteGuard<Box<SvcBase>>, Error<'a, Key>> {
        match self.get_service(key) {
            Some(service) => match service.try_write() {
                Ok(r) => Ok(r),
                Err(TryLockError::Poisoned(_)) => Err(Error::Poisoned{ key: key }),
                Err(TryLockError::WouldBlock) => Err(Error::WouldBlock{ key: key })
            },
            None => Err(Error::NotFound{ key: key })
        }
    }

    pub fn try_read_service<'a, Svc>(
        &'a self,
        key: &'a Key
    ) -> Result<ReadGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: Any, SvcBase: Downcast<Svc>
    {
        let base = try!{self.try_read_service_base(key)};
        if !base.is_type() {
            return Err(Error::MismatchedType{
                key: key,
                expected: type_name::<Svc>(),
                found: type_name::<Svc>(),
            })
        };
        Ok(ReadGuard::new(base))
    }

    pub fn try_write_service<'a, Svc>(
        &'a self,
        key: &'a Key
    ) -> Result<WriteGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: Any, SvcBase: Downcast<Svc>
    {
        let base = try!{self.try_write_service_base(key)};
        if !base.is_type() {
            return Err(Error::MismatchedType{
                key: key,
                expected: type_name::<Svc>(),
                found: type_name::<Svc>(),
            })
        };
        Ok(WriteGuard::new(base))
    }

    pub fn try_read<'a, Svc>(
        &'a self
    ) -> Result<ReadGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: reflect::Service<Key = Key>, SvcBase: Downcast<Svc>
    {
        self.try_read_service(Svc::key())
    }

    pub fn try_write<'a, Svc>(
        &'a self
    ) -> Result<WriteGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: reflect::Service<Key = Key>, SvcBase: Downcast<Svc>
    {
        self.try_write_service(Svc::key())
    }

    pub fn resolve<'a, M>(&'a self) -> Result<M::Ret, Error<Key>>
        where M: Method<'a, Key, SvcBase>
    {
        M::resolve(self)
    }
    //pub fn try_resolve
}

<commit_msg>add ContainerBuilder<commit_after>use errors::Error;
use guards::{ReadGuard, WriteGuard};
use methods::Method;
use reflect;

use downcast::Downcast;

use std::any::Any;
use std::collections::BTreeMap;
use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard, TryLockError};

fn type_name<T: ::std::marker::Reflect>() -> &'static str {
    unsafe { ::std::intrinsics::type_name::<T>() }
}

// ++++++++++++++++++++ Container ++++++++++++++++++++

pub struct Container<Key, SvcBase: ?Sized> {
    services: BTreeMap<Key, RwLock<Box<SvcBase>>>,
}

impl<Key, SvcBase: ?Sized> Container<Key, SvcBase>
    where Key: reflect::Key, SvcBase: Any
{
    #[doc(hidden)]
    pub fn new() -> Self {
        Container{ services: BTreeMap::new() }
    }

    #[doc(hidden)]
    pub fn register_service(&mut self, key: Key, svc: Box<SvcBase>) -> &mut Self {
        self.services.insert(key, RwLock::new(svc));
        self
    }

    #[doc(hidden)]
    pub fn register<Svc>(&mut self, svc: Svc) -> &mut Self
    where
        Svc: reflect::Service<Key = Key>,
        Box<Svc>: Into<Box<SvcBase>>,
    {
        self.register_service(Svc::key().clone(), Box::new(svc).into())
    }

    pub fn services(&self) -> &BTreeMap<Key, RwLock<Box<SvcBase>>> {
        &self.services
    }

    pub fn get_service(&self, key: &Key) -> Option<&RwLock<Box<SvcBase>>> {
        self.services.get(key)
    }

    pub fn read_service_base<'a>(
        &'a self,
        key: &'a Key
    ) -> Result<RwLockReadGuard<Box<SvcBase>>, Error<'a, Key>> {
        match self.get_service(key) {
            Some(service) => match service.read() {
                Ok(r) => Ok(r),
                Err(_) => Err(Error::Poisoned{ key: key })
            },
            None => Err(Error::NotFound{ key: key })
        }
    }

    pub fn write_service_base<'a>(
        &'a self,
        key: &'a Key
    ) -> Result<RwLockWriteGuard<Box<SvcBase>>, Error<'a, Key>> {
        match self.get_service(key) {
            Some(service) => match service.write() {
                Ok(r) => Ok(r),
                Err(_) => Err(Error::Poisoned{ key: key })
            },
            None => Err(Error::NotFound{ key: key })
        }
    }

    pub fn read_service<'a, Svc>(
        &'a self,
        key: &'a Key
    ) -> Result<ReadGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: Any, SvcBase: Downcast<Svc>
    {
        let base = try!{self.read_service_base(key)};
        if !base.is_type() {
            return Err(Error::MismatchedType{
                key: key,
                expected: type_name::<Svc>(),
                found: type_name::<Svc>(),
            })
        };
        Ok(ReadGuard::new(base))
    }

    pub fn write_service<'a, Svc>(
        &'a self,
        key: &'a Key
    ) -> Result<WriteGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: Any, SvcBase: Downcast<Svc>
    {
        let base = try!{self.write_service_base(key)};
        if !base.is_type() {
            return Err(Error::MismatchedType{
                key: key,
                expected: type_name::<Svc>(),
                found: type_name::<Svc>(),
            })
        };
        Ok(WriteGuard::new(base))
    }

    pub fn read<'a, Svc>(
        &'a self
    ) -> Result<ReadGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: reflect::Service<Key = Key>, SvcBase: Downcast<Svc>
    {
        self.read_service(Svc::key())
    }

    pub fn write<'a, Svc>(
        &'a self
    ) -> Result<WriteGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: reflect::Service<Key = Key>, SvcBase: Downcast<Svc>
    {
        self.write_service(Svc::key())
    }

    pub fn try_read_service_base<'a>(
        &'a self,
        key: &'a Key
    ) -> Result<RwLockReadGuard<Box<SvcBase>>, Error<'a, Key>> {
        match self.get_service(key) {
            Some(service) => match service.try_read() {
                Ok(r) => Ok(r),
                Err(TryLockError::Poisoned(_)) => Err(Error::Poisoned{ key: key }),
                Err(TryLockError::WouldBlock) => Err(Error::WouldBlock{ key: key })
            },
            None => Err(Error::NotFound{ key: key })
        }
    }

    pub fn try_write_service_base<'a>(
        &'a self,
        key: &'a Key
    ) -> Result<RwLockWriteGuard<Box<SvcBase>>, Error<'a, Key>> {
        match self.get_service(key) {
            Some(service) => match service.try_write() {
                Ok(r) => Ok(r),
                Err(TryLockError::Poisoned(_)) => Err(Error::Poisoned{ key: key }),
                Err(TryLockError::WouldBlock) => Err(Error::WouldBlock{ key: key })
            },
            None => Err(Error::NotFound{ key: key })
        }
    }

    pub fn try_read_service<'a, Svc>(
        &'a self,
        key: &'a Key
    ) -> Result<ReadGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: Any, SvcBase: Downcast<Svc>
    {
        let base = try!{self.try_read_service_base(key)};
        if !base.is_type() {
            return Err(Error::MismatchedType{
                key: key,
                expected: type_name::<Svc>(),
                found: type_name::<Svc>(),
            })
        };
        Ok(ReadGuard::new(base))
    }

    pub fn try_write_service<'a, Svc>(
        &'a self,
        key: &'a Key
    ) -> Result<WriteGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: Any, SvcBase: Downcast<Svc>
    {
        let base = try!{self.try_write_service_base(key)};
        if !base.is_type() {
            return Err(Error::MismatchedType{
                key: key,
                expected: type_name::<Svc>(),
                found: type_name::<Svc>(),
            })
        };
        Ok(WriteGuard::new(base))
    }

    pub fn try_read<'a, Svc>(
        &'a self
    ) -> Result<ReadGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: reflect::Service<Key = Key>, SvcBase: Downcast<Svc>
    {
        self.try_read_service(Svc::key())
    }

    pub fn try_write<'a, Svc>(
        &'a self
    ) -> Result<WriteGuard<Svc, SvcBase>, Error<'a, Key>>
        where Svc: reflect::Service<Key = Key>, SvcBase: Downcast<Svc>
    {
        self.try_write_service(Svc::key())
    }

    pub fn resolve<'a, M>(&'a self) -> Result<M::Ret, Error<Key>>
        where M: Method<'a, Key, SvcBase>
    {
        M::resolve(self)
    }
    //pub fn try_resolve
}

// ++++++++++++++++++++ ContainerBuilder ++++++++++++++++++++

pub struct ContainerBuilder<Key, SvcBase: ?Sized> {
    cont: Container<Key, SvcBase>
}

impl<Key, SvcBase: ?Sized> ContainerBuilder<Key, SvcBase>
    where Key: reflect::Key, SvcBase: Any
{
    pub fn new() -> Self {
        ContainerBuilder{ cont: Container::new() }
    }

    pub fn register_service(&mut self, key: Key, svc: Box<SvcBase>) -> &mut Self {
        self.cont.register_service(key, svc);
        self
    }

    /// NOTE: The `Box<Svc>: Into<Box<Base>>`-clause is needed due to rusts lack of
    /// HKT or a `Coercible`-trait (to name two solutions).
    pub fn register<Svc>(&mut self, svc: Svc) -> &mut Self
    where
        Svc: reflect::Service<Key = Key>,
        Box<Svc>: Into<Box<SvcBase>>,
    {
        self.cont.register::<Svc>(svc);
        self
    }

    pub fn build(self) -> Container<Key, SvcBase> {
        self.cont
    }
}

impl<Key, SvcBase: ?Sized> Default for Container<Key, SvcBase>
    where Key: reflect::Key, SvcBase: Any
{
    fn default() -> Self { Self::new() }
}
<|endoftext|>


<commit_before>// TODO: drop all panic!

use std::any::Any;
use std::any::TypeId;
use std::default::Default;
use std::fmt;
use std::io::Read;
use std::io::Write;

use clear::Clear;
use reflect::MessageDescriptor;
use reflect::EnumDescriptor;
use reflect::EnumValueDescriptor;
use unknown::UnknownFields;
use stream::WithCodedInputStream;
use stream::WithCodedOutputStream;
use stream::CodedInputStream;
use stream::CodedOutputStream;
use stream::with_coded_output_stream_to_bytes;
use error::ProtobufError;
use error::ProtobufResult;

pub trait Message : fmt::Debug + Clear + Any + 'static {
    // All generated Message types also implement MessageStatic.
    // However, rust doesn't allow these types to be extended by
    // Message.

    fn descriptor(&self) -> &'static MessageDescriptor;

    // all required fields set
    fn is_initialized(&self) -> bool;
    fn merge_from(&mut self, is: &mut CodedInputStream) -> ProtobufResult<()>;

    // sizes of this messages (and nested messages) must be cached
    // by calling `compute_size` prior to this call
    fn write_to_with_cached_sizes(&self, os: &mut CodedOutputStream) -> ProtobufResult<()>;

    // compute and cache size of this message and all nested messages
    fn compute_size(&self) -> u32;

    // get size previously computed by `compute_size`
    fn get_cached_size(&self) -> u32;

    fn write_to(&self, os: &mut CodedOutputStream) -> ProtobufResult<()> {
        try!(self.check_initialized());

        // cache sizes
        self.compute_size();
        try!(self.write_to_with_cached_sizes(os));

        // TODO: assert we've written same number of bytes as computed

        Ok(())
    }

    fn write_length_delimited_to(&self, os: &mut CodedOutputStream) -> ProtobufResult<()> {
        let size = self.compute_size();
        try!(os.write_raw_varint32(size));
        try!(self.write_to_with_cached_sizes(os));

        // TODO: assert we've written same number of bytes as computed

        Ok(())
    }

    fn merge_from_bytes(&mut self, bytes: &[u8]) -> ProtobufResult<()> {
        let mut is = CodedInputStream::from_bytes(bytes);
        self.merge_from(&mut is)
    }

    fn check_initialized(&self) -> ProtobufResult<()> {
        if !self.is_initialized() {
            Err((ProtobufError::message_not_initialized(self.descriptor().name())))
        } else {
            Ok(())
        }
    }

    fn write_to_writer(&self, w: &mut Write) -> ProtobufResult<()> {
        w.with_coded_output_stream(|os| {
            self.write_to(os)
        })
    }

    fn write_to_vec(&self, v: &mut Vec<u8>) -> ProtobufResult<()> {
        v.with_coded_output_stream(|os| {
            self.write_to(os)
        })
    }

    fn write_to_bytes(&self) -> ProtobufResult<Vec<u8>> {
        // TODO: compute message size and reserve that size
        let mut v = Vec::new();
        try!(self.write_to_vec(&mut v));
        Ok(v)
    }

    fn write_length_delimited_to_writer(&self, w: &mut Write) -> ProtobufResult<()> {
        w.with_coded_output_stream(|os| {
            self.write_length_delimited_to(os)
        })
    }

    fn write_length_delimited_to_bytes(&self) -> ProtobufResult<Vec<u8>> {
        with_coded_output_stream_to_bytes(|os| {
            self.write_length_delimited_to(os)
        })
    }

    fn get_unknown_fields<'s>(&'s self) -> &'s UnknownFields;
    fn mut_unknown_fields<'s>(&'s mut self) -> &'s mut UnknownFields;

    fn type_id(&self) -> TypeId;
    fn as_any(&self) -> &Any;

    // Rust does not allow implementation of trait for trait:
    // impl<M : Message> fmt::Debug for M {
    // ...
    // }
}

// For some reason Rust doesn't allow conversion of &Foo to &Message it
// Message contains static functions. So static functions must be placed
// into separate place.
//
// See https://github.com/rust-lang/rust/commit/cd31e6ff for details.
pub trait MessageStatic : Message + Clone + Default + PartialEq /* + ProtobufValue */ {
    fn new() -> Self;

    // http://stackoverflow.com/q/20342436/15018
    fn descriptor_static(_: Option<Self>) -> &'static MessageDescriptor {
        panic!("descriptor_static is not implemented for message, \
            LITE_RUNTIME must be used");
    }
}

pub fn message_is<M : Message>(m: &Message) -> bool {
    TypeId::of::<M>() == m.type_id()
}

pub fn message_down_cast<'a, M : Message + 'a>(m: &'a Message) -> &'a M {
    assert!(message_is::<M>(m));
    m.as_any().downcast_ref::<M>().unwrap()
}

pub trait ProtobufEnum : Eq + Sized + Copy + 'static /* + ProtobufValue */ {
    fn value(&self) -> i32;

    fn from_i32(v: i32) -> Option<Self>;

    fn values() -> &'static [Self] {
        panic!();
    }

    fn descriptor(&self) -> &'static EnumValueDescriptor {
        self.enum_descriptor().value_by_number(self.value())
    }

    fn enum_descriptor(&self) -> &'static EnumDescriptor {
        ProtobufEnum::enum_descriptor_static(None::<Self>)
    }

    // http://stackoverflow.com/q/20342436/15018
    fn enum_descriptor_static(_: Option<Self>) -> &'static EnumDescriptor {
        panic!();
    }
}

pub fn parse_from<M : Message + MessageStatic>(is: &mut CodedInputStream) -> ProtobufResult<M> {
    let mut r: M = MessageStatic::new();
    try!(r.merge_from(is));
    try!(r.check_initialized());
    Ok(r)
}

pub fn parse_from_reader<M : Message + MessageStatic>(reader: &mut Read) -> ProtobufResult<M> {
    reader.with_coded_input_stream(|is| {
        parse_from::<M>(is)
    })
}

pub fn parse_from_bytes<M : Message + MessageStatic>(bytes: &[u8]) -> ProtobufResult<M> {
    bytes.with_coded_input_stream(|is| {
        parse_from::<M>(is)
    })
}

pub fn parse_length_delimited_from<M : Message + MessageStatic>(is: &mut CodedInputStream)
        -> ProtobufResult<M>
{
    is.read_message::<M>()
}

pub fn parse_length_delimited_from_reader<M : Message + MessageStatic>(r: &mut Read) -> ProtobufResult<M> {
    // TODO: wrong: we may read length first, and then read exact number of bytes needed
    r.with_coded_input_stream(|is| {
        is.read_message::<M>()
    })
}

pub fn parse_length_delimited_from_bytes<M : Message + MessageStatic>(bytes: &[u8]) -> ProtobufResult<M> {
    bytes.with_coded_input_stream(|is| {
        is.read_message::<M>()
    })
}

<commit_msg>Remove unused code<commit_after>// TODO: drop all panic!

use std::any::Any;
use std::any::TypeId;
use std::default::Default;
use std::fmt;
use std::io::Read;
use std::io::Write;

use clear::Clear;
use reflect::MessageDescriptor;
use reflect::EnumDescriptor;
use reflect::EnumValueDescriptor;
use unknown::UnknownFields;
use stream::WithCodedInputStream;
use stream::WithCodedOutputStream;
use stream::CodedInputStream;
use stream::CodedOutputStream;
use stream::with_coded_output_stream_to_bytes;
use error::ProtobufError;
use error::ProtobufResult;

pub trait Message : fmt::Debug + Clear + Any + 'static {
    // All generated Message types also implement MessageStatic.
    // However, rust doesn't allow these types to be extended by
    // Message.

    fn descriptor(&self) -> &'static MessageDescriptor;

    // all required fields set
    fn is_initialized(&self) -> bool;
    fn merge_from(&mut self, is: &mut CodedInputStream) -> ProtobufResult<()>;

    // sizes of this messages (and nested messages) must be cached
    // by calling `compute_size` prior to this call
    fn write_to_with_cached_sizes(&self, os: &mut CodedOutputStream) -> ProtobufResult<()>;

    // compute and cache size of this message and all nested messages
    fn compute_size(&self) -> u32;

    // get size previously computed by `compute_size`
    fn get_cached_size(&self) -> u32;

    fn write_to(&self, os: &mut CodedOutputStream) -> ProtobufResult<()> {
        try!(self.check_initialized());

        // cache sizes
        self.compute_size();
        try!(self.write_to_with_cached_sizes(os));

        // TODO: assert we've written same number of bytes as computed

        Ok(())
    }

    fn write_length_delimited_to(&self, os: &mut CodedOutputStream) -> ProtobufResult<()> {
        let size = self.compute_size();
        try!(os.write_raw_varint32(size));
        try!(self.write_to_with_cached_sizes(os));

        // TODO: assert we've written same number of bytes as computed

        Ok(())
    }

    fn merge_from_bytes(&mut self, bytes: &[u8]) -> ProtobufResult<()> {
        let mut is = CodedInputStream::from_bytes(bytes);
        self.merge_from(&mut is)
    }

    fn check_initialized(&self) -> ProtobufResult<()> {
        if !self.is_initialized() {
            Err((ProtobufError::message_not_initialized(self.descriptor().name())))
        } else {
            Ok(())
        }
    }

    fn write_to_writer(&self, w: &mut Write) -> ProtobufResult<()> {
        w.with_coded_output_stream(|os| {
            self.write_to(os)
        })
    }

    fn write_to_vec(&self, v: &mut Vec<u8>) -> ProtobufResult<()> {
        v.with_coded_output_stream(|os| {
            self.write_to(os)
        })
    }

    fn write_to_bytes(&self) -> ProtobufResult<Vec<u8>> {
        // TODO: compute message size and reserve that size
        let mut v = Vec::new();
        try!(self.write_to_vec(&mut v));
        Ok(v)
    }

    fn write_length_delimited_to_writer(&self, w: &mut Write) -> ProtobufResult<()> {
        w.with_coded_output_stream(|os| {
            self.write_length_delimited_to(os)
        })
    }

    fn write_length_delimited_to_bytes(&self) -> ProtobufResult<Vec<u8>> {
        with_coded_output_stream_to_bytes(|os| {
            self.write_length_delimited_to(os)
        })
    }

    fn get_unknown_fields<'s>(&'s self) -> &'s UnknownFields;
    fn mut_unknown_fields<'s>(&'s mut self) -> &'s mut UnknownFields;

    fn type_id(&self) -> TypeId;
    fn as_any(&self) -> &Any;

    // Rust does not allow implementation of trait for trait:
    // impl<M : Message> fmt::Debug for M {
    // ...
    // }
}

// For some reason Rust doesn't allow conversion of &Foo to &Message it
// Message contains static functions. So static functions must be placed
// into separate place.
//
// See https://github.com/rust-lang/rust/commit/cd31e6ff for details.
pub trait MessageStatic : Message + Clone + Default + PartialEq /* + ProtobufValue */ {
    fn new() -> Self;

    // http://stackoverflow.com/q/20342436/15018
    fn descriptor_static(_: Option<Self>) -> &'static MessageDescriptor {
        panic!("descriptor_static is not implemented for message, \
            LITE_RUNTIME must be used");
    }
}

pub fn message_down_cast<'a, M : Message + 'a>(m: &'a Message) -> &'a M {
    m.as_any().downcast_ref::<M>().unwrap()
}

pub trait ProtobufEnum : Eq + Sized + Copy + 'static /* + ProtobufValue */ {
    fn value(&self) -> i32;

    fn from_i32(v: i32) -> Option<Self>;

    fn values() -> &'static [Self] {
        panic!();
    }

    fn descriptor(&self) -> &'static EnumValueDescriptor {
        self.enum_descriptor().value_by_number(self.value())
    }

    fn enum_descriptor(&self) -> &'static EnumDescriptor {
        ProtobufEnum::enum_descriptor_static(None::<Self>)
    }

    // http://stackoverflow.com/q/20342436/15018
    fn enum_descriptor_static(_: Option<Self>) -> &'static EnumDescriptor {
        panic!();
    }
}

pub fn parse_from<M : Message + MessageStatic>(is: &mut CodedInputStream) -> ProtobufResult<M> {
    let mut r: M = MessageStatic::new();
    try!(r.merge_from(is));
    try!(r.check_initialized());
    Ok(r)
}

pub fn parse_from_reader<M : Message + MessageStatic>(reader: &mut Read) -> ProtobufResult<M> {
    reader.with_coded_input_stream(|is| {
        parse_from::<M>(is)
    })
}

pub fn parse_from_bytes<M : Message + MessageStatic>(bytes: &[u8]) -> ProtobufResult<M> {
    bytes.with_coded_input_stream(|is| {
        parse_from::<M>(is)
    })
}

pub fn parse_length_delimited_from<M : Message + MessageStatic>(is: &mut CodedInputStream)
        -> ProtobufResult<M>
{
    is.read_message::<M>()
}

pub fn parse_length_delimited_from_reader<M : Message + MessageStatic>(r: &mut Read) -> ProtobufResult<M> {
    // TODO: wrong: we may read length first, and then read exact number of bytes needed
    r.with_coded_input_stream(|is| {
        is.read_message::<M>()
    })
}

pub fn parse_length_delimited_from_bytes<M : Message + MessageStatic>(bytes: &[u8]) -> ProtobufResult<M> {
    bytes.with_coded_input_stream(|is| {
        is.read_message::<M>()
    })
}

<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

/// A type that holds metadata about the RRG agent.
pub struct Metadata {
    /// Name of the RRG agent.
    pub name: String,
    /// Description of the RRG agent.
    pub description: String,
    /// Version of the RRG agent.
    pub version: Version,
}

impl Metadata {

    /// Constructs metadata object from Cargo information.
    ///
    /// This function assumes that are relevant crate information is correctly
    /// specified in the `Cargo.toml` file.
    pub fn from_cargo() -> Metadata {
        Metadata {
            name: String::from(env!("CARGO_PKG_NAME")),
            description: String::from(env!("CARGO_PKG_DESCRIPTION")),
            version: Version::from_cargo(),
        }
    }
}

/// A type for representing version metadata.
pub struct Version {
    /// Major version of the RRG agent (`x` in `x.y.z.r`).
    pub major: u8,
    /// Minor version of the RRG agent (`y` in `x.y.z.r`).
    pub minor: u8,
    /// Patch version of the RRG agent (`z` in `x.y.z.r`).
    pub patch: u8,
    /// Revision version of the RRG agent (`r` in `x.y.z.r`).
    pub revision: u8,
}

impl Version {

    /// Constructs version metadata from Cargo information.
    ///
    /// This function assumes that are relevant crate information is correctly
    /// specified in the `Cargo.toml` file.
    pub fn from_cargo() -> Version {
        Version {
            major: env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap_or(0),
            minor: env!("CARGO_PKG_VERSION_MINOR").parse().unwrap_or(0),
            patch: env!("CARGO_PKG_VERSION_PATCH").parse().unwrap_or(0),
            revision: env!("CARGO_PKG_VERSION_PRE").parse().unwrap_or(0),
        }
    }

    /// Returns a numeric representation of version metadata.
    ///
    /// This function assumes that all version components are smaller than 10.
    /// In other cases, the output is undefined (but the function call itself
    /// does not panic).
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg::metadata::Version;
    ///
    /// let version = Version {
    ///     major: 1,
    ///     minor: 2,
    ///     patch: 3,
    ///     revision: 4,
    /// };
    ///
    /// assert_eq!(version.as_numeric(), 1234)
    /// ```
    pub fn as_numeric(&self) -> u32 {
        let mut result = 0;
        result = 10 * result + self.major as u32;
        result = 10 * result + self.minor as u32;
        result = 10 * result + self.patch as u32;
        result = 10 * result + self.revision as u32;
        result
    }
}

impl Into<rrg_proto::ClientInformation> for Metadata {

    fn into(self) -> rrg_proto::ClientInformation {
        // TODO: Add support for labels.
        rrg_proto::ClientInformation {
            client_name: Some(self.name),
            client_version: Some(self.version.as_numeric()),
            client_description: Some(self.description),
            ..Default::default()
        }
    }
}
<commit_msg>Implement agent metadata conversion.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

// TODO(panhania): Add support for binary paths in the `Metadata` object.

/// A type that holds metadata about the RRG agent.
pub struct Metadata {
    /// Name of the RRG agent.
    pub name: String,
    /// Description of the RRG agent.
    pub description: String,
    /// Version of the RRG agent.
    pub version: Version,
}

impl Metadata {

    /// Constructs metadata object from Cargo information.
    ///
    /// This function assumes that are relevant crate information is correctly
    /// specified in the `Cargo.toml` file.
    pub fn from_cargo() -> Metadata {
        Metadata {
            name: String::from(env!("CARGO_PKG_NAME")),
            description: String::from(env!("CARGO_PKG_DESCRIPTION")),
            version: Version::from_cargo(),
        }
    }
}

/// A type for representing version metadata.
pub struct Version {
    /// Major version of the RRG agent (`x` in `x.y.z.r`).
    pub major: u8,
    /// Minor version of the RRG agent (`y` in `x.y.z.r`).
    pub minor: u8,
    /// Patch version of the RRG agent (`z` in `x.y.z.r`).
    pub patch: u8,
    /// Revision version of the RRG agent (`r` in `x.y.z.r`).
    pub revision: u8,
}

impl Version {

    /// Constructs version metadata from Cargo information.
    ///
    /// This function assumes that are relevant crate information is correctly
    /// specified in the `Cargo.toml` file.
    pub fn from_cargo() -> Version {
        Version {
            major: env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap_or(0),
            minor: env!("CARGO_PKG_VERSION_MINOR").parse().unwrap_or(0),
            patch: env!("CARGO_PKG_VERSION_PATCH").parse().unwrap_or(0),
            revision: env!("CARGO_PKG_VERSION_PRE").parse().unwrap_or(0),
        }
    }

    /// Returns a numeric representation of version metadata.
    ///
    /// This function assumes that all version components are smaller than 10.
    /// In other cases, the output is undefined (but the function call itself
    /// does not panic).
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg::metadata::Version;
    ///
    /// let version = Version {
    ///     major: 1,
    ///     minor: 2,
    ///     patch: 3,
    ///     revision: 4,
    /// };
    ///
    /// assert_eq!(version.as_numeric(), 1234)
    /// ```
    pub fn as_numeric(&self) -> u32 {
        let mut result = 0;
        result = 10 * result + self.major as u32;
        result = 10 * result + self.minor as u32;
        result = 10 * result + self.patch as u32;
        result = 10 * result + self.revision as u32;
        result
    }
}

impl Into<rrg_proto::ClientInformation> for Metadata {

    fn into(self) -> rrg_proto::ClientInformation {
        // TODO: Add support for labels.
        rrg_proto::ClientInformation {
            client_name: Some(self.name),
            client_version: Some(self.version.as_numeric()),
            client_description: Some(self.description),
            ..Default::default()
        }
    }
}

impl Into<rrg_proto::protobuf::jobs::ClientInformation> for Metadata {

    fn into(self) -> rrg_proto::protobuf::jobs::ClientInformation {
        let mut proto = rrg_proto::protobuf::jobs::ClientInformation::new();
        proto.set_client_name(self.name);
        proto.set_client_version(self.version.as_numeric());
        proto.set_client_description(self.description);

        proto
    }
}
<|endoftext|>


<commit_before>use boxed::Box;
use string::String;

use sync::{Arc, Weak};

use sync::spin::{RwLock, RwLockReadGuard, RwLockWriteGuard};

use net::{Instance, InstanceWeak};

use net::defs::{HwAddr, Ipv4Addr, Device};

use hal::net::HwInterface;

// XXX: Should this be in net::defs ?
/// IPv4 configuration of an interface
pub struct V4Configuration {
    /// Main IPv4 address
    pub ipv4: Ipv4Addr,
    /// Subnet mask
    pub ipv4_mask: Ipv4Addr,
    /// Gateway IPv4 address
    pub ipv4_gateway: Ipv4Addr,
}

#[derive(Clone)]
/// A shareable network interface.
///
/// This is backed by an Arc and a RwLock so that accesses are safe and the
/// entity can be shared.
pub struct Interface(Arc<RwLock<InterfaceRaw>>);

unsafe impl Send for Interface {}

#[derive(Clone)]
/// A interface weak reference
pub struct InterfaceWeak(Weak<RwLock<InterfaceRaw>>);

unsafe impl Send for InterfaceWeak {}

/// The raw network interface
pub struct InterfaceRaw {
    /// The network stack the interface belongs to
    instance: InstanceWeak,
    /// Name of the interface
    name: String,
    /// Hardware address of the interface
    hw_addr: HwAddr,
    /// IPv4 configuration of the interface
    conf: V4Configuration,
    /// Underlying driver
    pv_device: Option<Box<HwInterface>>,
}

impl Interface {
    /// Creates a new network interface
    pub fn new(instance: &Instance) -> Self {
        let inner = InterfaceRaw {
            instance: instance.downgrade(),
            name: String::new(),
            hw_addr: HwAddr::empty(),
            conf: V4Configuration {
                ipv4: Ipv4Addr::new(0, 0, 0, 0),
                ipv4_mask: Ipv4Addr::new(0, 0, 0, 0),
                ipv4_gateway: Ipv4Addr::new(0, 0, 0, 0),
            },
            pv_device: None,
        };

        Interface(Arc::new(RwLock::new(inner)))
    }

    /// Get a weak reference over the interface
    pub fn downgrade(&self) -> InterfaceWeak {
        InterfaceWeak(Arc::downgrade(&self.0))
    }

    /// Lock the interface with shared read access
    ///
    /// For more info see spin::RwLock::read()
    pub fn read(&self) -> RwLockReadGuard<InterfaceRaw> {
        self.0.read()
    }

    /// Lock the interface with exclusive write access
    ///
    /// For more info see spin::RwLock::write()
    pub fn write(&self) -> RwLockWriteGuard<InterfaceRaw> {
        self.0.write()
    }
}

impl InterfaceWeak {
    /// Upgrade the weak reference to a real reference
    pub fn upgrade(&self) -> Option<Interface> {
        self.0.upgrade().map(Interface)
    }
}

impl InterfaceRaw {
    #[inline]
    /// Returns a reference over the name of the interface
    pub fn name_ref(&self) -> &str {
        &self.name
    }

    #[inline]
    /// Returns a reference over the hardware of the interface
    pub fn hw_addr_ref(&self) -> &HwAddr {
        &self.hw_addr
    }

    #[inline]
    /// Returns a reference over the IPv4 configuration of the interface
    pub fn v4_configuration_ref(&self) -> &V4Configuration {
        &self.conf
    }

    #[inline]
    /// Returns a mutable reference over the name of the interface
    pub fn name_mut(&mut self) -> &mut String {
        &mut self.name
    }

    #[inline]
    /// Returns a mutable reference over the hardware of the interface
    pub fn hw_addr_mut(&mut self) -> &mut HwAddr {
        &mut self.hw_addr
    }

    #[inline]
    /// Returns a mutable reference over the IPv4 configuration of the interface
    pub fn v4_configuration_mut(&mut self) -> &mut V4Configuration {
        &mut self.conf
    }

    #[inline]
    #[doc(hidden)]
    pub fn pv_device_set(&mut self, pv: Box<HwInterface>) {
        self.pv_device = Some(pv);
    }

    #[inline]
    /// Refresh underlying driver
    pub fn refresh(&mut self) {
        self.pv_device.as_mut().unwrap().refresh();
    }
}
<commit_msg>net/intf: Add prototype of rx_packet() and tx_packet()<commit_after>use boxed::Box;
use string::String;

use sync::{Arc, Weak};

use sync::spin::{RwLock, RwLockReadGuard, RwLockWriteGuard};

use net::{Instance, InstanceWeak, Packet, PacketBuilder};

use net::defs::{Rule, HwAddr, Ipv4Addr, Device};

use hal::net::HwInterface;

// XXX: Should this be in net::defs ?
/// IPv4 configuration of an interface
pub struct V4Configuration {
    /// Main IPv4 address
    pub ipv4: Ipv4Addr,
    /// Subnet mask
    pub ipv4_mask: Ipv4Addr,
    /// Gateway IPv4 address
    pub ipv4_gateway: Ipv4Addr,
}

#[derive(Clone)]
/// A shareable network interface.
///
/// This is backed by an Arc and a RwLock so that accesses are safe and the
/// entity can be shared.
pub struct Interface(Arc<RwLock<InterfaceRaw>>);

unsafe impl Send for Interface {}

#[derive(Clone)]
/// A interface weak reference
pub struct InterfaceWeak(Weak<RwLock<InterfaceRaw>>);

unsafe impl Send for InterfaceWeak {}

/// The raw network interface
pub struct InterfaceRaw {
    /// The network stack the interface belongs to
    instance: InstanceWeak,
    /// Name of the interface
    name: String,
    /// Hardware address of the interface
    hw_addr: HwAddr,
    /// IPv4 configuration of the interface
    conf: V4Configuration,
    /// Underlying driver
    pv_device: Option<Box<HwInterface>>,
}

impl Interface {
    /// Creates a new network interface
    pub fn new(instance: &Instance) -> Self {
        let inner = InterfaceRaw {
            instance: instance.downgrade(),
            name: String::new(),
            hw_addr: HwAddr::empty(),
            conf: V4Configuration {
                ipv4: Ipv4Addr::new(0, 0, 0, 0),
                ipv4_mask: Ipv4Addr::new(0, 0, 0, 0),
                ipv4_gateway: Ipv4Addr::new(0, 0, 0, 0),
            },
            pv_device: None,
        };

        Interface(Arc::new(RwLock::new(inner)))
    }

    /// Get a weak reference over the interface
    pub fn downgrade(&self) -> InterfaceWeak {
        InterfaceWeak(Arc::downgrade(&self.0))
    }

    /// Lock the interface with shared read access
    ///
    /// For more info see spin::RwLock::read()
    pub fn read(&self) -> RwLockReadGuard<InterfaceRaw> {
        self.0.read()
    }

    /// Lock the interface with exclusive write access
    ///
    /// For more info see spin::RwLock::write()
    pub fn write(&self) -> RwLockWriteGuard<InterfaceRaw> {
        self.0.write()
    }

    /// Receive a packet on the interface
    pub fn rx_packet(&self, _pkt: Packet) {
        unimplemented!();
    }

    /// Transmit a packet through the interface
    pub fn tx_packet(&self, _builder: PacketBuilder,
                     _rule: &Rule) -> Result<(), ()> {
        unimplemented!();
    }
}

impl InterfaceWeak {
    /// Upgrade the weak reference to a real reference
    pub fn upgrade(&self) -> Option<Interface> {
        self.0.upgrade().map(Interface)
    }
}

impl InterfaceRaw {
    #[inline]
    /// Returns a reference over the name of the interface
    pub fn name_ref(&self) -> &str {
        &self.name
    }

    #[inline]
    /// Returns a reference over the hardware of the interface
    pub fn hw_addr_ref(&self) -> &HwAddr {
        &self.hw_addr
    }

    #[inline]
    /// Returns a reference over the IPv4 configuration of the interface
    pub fn v4_configuration_ref(&self) -> &V4Configuration {
        &self.conf
    }

    #[inline]
    /// Returns a mutable reference over the name of the interface
    pub fn name_mut(&mut self) -> &mut String {
        &mut self.name
    }

    #[inline]
    /// Returns a mutable reference over the hardware of the interface
    pub fn hw_addr_mut(&mut self) -> &mut HwAddr {
        &mut self.hw_addr
    }

    #[inline]
    /// Returns a mutable reference over the IPv4 configuration of the interface
    pub fn v4_configuration_mut(&mut self) -> &mut V4Configuration {
        &mut self.conf
    }

    #[inline]
    #[doc(hidden)]
    pub fn pv_device_set(&mut self, pv: Box<HwInterface>) {
        self.pv_device = Some(pv);
    }

    #[inline]
    /// Refresh underlying driver
    pub fn refresh(&mut self) {
        self.pv_device.as_mut().unwrap().refresh();
    }
}
<|endoftext|>