<commit_before>// You have to ctrl-C after running this benchmark, since there is no way to kill
// a rust-http server.

extern crate http;
extern crate hyper;
extern crate test;

use test::Bencher;
use std::io::net::ip::{SocketAddr, Ipv4Addr};

use http::server::Server;

static phrase: &'static [u8] = b"Benchmarking hyper vs others!";

fn request(url: hyper::Url) {
    let req = hyper::client::Request::get(url).unwrap();
    req.start().unwrap().send().unwrap().read_to_string().unwrap();
}

fn hyper_handle(mut incoming: hyper::server::Incoming) {
    for (_, mut res) in incoming {
        let mut res = res.start().unwrap();
        res.write(phrase).unwrap();
        res.end().unwrap();
    }
}

#[bench]
fn bench_hyper(b: &mut Bencher) {
    let server = hyper::Server::http(Ipv4Addr(127, 0, 0, 1), 0);
    let mut listener = server.listen(hyper_handle).unwrap();

    let url = hyper::Url::parse(format!("http://{}", listener.sockets[0]).as_slice()).unwrap();
    b.iter(|| request(url.clone()));
    listener.close().unwrap();
}

static mut created_http: bool = false;

#[deriving(Clone)]
struct HttpServer;

impl Server for HttpServer {
    fn get_config(&self) -> http::server::Config {
        http::server::Config {
            bind_address: SocketAddr {
                ip: Ipv4Addr(127, 0, 0, 1),
                port: 4000
            }
        }
    }

    fn handle_request(&self, _: http::server::Request, res: &mut http::server::ResponseWriter) {
        res.write(phrase).unwrap();
    }
}

#[bench]
fn bench_http(b: &mut Bencher) {
    if unsafe { !created_http } {
        spawn(proc() { HttpServer.serve_forever() });
        unsafe { created_http = true }
        // Mega hack because there is no way to wait for serve_forever to start:
        std::io::timer::sleep(std::time::duration::Duration::seconds(1));
    }

    let url = hyper::Url::parse("http://localhost:4000").unwrap();
    b.iter(|| request(url.clone()));
}

<commit_msg>Uppercase phrase constant to remove warnings<commit_after>// You have to ctrl-C after running this benchmark, since there is no way to kill
// a rust-http server.

extern crate http;
extern crate hyper;
extern crate test;

use test::Bencher;
use std::io::net::ip::{SocketAddr, Ipv4Addr};

use http::server::Server;

static PHRASE: &'static [u8] = b"Benchmarking hyper vs others!";

fn request(url: hyper::Url) {
    let req = hyper::client::Request::get(url).unwrap();
    req.start().unwrap().send().unwrap().read_to_string().unwrap();
}

fn hyper_handle(mut incoming: hyper::server::Incoming) {
    for (_, mut res) in incoming {
        let mut res = res.start().unwrap();
        res.write(PHRASE).unwrap();
        res.end().unwrap();
    }
}

#[bench]
fn bench_hyper(b: &mut Bencher) {
    let server = hyper::Server::http(Ipv4Addr(127, 0, 0, 1), 0);
    let mut listener = server.listen(hyper_handle).unwrap();

    let url = hyper::Url::parse(format!("http://{}", listener.sockets[0]).as_slice()).unwrap();
    b.iter(|| request(url.clone()));
    listener.close().unwrap();
}

static mut created_http: bool = false;

#[deriving(Clone)]
struct HttpServer;

impl Server for HttpServer {
    fn get_config(&self) -> http::server::Config {
        http::server::Config {
            bind_address: SocketAddr {
                ip: Ipv4Addr(127, 0, 0, 1),
                port: 4000
            }
        }
    }

    fn handle_request(&self, _: http::server::Request, res: &mut http::server::ResponseWriter) {
        res.write(PHRASE).unwrap();
    }
}

#[bench]
fn bench_http(b: &mut Bencher) {
    if unsafe { !created_http } {
        spawn(proc() { HttpServer.serve_forever() });
        unsafe { created_http = true }
        // Mega hack because there is no way to wait for serve_forever to start:
        std::io::timer::sleep(std::time::duration::Duration::seconds(1));
    }

    let url = hyper::Url::parse("http://localhost:4000").unwrap();
    b.iter(|| request(url.clone()));
}

<|endoftext|>


<commit_before>use std::collections::HashMap;

use bytes::{Buf, Bytes};
use hashing::Digest;
use parking_lot::Mutex;
use task_executor::Executor;
use tempfile::TempDir;

use crate::{ShardedLmdb, DEFAULT_LEASE_TIME};

fn new_store(shard_count: u8) -> (ShardedLmdb, TempDir) {
  let tempdir = TempDir::new().unwrap();
  let s = ShardedLmdb::new(
    tempdir.path().to_owned(),
    10_000_000,
    Executor::new(),
    DEFAULT_LEASE_TIME,
    shard_count,
  )
  .unwrap();
  (s, tempdir)
}

#[tokio::test]
async fn shard_counts() {
  let shard_counts = vec![1, 2, 4, 8, 16, 32, 64, 128];
  for shard_count in shard_counts {
    let (s, _tempdir) = new_store(shard_count);
    assert_eq!(s.all_lmdbs().len(), shard_count as usize);

    // Confirm that each database gets an even share.
    let mut databases = HashMap::new();
    for prefix_byte in 0u8..=255u8 {
      *databases
        .entry(s.get_raw(&[prefix_byte]).0.clone())
        .or_insert(0) += 1;
    }
    assert_eq!(databases.len(), shard_count as usize);
    for (_, count) in databases {
      assert_eq!(count, 256 / shard_count as usize);
    }
  }
}

#[tokio::test]
async fn store_immutable() {
  let (s, _tempdir) = new_store(1);
  let digest = s.store(true, true, || Ok(bytes(0).reader())).await.unwrap();
  assert_eq!(digest, Digest::of_bytes(&bytes(0)));
}

#[tokio::test]
async fn store_stable() {
  let (s, _tempdir) = new_store(1);
  let digest = s
    .store(true, false, || Ok(bytes(0).reader()))
    .await
    .unwrap();
  assert_eq!(digest, Digest::of_bytes(&bytes(0)));
}

#[tokio::test]
async fn store_changing() {
  let (s, _tempdir) = new_store(1);

  // Produces Readers that change during the first two reads, but stabilize on the third and
  // fourth.
  let contents = Mutex::new(vec![bytes(0), bytes(1), bytes(2), bytes(2)].into_iter());

  let digest = s
    .store(true, false, move || {
      Ok(contents.lock().next().unwrap().reader())
    })
    .await
    .unwrap();
  assert_eq!(digest, Digest::of_bytes(&bytes(2)));
}

#[tokio::test]
async fn store_failure() {
  let (s, _tempdir) = new_store(1);

  // Produces Readers that never stabilize.
  let contents = Mutex::new((0..100).map(|b| bytes(b)));

  let result = s
    .store(true, false, move || {
      Ok(contents.lock().next().unwrap().reader())
    })
    .await;
  assert!(result.is_err());
}

fn bytes(content: u8) -> Bytes {
  Bytes::from(vec![content; 100])
}
<commit_msg>increase LMDB size to fix a test on Apple M1 (#16672)<commit_after>use std::collections::HashMap;

use bytes::{Buf, Bytes};
use hashing::Digest;
use parking_lot::Mutex;
use task_executor::Executor;
use tempfile::TempDir;

use crate::{ShardedLmdb, DEFAULT_LEASE_TIME};

fn new_store(shard_count: u8) -> (ShardedLmdb, TempDir) {
  let tempdir = TempDir::new().unwrap();
  let s = ShardedLmdb::new(
    tempdir.path().to_owned(),
    15_000_000,
    Executor::new(),
    DEFAULT_LEASE_TIME,
    shard_count,
  )
  .unwrap();
  (s, tempdir)
}

#[tokio::test]
async fn shard_counts() {
  let shard_counts = vec![1, 2, 4, 8, 16, 32, 64, 128];
  for shard_count in shard_counts {
    let (s, _tempdir) = new_store(shard_count);
    assert_eq!(s.all_lmdbs().len(), shard_count as usize);

    // Confirm that each database gets an even share.
    let mut databases = HashMap::new();
    for prefix_byte in 0u8..=255u8 {
      *databases
        .entry(s.get_raw(&[prefix_byte]).0.clone())
        .or_insert(0) += 1;
    }
    assert_eq!(databases.len(), shard_count as usize);
    for (_, count) in databases {
      assert_eq!(count, 256 / shard_count as usize);
    }
  }
}

#[tokio::test]
async fn store_immutable() {
  let (s, _tempdir) = new_store(1);
  let digest = s.store(true, true, || Ok(bytes(0).reader())).await.unwrap();
  assert_eq!(digest, Digest::of_bytes(&bytes(0)));
}

#[tokio::test]
async fn store_stable() {
  let (s, _tempdir) = new_store(1);
  let digest = s
    .store(true, false, || Ok(bytes(0).reader()))
    .await
    .unwrap();
  assert_eq!(digest, Digest::of_bytes(&bytes(0)));
}

#[tokio::test]
async fn store_changing() {
  let (s, _tempdir) = new_store(1);

  // Produces Readers that change during the first two reads, but stabilize on the third and
  // fourth.
  let contents = Mutex::new(vec![bytes(0), bytes(1), bytes(2), bytes(2)].into_iter());

  let digest = s
    .store(true, false, move || {
      Ok(contents.lock().next().unwrap().reader())
    })
    .await
    .unwrap();
  assert_eq!(digest, Digest::of_bytes(&bytes(2)));
}

#[tokio::test]
async fn store_failure() {
  let (s, _tempdir) = new_store(1);

  // Produces Readers that never stabilize.
  let contents = Mutex::new((0..100).map(|b| bytes(b)));

  let result = s
    .store(true, false, move || {
      Ok(contents.lock().next().unwrap().reader())
    })
    .await;
  assert!(result.is_err());
}

fn bytes(content: u8) -> Bytes {
  Bytes::from(vec![content; 100])
}
<|endoftext|>


<commit_before>use bifrost::rpc::*;
use client::AsyncClient;
use index::lsmtree::service::inner::LSMTreeIns;
use index::lsmtree::tree::LSMTree;
use index::{EntryKey, Ordering};
use itertools::Itertools;
use parking_lot::RwLock;
use smallvec::SmallVec;
use std::collections::HashMap;
use std::path::Component::CurDir;
use std::sync::atomic;
use std::sync::atomic::AtomicU64;
use rayon::iter::IntoParallelRefIterator;
use rayon::iter::ParallelIterator;
use std::thread;

#[derive(Serialize, Deserialize)]
enum LSMTreeSvrError {
    TreeNotFound,
}

#[derive(Serialize, Deserialize)]
struct LSMTreeSummary {
    id: u64,
    count: u64,
    range: (Vec<u8>, Vec<u8>),
}

service! {
    rpc seek(tree_id: u64, key: Vec<u8>, ordering: Ordering) -> u64 | LSMTreeSvrError;
    rpc next(tree_id: u64, id: u64) -> Option<bool> | LSMTreeSvrError;
    rpc current(tree_id: u64, id: u64) -> Option<Option<Vec<u8>>> | LSMTreeSvrError;
    rpc complete(tree_id: u64, id: u64) -> bool | LSMTreeSvrError;
    rpc new_tree(start: Vec<u8>, end: Vec<u8>) -> u64;
    rpc summary() -> Vec<LSMTreeSummary>;
}

pub struct LSMTreeService {
    neb_client: Arc<AsyncClient>,
    counter: AtomicU64,
    trees: Arc<RwLock<HashMap<u64, Arc<LSMTreeIns>>>>,
}

dispatch_rpc_service_functions!(LSMTreeService);

impl Service for LSMTreeService {
    fn seek(
        &self,
        tree_id: u64,
        key: Vec<u8>,
        ordering: Ordering,
    ) -> Box<Future<Item = u64, Error = LSMTreeSvrError>> {
        let trees = self.trees.read();
        box future::result(
            trees
                .get(&tree_id)
                .ok_or(LSMTreeSvrError::TreeNotFound)
                .map(|tree| tree.seek(SmallVec::from(key), ordering)),
        )
    }

    fn next(
        &self,
        tree_id: u64,
        id: u64,
    ) -> Box<Future<Item = Option<bool>, Error = LSMTreeSvrError>> {
        let trees = self.trees.read();
        box future::result(
            trees
                .get(&tree_id)
                .ok_or(LSMTreeSvrError::TreeNotFound)
                .map(|tree| tree.next(&id)),
        )
    }

    fn current(
        &self,
        tree_id: u64,
        id: u64,
    ) -> Box<Future<Item = Option<Option<Vec<u8>>>, Error = LSMTreeSvrError>> {
        let trees = self.trees.read();
        box future::result(
            trees
                .get(&tree_id)
                .ok_or(LSMTreeSvrError::TreeNotFound)
                .map(|tree| tree.current(&id)),
        )
    }

    fn complete(&self, tree_id: u64, id: u64) -> Box<Future<Item = bool, Error = LSMTreeSvrError>> {
        let trees = self.trees.read();
        box future::result(
            trees
                .get(&tree_id)
                .ok_or(LSMTreeSvrError::TreeNotFound)
                .map(|tree| tree.complete(&id)),
        )
    }

    fn new_tree(&self, start: Vec<u8>, end: Vec<u8>) -> Box<Future<Item = u64, Error = ()>> {
        let mut trees = self.trees.write();
        let tree_id = self.counter.fetch_add(1, atomic::Ordering::Relaxed);
        trees.insert(
            tree_id,
            Arc::new(LSMTreeIns::new(
                &self.neb_client,
                (EntryKey::from(start), EntryKey::from(end)),
            )),
        );
        box future::ok(tree_id)
    }

    fn summary(&self) -> Box<Future<Item = Vec<LSMTreeSummary>, Error = ()>> {
        let trees = self.trees.read();
        box future::ok(
            trees
                .iter()
                .map(|(id, tree)| LSMTreeSummary {
                    id: *id,
                    count: tree.count(),
                    range: tree.range(),
                })
                .sorted_by_key(|tree| tree.range.0.clone())
                .collect(),
        )
    }
}

impl LSMTreeService {
    pub fn new(neb_client: &Arc<AsyncClient>) -> Arc<Self> {
        Arc::new(Self {
            neb_client: neb_client.clone(),
            counter: AtomicU64::new(0),
            trees: Arc::new(RwLock::new(HashMap::new())),
        })
    }

    pub fn start_sentinel(&self) {
        let trees_lock = self.trees.clone();
        thread::Builder::new()
            .name("LSM-Tree Serivce Sentinel".to_string())
            .spawn(move || {
                loop {
                    let trees = trees_lock.read();
                    trees.par_iter().for_each(|(_, tree)| {
                        tree.check_and_merge();
                    });
                    thread::sleep(Duration::from_millis(50));
                }
            });
    }
}
<commit_msg>tree ref clone for sentinel<commit_after>use bifrost::rpc::*;
use client::AsyncClient;
use index::lsmtree::service::inner::LSMTreeIns;
use index::lsmtree::tree::LSMTree;
use index::{EntryKey, Ordering};
use itertools::Itertools;
use parking_lot::RwLock;
use smallvec::SmallVec;
use std::collections::HashMap;
use std::path::Component::CurDir;
use std::sync::atomic;
use std::sync::atomic::AtomicU64;
use rayon::iter::IntoParallelRefIterator;
use rayon::iter::ParallelIterator;
use std::thread;

#[derive(Serialize, Deserialize)]
enum LSMTreeSvrError {
    TreeNotFound,
}

#[derive(Serialize, Deserialize)]
struct LSMTreeSummary {
    id: u64,
    count: u64,
    range: (Vec<u8>, Vec<u8>),
}

service! {
    rpc seek(tree_id: u64, key: Vec<u8>, ordering: Ordering) -> u64 | LSMTreeSvrError;
    rpc next(tree_id: u64, id: u64) -> Option<bool> | LSMTreeSvrError;
    rpc current(tree_id: u64, id: u64) -> Option<Option<Vec<u8>>> | LSMTreeSvrError;
    rpc complete(tree_id: u64, id: u64) -> bool | LSMTreeSvrError;
    rpc new_tree(start: Vec<u8>, end: Vec<u8>) -> u64;
    rpc summary() -> Vec<LSMTreeSummary>;
}

pub struct LSMTreeService {
    neb_client: Arc<AsyncClient>,
    counter: AtomicU64,
    trees: Arc<RwLock<HashMap<u64, Arc<LSMTreeIns>>>>,
}

dispatch_rpc_service_functions!(LSMTreeService);

impl Service for LSMTreeService {
    fn seek(
        &self,
        tree_id: u64,
        key: Vec<u8>,
        ordering: Ordering,
    ) -> Box<Future<Item = u64, Error = LSMTreeSvrError>> {
        let trees = self.trees.read();
        box future::result(
            trees
                .get(&tree_id)
                .ok_or(LSMTreeSvrError::TreeNotFound)
                .map(|tree| tree.seek(SmallVec::from(key), ordering)),
        )
    }

    fn next(
        &self,
        tree_id: u64,
        id: u64,
    ) -> Box<Future<Item = Option<bool>, Error = LSMTreeSvrError>> {
        let trees = self.trees.read();
        box future::result(
            trees
                .get(&tree_id)
                .ok_or(LSMTreeSvrError::TreeNotFound)
                .map(|tree| tree.next(&id)),
        )
    }

    fn current(
        &self,
        tree_id: u64,
        id: u64,
    ) -> Box<Future<Item = Option<Option<Vec<u8>>>, Error = LSMTreeSvrError>> {
        let trees = self.trees.read();
        box future::result(
            trees
                .get(&tree_id)
                .ok_or(LSMTreeSvrError::TreeNotFound)
                .map(|tree| tree.current(&id)),
        )
    }

    fn complete(&self, tree_id: u64, id: u64) -> Box<Future<Item = bool, Error = LSMTreeSvrError>> {
        let trees = self.trees.read();
        box future::result(
            trees
                .get(&tree_id)
                .ok_or(LSMTreeSvrError::TreeNotFound)
                .map(|tree| tree.complete(&id)),
        )
    }

    fn new_tree(&self, start: Vec<u8>, end: Vec<u8>) -> Box<Future<Item = u64, Error = ()>> {
        let mut trees = self.trees.write();
        let tree_id = self.counter.fetch_add(1, atomic::Ordering::Relaxed);
        trees.insert(
            tree_id,
            Arc::new(LSMTreeIns::new(
                &self.neb_client,
                (EntryKey::from(start), EntryKey::from(end)),
            )),
        );
        box future::ok(tree_id)
    }

    fn summary(&self) -> Box<Future<Item = Vec<LSMTreeSummary>, Error = ()>> {
        let trees = self.trees.read();
        box future::ok(
            trees
                .iter()
                .map(|(id, tree)| LSMTreeSummary {
                    id: *id,
                    count: tree.count(),
                    range: tree.range(),
                })
                .sorted_by_key(|tree| tree.range.0.clone())
                .collect(),
        )
    }
}

impl LSMTreeService {
    pub fn new(neb_client: &Arc<AsyncClient>) -> Arc<Self> {
        Arc::new(Self {
            neb_client: neb_client.clone(),
            counter: AtomicU64::new(0),
            trees: Arc::new(RwLock::new(HashMap::new())),
        })
    }

    pub fn start_sentinel(&self) {
        let trees_lock = self.trees.clone();
        thread::Builder::new()
            .name("LSM-Tree Serivce Sentinel".to_string())
            .spawn(move || {
                loop {
                    let trees = trees_lock.read().values().cloned().collect_vec();
                    trees.par_iter().for_each(|tree| {
                        tree.check_and_merge();
                    });
                    thread::sleep(Duration::from_millis(50));
                }
            });
    }
}
<|endoftext|>


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

use crate::opengl;
use cgmath::{
    Decomposed, Deg, InnerSpace, Matrix4, One, PerspectiveFov, Quaternion, Rad, Rotation,
    Rotation3, Transform, Vector3, Zero,
};
use point_viewer::math::Isometry3;
use serde_derive::{Deserialize, Serialize};
use std::f64;
use time;

#[derive(Debug)]
struct RotationAngle {
    theta: Rad<f64>,
    phi: Rad<f64>,
}

impl RotationAngle {
    pub fn zero() -> Self {
        RotationAngle {
            theta: Rad::zero(),
            phi: Rad::zero(),
        }
    }
}

#[derive(Debug)]
struct CtMode {
    pub enabled: bool,
    near_plane: f32,
    far_plane: f32,
}
#[derive(Debug)]
pub struct Camera {
    pub moving_backward: bool,
    pub moving_forward: bool,
    pub moving_left: bool,
    pub moving_right: bool,
    pub moving_down: bool,
    pub moving_up: bool,
    pub turning_left: bool,
    pub turning_right: bool,
    pub turning_down: bool,
    pub turning_up: bool,
    pub width: i32,
    pub height: i32,
    ct_mode: CtMode,

    movement_speed: f64,
    theta: Rad<f64>,
    phi: Rad<f64>,
    pan: Vector3<f64>,

    // The speed we currently want to rotate at. This is multiplied with the seconds since the last
    // frame to get to an absolute rotation.
    rotation_speed: RotationAngle,

    // An absolute value that we should rotate around. This is used when the user is clicking and
    // dragging with the mouse, at which point we want to follow the mouse and ignore rotation
    // speed from the Joystick.
    delta_rotation: RotationAngle,

    moved: bool,
    transform: Decomposed<Vector3<f64>, Quaternion<f64>>,

    projection_matrix: Matrix4<f32>,
    local_from_global: Matrix4<f64>,
}

#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
pub struct State {
    transform: Decomposed<Vector3<f64>, Quaternion<f64>>,
    phi: Rad<f64>,
    theta: Rad<f64>,
}

const FAR_PLANE: f32 = 10000.;
const NEAR_PLANE: f32 = 0.1;

impl Camera {
    pub fn new(
        gl: &opengl::Gl,
        width: i32,
        height: i32,
        local_from_global: Option<Isometry3<f64>>,
    ) -> Self {
        let local_from_global = local_from_global.map_or_else(One::one, |local_from_global| {
            let decomposed: Decomposed<Vector3<f64>, Quaternion<f64>> = local_from_global.into();
            decomposed.into()
        });
        let mut camera = Camera {
            movement_speed: 10.,
            moving_backward: false,
            moving_forward: false,
            moving_left: false,
            moving_right: false,
            moving_down: false,
            moving_up: false,
            turning_left: false,
            turning_right: false,
            turning_down: false,
            turning_up: false,
            moved: true,
            theta: Rad::zero(),
            phi: Rad::zero(),
            pan: Vector3::zero(),
            rotation_speed: RotationAngle::zero(),
            delta_rotation: RotationAngle::zero(),
            transform: Decomposed {
                scale: 1.,
                rot: Quaternion::one(),
                disp: Vector3::new(0., 0., 150.),
            },
            local_from_global,

            // These will be set by set_size().
            projection_matrix: One::one(),
            width: 0,
            height: 0,
            ct_mode: CtMode {
                enabled: false,
                near_plane: 2.,
                far_plane: 5.,
            },
        };
        camera.set_size(gl, width, height);
        camera
    }

    pub fn move_ct(&mut self, delta: f32, gl: &opengl::Gl) {
        if self.ct_mode.near_plane + delta > 0. {
            self.ct_mode.near_plane += delta;
            self.ct_mode.far_plane += delta;
            self.update_viewport(gl);
        }
    }

    pub fn move_far_plane_ct(&mut self, delta: f32, gl: &opengl::Gl) {
        self.ct_mode.far_plane =
            (self.ct_mode.near_plane + 0.5).max(self.ct_mode.far_plane + delta);
        self.update_viewport(gl);
    }

    pub fn state(&self) -> State {
        State {
            transform: self.transform,
            phi: self.phi,
            theta: self.theta,
        }
    }

    pub fn set_state(&mut self, state: State) {
        self.transform = state.transform;
        self.phi = state.phi;
        self.theta = state.theta;
        self.moved = true;
    }

    pub fn set_size(&mut self, gl: &opengl::Gl, width: i32, height: i32) {
        self.width = width;
        self.height = height;
        self.update_viewport(gl);
    }

    pub fn update_viewport(&mut self, gl: &opengl::Gl) {
        let (near, far) = if self.ct_mode.enabled {
            (self.ct_mode.near_plane, self.ct_mode.far_plane)
        } else {
            (NEAR_PLANE, FAR_PLANE)
        };

        self.projection_matrix = Matrix4::from(PerspectiveFov {
            fovy: Rad::from(Deg(45.)),
            aspect: self.width as f32 / self.height as f32,
            near,
            far,
        });
        unsafe {
            gl.Viewport(0, 0, self.width, self.height);
        }
        self.moved = true;
    }

    pub fn toggle_ct_mode(&mut self, gl: &opengl::Gl) {
        self.ct_mode.enabled = !self.ct_mode.enabled;
        self.update_viewport(gl);
    }

    pub fn get_world_to_gl(&self) -> Matrix4<f64> {
        let camera_from_local: Matrix4<f64> = self.transform.inverse_transform().unwrap().into();
        self.projection_matrix.cast::<f64>().unwrap() * camera_from_local * self.local_from_global
    }

    /// Update the camera position for the current frame. Returns true if the camera moved in this
    /// step.
    pub fn update(&mut self, elapsed: time::Duration) -> bool {
        let mut moved = self.moved;
        self.moved = false;

        // Handle keyboard input
        let mut pan = Vector3::zero();
        if self.moving_right {
            pan.x += 1.;
        }
        if self.moving_left {
            pan.x -= 1.;
        }
        if self.moving_backward {
            pan.z += 1.;
        }
        if self.moving_forward {
            pan.z -= 1.;
        }
        if self.moving_up {
            pan.y += 1.;
        }
        if self.moving_down {
            pan.y -= 1.;
        }
        if pan.magnitude2() > 0. {
            self.pan += pan.normalize();
        }

        let elapsed_seconds = elapsed.num_milliseconds() as f64 / 1000.;

        const TURNING_SPEED: Rad<f64> = Rad(0.15);
        if self.turning_left {
            self.rotation_speed.theta += TURNING_SPEED;
        }
        if self.turning_right {
            self.rotation_speed.theta -= TURNING_SPEED;
        }
        if self.turning_up {
            self.rotation_speed.phi += TURNING_SPEED;
        }
        if self.turning_down {
            self.rotation_speed.phi -= TURNING_SPEED;
        }

        // Apply changes
        if self.pan.magnitude2() > 0. {
            moved = true;
            let translation = self
                .transform
                .rot
                .rotate_vector(self.pan * self.movement_speed * elapsed_seconds);
            self.transform.disp += translation;
        }

        if !self.rotation_speed.theta.is_zero()
            || !self.rotation_speed.phi.is_zero()
            || !self.delta_rotation.theta.is_zero()
            || !self.delta_rotation.phi.is_zero()
        {
            moved = true;
            if !self.delta_rotation.theta.is_zero() || !self.delta_rotation.phi.is_zero() {
                self.theta += self.delta_rotation.theta;
                self.phi += self.delta_rotation.phi;
            } else {
                self.theta += self.rotation_speed.theta * elapsed_seconds;
                self.phi += self.rotation_speed.phi * elapsed_seconds;
            }
            let rotation_z = Quaternion::from_angle_z(self.theta);
            let rotation_x = Quaternion::from_angle_x(self.phi);
            self.transform.rot = rotation_z * rotation_x;
        }

        self.pan = Vector3::zero();
        self.rotation_speed.theta = Rad::zero();
        self.rotation_speed.phi = Rad::zero();
        self.delta_rotation.theta = Rad::zero();
        self.delta_rotation.phi = Rad::zero();
        moved
    }

    pub fn mouse_drag_pan(&mut self, delta_x: i32, delta_y: i32) {
        self.pan.x -= 100. * f64::from(delta_x) / f64::from(self.width);
        self.pan.y += 100. * f64::from(delta_y) / f64::from(self.height);
    }

    pub fn mouse_drag_rotate(&mut self, delta_x: i32, delta_y: i32) {
        self.delta_rotation.theta -=
            Rad(2. * f64::consts::PI * f64::from(delta_x) / f64::from(self.width));
        self.delta_rotation.phi -=
            Rad(2. * f64::consts::PI * f64::from(delta_y) / f64::from(self.height));
    }

    pub fn mouse_wheel(&mut self, delta: i32) {
        let sign = f64::from(delta.signum());
        self.movement_speed += sign * 0.1 * self.movement_speed;
        self.movement_speed = self.movement_speed.max(0.01);
    }

    pub fn pan(&mut self, x: f64, y: f64, z: f64) {
        self.pan.x += x;
        self.pan.y += y;
        self.pan.z += z;
    }

    pub fn rotate(&mut self, up: f64, around: f64) {
        self.rotation_speed.phi += Rad(up);
        self.rotation_speed.theta += Rad(around);
    }
}
<commit_msg>Increase annoyingly low rotation speed in sdl_viewer (#343)<commit_after>// Copyright 2016 The Cartographer Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::opengl;
use cgmath::{
    Decomposed, Deg, InnerSpace, Matrix4, One, PerspectiveFov, Quaternion, Rad, Rotation,
    Rotation3, Transform, Vector3, Zero,
};
use point_viewer::math::Isometry3;
use serde_derive::{Deserialize, Serialize};
use std::f64;
use time;

#[derive(Debug)]
struct RotationAngle {
    theta: Rad<f64>,
    phi: Rad<f64>,
}

impl RotationAngle {
    pub fn zero() -> Self {
        RotationAngle {
            theta: Rad::zero(),
            phi: Rad::zero(),
        }
    }
}

#[derive(Debug)]
struct CtMode {
    pub enabled: bool,
    near_plane: f32,
    far_plane: f32,
}
#[derive(Debug)]
pub struct Camera {
    pub moving_backward: bool,
    pub moving_forward: bool,
    pub moving_left: bool,
    pub moving_right: bool,
    pub moving_down: bool,
    pub moving_up: bool,
    pub turning_left: bool,
    pub turning_right: bool,
    pub turning_down: bool,
    pub turning_up: bool,
    pub width: i32,
    pub height: i32,
    ct_mode: CtMode,

    movement_speed: f64,
    theta: Rad<f64>,
    phi: Rad<f64>,
    pan: Vector3<f64>,

    // The speed we currently want to rotate at. This is multiplied with the seconds since the last
    // frame to get to an absolute rotation.
    rotation_speed: RotationAngle,

    // An absolute value that we should rotate around. This is used when the user is clicking and
    // dragging with the mouse, at which point we want to follow the mouse and ignore rotation
    // speed from the Joystick.
    delta_rotation: RotationAngle,

    moved: bool,
    transform: Decomposed<Vector3<f64>, Quaternion<f64>>,

    projection_matrix: Matrix4<f32>,
    local_from_global: Matrix4<f64>,
}

#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
pub struct State {
    transform: Decomposed<Vector3<f64>, Quaternion<f64>>,
    phi: Rad<f64>,
    theta: Rad<f64>,
}

const FAR_PLANE: f32 = 10000.;
const NEAR_PLANE: f32 = 0.1;

impl Camera {
    pub fn new(
        gl: &opengl::Gl,
        width: i32,
        height: i32,
        local_from_global: Option<Isometry3<f64>>,
    ) -> Self {
        let local_from_global = local_from_global.map_or_else(One::one, |local_from_global| {
            let decomposed: Decomposed<Vector3<f64>, Quaternion<f64>> = local_from_global.into();
            decomposed.into()
        });
        let mut camera = Camera {
            movement_speed: 10.,
            moving_backward: false,
            moving_forward: false,
            moving_left: false,
            moving_right: false,
            moving_down: false,
            moving_up: false,
            turning_left: false,
            turning_right: false,
            turning_down: false,
            turning_up: false,
            moved: true,
            theta: Rad::zero(),
            phi: Rad::zero(),
            pan: Vector3::zero(),
            rotation_speed: RotationAngle::zero(),
            delta_rotation: RotationAngle::zero(),
            transform: Decomposed {
                scale: 1.,
                rot: Quaternion::one(),
                disp: Vector3::new(0., 0., 150.),
            },
            local_from_global,

            // These will be set by set_size().
            projection_matrix: One::one(),
            width: 0,
            height: 0,
            ct_mode: CtMode {
                enabled: false,
                near_plane: 2.,
                far_plane: 5.,
            },
        };
        camera.set_size(gl, width, height);
        camera
    }

    pub fn move_ct(&mut self, delta: f32, gl: &opengl::Gl) {
        if self.ct_mode.near_plane + delta > 0. {
            self.ct_mode.near_plane += delta;
            self.ct_mode.far_plane += delta;
            self.update_viewport(gl);
        }
    }

    pub fn move_far_plane_ct(&mut self, delta: f32, gl: &opengl::Gl) {
        self.ct_mode.far_plane =
            (self.ct_mode.near_plane + 0.5).max(self.ct_mode.far_plane + delta);
        self.update_viewport(gl);
    }

    pub fn state(&self) -> State {
        State {
            transform: self.transform,
            phi: self.phi,
            theta: self.theta,
        }
    }

    pub fn set_state(&mut self, state: State) {
        self.transform = state.transform;
        self.phi = state.phi;
        self.theta = state.theta;
        self.moved = true;
    }

    pub fn set_size(&mut self, gl: &opengl::Gl, width: i32, height: i32) {
        self.width = width;
        self.height = height;
        self.update_viewport(gl);
    }

    pub fn update_viewport(&mut self, gl: &opengl::Gl) {
        let (near, far) = if self.ct_mode.enabled {
            (self.ct_mode.near_plane, self.ct_mode.far_plane)
        } else {
            (NEAR_PLANE, FAR_PLANE)
        };

        self.projection_matrix = Matrix4::from(PerspectiveFov {
            fovy: Rad::from(Deg(45.)),
            aspect: self.width as f32 / self.height as f32,
            near,
            far,
        });
        unsafe {
            gl.Viewport(0, 0, self.width, self.height);
        }
        self.moved = true;
    }

    pub fn toggle_ct_mode(&mut self, gl: &opengl::Gl) {
        self.ct_mode.enabled = !self.ct_mode.enabled;
        self.update_viewport(gl);
    }

    pub fn get_world_to_gl(&self) -> Matrix4<f64> {
        let camera_from_local: Matrix4<f64> = self.transform.inverse_transform().unwrap().into();
        self.projection_matrix.cast::<f64>().unwrap() * camera_from_local * self.local_from_global
    }

    /// Update the camera position for the current frame. Returns true if the camera moved in this
    /// step.
    pub fn update(&mut self, elapsed: time::Duration) -> bool {
        let mut moved = self.moved;
        self.moved = false;

        // Handle keyboard input
        let mut pan = Vector3::zero();
        if self.moving_right {
            pan.x += 1.;
        }
        if self.moving_left {
            pan.x -= 1.;
        }
        if self.moving_backward {
            pan.z += 1.;
        }
        if self.moving_forward {
            pan.z -= 1.;
        }
        if self.moving_up {
            pan.y += 1.;
        }
        if self.moving_down {
            pan.y -= 1.;
        }
        if pan.magnitude2() > 0. {
            self.pan += pan.normalize();
        }

        let elapsed_seconds = elapsed.num_milliseconds() as f64 / 1000.;

        const TURNING_SPEED: Rad<f64> = Rad(0.5);
        if self.turning_left {
            self.rotation_speed.theta += TURNING_SPEED;
        }
        if self.turning_right {
            self.rotation_speed.theta -= TURNING_SPEED;
        }
        if self.turning_up {
            self.rotation_speed.phi += TURNING_SPEED;
        }
        if self.turning_down {
            self.rotation_speed.phi -= TURNING_SPEED;
        }

        // Apply changes
        if self.pan.magnitude2() > 0. {
            moved = true;
            let translation = self
                .transform
                .rot
                .rotate_vector(self.pan * self.movement_speed * elapsed_seconds);
            self.transform.disp += translation;
        }

        if !self.rotation_speed.theta.is_zero()
            || !self.rotation_speed.phi.is_zero()
            || !self.delta_rotation.theta.is_zero()
            || !self.delta_rotation.phi.is_zero()
        {
            moved = true;
            if !self.delta_rotation.theta.is_zero() || !self.delta_rotation.phi.is_zero() {
                self.theta += self.delta_rotation.theta;
                self.phi += self.delta_rotation.phi;
            } else {
                self.theta += self.rotation_speed.theta * elapsed_seconds;
                self.phi += self.rotation_speed.phi * elapsed_seconds;
            }
            let rotation_z = Quaternion::from_angle_z(self.theta);
            let rotation_x = Quaternion::from_angle_x(self.phi);
            self.transform.rot = rotation_z * rotation_x;
        }

        self.pan = Vector3::zero();
        self.rotation_speed.theta = Rad::zero();
        self.rotation_speed.phi = Rad::zero();
        self.delta_rotation.theta = Rad::zero();
        self.delta_rotation.phi = Rad::zero();
        moved
    }

    pub fn mouse_drag_pan(&mut self, delta_x: i32, delta_y: i32) {
        self.pan.x -= 100. * f64::from(delta_x) / f64::from(self.width);
        self.pan.y += 100. * f64::from(delta_y) / f64::from(self.height);
    }

    pub fn mouse_drag_rotate(&mut self, delta_x: i32, delta_y: i32) {
        self.delta_rotation.theta -=
            Rad(2. * f64::consts::PI * f64::from(delta_x) / f64::from(self.width));
        self.delta_rotation.phi -=
            Rad(2. * f64::consts::PI * f64::from(delta_y) / f64::from(self.height));
    }

    pub fn mouse_wheel(&mut self, delta: i32) {
        let sign = f64::from(delta.signum());
        self.movement_speed += sign * 0.1 * self.movement_speed;
        self.movement_speed = self.movement_speed.max(0.01);
    }

    pub fn pan(&mut self, x: f64, y: f64, z: f64) {
        self.pan.x += x;
        self.pan.y += y;
        self.pan.z += z;
    }

    pub fn rotate(&mut self, up: f64, around: f64) {
        self.rotation_speed.phi += Rad(up);
        self.rotation_speed.theta += Rad(around);
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

pub type in_addr_t = u32;
pub type in_port_t = u16;

pub type socklen_t = u32;
pub type sa_family_t = u16;

pub const AF_INET: sa_family_t = 2;
pub const AF_INET6: sa_family_t = 23;

#[derive(Copy, Clone)]
#[repr(C)]
pub struct in_addr {
    pub s_addr: in_addr_t,
}

#[derive(Copy, Clone)]
#[repr(C)]
pub struct in6_addr {
    pub s6_addr: [u8; 16],
    __align: [u32; 0],
}

#[derive(Copy, Clone)]
#[repr(C)]
pub struct sockaddr {
    pub sa_family: sa_family_t,
    pub sa_data: [u8; 14],
}

#[derive(Copy, Clone)]
#[repr(C)]
pub struct sockaddr_in {
    pub sin_family: sa_family_t,
    pub sin_port: in_port_t,
    pub sin_addr: in_addr,
    pub sin_zero: [u8; 8],
}

#[derive(Copy, Clone)]
#[repr(C)]
pub struct sockaddr_in6 {
    pub sin6_family: sa_family_t,
    pub sin6_port: in_port_t,
    pub sin6_flowinfo: u32,
    pub sin6_addr: in6_addr,
    pub sin6_scope_id: u32,
}
<commit_msg>Use repr(align(x)) for redox in6_addr<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

pub type in_addr_t = u32;
pub type in_port_t = u16;

pub type socklen_t = u32;
pub type sa_family_t = u16;

pub const AF_INET: sa_family_t = 2;
pub const AF_INET6: sa_family_t = 23;

#[derive(Copy, Clone)]
#[repr(C)]
pub struct in_addr {
    pub s_addr: in_addr_t,
}

#[derive(Copy, Clone)]
#[repr(align(4))]
#[repr(C)]
pub struct in6_addr {
    pub s6_addr: [u8; 16],
}

#[derive(Copy, Clone)]
#[repr(C)]
pub struct sockaddr {
    pub sa_family: sa_family_t,
    pub sa_data: [u8; 14],
}

#[derive(Copy, Clone)]
#[repr(C)]
pub struct sockaddr_in {
    pub sin_family: sa_family_t,
    pub sin_port: in_port_t,
    pub sin_addr: in_addr,
    pub sin_zero: [u8; 8],
}

#[derive(Copy, Clone)]
#[repr(C)]
pub struct sockaddr_in6 {
    pub sin6_family: sa_family_t,
    pub sin6_port: in_port_t,
    pub sin6_flowinfo: u32,
    pub sin6_addr: in6_addr,
    pub sin6_scope_id: u32,
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Windows-specific extensions for the primitives in `std::fs`

#![stable(feature = "rust1", since = "1.0.0")]

use fs::{self, OpenOptions, Metadata};
use io;
use path::Path;
use sys;
use sys_common::{AsInnerMut, AsInner};

/// Windows-specific extensions to `File`
#[stable(feature = "file_offset", since = "1.15.0")]
pub trait FileExt {
    /// Seeks to a given position and reads a number of bytes.
    ///
    /// Returns the number of bytes read.
    ///
    /// The offset is relative to the start of the file and thus independent
    /// from the current cursor. The current cursor **is** affected by this
    /// function, it is set to the end of the read.
    ///
    /// Reading beyond the end of the file will always return with a length of
    /// 0.
    ///
    /// Note that similar to `File::read`, it is not an error to return with a
    /// short read. When returning from such a short read, the file pointer is
    /// still updated.
    #[stable(feature = "file_offset", since = "1.15.0")]
    fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;

    /// Seeks to a given position and writes a number of bytes.
    ///
    /// Returns the number of bytes written.
    ///
    /// The offset is relative to the start of the file and thus independent
    /// from the current cursor. The current cursor **is** affected by this
    /// function, it is set to the end of the write.
    ///
    /// When writing beyond the end of the file, the file is appropiately
    /// extended and the intermediate bytes are left uninitialized.
    ///
    /// Note that similar to `File::write`, it is not an error to return a
    /// short write. When returning from such a short write, the file pointer
    /// is still updated.
    #[stable(feature = "file_offset", since = "1.15.0")]
    fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
}

#[stable(feature = "file_offset", since = "1.15.0")]
impl FileExt for fs::File {
    fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
        self.as_inner().read_at(buf, offset)
    }

    fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
        self.as_inner().write_at(buf, offset)
    }
}

/// Windows-specific extensions to `OpenOptions`
#[stable(feature = "open_options_ext", since = "1.10.0")]
pub trait OpenOptionsExt {
    /// Overrides the `dwDesiredAccess` argument to the call to `CreateFile`
    /// with the specified value.
    ///
    /// This will override the `read`, `write`, and `append` flags on the
    /// `OpenOptions` structure. This method provides fine-grained control over
    /// the permissions to read, write and append data, attributes (like hidden
    /// and system) and extended attributes.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::fs::OpenOptions;
    /// use std::os::windows::fs::OpenOptionsExt;
    ///
    /// // Open without read and write permission, for example if you only need
    /// // to call `stat()` on the file
    /// let file = OpenOptions::new().access_mode(0).open("foo.txt");
    /// ```
    #[stable(feature = "open_options_ext", since = "1.10.0")]
    fn access_mode(&mut self, access: u32) -> &mut Self;

    /// Overrides the `dwShareMode` argument to the call to `CreateFile` with
    /// the specified value.
    ///
    /// By default `share_mode` is set to
    /// `FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE`. Specifying
    /// less permissions denies others to read from, write to and/or delete the
    /// file while it is open.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::fs::OpenOptions;
    /// use std::os::windows::fs::OpenOptionsExt;
    ///
    /// // Do not allow others to read or modify this file while we have it open
    /// // for writing
    /// let file = OpenOptions::new().write(true)
    ///                              .share_mode(0)
    ///                              .open("foo.txt");
    /// ```
    #[stable(feature = "open_options_ext", since = "1.10.0")]
    fn share_mode(&mut self, val: u32) -> &mut Self;

    /// Sets extra flags for the `dwFileFlags` argument to the call to
    /// `CreateFile2` (or combines it with `attributes` and `security_qos_flags`
    /// to set the `dwFlagsAndAttributes` for `CreateFile`).
    ///
    /// Custom flags can only set flags, not remove flags set by Rusts options.
    /// This options overwrites any previously set custom flags.
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// extern crate winapi;
    /// use std::fs::OpenOptions;
    /// use std::os::windows::fs::OpenOptionsExt;
    ///
    /// let mut options = OpenOptions::new();
    /// options.create(true).write(true);
    /// if cfg!(windows) {
    ///     options.custom_flags(winapi::FILE_FLAG_DELETE_ON_CLOSE);
    /// }
    /// let file = options.open("foo.txt");
    /// ```
    #[stable(feature = "open_options_ext", since = "1.10.0")]
    fn custom_flags(&mut self, flags: u32) -> &mut Self;

    /// Sets the `dwFileAttributes` argument to the call to `CreateFile2` to
    /// the specified value (or combines it with `custom_flags` and
    /// `security_qos_flags` to set the `dwFlagsAndAttributes` for
    /// `CreateFile`).
    ///
    /// If a _new_ file is created because it does not yet exist and
    ///`.create(true)` or `.create_new(true)` are specified, the new file is
    /// given the attributes declared with `.attributes()`.
    ///
    /// If an _existing_ file is opened with `.create(true).truncate(true)`, its
    /// existing attributes are preserved and combined with the ones declared
    /// with `.attributes()`.
    ///
    /// In all other cases the attributes get ignored.
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// extern crate winapi;
    /// use std::fs::OpenOptions;
    /// use std::os::windows::fs::OpenOptionsExt;
    ///
    /// let file = OpenOptions::new().write(true).create(true)
    ///                              .attributes(winapi::FILE_ATTRIBUTE_HIDDEN)
    ///                              .open("foo.txt");
    /// ```
    #[stable(feature = "open_options_ext", since = "1.10.0")]
    fn attributes(&mut self, val: u32) -> &mut Self;

    /// Sets the `dwSecurityQosFlags` argument to the call to `CreateFile2` to
    /// the specified value (or combines it with `custom_flags` and `attributes`
    /// to set the `dwFlagsAndAttributes` for `CreateFile`).
    #[stable(feature = "open_options_ext", since = "1.10.0")]
    fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions;
}

#[stable(feature = "open_options_ext", since = "1.10.0")]
impl OpenOptionsExt for OpenOptions {
    fn access_mode(&mut self, access: u32) -> &mut OpenOptions {
        self.as_inner_mut().access_mode(access); self
    }

    fn share_mode(&mut self, share: u32) -> &mut OpenOptions {
        self.as_inner_mut().share_mode(share); self
    }

    fn custom_flags(&mut self, flags: u32) -> &mut OpenOptions {
        self.as_inner_mut().custom_flags(flags); self
    }

    fn attributes(&mut self, attributes: u32) -> &mut OpenOptions {
        self.as_inner_mut().attributes(attributes); self
    }

    fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions {
        self.as_inner_mut().security_qos_flags(flags); self
    }
}

/// Extension methods for `fs::Metadata` to access the raw fields contained
/// within.
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
    /// Returns the value of the `dwFileAttributes` field of this metadata.
    ///
    /// This field contains the file system attribute information for a file
    /// or directory.
    #[stable(feature = "metadata_ext", since = "1.1.0")]
    fn file_attributes(&self) -> u32;

    /// Returns the value of the `ftCreationTime` field of this metadata.
    ///
    /// The returned 64-bit value represents the number of 100-nanosecond
    /// intervals since January 1, 1601 (UTC).
    #[stable(feature = "metadata_ext", since = "1.1.0")]
    fn creation_time(&self) -> u64;

    /// Returns the value of the `ftLastAccessTime` field of this metadata.
    ///
    /// The returned 64-bit value represents the number of 100-nanosecond
    /// intervals since January 1, 1601 (UTC).
    #[stable(feature = "metadata_ext", since = "1.1.0")]
    fn last_access_time(&self) -> u64;

    /// Returns the value of the `ftLastWriteTime` field of this metadata.
    ///
    /// The returned 64-bit value represents the number of 100-nanosecond
    /// intervals since January 1, 1601 (UTC).
    #[stable(feature = "metadata_ext", since = "1.1.0")]
    fn last_write_time(&self) -> u64;

    /// Returns the value of the `nFileSize{High,Low}` fields of this
    /// metadata.
    ///
    /// The returned value does not have meaning for directories.
    #[stable(feature = "metadata_ext", since = "1.1.0")]
    fn file_size(&self) -> u64;
}

#[stable(feature = "metadata_ext", since = "1.1.0")]
impl MetadataExt for Metadata {
    fn file_attributes(&self) -> u32 { self.as_inner().attrs() }
    fn creation_time(&self) -> u64 { self.as_inner().created_u64() }
    fn last_access_time(&self) -> u64 { self.as_inner().accessed_u64() }
    fn last_write_time(&self) -> u64 { self.as_inner().modified_u64() }
    fn file_size(&self) -> u64 { self.as_inner().size() }
}

/// Creates a new file symbolic link on the filesystem.
///
/// The `dst` path will be a file symbolic link pointing to the `src`
/// path.
///
/// # Examples
///
/// ```ignore
/// use std::os::windows::fs;
///
/// # fn foo() -> std::io::Result<()> {
/// fs::symlink_file("a.txt", "b.txt")?;
/// # Ok(())
/// # }
/// ```
#[stable(feature = "symlink", since = "1.1.0")]
pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
                                                    -> io::Result<()> {
    sys::fs::symlink_inner(src.as_ref(), dst.as_ref(), false)
}

/// Creates a new directory symlink on the filesystem.
///
/// The `dst` path will be a directory symbolic link pointing to the `src`
/// path.
///
/// # Examples
///
/// ```ignore
/// use std::os::windows::fs;
///
/// # fn foo() -> std::io::Result<()> {
/// fs::symlink_file("a", "b")?;
/// # Ok(())
/// # }
/// ```
#[stable(feature = "symlink", since = "1.1.0")]
pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
                                                   -> io::Result<()> {
    sys::fs::symlink_inner(src.as_ref(), dst.as_ref(), true)
}
<commit_msg>Update documentation in windows::ffi<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Windows-specific extensions for the primitives in the `std::fs` module.

#![stable(feature = "rust1", since = "1.0.0")]

use fs::{self, OpenOptions, Metadata};
use io;
use path::Path;
use sys;
use sys_common::{AsInnerMut, AsInner};

/// Windows-specific extensions to `File`
#[stable(feature = "file_offset", since = "1.15.0")]
pub trait FileExt {
    /// Seeks to a given position and reads a number of bytes.
    ///
    /// Returns the number of bytes read.
    ///
    /// The offset is relative to the start of the file and thus independent
    /// from the current cursor. The current cursor **is** affected by this
    /// function, it is set to the end of the read.
    ///
    /// Reading beyond the end of the file will always return with a length of
    /// 0.
    ///
    /// Note that similar to `File::read`, it is not an error to return with a
    /// short read. When returning from such a short read, the file pointer is
    /// still updated.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io;
    /// use std::io::prelude::*;
    /// use std::fs::File;
    /// use std::os::windows::prelude::*;
    ///
    /// # fn foo() -> io::Result<()> {
    /// let mut file = File::open("foo.txt")?;
    /// let mut buffer = [0; 10];
    ///
    /// // Read 10 bytes, starting 72 bytes from the
    /// // start of the file.
    /// file.seek_read(&mut buffer[..], 72)?;
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "file_offset", since = "1.15.0")]
    fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;

    /// Seeks to a given position and writes a number of bytes.
    ///
    /// Returns the number of bytes written.
    ///
    /// The offset is relative to the start of the file and thus independent
    /// from the current cursor. The current cursor **is** affected by this
    /// function, it is set to the end of the write.
    ///
    /// When writing beyond the end of the file, the file is appropiately
    /// extended and the intermediate bytes are left uninitialized.
    ///
    /// Note that similar to `File::write`, it is not an error to return a
    /// short write. When returning from such a short write, the file pointer
    /// is still updated.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::prelude::*;
    /// use std::fs::File;
    /// use std::os::windows::prelude::*;
    ///
    /// # fn foo() -> std::io::Result<()> {
    /// let mut buffer = File::create("foo.txt")?;
    ///
    /// // Write a byte string starting 72 bytes from
    /// // the start of the file.
    /// buffer.write(b"some bytes", offset)?;
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "file_offset", since = "1.15.0")]
    fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
}

#[stable(feature = "file_offset", since = "1.15.0")]
impl FileExt for fs::File {
    fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
        self.as_inner().read_at(buf, offset)
    }

    fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
        self.as_inner().write_at(buf, offset)
    }
}

/// Windows-specific extensions to `OpenOptions`
#[stable(feature = "open_options_ext", since = "1.10.0")]
pub trait OpenOptionsExt {
    /// Overrides the `dwDesiredAccess` argument to the call to [`CreateFile`]
    /// with the specified value.
    ///
    /// This will override the `read`, `write`, and `append` flags on the
    /// `OpenOptions` structure. This method provides fine-grained control over
    /// the permissions to read, write and append data, attributes (like hidden
    /// and system), and extended attributes.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::fs::OpenOptions;
    /// use std::os::windows::fs::OpenOptionsExt;
    ///
    /// // Open without read and write permission, for example if you only need
    /// // to call `stat()` on the file
    /// let file = OpenOptions::new().access_mode(0).open("foo.txt");
    /// ```
    ///
    /// [`CreateFile`]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx
    #[stable(feature = "open_options_ext", since = "1.10.0")]
    fn access_mode(&mut self, access: u32) -> &mut Self;

    /// Overrides the `dwShareMode` argument to the call to [`CreateFile`] with
    /// the specified value.
    ///
    /// By default `share_mode` is set to
    /// `FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE`. This allows
    /// other processes to to read, write, and delete/rename the same file
    /// while it is open. Removing any of the flags will prevent other
    /// processes from performing the corresponding operation until the file
    /// handle is closed.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::fs::OpenOptions;
    /// use std::os::windows::fs::OpenOptionsExt;
    ///
    /// // Do not allow others to read or modify this file while we have it open
    /// // for writing.
    /// let file = OpenOptions::new().write(true)
    ///                              .share_mode(0)
    ///                              .open("foo.txt");
    /// ```
    ///
    /// [`CreateFile`]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx
    #[stable(feature = "open_options_ext", since = "1.10.0")]
    fn share_mode(&mut self, val: u32) -> &mut Self;

    /// Sets extra flags for the `dwFileFlags` argument to the call to
    /// [`CreateFile2`] to the specified value (or combines it with
    /// `attributes` and `security_qos_flags` to set the `dwFlagsAndAttributes`
    /// for [`CreateFile`]).
    ///
    /// Custom flags can only set flags, not remove flags set by Rust's options.
    /// This option overwrites any previously set custom flags.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// extern crate winapi;
    /// use std::fs::OpenOptions;
    /// use std::os::windows::fs::OpenOptionsExt;
    ///
    /// let mut options = OpenOptions::new();
    /// options.create(true).write(true);
    /// options.custom_flags(winapi::FILE_FLAG_DELETE_ON_CLOSE);
    /// let file = options.open("foo.txt");
    /// ```
    ///
    /// [`CreateFile`]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx
    /// [`CreateFile2`]: https://msdn.microsoft.com/en-us/library/windows/desktop/hh449422.aspx
    #[stable(feature = "open_options_ext", since = "1.10.0")]
    fn custom_flags(&mut self, flags: u32) -> &mut Self;

    /// Sets the `dwFileAttributes` argument to the call to [`CreateFile2`] to
    /// the specified value (or combines it with `custom_flags` and
    /// `security_qos_flags` to set the `dwFlagsAndAttributes` for
    /// [`CreateFile`]).
    ///
    /// If a _new_ file is created because it does not yet exist and
    ///`.create(true)` or `.create_new(true)` are specified, the new file is
    /// given the attributes declared with `.attributes()`.
    ///
    /// If an _existing_ file is opened with `.create(true).truncate(true)`, its
    /// existing attributes are preserved and combined with the ones declared
    /// with `.attributes()`.
    ///
    /// In all other cases the attributes get ignored.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// extern crate winapi;
    /// use std::fs::OpenOptions;
    /// use std::os::windows::fs::OpenOptionsExt;
    ///
    /// let file = OpenOptions::new().write(true).create(true)
    ///                              .attributes(winapi::FILE_ATTRIBUTE_HIDDEN)
    ///                              .open("foo.txt");
    /// ```
    ///
    /// [`CreateFile`]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx
    /// [`CreateFile2`]: https://msdn.microsoft.com/en-us/library/windows/desktop/hh449422.aspx
    #[stable(feature = "open_options_ext", since = "1.10.0")]
    fn attributes(&mut self, val: u32) -> &mut Self;

    /// Sets the `dwSecurityQosFlags` argument to the call to [`CreateFile2`] to
    /// the specified value (or combines it with `custom_flags` and `attributes`
    /// to set the `dwFlagsAndAttributes` for [`CreateFile`]).
    ///
    /// By default, `security_qos_flags` is set to `SECURITY_ANONYMOUS`. For
    /// information about possible values, see [Impersonation Levels] on the
    /// Windows Dev Center site.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use std::fs::OpenOptions;
    /// use std::os::windows::fs::OpenOptionsExt;
    ///
    /// let options = OpenOptions::new();
    /// options.write(true).create(true);
    ///
    /// // Sets the flag value to `SecurityIdentification`.
    /// options.security_qos_flags(1);
    ///
    /// let file = options.open("foo.txt");
    /// ```
    ///
    /// [`CreateFile`]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx
    /// [`CreateFile2`]: https://msdn.microsoft.com/en-us/library/windows/desktop/hh449422.aspx
    /// [Impersonation Levels]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa379572.aspx
    #[stable(feature = "open_options_ext", since = "1.10.0")]
    fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions;
}

#[stable(feature = "open_options_ext", since = "1.10.0")]
impl OpenOptionsExt for OpenOptions {
    fn access_mode(&mut self, access: u32) -> &mut OpenOptions {
        self.as_inner_mut().access_mode(access); self
    }

    fn share_mode(&mut self, share: u32) -> &mut OpenOptions {
        self.as_inner_mut().share_mode(share); self
    }

    fn custom_flags(&mut self, flags: u32) -> &mut OpenOptions {
        self.as_inner_mut().custom_flags(flags); self
    }

    fn attributes(&mut self, attributes: u32) -> &mut OpenOptions {
        self.as_inner_mut().attributes(attributes); self
    }

    fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions {
        self.as_inner_mut().security_qos_flags(flags); self
    }
}

/// Extension methods for `fs::Metadata` to access the raw fields contained
/// within.
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
    /// Returns the value of the `dwFileAttributes` field of this metadata.
    ///
    /// This field contains the file system attribute information for a file
    /// or directory.
    #[stable(feature = "metadata_ext", since = "1.1.0")]
    fn file_attributes(&self) -> u32;

    /// Returns the value of the `ftCreationTime` field of this metadata.
    ///
    /// The returned 64-bit value represents the number of 100-nanosecond
    /// intervals since January 1, 1601 (UTC).
    #[stable(feature = "metadata_ext", since = "1.1.0")]
    fn creation_time(&self) -> u64;

    /// Returns the value of the `ftLastAccessTime` field of this metadata.
    ///
    /// The returned 64-bit value represents the number of 100-nanosecond
    /// intervals since January 1, 1601 (UTC).
    #[stable(feature = "metadata_ext", since = "1.1.0")]
    fn last_access_time(&self) -> u64;

    /// Returns the value of the `ftLastWriteTime` field of this metadata.
    ///
    /// The returned 64-bit value represents the number of 100-nanosecond
    /// intervals since January 1, 1601 (UTC).
    #[stable(feature = "metadata_ext", since = "1.1.0")]
    fn last_write_time(&self) -> u64;

    /// Returns the value of the `nFileSize{High,Low}` fields of this
    /// metadata.
    ///
    /// The returned value does not have meaning for directories.
    #[stable(feature = "metadata_ext", since = "1.1.0")]
    fn file_size(&self) -> u64;
}

#[stable(feature = "metadata_ext", since = "1.1.0")]
impl MetadataExt for Metadata {
    fn file_attributes(&self) -> u32 { self.as_inner().attrs() }
    fn creation_time(&self) -> u64 { self.as_inner().created_u64() }
    fn last_access_time(&self) -> u64 { self.as_inner().accessed_u64() }
    fn last_write_time(&self) -> u64 { self.as_inner().modified_u64() }
    fn file_size(&self) -> u64 { self.as_inner().size() }
}

/// Creates a new file symbolic link on the filesystem.
///
/// The `dst` path will be a file symbolic link pointing to the `src`
/// path.
///
/// # Examples
///
/// ```ignore
/// use std::os::windows::fs;
///
/// # fn foo() -> std::io::Result<()> {
/// fs::symlink_file("a.txt", "b.txt")?;
/// # Ok(())
/// # }
/// ```
#[stable(feature = "symlink", since = "1.1.0")]
pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
                                                    -> io::Result<()> {
    sys::fs::symlink_inner(src.as_ref(), dst.as_ref(), false)
}

/// Creates a new directory symlink on the filesystem.
///
/// The `dst` path will be a directory symbolic link pointing to the `src`
/// path.
///
/// # Examples
///
/// ```ignore
/// use std::os::windows::fs;
///
/// # fn foo() -> std::io::Result<()> {
/// fs::symlink_file("a", "b")?;
/// # Ok(())
/// # }
/// ```
#[stable(feature = "symlink", since = "1.1.0")]
pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
                                                   -> io::Result<()> {
    sys::fs::symlink_inner(src.as_ref(), dst.as_ref(), true)
}
<|endoftext|>


<commit_before>use std::{
    collections::HashSet,
    fmt,
};
use crate::client::Context;
use crate::model::{
    channel::Message,
    permissions::Permissions,
    id::UserId,
};
use crate::utils::Colour;
use super::Args;

mod check;
pub mod buckets;

pub use self::check::*;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OnlyIn {
    Dm,
    Guild,
    None,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl Default for OnlyIn {
    fn default() -> Self { Self::None }
}

#[derive(Debug, Default, PartialEq)]
pub struct CommandOptions {
    /// A set of checks to be called prior to executing the command. The checks
    /// will short-circuit on the first check that returns `false`.
    pub checks: &'static [&'static Check],
    /// Ratelimit bucket.
    pub bucket: Option<&'static str>,
    /// Names that the command can be referred to.
    pub names: &'static [&'static str],
    /// Command description, used by other commands.
    pub desc: Option<&'static str>,
    /// Delimiters used to split the arguments of the command by.
    /// If empty, the [global delimiters](struct.Configuration.html#method.delimiters) are used.
    pub delimiters: &'static [&'static str],
    /// Command usage schema, used by other commands.
    pub usage: Option<&'static str>,
    /// Example arguments, used by other commands.
    pub examples: &'static [&'static str],
    /// Minimum amount of arguments that should be passed.
    pub min_args: Option<u16>,
    /// Maximum amount of arguments that can be passed.
    pub max_args: Option<u16>,
    /// Roles allowed to use this command.
    pub allowed_roles: &'static [&'static str],
    /// Permissions required to use this command.
    pub required_permissions: Permissions,
    /// Whether the command should be displayed in help list or not, used by other commands.
    pub help_available: bool,
    /// Whether the command can only be used in dms or guilds; or both.
    pub only_in: OnlyIn,
    /// Whether the command can only be used by owners or not.
    pub owners_only: bool,
    /// Whether the command treats owners as normal users.
    pub owner_privilege: bool,
    /// Other commands belonging to this command.
    pub sub_commands: &'static [&'static Command],
}

#[derive(Debug, Default, PartialEq)]
pub struct GroupOptions {
    pub prefixes: &'static [&'static str],
    pub only_in: OnlyIn,
    pub owners_only: bool,
    pub owner_privilege: bool,
    pub help_available: bool,
    pub allowed_roles: &'static [&'static str],
    pub required_permissions: Permissions,
    pub checks: &'static [&'static Check],
    pub default_command: Option<&'static Command>,
    pub description: Option<&'static str>,
}

#[derive(Debug, Clone)]
pub struct CommandError(pub String);

impl<T: fmt::Display> From<T> for CommandError {
    #[inline]
    fn from(d: T) -> Self {
        CommandError(d.to_string())
    }
}

pub type CommandResult = ::std::result::Result<(), CommandError>;

pub type CommandFn = fn(&mut Context, &Message, Args) -> CommandResult;

pub struct Command {
    pub fun: CommandFn,
    pub options: &'static CommandOptions,
}

impl fmt::Debug for Command {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Command")
            .field("options", &self.options)
            .finish()
    }
}

impl PartialEq for Command {
    #[inline]
    fn eq(&self, other: &Command) -> bool {
        (self.fun as usize == other.fun as usize) && (self.options == other.options)
    }
}

pub type HelpCommandFn = fn(
    &mut Context,
    &Message,
    Args,
    &'static HelpOptions,
    &[&'static CommandGroup],
    HashSet<UserId>,
) -> CommandResult;

pub struct HelpCommand {
    pub fun: HelpCommandFn,
    pub options: &'static HelpOptions,
}

impl fmt::Debug for HelpCommand {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("HelpCommand")
            .field("fun", &"<function>")
            .field("options", &self.options)
            .finish()
    }
}

impl PartialEq for HelpCommand {
    #[inline]
    fn eq(&self, other: &HelpCommand) -> bool {
        (self.fun as usize == other.fun as usize) && (self.options == other.options)
    }
}

/// Describes the behaviour the help-command shall execute once it encounters
/// a command which the user or command fails to meet following criteria :
/// Lacking required permissions to execute the command.
/// Lacking required roles to execute the command.
/// The command can't be used in the current channel (as in `DM only` or `guild only`).
#[derive(Copy, Clone, Debug, PartialOrd, Ord, Eq, PartialEq)]
pub enum HelpBehaviour {
    /// The command will be displayed, hence nothing will be done.
    Nothing,
    /// Strikes a command by applying `~~{command_name}~~`.
    Strike,
    /// Does not list a command in the help-menu.
    Hide,
    #[doc(hidden)]
    __Nonexhaustive,
}

#[derive(Clone, Debug, PartialEq)]
pub struct HelpOptions {
    /// Which names should the help command use for dispatching.
    /// Defaults to `["help"]`
    pub names: &'static [&'static str],
    /// Suggests a command's name.
    pub suggestion_text: &'static str,
    /// If no help is available, this text will be displayed.
    pub no_help_available_text: &'static str,
    /// How to use a command, `{usage_label}: {command_name} {args}`
    pub usage_label: &'static str,
    /// Actual sample label, `{usage_sample_label}: {command_name} {args}`
    pub usage_sample_label: &'static str,
    /// Text labeling ungrouped commands, `{ungrouped_label}: ...`
    pub ungrouped_label: &'static str,
    /// Text labeling the start of the description.
    pub description_label: &'static str,
    /// Text labeling grouped commands, `{grouped_label} {group_name}: ...`
    pub grouped_label: &'static str,
    /// Text labeling a command's alternative names (aliases).
    pub aliases_label: &'static str,
    /// Text specifying that a command is only usable in a guild.
    pub guild_only_text: &'static str,
    /// Text labeling a command's names of checks.
    pub checks_label: &'static str,
    /// Text specifying that a command is only usable in via DM.
    pub dm_only_text: &'static str,
    /// Text specifying that a command can be used via DM and in guilds.
    pub dm_and_guild_text: &'static str,
    /// Text expressing that a command is available.
    pub available_text: &'static str,
    /// Error-message once a command could not be found.
    /// Output-example (without whitespace between both substitutions: `{command_not_found_text}{command_name}`
    /// `{command_name}` describes user's input as in: `{prefix}help {command_name}`.
    pub command_not_found_text: &'static str,
    /// Explains the user on how to use access a single command's details.
    pub individual_command_tip: &'static str,
    /// Explains reasoning behind strikethrough-commands, see fields requiring `HelpBehaviour` for further information.
    /// If `HelpBehaviour::Strike` is unused, this field will evaluate to `None` during creation
    /// inside of the help macro.
    ///
    /// **Note**: Text is only used in direct messages.
    pub strikethrough_commands_tip_in_dm: Option<&'static str>,
    /// Explains reasoning behind strikethrough-commands, see fields requiring `HelpBehaviour` for further information.
    /// If `HelpBehaviour::Strike` is unused, this field will evaluate to `None` during creation
    /// inside of the help macro.
    ///
    /// **Note**: Text is only used in guilds.
    pub strikethrough_commands_tip_in_guild: Option<&'static str>,
    /// Announcing a group's prefix as in: {group_prefix} {prefix}.
    pub group_prefix: &'static str,
    /// If a user lacks required roles, this will treat how these commands will be displayed.
    pub lacking_role: HelpBehaviour,
    /// If a user lacks permissions, this will treat how these commands will be displayed.
    pub lacking_permissions: HelpBehaviour,
    /// If a user lacks ownership, this will treat how these commands will be displayed.
    pub lacking_ownership: HelpBehaviour,
    /// If conditions (of a check) may be lacking by the user, this will treat how these commands will be displayed.
    pub lacking_conditions: HelpBehaviour,
    /// If a user is using the help-command in a channel where a command is not available,
    /// this behaviour will be executed.
    pub wrong_channel: HelpBehaviour,
    /// Colour help-embed will use upon encountering an error.
    pub embed_error_colour: Colour,
    /// Colour help-embed will use if no error occurred.
    pub embed_success_colour: Colour,
    /// If not 0, help will check whether a command is similar to searched named.
    pub max_levenshtein_distance: usize,
    /// Help will use this as prefix to express how deeply nested a command or
    /// group is.
    pub indention_prefix: &'static str,
}

#[derive(Debug, PartialEq)]
pub struct CommandGroup {
    pub name: &'static str,
    pub options: &'static GroupOptions,
}

#[cfg(test)]
#[cfg(all(feature = "cache", feature = "http"))]
mod levenshtein_tests {
    use super::HelpBehaviour;

    #[test]
    fn help_behaviour_eq() {
        assert_eq!(HelpBehaviour::Hide, std::cmp::max(HelpBehaviour::Hide, HelpBehaviour::Hide));
        assert_eq!(HelpBehaviour::Strike, std::cmp::max(HelpBehaviour::Strike, HelpBehaviour::Strike));
        assert_eq!(HelpBehaviour::Nothing, std::cmp::max(HelpBehaviour::Nothing, HelpBehaviour::Nothing));
    }

    #[test]
    fn help_behaviour_hide() {
        assert_eq!(HelpBehaviour::Hide, std::cmp::max(HelpBehaviour::Hide, HelpBehaviour::Nothing));
        assert_eq!(HelpBehaviour::Hide, std::cmp::max(HelpBehaviour::Hide, HelpBehaviour::Strike));
    }

    #[test]
    fn help_behaviour_strike() {
        assert_eq!(HelpBehaviour::Strike, std::cmp::max(HelpBehaviour::Strike, HelpBehaviour::Nothing));
        assert_eq!(HelpBehaviour::Hide, std::cmp::max(HelpBehaviour::Strike, HelpBehaviour::Hide));
    }

    #[test]
    fn help_behaviour_nothing() {
        assert_eq!(HelpBehaviour::Strike, std::cmp::max(HelpBehaviour::Nothing, HelpBehaviour::Strike));
        assert_eq!(HelpBehaviour::Hide, std::cmp::max(HelpBehaviour::Nothing, HelpBehaviour::Hide));
    }
}
<commit_msg>Fix regression of the `CommandGroup` struct (#751)<commit_after>use std::{
    collections::HashSet,
    fmt,
};
use crate::client::Context;
use crate::model::{
    channel::Message,
    permissions::Permissions,
    id::UserId,
};
use crate::utils::Colour;
use super::Args;

mod check;
pub mod buckets;

pub use self::check::*;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OnlyIn {
    Dm,
    Guild,
    None,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl Default for OnlyIn {
    fn default() -> Self { Self::None }
}

#[derive(Debug, Default, PartialEq)]
pub struct CommandOptions {
    /// A set of checks to be called prior to executing the command. The checks
    /// will short-circuit on the first check that returns `false`.
    pub checks: &'static [&'static Check],
    /// Ratelimit bucket.
    pub bucket: Option<&'static str>,
    /// Names that the command can be referred to.
    pub names: &'static [&'static str],
    /// Command description, used by other commands.
    pub desc: Option<&'static str>,
    /// Delimiters used to split the arguments of the command by.
    /// If empty, the [global delimiters](struct.Configuration.html#method.delimiters) are used.
    pub delimiters: &'static [&'static str],
    /// Command usage schema, used by other commands.
    pub usage: Option<&'static str>,
    /// Example arguments, used by other commands.
    pub examples: &'static [&'static str],
    /// Minimum amount of arguments that should be passed.
    pub min_args: Option<u16>,
    /// Maximum amount of arguments that can be passed.
    pub max_args: Option<u16>,
    /// Roles allowed to use this command.
    pub allowed_roles: &'static [&'static str],
    /// Permissions required to use this command.
    pub required_permissions: Permissions,
    /// Whether the command should be displayed in help list or not, used by other commands.
    pub help_available: bool,
    /// Whether the command can only be used in dms or guilds; or both.
    pub only_in: OnlyIn,
    /// Whether the command can only be used by owners or not.
    pub owners_only: bool,
    /// Whether the command treats owners as normal users.
    pub owner_privilege: bool,
    /// Other commands belonging to this command.
    pub sub_commands: &'static [&'static Command],
}

#[derive(Debug, Clone)]
pub struct CommandError(pub String);

impl<T: fmt::Display> From<T> for CommandError {
    #[inline]
    fn from(d: T) -> Self {
        CommandError(d.to_string())
    }
}

pub type CommandResult = ::std::result::Result<(), CommandError>;

pub type CommandFn = fn(&mut Context, &Message, Args) -> CommandResult;

pub struct Command {
    pub fun: CommandFn,
    pub options: &'static CommandOptions,
}

impl fmt::Debug for Command {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Command")
            .field("options", &self.options)
            .finish()
    }
}

impl PartialEq for Command {
    #[inline]
    fn eq(&self, other: &Command) -> bool {
        (self.fun as usize == other.fun as usize) && (self.options == other.options)
    }
}

pub type HelpCommandFn = fn(
    &mut Context,
    &Message,
    Args,
    &'static HelpOptions,
    &[&'static CommandGroup],
    HashSet<UserId>,
) -> CommandResult;

pub struct HelpCommand {
    pub fun: HelpCommandFn,
    pub options: &'static HelpOptions,
}

impl fmt::Debug for HelpCommand {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("HelpCommand")
            .field("fun", &"<function>")
            .field("options", &self.options)
            .finish()
    }
}

impl PartialEq for HelpCommand {
    #[inline]
    fn eq(&self, other: &HelpCommand) -> bool {
        (self.fun as usize == other.fun as usize) && (self.options == other.options)
    }
}

/// Describes the behaviour the help-command shall execute once it encounters
/// a command which the user or command fails to meet following criteria :
/// Lacking required permissions to execute the command.
/// Lacking required roles to execute the command.
/// The command can't be used in the current channel (as in `DM only` or `guild only`).
#[derive(Copy, Clone, Debug, PartialOrd, Ord, Eq, PartialEq)]
pub enum HelpBehaviour {
    /// The command will be displayed, hence nothing will be done.
    Nothing,
    /// Strikes a command by applying `~~{command_name}~~`.
    Strike,
    /// Does not list a command in the help-menu.
    Hide,
    #[doc(hidden)]
    __Nonexhaustive,
}

#[derive(Clone, Debug, PartialEq)]
pub struct HelpOptions {
    /// Which names should the help command use for dispatching.
    /// Defaults to `["help"]`
    pub names: &'static [&'static str],
    /// Suggests a command's name.
    pub suggestion_text: &'static str,
    /// If no help is available, this text will be displayed.
    pub no_help_available_text: &'static str,
    /// How to use a command, `{usage_label}: {command_name} {args}`
    pub usage_label: &'static str,
    /// Actual sample label, `{usage_sample_label}: {command_name} {args}`
    pub usage_sample_label: &'static str,
    /// Text labeling ungrouped commands, `{ungrouped_label}: ...`
    pub ungrouped_label: &'static str,
    /// Text labeling the start of the description.
    pub description_label: &'static str,
    /// Text labeling grouped commands, `{grouped_label} {group_name}: ...`
    pub grouped_label: &'static str,
    /// Text labeling a command's alternative names (aliases).
    pub aliases_label: &'static str,
    /// Text specifying that a command is only usable in a guild.
    pub guild_only_text: &'static str,
    /// Text labeling a command's names of checks.
    pub checks_label: &'static str,
    /// Text specifying that a command is only usable in via DM.
    pub dm_only_text: &'static str,
    /// Text specifying that a command can be used via DM and in guilds.
    pub dm_and_guild_text: &'static str,
    /// Text expressing that a command is available.
    pub available_text: &'static str,
    /// Error-message once a command could not be found.
    /// Output-example (without whitespace between both substitutions: `{command_not_found_text}{command_name}`
    /// `{command_name}` describes user's input as in: `{prefix}help {command_name}`.
    pub command_not_found_text: &'static str,
    /// Explains the user on how to use access a single command's details.
    pub individual_command_tip: &'static str,
    /// Explains reasoning behind strikethrough-commands, see fields requiring `HelpBehaviour` for further information.
    /// If `HelpBehaviour::Strike` is unused, this field will evaluate to `None` during creation
    /// inside of the help macro.
    ///
    /// **Note**: Text is only used in direct messages.
    pub strikethrough_commands_tip_in_dm: Option<&'static str>,
    /// Explains reasoning behind strikethrough-commands, see fields requiring `HelpBehaviour` for further information.
    /// If `HelpBehaviour::Strike` is unused, this field will evaluate to `None` during creation
    /// inside of the help macro.
    ///
    /// **Note**: Text is only used in guilds.
    pub strikethrough_commands_tip_in_guild: Option<&'static str>,
    /// Announcing a group's prefix as in: {group_prefix} {prefix}.
    pub group_prefix: &'static str,
    /// If a user lacks required roles, this will treat how these commands will be displayed.
    pub lacking_role: HelpBehaviour,
    /// If a user lacks permissions, this will treat how these commands will be displayed.
    pub lacking_permissions: HelpBehaviour,
    /// If a user lacks ownership, this will treat how these commands will be displayed.
    pub lacking_ownership: HelpBehaviour,
    /// If conditions (of a check) may be lacking by the user, this will treat how these commands will be displayed.
    pub lacking_conditions: HelpBehaviour,
    /// If a user is using the help-command in a channel where a command is not available,
    /// this behaviour will be executed.
    pub wrong_channel: HelpBehaviour,
    /// Colour help-embed will use upon encountering an error.
    pub embed_error_colour: Colour,
    /// Colour help-embed will use if no error occurred.
    pub embed_success_colour: Colour,
    /// If not 0, help will check whether a command is similar to searched named.
    pub max_levenshtein_distance: usize,
    /// Help will use this as prefix to express how deeply nested a command or
    /// group is.
    pub indention_prefix: &'static str,
}

#[derive(Debug, Default, PartialEq)]
pub struct GroupOptions {
    pub prefixes: &'static [&'static str],
    pub only_in: OnlyIn,
    pub owners_only: bool,
    pub owner_privilege: bool,
    pub help_available: bool,
    pub allowed_roles: &'static [&'static str],
    pub required_permissions: Permissions,
    pub checks: &'static [&'static Check],
    pub default_command: Option<&'static Command>,
    pub description: Option<&'static str>,
    pub commands: &'static [&'static Command],
    pub sub_groups: &'static [&'static CommandGroup],
}

#[derive(Debug, PartialEq)]
pub struct CommandGroup {
    pub name: &'static str,
    pub options: &'static GroupOptions,
}

#[cfg(test)]
#[cfg(all(feature = "cache", feature = "http"))]
mod levenshtein_tests {
    use super::HelpBehaviour;

    #[test]
    fn help_behaviour_eq() {
        assert_eq!(HelpBehaviour::Hide, std::cmp::max(HelpBehaviour::Hide, HelpBehaviour::Hide));
        assert_eq!(HelpBehaviour::Strike, std::cmp::max(HelpBehaviour::Strike, HelpBehaviour::Strike));
        assert_eq!(HelpBehaviour::Nothing, std::cmp::max(HelpBehaviour::Nothing, HelpBehaviour::Nothing));
    }

    #[test]
    fn help_behaviour_hide() {
        assert_eq!(HelpBehaviour::Hide, std::cmp::max(HelpBehaviour::Hide, HelpBehaviour::Nothing));
        assert_eq!(HelpBehaviour::Hide, std::cmp::max(HelpBehaviour::Hide, HelpBehaviour::Strike));
    }

    #[test]
    fn help_behaviour_strike() {
        assert_eq!(HelpBehaviour::Strike, std::cmp::max(HelpBehaviour::Strike, HelpBehaviour::Nothing));
        assert_eq!(HelpBehaviour::Hide, std::cmp::max(HelpBehaviour::Strike, HelpBehaviour::Hide));
    }

    #[test]
    fn help_behaviour_nothing() {
        assert_eq!(HelpBehaviour::Strike, std::cmp::max(HelpBehaviour::Nothing, HelpBehaviour::Strike));
        assert_eq!(HelpBehaviour::Hide, std::cmp::max(HelpBehaviour::Nothing, HelpBehaviour::Hide));
    }
}
<|endoftext|>


<commit_before>extern crate smoke;

use smoke::async::Task;

fn hello() -> Task<&'static str> {
  Task::delay(100).map(|_| "hello")
}

fn main() {
  println!("{:?}", hello().wait());
}
<commit_msg>workbench checkin<commit_after>extern crate smoke;

use smoke::async::Task;
use smoke::async::Stream;
use std::thread;
use std::net::{TcpListener, TcpStream};

/// simple tcp server.
fn server(local: &'static str) -> Stream<TcpStream> {
  Stream::new(move |sender| {
    let listener = TcpListener::bind(local).unwrap();
    for stream in listener.incoming() {
        try!(sender.send(stream.unwrap()))
    } Ok(())
  })
}

/// simple tcp client stream.
fn client(remote: &'static str) -> Task<TcpStream> {
  Task::new(move |sender| {
    let stream = TcpStream::connect(remote).unwrap();
    sender.send(stream)
  })
}

fn main() {

  // server handler....
  thread::spawn(|| {
    for stream in server("localhost:5000").read(0) {
        println!("server: new stream");
    }
  });

  // clients..
  let tasks = (0..50).map(|n| client("localhost:5000")).collect::<Vec<_>>();
  Task::all(4, tasks).async(|streams| {
     println!("clients connected: {:?}", streams);
  }).wait();

  thread::sleep_ms(100);

}<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::process::exit;
use std::sync::mpsc::Sender;

use datatype::{AccessToken, Command, Config, Error, Event, UpdateReport,
               UpdateRequestId, UpdateState, UpdateResultCode};
use datatype::Command::*;
use package_manager::PackageManager;
use http_client::HttpClient2;
use interaction_library::interpreter::Interpreter;
use new_auth_plus::authenticate;
use new_ota_plus::{get_package_updates, download_package_update,
                   post_packages, send_install_report};

#[allow(dead_code)]
pub struct Env<'a> {
    config:       &'a Config,
    access_token: Option<Cow<'a, AccessToken>>,

    // XXX: remove, already in config.
    pkg_manager:  &'a PackageManager,
    http_client:  &'a HttpClient2,
}

// This macro partially applies the config and http client to the passed
// in functions.
macro_rules! partial_apply {
    ([ $( $fun0: ident ),* ], [ $( $fun1: ident ),* ], [ $( $fun2: ident ),* ],  $env: expr, $token: expr) => {
        $(let $fun0 = ||           $fun0($env.config, $env.http_client, $token);)*;
        $(let $fun1 = |arg|        $fun1($env.config, $env.http_client, $token, &arg);)*;
        $(let $fun2 = |arg1, arg2| $fun2($env.config, $env.http_client, $token, &arg1, &arg2);)*;
    }
}

// XXX: Move this somewhere else?
fn install_package_update(config:      &Config,
                          http_client: &HttpClient2,
                          token:       &AccessToken,
                          id:          &UpdateRequestId,
                          tx:          &Sender<Event>) -> Result<UpdateReport, Error> {

    match download_package_update(config, http_client, token, id) {

        Ok(path) => {
            info!("Downloaded at {:?}. Installing...", path);
            try!(tx.send(Event::UpdateStateChanged(id.clone(), UpdateState::Installing)));

            let p = try!(path.to_str()
                         .ok_or(Error::ParseError(format!("Path is not valid UTF-8: {:?}", path))));

            match config.ota.package_manager.install_package(p) {

                Ok((code, output)) => {
                    try!(tx.send(Event::UpdateStateChanged(id.clone(), UpdateState::Installed)));
                    Ok(UpdateReport::new(id.clone(), code, output))
                }

                Err((code, output)) => {
                    try!(tx.send(Event::UpdateErrored(id.clone(), format!("{:?}: {:?}", code, output))));
                    Ok(UpdateReport::new(id.clone(), code, output))
                }

            }

        }

        Err(err) => {
            try!(tx.send(Event::UpdateErrored(id.clone(), format!("{:?}", err))));
            Ok(UpdateReport::new(id.clone(),
                              UpdateResultCode::GENERAL_ERROR,
                              format!("Download failed: {:?}", err)))
        }
    }

}

fn interpreter(env: &mut Env, cmd: Command, tx: &Sender<Event>) -> Result<(), Error> {

    Ok(if let Some(token) = env.access_token.to_owned() {

        partial_apply!(
            [get_package_updates],
            [post_packages, send_install_report],
            [install_package_update], &env, &token);

        match cmd {

            Authenticate(_)       => (), // Already authenticated.

            AcceptUpdate(ref id)  => {
                try!(tx.send(Event::UpdateStateChanged(id.clone(), UpdateState::Downloading)));
                let report = try!(install_package_update(id.to_owned(), tx.to_owned()));
                try!(send_install_report(report.clone()));
                info!("Update finished. Report sent: {:?}", report)
            }

            GetPendingUpdates     => {
                let updates = try!(get_package_updates());
                let update_events: Vec<Event> = updates
                    .iter()
                    .map(|id| Event::NewUpdateAvailable(id.clone()))
                    .collect();
                info!("New package updates available: {:?}", update_events);
                try!(tx.send(Event::Batch(update_events)))
            }

            ListInstalledPackages => {
                let pkgs = try!(env.config.ota.package_manager.installed_packages());
                try!(tx.send(Event::FoundInstalledPackages(pkgs.clone())))
            }

            PostInstalledPackages => {
                let pkgs = try!(env.config.ota.package_manager.installed_packages());
                debug!("Found installed packages in the system: {:?}", pkgs);
                try!(post_packages(pkgs));
                info!("Posted installed packages to the server.")
            }

            Shutdown              => exit(0)
        }

    } else {

        match cmd {

            Authenticate(_)               => {
                let token = try!(authenticate(&env.config.auth, env.http_client));
                env.access_token = Some(token.into())
            }

            Shutdown                      => exit(0),

            AcceptUpdate(_)       |
            GetPendingUpdates     |
            ListInstalledPackages |
            PostInstalledPackages         =>
                tx.send(Event::NotAuthenticated)
                  .unwrap_or(error!("not_auth: send failed."))
            }

    })

}

pub struct OurInterpreter;

impl<'a> Interpreter<Env<'a>, Command, Event> for OurInterpreter {

    fn interpret(env: &mut Env, cmd: Command, tx: Sender<Event>) {
        interpreter(env, cmd, &tx)
            .unwrap_or_else(|err| tx.send(Event::Error(format!("{}", err)))
                            .unwrap_or(error!("interpret: send failed.")))
    }

}
<commit_msg>Remove package manager from env (it's already in config).<commit_after>use std::borrow::Cow;
use std::process::exit;
use std::sync::mpsc::Sender;

use datatype::{AccessToken, Command, Config, Error, Event, UpdateReport,
               UpdateRequestId, UpdateState, UpdateResultCode};
use datatype::Command::*;
use http_client::HttpClient2;
use interaction_library::interpreter::Interpreter;
use new_auth_plus::authenticate;
use new_ota_plus::{get_package_updates, download_package_update,
                   post_packages, send_install_report};

#[allow(dead_code)]
pub struct Env<'a> {
    config:       &'a Config,
    access_token: Option<Cow<'a, AccessToken>>,
    http_client:  &'a HttpClient2,
}

// This macro partially applies the config and http client to the passed
// in functions.
macro_rules! partial_apply {
    ([ $( $fun0: ident ),* ], [ $( $fun1: ident ),* ], [ $( $fun2: ident ),* ],  $env: expr, $token: expr) => {
        $(let $fun0 = ||           $fun0($env.config, $env.http_client, $token);)*;
        $(let $fun1 = |arg|        $fun1($env.config, $env.http_client, $token, &arg);)*;
        $(let $fun2 = |arg1, arg2| $fun2($env.config, $env.http_client, $token, &arg1, &arg2);)*;
    }
}

// XXX: Move this somewhere else?
fn install_package_update(config:      &Config,
                          http_client: &HttpClient2,
                          token:       &AccessToken,
                          id:          &UpdateRequestId,
                          tx:          &Sender<Event>) -> Result<UpdateReport, Error> {

    match download_package_update(config, http_client, token, id) {

        Ok(path) => {
            info!("Downloaded at {:?}. Installing...", path);
            try!(tx.send(Event::UpdateStateChanged(id.clone(), UpdateState::Installing)));

            let p = try!(path.to_str()
                         .ok_or(Error::ParseError(format!("Path is not valid UTF-8: {:?}", path))));

            match config.ota.package_manager.install_package(p) {

                Ok((code, output)) => {
                    try!(tx.send(Event::UpdateStateChanged(id.clone(), UpdateState::Installed)));
                    Ok(UpdateReport::new(id.clone(), code, output))
                }

                Err((code, output)) => {
                    try!(tx.send(Event::UpdateErrored(id.clone(), format!("{:?}: {:?}", code, output))));
                    Ok(UpdateReport::new(id.clone(), code, output))
                }

            }

        }

        Err(err) => {
            try!(tx.send(Event::UpdateErrored(id.clone(), format!("{:?}", err))));
            Ok(UpdateReport::new(id.clone(),
                              UpdateResultCode::GENERAL_ERROR,
                              format!("Download failed: {:?}", err)))
        }
    }

}

fn interpreter(env: &mut Env, cmd: Command, tx: &Sender<Event>) -> Result<(), Error> {

    Ok(if let Some(token) = env.access_token.to_owned() {

        partial_apply!(
            [get_package_updates],
            [post_packages, send_install_report],
            [install_package_update], &env, &token);

        match cmd {

            Authenticate(_)       => (), // Already authenticated.

            AcceptUpdate(ref id)  => {
                try!(tx.send(Event::UpdateStateChanged(id.clone(), UpdateState::Downloading)));
                let report = try!(install_package_update(id.to_owned(), tx.to_owned()));
                try!(send_install_report(report.clone()));
                info!("Update finished. Report sent: {:?}", report)
            }

            GetPendingUpdates     => {
                let updates = try!(get_package_updates());
                let update_events: Vec<Event> = updates
                    .iter()
                    .map(|id| Event::NewUpdateAvailable(id.clone()))
                    .collect();
                info!("New package updates available: {:?}", update_events);
                try!(tx.send(Event::Batch(update_events)))
            }

            ListInstalledPackages => {
                let pkgs = try!(env.config.ota.package_manager.installed_packages());
                try!(tx.send(Event::FoundInstalledPackages(pkgs.clone())))
            }

            PostInstalledPackages => {
                let pkgs = try!(env.config.ota.package_manager.installed_packages());
                debug!("Found installed packages in the system: {:?}", pkgs);
                try!(post_packages(pkgs));
                info!("Posted installed packages to the server.")
            }

            Shutdown              => exit(0)
        }

    } else {

        match cmd {

            Authenticate(_)               => {
                let token = try!(authenticate(&env.config.auth, env.http_client));
                env.access_token = Some(token.into())
            }

            Shutdown                      => exit(0),

            AcceptUpdate(_)       |
            GetPendingUpdates     |
            ListInstalledPackages |
            PostInstalledPackages         =>
                tx.send(Event::NotAuthenticated)
                  .unwrap_or(error!("not_auth: send failed."))
            }

    })

}

pub struct OurInterpreter;

impl<'a> Interpreter<Env<'a>, Command, Event> for OurInterpreter {

    fn interpret(env: &mut Env, cmd: Command, tx: Sender<Event>) {
        interpreter(env, cmd, &tx)
            .unwrap_or_else(|err| tx.send(Event::Error(format!("{}", err)))
                            .unwrap_or(error!("interpret: send failed.")))
    }

}
<|endoftext|>