<commit_before>extern crate luthor;

use std::rc::Rc;
use std::cell::RefCell;
use std::old_io::{File, Open, Read, Write};
use std::old_io::IoError;
use std::old_io::IoResult;
use super::GapBuffer;
use super::gap_buffer;
use super::Position;
use super::Range;
use super::Cursor;
use self::luthor::token::{Token, Category};

/// A UTF-8 buffer with bounds-checked cursor management and persistence.
pub struct Buffer {
    data: Rc<RefCell<GapBuffer>>,
    lexer: Option<fn(&str) -> Vec<Token>>,
    pub path: Option<Path>,
    pub cursor: Cursor,
}

impl Buffer {
    /// Returns the contents of the buffer as a string.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut buffer = scribe::buffer::new();
    /// buffer.insert("scribe");
    /// assert_eq!(buffer.data(), "scribe");
    /// ```
    pub fn data(&self) -> String {
        self.data.borrow().to_string()
    }

    /// Writes the contents of the buffer to its path.
    ///
    /// # Examples
    ///
    /// ```
    /// # use std::old_io::{File, Open, Read};
    ///
    /// // Set up a buffer and point it to a path.
    /// let mut buffer = scribe::buffer::new();
    /// let write_path = Path::new("my_doc");
    /// buffer.path = Some(write_path.clone());
    ///
    /// // Put some data into the buffer and save it.
    /// buffer.insert("scribe");
    /// buffer.save();
    ///
    /// # let saved_data = File::open_mode(&write_path, Open, Read)
    /// #   .unwrap().read_to_string().unwrap();
    /// # assert_eq!(saved_data, "scribe");
    ///
    /// # std::old_io::fs::unlink(&write_path);
    /// ```
    pub fn save(&self) -> Option<IoError> {
        let path = match self.path.clone() {
            Some(p) => p,
            None => Path::new(""),
        };

        // Try to open and write to the file, returning any errors encountered.
        let mut file = match File::open_mode(&path, Open, Write) {
            Ok(f) => f,
            Err(error) => return Some(error),
        };

        // We use to_string here because we don't want to write the gap contents.
        match file.write(self.data().to_string().as_bytes()) {
            Ok(_) => (),
            Err(error) => return Some(error),
        }

        return None
    }

    /// Inserts `data` into the buffer at the cursor position.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut buffer = scribe::buffer::new();
    /// buffer.insert("scribe");
    /// assert_eq!(buffer.data(), "scribe");
    /// ```
    pub fn insert(&mut self, data: &str) {
        self.data.borrow_mut().insert(data, &self.cursor);
    }

    /// Deletes a character at the cursor position.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut buffer = scribe::buffer::new();
    /// buffer.insert("scribe");
    /// buffer.delete();
    /// assert_eq!(buffer.data(), "cribe");
    /// ```
    pub fn delete(&mut self) {
        let mut end = self.cursor.clone();
        end.offset += 1;
        self.data.borrow_mut().delete(&Range{ start: *self.cursor, end: end});
    }

    pub fn tokens(&self) -> Vec<Token> {
        match self.lexer {
            Some(lexer) => lexer(&self.data()),
            None => vec![Token{ lexeme: self.data(), category: Category::Text }],
        }
    }
}

/// Creates a new empty buffer. The buffer's cursor is set to the beginning of the buffer.
///
/// # Examples
///
/// ```
/// let buffer = scribe::buffer::new();
/// # assert_eq!(buffer.cursor.line, 0);
/// # assert_eq!(buffer.cursor.offset, 0);
/// ```
pub fn new() -> Buffer {
    let data = Rc::new(RefCell::new(gap_buffer::new(String::new())));
    let cursor = Cursor{ data: data.clone(), position: Position{ line: 0, offset: 0 }};

    Buffer{ data: data.clone(), path: None, cursor: cursor, lexer: None }
}

/// Creates a new buffer by reading the UTF-8 interpreted file contents of the specified path.
/// The buffer's cursor is set to the beginning of the buffer.
///
/// # Examples
///
/// ```
/// let buffer = scribe::buffer::from_file(&Path::new("tests/sample/file")).unwrap();
/// assert_eq!(buffer.data(), "it works!\n");
/// # assert_eq!(buffer.cursor.line, 0);
/// # assert_eq!(buffer.cursor.offset, 0);
/// ```
pub fn from_file(path: &Path) -> IoResult<Buffer> {
    // Try to open and read the file, returning any errors encountered.
    let mut file = match File::open_mode(path, Open, Read) {
        Ok(f) => f,
        Err(error) => return Err(error),
    };
    let mut data = match file.read_to_string() {
        Ok(d) => d,
        Err(error) => return Err(error),
    };

    let data = Rc::new(RefCell::new(gap_buffer::new(data)));
    let cursor = Cursor{ data: data.clone(), position: Position{ line: 0, offset: 0 }};

    // Create a new buffer using the loaded data, path, and other defaults.
    Ok(Buffer{ data: data.clone(), path: Some(path.clone()), cursor: cursor, lexer: None })
}

#[cfg(test)]
mod tests {
    use super::new;
    use super::luthor::token::{Token, Category};

    fn placeholder_lexer(_: &str) -> Vec<Token> {
        vec![Token{ lexeme: "lexer".to_string(), category: Category::Text }]
    }

    #[test]
    fn tokens_returns_one_text_token_when_no_lexer_is_set() {
        let mut buffer = new();
        buffer.insert("scribe");
        let expected_tokens = vec![Token{ lexeme: "scribe".to_string(), category: Category::Text }];
        assert_eq!(buffer.tokens(), expected_tokens);
    }

    #[test]
    fn tokens_returns_result_of_lexer_when_set() {
        let mut buffer = new();
        let expected_tokens = placeholder_lexer("scribe");
        buffer.lexer = Some(placeholder_lexer);
        assert_eq!(buffer.tokens(), expected_tokens);
    }
}
<commit_msg>Add documentation for the buffer tokens method.<commit_after>extern crate luthor;

use std::rc::Rc;
use std::cell::RefCell;
use std::old_io::{File, Open, Read, Write};
use std::old_io::IoError;
use std::old_io::IoResult;
use super::GapBuffer;
use super::gap_buffer;
use super::Position;
use super::Range;
use super::Cursor;
use self::luthor::token::{Token, Category};

/// A UTF-8 buffer with bounds-checked cursor management and persistence.
pub struct Buffer {
    data: Rc<RefCell<GapBuffer>>,
    lexer: Option<fn(&str) -> Vec<Token>>,
    pub path: Option<Path>,
    pub cursor: Cursor,
}

impl Buffer {
    /// Returns the contents of the buffer as a string.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut buffer = scribe::buffer::new();
    /// buffer.insert("scribe");
    /// assert_eq!(buffer.data(), "scribe");
    /// ```
    pub fn data(&self) -> String {
        self.data.borrow().to_string()
    }

    /// Writes the contents of the buffer to its path.
    ///
    /// # Examples
    ///
    /// ```
    /// # use std::old_io::{File, Open, Read};
    ///
    /// // Set up a buffer and point it to a path.
    /// let mut buffer = scribe::buffer::new();
    /// let write_path = Path::new("my_doc");
    /// buffer.path = Some(write_path.clone());
    ///
    /// // Put some data into the buffer and save it.
    /// buffer.insert("scribe");
    /// buffer.save();
    ///
    /// # let saved_data = File::open_mode(&write_path, Open, Read)
    /// #   .unwrap().read_to_string().unwrap();
    /// # assert_eq!(saved_data, "scribe");
    ///
    /// # std::old_io::fs::unlink(&write_path);
    /// ```
    pub fn save(&self) -> Option<IoError> {
        let path = match self.path.clone() {
            Some(p) => p,
            None => Path::new(""),
        };

        // Try to open and write to the file, returning any errors encountered.
        let mut file = match File::open_mode(&path, Open, Write) {
            Ok(f) => f,
            Err(error) => return Some(error),
        };

        // We use to_string here because we don't want to write the gap contents.
        match file.write(self.data().to_string().as_bytes()) {
            Ok(_) => (),
            Err(error) => return Some(error),
        }

        return None
    }

    /// Inserts `data` into the buffer at the cursor position.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut buffer = scribe::buffer::new();
    /// buffer.insert("scribe");
    /// assert_eq!(buffer.data(), "scribe");
    /// ```
    pub fn insert(&mut self, data: &str) {
        self.data.borrow_mut().insert(data, &self.cursor);
    }

    /// Deletes a character at the cursor position.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut buffer = scribe::buffer::new();
    /// buffer.insert("scribe");
    /// buffer.delete();
    /// assert_eq!(buffer.data(), "cribe");
    /// ```
    pub fn delete(&mut self) {
        let mut end = self.cursor.clone();
        end.offset += 1;
        self.data.borrow_mut().delete(&Range{ start: *self.cursor, end: end});
    }

    /// Produces a set of tokens based on the buffer data
    /// suitable for colorized display, using a lexer for the
    /// buffer data's language and/or format. If a lexer is not
    /// available, the set will consist of a single text-category token.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut buffer = scribe::buffer::new();
    /// buffer.insert("scribe");
    ///
    /// // Build the buffer data string back by combining its token lexemes.
    /// let mut data = String::new();
    /// for token in buffer.tokens().iter() {
    ///     data.push_str(token.lexeme.as_slice());
    /// }
    /// assert_eq!(data, "scribe");
    /// ```
    pub fn tokens(&self) -> Vec<Token> {
        match self.lexer {
            Some(lexer) => lexer(&self.data()),
            None => vec![Token{ lexeme: self.data(), category: Category::Text }],
        }
    }
}

/// Creates a new empty buffer. The buffer's cursor is set to the beginning of the buffer.
///
/// # Examples
///
/// ```
/// let buffer = scribe::buffer::new();
/// # assert_eq!(buffer.cursor.line, 0);
/// # assert_eq!(buffer.cursor.offset, 0);
/// ```
pub fn new() -> Buffer {
    let data = Rc::new(RefCell::new(gap_buffer::new(String::new())));
    let cursor = Cursor{ data: data.clone(), position: Position{ line: 0, offset: 0 }};

    Buffer{ data: data.clone(), path: None, cursor: cursor, lexer: None }
}

/// Creates a new buffer by reading the UTF-8 interpreted file contents of the specified path.
/// The buffer's cursor is set to the beginning of the buffer.
///
/// # Examples
///
/// ```
/// let buffer = scribe::buffer::from_file(&Path::new("tests/sample/file")).unwrap();
/// assert_eq!(buffer.data(), "it works!\n");
/// # assert_eq!(buffer.cursor.line, 0);
/// # assert_eq!(buffer.cursor.offset, 0);
/// ```
pub fn from_file(path: &Path) -> IoResult<Buffer> {
    // Try to open and read the file, returning any errors encountered.
    let mut file = match File::open_mode(path, Open, Read) {
        Ok(f) => f,
        Err(error) => return Err(error),
    };
    let mut data = match file.read_to_string() {
        Ok(d) => d,
        Err(error) => return Err(error),
    };

    let data = Rc::new(RefCell::new(gap_buffer::new(data)));
    let cursor = Cursor{ data: data.clone(), position: Position{ line: 0, offset: 0 }};

    // Create a new buffer using the loaded data, path, and other defaults.
    Ok(Buffer{ data: data.clone(), path: Some(path.clone()), cursor: cursor, lexer: None })
}

#[cfg(test)]
mod tests {
    use super::new;
    use super::luthor::token::{Token, Category};

    fn placeholder_lexer(_: &str) -> Vec<Token> {
        vec![Token{ lexeme: "lexer".to_string(), category: Category::Text }]
    }

    #[test]
    fn tokens_returns_one_text_token_when_no_lexer_is_set() {
        let mut buffer = new();
        buffer.insert("scribe");
        let expected_tokens = vec![Token{ lexeme: "scribe".to_string(), category: Category::Text }];
        assert_eq!(buffer.tokens(), expected_tokens);
    }

    #[test]
    fn tokens_returns_result_of_lexer_when_set() {
        let mut buffer = new();
        let expected_tokens = placeholder_lexer("scribe");
        buffer.lexer = Some(placeholder_lexer);
        assert_eq!(buffer.tokens(), expected_tokens);
    }
}
<|endoftext|>


<commit_before>use actix_web::pred::*;
use actix_web::{self, AsyncResponder, FromRequest, HttpMessage, HttpRequest, HttpResponse, Query};
use futures::{Future, IntoFuture};
use serde::de::DeserializeOwned;
use serde::Serialize;
use serde_json;

use context::{ApiContext, ApiContextMut};
use error;
use {Endpoint, EndpointMut, EndpointMutSpec, EndpointSpec};

pub type RequestHandler =
    Fn(HttpRequest<ApiContextMut>) -> Box<Future<Item = HttpResponse, Error = actix_web::Error>>;

pub struct EndpointHandler {
    pub name: &'static str,
    pub method: actix_web::http::Method,
    pub handler: Box<RequestHandler>,
}

impl EndpointHandler {
    pub fn from_endpoint<E: Endpoint>(_: E) -> EndpointHandler {
        let index = move |request: HttpRequest<ApiContextMut>| -> Box<Future<Item=HttpResponse, Error=actix_web::Error>> {
            let to_response = |request: HttpRequest<ApiContextMut>| -> Result<HttpResponse, actix_web::Error> {
                let context = request.state();
                let query = Query::<E::Request>::from_request(&request, &())?;
                let value = E::handle(context, query.into_inner())?;
                Ok(HttpResponse::Ok().json(value))
            };

            Box::new(to_response(request).into_future())
        };

        EndpointHandler {
            name: E::NAME,
            handler: Box::new(index),
            method: actix_web::http::Method::GET,
        }
    }

    pub fn from_endpoint_mut<E: EndpointMut>(_: E) -> EndpointHandler {
        let index = move |request: HttpRequest<ApiContextMut>| -> Box<Future<Item=HttpResponse, Error=actix_web::Error>> {
            let context = request.state().clone();
            request.json().from_err().and_then(move |query: E::Request| {
                let value = E::handle(&context, query)?;
                Ok(HttpResponse::Ok().json(value))
            }).responder()
        };

        EndpointHandler {
            name: E::NAME,
            handler: Box::new(index),
            method: actix_web::http::Method::POST,
        }
    }
}

pub struct ServiceApiWebBackend {
    endpoints: Vec<EndpointHandler>,
}

impl ServiceApiWebBackend {
    pub fn new() -> ServiceApiWebBackend {
        ServiceApiWebBackend {
            endpoints: Vec::new(),
        }
    }

    pub fn endpoints(self) -> Vec<EndpointHandler> {
        self.endpoints
    }
}

pub trait ServiceApiBackend {
    type RawHandler;
    type Method;

    fn endpoint<E: Endpoint>(self, endpoint: E) -> Self;
    fn endpoint_mut<E: EndpointMut>(self, endpoint: E) -> Self;
    fn raw_handler(
        self,
        name: &'static str,
        method: Self::Method,
        handler: Self::RawHandler,
    ) -> Self;
}

impl ServiceApiBackend for ServiceApiWebBackend {
    type RawHandler = Box<RequestHandler>;
    type Method = actix_web::http::Method;

    fn endpoint<E: Endpoint>(mut self, endpoint: E) -> Self {
        let spec = EndpointSpec::from(endpoint);
        self.endpoints.push(spec.into());
        self
    }

    fn endpoint_mut<E: EndpointMut>(mut self, endpoint: E) -> Self {
        let spec = EndpointMutSpec::from(endpoint);
        self.endpoints.push(spec.into());
        self
    }

    fn raw_handler(
        mut self,
        name: &'static str,
        method: Self::Method,
        handler: Self::RawHandler,
    ) -> Self {
        self.endpoints.push(EndpointHandler {
            name,
            method,
            handler,
        });
        self
    }
}

impl<Q, R, F> From<EndpointSpec<Q, R, F>> for EndpointHandler
where
    Q: DeserializeOwned + 'static,
    R: Serialize + 'static,
    F: 'static,
    for<'r> F: Fn(&'r ApiContext, Q) -> Result<R, error::Error>,
{
    fn from(spec: EndpointSpec<Q, R, F>) -> Self {
        let name = spec.name;
        let index = move |request: HttpRequest<ApiContextMut>| -> Box<Future<Item=HttpResponse, Error=actix_web::Error>> {
            let to_response = |request: HttpRequest<ApiContextMut>| -> Result<HttpResponse, actix_web::Error> {
                let context = request.state();
                let query: Query<Q> = Query::from_request(&request, &())?;
                let value = (spec.handler)(context, query.into_inner())?;
                Ok(HttpResponse::Ok().json(value))
            };

            Box::new(to_response(request).into_future())
        };

        EndpointHandler {
            name: name,
            handler: Box::new(index),
            method: actix_web::http::Method::GET,
        }
    }
}

impl<Q, R, F> From<EndpointMutSpec<Q, R, F>> for EndpointHandler
where
    Q: DeserializeOwned + 'static,
    R: Serialize + 'static,
    F: 'static + Clone,
    for<'r> F: Fn(&'r ApiContextMut, Q) -> Result<R, error::Error>,
{
    fn from(spec: EndpointMutSpec<Q, R, F>) -> Self {
        let name = spec.name;
        let index = move |request: HttpRequest<ApiContextMut>| -> Box<Future<Item=HttpResponse, Error=actix_web::Error>> {
            let context = request.state().clone();
            let handler = spec.handler.clone();
            request.json().from_err().and_then(move |query: Q| {
                let value = (handler)(&context, query)?;
                Ok(HttpResponse::Ok().json(value))
            }).responder()
        };

        EndpointHandler {
            name: name,
            handler: Box::new(index),
            method: actix_web::http::Method::GET,
        }
    }
}
<commit_msg>Complete generic impl<commit_after>use actix_web::pred::*;
use actix_web::{self, AsyncResponder, FromRequest, HttpMessage, HttpRequest, HttpResponse, Query};
use futures::{Future, IntoFuture};
use serde::de::DeserializeOwned;
use serde::Serialize;
use serde_json;

use context::{ApiContext, ApiContextMut};
use error;
use {Endpoint, EndpointMut, EndpointMutSpec, EndpointSpec};

pub type RequestHandler =
    Fn(HttpRequest<ApiContextMut>) -> Box<Future<Item = HttpResponse, Error = actix_web::Error>>;

pub struct EndpointHandler {
    pub name: &'static str,
    pub method: actix_web::http::Method,
    pub handler: Box<RequestHandler>,
}

pub struct ServiceApiWebBackend {
    endpoints: Vec<EndpointHandler>,
}

impl ServiceApiWebBackend {
    pub fn new() -> ServiceApiWebBackend {
        ServiceApiWebBackend {
            endpoints: Vec::new(),
        }
    }

    pub fn endpoints(self) -> Vec<EndpointHandler> {
        self.endpoints
    }
}

pub trait ServiceApiBackend {
    type RawHandler;
    type Method;

    fn endpoint<Q, R, F, E>(self, endpoint: E) -> Self
    where
        Q: DeserializeOwned + 'static,
        R: Serialize + 'static,
        F: 'static,
        for<'r> F: Fn(&'r ApiContext, Q) -> Result<R, error::Error>,
        E: Into<EndpointSpec<Q, R, F>>;
    fn endpoint_mut<Q, R, F, E>(self, endpoint: E) -> Self
    where
        Q: DeserializeOwned + 'static,
        R: Serialize + 'static,
        F: 'static + Clone,
        for<'r> F: Fn(&'r ApiContextMut, Q) -> Result<R, error::Error>,
        E: Into<EndpointMutSpec<Q, R, F>>;
    fn raw_handler(
        self,
        name: &'static str,
        method: Self::Method,
        handler: Self::RawHandler,
    ) -> Self;
}

impl ServiceApiBackend for ServiceApiWebBackend {
    type RawHandler = Box<RequestHandler>;
    type Method = actix_web::http::Method;

    fn endpoint<Q, R, F, E>(mut self, endpoint: E) -> Self
    where
        Q: DeserializeOwned + 'static,
        R: Serialize + 'static,
        F: 'static,
        for<'r> F: Fn(&'r ApiContext, Q) -> Result<R, error::Error>,
        E: Into<EndpointSpec<Q, R, F>>,
    {
        let spec = endpoint.into();
        self.endpoints.push(spec.into());
        self
    }

    fn endpoint_mut<Q, R, F, E>(mut self, endpoint: E) -> Self
        where
        Q: DeserializeOwned + 'static,
        R: Serialize + 'static,
        F: 'static + Clone,
        for<'r> F: Fn(&'r ApiContextMut, Q) -> Result<R, error::Error>,
        E: Into<EndpointMutSpec<Q, R, F>>
    {
        let spec = endpoint.into();
        self.endpoints.push(spec.into());
        self
    }

    fn raw_handler(
        mut self,
        name: &'static str,
        method: Self::Method,
        handler: Self::RawHandler,
    ) -> Self {
        self.endpoints.push(EndpointHandler {
            name,
            method,
            handler,
        });
        self
    }
}

impl<Q, R, F> From<EndpointSpec<Q, R, F>> for EndpointHandler
where
    Q: DeserializeOwned + 'static,
    R: Serialize + 'static,
    F: 'static,
    for<'r> F: Fn(&'r ApiContext, Q) -> Result<R, error::Error>,
{
    fn from(spec: EndpointSpec<Q, R, F>) -> Self {
        let name = spec.name;
        let index = move |request: HttpRequest<ApiContextMut>| -> Box<Future<Item=HttpResponse, Error=actix_web::Error>> {
            let to_response = |request: HttpRequest<ApiContextMut>| -> Result<HttpResponse, actix_web::Error> {
                let context = request.state();
                let query: Query<Q> = Query::from_request(&request, &())?;
                let value = (spec.handler)(context, query.into_inner())?;
                Ok(HttpResponse::Ok().json(value))
            };

            Box::new(to_response(request).into_future())
        };

        EndpointHandler {
            name: name,
            handler: Box::new(index),
            method: actix_web::http::Method::GET,
        }
    }
}

impl<Q, R, F> From<EndpointMutSpec<Q, R, F>> for EndpointHandler
where
    Q: DeserializeOwned + 'static,
    R: Serialize + 'static,
    F: 'static + Clone,
    for<'r> F: Fn(&'r ApiContextMut, Q) -> Result<R, error::Error>,
{
    fn from(spec: EndpointMutSpec<Q, R, F>) -> Self {
        let name = spec.name;
        let index = move |request: HttpRequest<ApiContextMut>| -> Box<Future<Item=HttpResponse, Error=actix_web::Error>> {
            let context = request.state().clone();
            let handler = spec.handler.clone();
            request.json().from_err().and_then(move |query: Q| {
                let value = (handler)(&context, query)?;
                Ok(HttpResponse::Ok().json(value))
            }).responder()
        };

        EndpointHandler {
            name: name,
            handler: Box::new(index),
            method: actix_web::http::Method::GET,
        }
    }
}
<|endoftext|>


<commit_before>use cgmath::Matrix4;
use cgmath;
use character::controls::CharacterInputState;
use graphics::orientation::{Orientation, Stance};
use graphics::{Dimensions, get_orientation, can_move};
use graphics::camera::CameraInputState;
use data;
use game::constants::{ASPECT_RATIO, RUN_SPRITE_OFFSET, CHARSHEET_TOTAL_WIDTH, SPRITE_OFFSET};
use shaders::{pipe, VertexData, CharacterSheet, Position, Projection};
use gfx;
use graphics::load_texture;
use gfx_app::mouse_controls::MouseInputState;
use gfx_app::{ColorFormat, DepthFormat};
use critter::{CharacterSprite, CritterData};
use specs;
use specs::{Fetch, ReadStorage, WriteStorage};

mod audio;
pub mod controls;

const SHADER_VERT: &'static [u8] = include_bytes!("../shaders/character.v.glsl");
const SHADER_FRAG: &'static [u8] = include_bytes!("../shaders/character.f.glsl");

pub struct CharacterDrawable {
  projection: Projection,
  pub position: Position,
  orientation: Orientation,
  pub stance: Stance,
  direction: Orientation,
  audio: audio::CharacterAudio,
  pub can_move: bool,
}

impl CharacterDrawable {
  pub fn new(view: Matrix4<f32>) -> CharacterDrawable {
    CharacterDrawable {
      projection: Projection {
        model: view.into(),
        view: view.into(),
        proj: cgmath::perspective(cgmath::Deg(60.0f32), ASPECT_RATIO, 0.1, 4000.0).into(),
      },
      position: Position {
        position: [0.0, 0.0],
      },
      orientation: Orientation::Right,
      stance: Stance::Walking,
      direction: Orientation::Right,
      audio: audio::CharacterAudio::new(),
      can_move: false,
    }
  }

  pub fn update(&mut self, world_to_clip: &Projection, ci: &CharacterInputState, cs: &mut CharacterSprite, mouse_input: &MouseInputState) {
    self.projection = *world_to_clip;
    let new_position = Position {
      position: [ci.x_movement, ci.y_movement]
    };

    if mouse_input.left_click_point.is_some() {
      self.stance = Stance::Firing;
      self.orientation = get_orientation(mouse_input);
      if cs.character_fire_idx == 1 {
        self.audio.play_pistol();
      }
    } else {
      self.stance = Stance::Walking;
      let dx = new_position.position[0] - self.position.position[0];
      let dy = new_position.position[1] - self.position.position[1];
      self.orientation =
        if dx == 0.0 && dy < 0.0       { Orientation::Down }
        else if dx > 0.0 && dy < 0.0   { Orientation::DownRight }
        else if dx < 0.0 && dy < 0.0   { Orientation::DownLeft }
        else if dx > 0.0 && dy == 0.0  { Orientation::Right }
        else if dx < 0.0 && dy == 0.0  { Orientation::Left }
        else if dx == 0.0 && dy > 0.0  { Orientation::Up }
        else if dx > 0.0 && dy > 0.0   { Orientation::UpRight }
        else if dx < 0.0 && dy > 0.0   { Orientation::UpLeft }
        else { Orientation::Still };

      if can_move(new_position.position) {
        self.position = new_position;
        self.can_move = true;
      } else {
        self.can_move = false;
        self.orientation = Orientation::Still;
      }
    }
  }
}

impl specs::Component for CharacterDrawable {
  type Storage = specs::VecStorage<CharacterDrawable>;
}

pub struct CharacterDrawSystem<R: gfx::Resources> {
  bundle: gfx::pso::bundle::Bundle<R, pipe::Data<R>>,
  data: Vec<CritterData>,
}

impl<R: gfx::Resources> CharacterDrawSystem<R> {
  pub fn new<F>(factory: &mut F,
                rtv: gfx::handle::RenderTargetView<R, ColorFormat>,
                dsv: gfx::handle::DepthStencilView<R, DepthFormat>) -> CharacterDrawSystem<R>
    where F: gfx::Factory<R> {
    use gfx::traits::FactoryExt;

    let charter_bytes = &include_bytes!("../../assets/character.png")[..];

    let vertex_data: Vec<VertexData> =
      vec![
        VertexData::new([-20.0, -28.0, 0.0], [0.0, 1.0]),
        VertexData::new([20.0, -28.0, 0.0], [1.0, 1.0]),
        VertexData::new([20.0, 28.0, 0.0], [1.0, 0.0]),
        VertexData::new([-20.0, -28.0, 0.0], [0.0, 1.0]),
        VertexData::new([20.0, 28.0, 0.0], [1.0, 0.0]),
        VertexData::new([-20.0, 28.0, 0.0], [0.0, 0.0]),
      ];

    let (vertex_buf, slice) = factory.create_vertex_buffer_with_slice(&vertex_data, ());

    let char_texture = load_texture(factory, charter_bytes).unwrap();
    let pso = factory
      .create_pipeline_simple(SHADER_VERT,
                              SHADER_FRAG,
                              pipe::new())
      .unwrap();

    let pipeline_data = pipe::Data {
      vbuf: vertex_buf,
      projection_cb: factory.create_constant_buffer(1),
      position_cb: factory.create_constant_buffer(1),
      character_sprite_cb: factory.create_constant_buffer(1),
      charactersheet: (char_texture, factory.create_sampler_linear()),
      out_color: rtv,
      out_depth: dsv,
    };

    let data = data::load_character();

    CharacterDrawSystem {
      bundle: gfx::Bundle::new(slice, pso, pipeline_data),
      data
    }
  }

  fn get_next_sprite(&self, character_idx: usize, character_fire_idx: usize, drawable: &mut CharacterDrawable) -> CharacterSheet {
    let char_sprite =
      if drawable.orientation == Orientation::Still && drawable.stance == Stance::Walking {
        let sprite_idx = (drawable.direction as usize * 28 + RUN_SPRITE_OFFSET) as usize;
        (&self.data[sprite_idx], sprite_idx)
      } else if drawable.stance == Stance::Walking {
        drawable.direction = drawable.orientation;
        let sprite_idx = (drawable.orientation as usize * 28 + character_idx + RUN_SPRITE_OFFSET) as usize;
        (&self.data[sprite_idx], sprite_idx)
      } else {
        let sprite_idx = (drawable.orientation as usize * 8 + character_fire_idx) as usize;
        (&self.data[sprite_idx], sprite_idx)
      };

    let elements_x = CHARSHEET_TOTAL_WIDTH / (char_sprite.0.data[2] + SPRITE_OFFSET);
    CharacterSheet {
      div: elements_x,
      index: char_sprite.1 as f32
    }
  }

  pub fn draw<C>(&mut self,
                 mut drawable: &mut CharacterDrawable,
                 character: &CharacterSprite,
                 encoder: &mut gfx::Encoder<R, C>)
    where C: gfx::CommandBuffer<R> {
    encoder.update_constant_buffer(&self.bundle.data.projection_cb, &drawable.projection);
    encoder.update_constant_buffer(&self.bundle.data.position_cb, &drawable.position);
    encoder.update_constant_buffer(&self.bundle.data.character_sprite_cb,
                                   &self.get_next_sprite(character.character_idx,
                                                             character.character_fire_idx,
                                                             &mut drawable));
    self.bundle.encode(encoder);
  }
}

#[derive(Debug)]
pub struct PreDrawSystem;

impl PreDrawSystem {
  pub fn new() -> PreDrawSystem {
    PreDrawSystem {}
  }
}

impl<'a> specs::System<'a> for PreDrawSystem {
  #[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
  type SystemData = (WriteStorage<'a, CharacterDrawable>,
                     ReadStorage<'a, CameraInputState>,
                     ReadStorage<'a, CharacterInputState>,
                     WriteStorage<'a, CharacterSprite>,
                     ReadStorage<'a, MouseInputState>,
                     Fetch<'a, Dimensions>);

  fn run(&mut self, (mut character, camera_input, character_input, mut character_sprite, mouse_input, dim): Self::SystemData) {
    use specs::Join;

    for (c, camera, ci, cs, mi) in (&mut character, &camera_input, &character_input, &mut character_sprite, &mouse_input).join() {
      let world_to_clip = dim.world_to_projection(camera);
      c.update(&world_to_clip, ci, cs, mi);
    }
  }
}
<commit_msg>Remove unnecessary can_move variable<commit_after>use cgmath::Matrix4;
use cgmath;
use character::controls::CharacterInputState;
use graphics::orientation::{Orientation, Stance};
use graphics::{Dimensions, get_orientation, can_move};
use graphics::camera::CameraInputState;
use data;
use game::constants::{ASPECT_RATIO, RUN_SPRITE_OFFSET, CHARSHEET_TOTAL_WIDTH, SPRITE_OFFSET};
use shaders::{pipe, VertexData, CharacterSheet, Position, Projection};
use gfx;
use graphics::load_texture;
use gfx_app::mouse_controls::MouseInputState;
use gfx_app::{ColorFormat, DepthFormat};
use critter::{CharacterSprite, CritterData};
use specs;
use specs::{Fetch, ReadStorage, WriteStorage};

mod audio;
pub mod controls;

const SHADER_VERT: &'static [u8] = include_bytes!("../shaders/character.v.glsl");
const SHADER_FRAG: &'static [u8] = include_bytes!("../shaders/character.f.glsl");

pub struct CharacterDrawable {
  projection: Projection,
  pub position: Position,
  orientation: Orientation,
  pub stance: Stance,
  direction: Orientation,
  audio: audio::CharacterAudio,
}

impl CharacterDrawable {
  pub fn new(view: Matrix4<f32>) -> CharacterDrawable {
    CharacterDrawable {
      projection: Projection {
        model: view.into(),
        view: view.into(),
        proj: cgmath::perspective(cgmath::Deg(60.0f32), ASPECT_RATIO, 0.1, 4000.0).into(),
      },
      position: Position {
        position: [0.0, 0.0],
      },
      orientation: Orientation::Right,
      stance: Stance::Walking,
      direction: Orientation::Right,
      audio: audio::CharacterAudio::new(),
    }
  }

  pub fn update(&mut self, world_to_clip: &Projection, ci: &CharacterInputState, cs: &mut CharacterSprite, mouse_input: &MouseInputState) {
    self.projection = *world_to_clip;
    let new_position = Position {
      position: [ci.x_movement, ci.y_movement]
    };

    if mouse_input.left_click_point.is_some() {
      self.stance = Stance::Firing;
      self.orientation = get_orientation(mouse_input);
      if cs.character_fire_idx == 1 {
        self.audio.play_pistol();
      }
    } else {
      self.stance = Stance::Walking;
      let dx = new_position.position[0] - self.position.position[0];
      let dy = new_position.position[1] - self.position.position[1];
      self.orientation =
        if dx == 0.0 && dy < 0.0       { Orientation::Down }
        else if dx > 0.0 && dy < 0.0   { Orientation::DownRight }
        else if dx < 0.0 && dy < 0.0   { Orientation::DownLeft }
        else if dx > 0.0 && dy == 0.0  { Orientation::Right }
        else if dx < 0.0 && dy == 0.0  { Orientation::Left }
        else if dx == 0.0 && dy > 0.0  { Orientation::Up }
        else if dx > 0.0 && dy > 0.0   { Orientation::UpRight }
        else if dx < 0.0 && dy > 0.0   { Orientation::UpLeft }
        else { Orientation::Still };

      if can_move(new_position.position) {
        self.position = new_position;
      } else {
        self.orientation = Orientation::Still;
      }
    }
  }
}

impl specs::Component for CharacterDrawable {
  type Storage = specs::VecStorage<CharacterDrawable>;
}

pub struct CharacterDrawSystem<R: gfx::Resources> {
  bundle: gfx::pso::bundle::Bundle<R, pipe::Data<R>>,
  data: Vec<CritterData>,
}

impl<R: gfx::Resources> CharacterDrawSystem<R> {
  pub fn new<F>(factory: &mut F,
                rtv: gfx::handle::RenderTargetView<R, ColorFormat>,
                dsv: gfx::handle::DepthStencilView<R, DepthFormat>) -> CharacterDrawSystem<R>
    where F: gfx::Factory<R> {
    use gfx::traits::FactoryExt;

    let charter_bytes = &include_bytes!("../../assets/character.png")[..];

    let vertex_data: Vec<VertexData> =
      vec![
        VertexData::new([-20.0, -28.0, 0.0], [0.0, 1.0]),
        VertexData::new([20.0, -28.0, 0.0], [1.0, 1.0]),
        VertexData::new([20.0, 28.0, 0.0], [1.0, 0.0]),
        VertexData::new([-20.0, -28.0, 0.0], [0.0, 1.0]),
        VertexData::new([20.0, 28.0, 0.0], [1.0, 0.0]),
        VertexData::new([-20.0, 28.0, 0.0], [0.0, 0.0]),
      ];

    let (vertex_buf, slice) = factory.create_vertex_buffer_with_slice(&vertex_data, ());

    let char_texture = load_texture(factory, charter_bytes).unwrap();
    let pso = factory
      .create_pipeline_simple(SHADER_VERT,
                              SHADER_FRAG,
                              pipe::new())
      .unwrap();

    let pipeline_data = pipe::Data {
      vbuf: vertex_buf,
      projection_cb: factory.create_constant_buffer(1),
      position_cb: factory.create_constant_buffer(1),
      character_sprite_cb: factory.create_constant_buffer(1),
      charactersheet: (char_texture, factory.create_sampler_linear()),
      out_color: rtv,
      out_depth: dsv,
    };

    let data = data::load_character();

    CharacterDrawSystem {
      bundle: gfx::Bundle::new(slice, pso, pipeline_data),
      data
    }
  }

  fn get_next_sprite(&self, character_idx: usize, character_fire_idx: usize, drawable: &mut CharacterDrawable) -> CharacterSheet {
    let char_sprite =
      if drawable.orientation == Orientation::Still && drawable.stance == Stance::Walking {
        let sprite_idx = (drawable.direction as usize * 28 + RUN_SPRITE_OFFSET) as usize;
        (&self.data[sprite_idx], sprite_idx)
      } else if drawable.stance == Stance::Walking {
        drawable.direction = drawable.orientation;
        let sprite_idx = (drawable.orientation as usize * 28 + character_idx + RUN_SPRITE_OFFSET) as usize;
        (&self.data[sprite_idx], sprite_idx)
      } else {
        let sprite_idx = (drawable.orientation as usize * 8 + character_fire_idx) as usize;
        (&self.data[sprite_idx], sprite_idx)
      };

    let elements_x = CHARSHEET_TOTAL_WIDTH / (char_sprite.0.data[2] + SPRITE_OFFSET);
    CharacterSheet {
      div: elements_x,
      index: char_sprite.1 as f32
    }
  }

  pub fn draw<C>(&mut self,
                 mut drawable: &mut CharacterDrawable,
                 character: &CharacterSprite,
                 encoder: &mut gfx::Encoder<R, C>)
    where C: gfx::CommandBuffer<R> {
    encoder.update_constant_buffer(&self.bundle.data.projection_cb, &drawable.projection);
    encoder.update_constant_buffer(&self.bundle.data.position_cb, &drawable.position);
    encoder.update_constant_buffer(&self.bundle.data.character_sprite_cb,
                                   &self.get_next_sprite(character.character_idx,
                                                             character.character_fire_idx,
                                                             &mut drawable));
    self.bundle.encode(encoder);
  }
}

#[derive(Debug)]
pub struct PreDrawSystem;

impl PreDrawSystem {
  pub fn new() -> PreDrawSystem {
    PreDrawSystem {}
  }
}

impl<'a> specs::System<'a> for PreDrawSystem {
  #[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
  type SystemData = (WriteStorage<'a, CharacterDrawable>,
                     ReadStorage<'a, CameraInputState>,
                     ReadStorage<'a, CharacterInputState>,
                     WriteStorage<'a, CharacterSprite>,
                     ReadStorage<'a, MouseInputState>,
                     Fetch<'a, Dimensions>);

  fn run(&mut self, (mut character, camera_input, character_input, mut character_sprite, mouse_input, dim): Self::SystemData) {
    use specs::Join;

    for (c, camera, ci, cs, mi) in (&mut character, &camera_input, &character_input, &mut character_sprite, &mouse_input).join() {
      let world_to_clip = dim.world_to_projection(camera);
      c.update(&world_to_clip, ci, cs, mi);
    }
  }
}
<|endoftext|>


<commit_before>#![feature(decl_macro, proc_macro_hygiene)]

extern crate turingarena_contest_webcontent;

use rocket::{
    http::{ContentType, Status},
    response::{self, content},
    State,
};
use std::ffi::OsStr;
use std::io::Cursor;
use std::path::PathBuf;
use turingarena_contest::*;
use turingarena_contest_webcontent::WebContent;

#[rocket::get("/graphiql")]
fn graphiql() -> content::Html<String> {
    juniper_rocket::graphiql_source("/graphql")
}

#[rocket::get("/graphql?<request>")]
fn get_graphql_handler(
    context: State<Context>,
    request: juniper_rocket::GraphQLRequest,
    schema: State<Schema>,
) -> juniper_rocket::GraphQLResponse {
    request.execute(&schema, &context)
}

#[rocket::post("/graphql", data = "<request>")]
fn post_graphql_handler(
    context: State<Context>,
    request: juniper_rocket::GraphQLRequest,
    schema: State<Schema>,
) -> juniper_rocket::GraphQLResponse {
    request.execute(&schema, &context)
}

#[rocket::get("/<file..>")]
fn dist<'r>(file: PathBuf) -> rocket::response::Result<'r> {
    let path = file.display().to_string();
    let filename = if path.eq("") {
        "/index.html".to_owned()
    } else {
        path
    };
    WebContent::get(&filename).map_or_else(
        || Err(Status::NotFound),
        |d| {
            let ext = file
                .as_path()
                .extension()
                .and_then(OsStr::to_str)
                .ok_or(Status::new(400, "Could not get file extension"))?;
            let content_type = ContentType::from_extension(ext)
                .ok_or(Status::new(400, "Could not get file content type"))?;
            response::Response::build()
                .header(content_type)
                .sized_body(Cursor::new(d))
                .ok()
        },
    )
}

fn main() {
    rocket::ignite()
        .manage(Schema::new(contest::Contest, contest::Contest))
        .manage(Context {})
        .mount(
            "/",
            rocket::routes![graphiql, get_graphql_handler, post_graphql_handler, dist],
        )
        .launch();
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}
<commit_msg>contest-serve: handle requests to root URI<commit_after>#![feature(decl_macro, proc_macro_hygiene)]

extern crate turingarena_contest_webcontent;

use rocket::{
    http::{ContentType, Status},
    response::{self, content},
    State,
};
use std::ffi::OsStr;
use std::io::Cursor;
use std::path::PathBuf;
use turingarena_contest::*;
use turingarena_contest_webcontent::WebContent;

#[rocket::get("/graphiql")]
fn graphiql() -> content::Html<String> {
    juniper_rocket::graphiql_source("/graphql")
}

#[rocket::get("/graphql?<request>")]
fn get_graphql_handler(
    context: State<Context>,
    request: juniper_rocket::GraphQLRequest,
    schema: State<Schema>,
) -> juniper_rocket::GraphQLResponse {
    request.execute(&schema, &context)
}

#[rocket::post("/graphql", data = "<request>")]
fn post_graphql_handler(
    context: State<Context>,
    request: juniper_rocket::GraphQLRequest,
    schema: State<Schema>,
) -> juniper_rocket::GraphQLResponse {
    request.execute(&schema, &context)
}

#[rocket::get("/")]
fn index<'r>() -> rocket::response::Result<'r> {
    dist(Some(PathBuf::from("index.html")))
}

#[rocket::get("/<file_option..>")]
fn dist<'r>(file_option: Option<PathBuf>) -> rocket::response::Result<'r> {
    let file = file_option.unwrap_or(PathBuf::new());
    let filename = file.display().to_string();
    let content = WebContent::get(&filename)
        .or(WebContent::get("index.html"))
        .unwrap();
    let ext = file
        .as_path()
        .extension()
        .and_then(OsStr::to_str)
        .unwrap_or("html");
    let content_type = ContentType::from_extension(ext)
        .ok_or(Status::new(400, "Could not get file content type"))?;
    response::Response::build()
        .header(content_type)
        .sized_body(Cursor::new(content))
        .ok()
}

fn main() {
    rocket::ignite()
        .manage(Schema::new(contest::Contest, contest::Contest))
        .manage(Context {})
        .mount(
            "/",
            rocket::routes![graphiql, get_graphql_handler, post_graphql_handler, index, dist],
        )
        .launch();
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}
<|endoftext|>


<commit_before>//! The integration suite helpers.

use std::process::Command;
use std::path::{Path, PathBuf};

/// List windows will give details about the active sessions in testing.
/// target: A string represented by the {named_session}:{named_window}
pub fn list_windows(target: &String) -> String {
    let output = Command::new("tmux")
                     .arg("list-windows")
                     .arg("-t")
                     .arg(target)
                     .output()
                     .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });

    String::from_utf8_lossy(&output.stdout).into_owned()
}

pub fn open_muxed(project: &String, project_root: &Path) -> () {
    println!("root: {}", project_root.display());
    let output = Command::new("./target/debug/muxed")
        .arg("-d")
        .arg("-p")
        .arg(format!("{}", project_root.display()))
        .arg(project)
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });

    println!("status: {}", output.status);
    println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
    println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
}

pub fn kill_session(target: &String) -> () {
    Command::new("tmux")
        .arg("kill-session")
        .arg("-t")
        .arg(target)
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });
}

pub struct TmuxSession {
    pub num_of_windows: usize,
}

pub fn session_object(results: &String) -> TmuxSession {
    let lines: Vec<&str> = results.split("\n").collect();
    let (_, window_lines) = lines.split_last().unwrap();
    TmuxSession{num_of_windows: window_lines.len()}
}
<commit_msg>Move the tmux session formatter<commit_after>//! The integration suite helpers.

use regex::Regex;
use std::process::Command;
use std::path::Path;
use std::collections::HashMap;
use std::str::FromStr;

/// List windows will give details about the active sessions in testing.
/// target: A string represented by the {named_session}:{named_window}
pub fn list_windows(target: &String) -> String {
    let output = Command::new("tmux")
                     .arg("list-windows")
                     .arg("-t")
                     .arg(target)
                     .output()
                     .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });

    String::from_utf8_lossy(&output.stdout).into_owned()
}

pub fn open_muxed(project: &String, project_root: &Path) -> () {
    println!("root: {}", project_root.display());
    let output = Command::new("./target/debug/muxed")
        .arg("-d")
        .arg("-p")
        .arg(format!("{}", project_root.display()))
        .arg(project)
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });

    println!("status: {}", output.status);
    println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
    println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
}

pub fn kill_session(target: &String) -> () {
    Command::new("tmux")
        .arg("kill-session")
        .arg("-t")
        .arg(target)
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });
}

#[derive(Debug)]
pub struct TmuxSession {
    pub num_of_windows: usize,
    pub windows: HashMap<String, HashMap<String, usize>>
}

impl TmuxSession {
    pub fn from_string(results: &String) -> TmuxSession {
        let window_name = Regex::new(r": (\w*)[$\*-]? \(").unwrap();

        let lines: Vec<&str> = results.split("\n").collect();
        let (_, window_lines) = lines.split_last().unwrap();

        let mut windows: HashMap<String, HashMap<String, usize>> = HashMap::new();
        let mut h = HashMap::new();

        for line in window_lines {
            for cap in window_name.captures_iter(line) {
                let name = cap.at(1).unwrap();
                h.insert("Panes".to_string(), TmuxSession::count_panes(line));
                windows.insert(name.to_string(), h.clone());
            }
        }

        TmuxSession {
          num_of_windows: window_lines.len(),
          windows: windows
        }
    }

    pub fn count_panes(line: &str) -> usize {
        let panes = Regex::new(r"\((\d*) panes\)").unwrap();
        let mut num: &str = "";

        for cap in panes.captures_iter(line) {
            num = cap.at(1).unwrap_or("0");
        }

        usize::from_str(num).unwrap()
    }
}
<|endoftext|>


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

use time;
use url::Url;
use hyper::{self, Client};
use hyper::client::{Request, Response};
use hyper::method::Method;
use rustc_serialize::json::{self, Json, Object};
use rustc_serialize::Encodable;
use multipart::client::Multipart;

use errors::WeChatError;
use types::WeChatResult;
use session::SessionStore;

const REFETCH_ACCESS_TOKEN_ERRCODES: [i32; 3] = [40001, 40014, 42001];

#[derive(Debug, Clone)]
pub struct APIClient<T: SessionStore> {
    pub appid: String,
    pub secret: String,
    pub session: T,
}

impl<T: SessionStore> APIClient<T> {

    #[inline]
    pub fn new<S: Into<String>>(appid: S, secret: S, session: T) -> APIClient<T> {
        APIClient {
            appid: appid.into(),
            secret: secret.into(),
            session: session,
        }
    }

    #[inline]
    pub fn with_access_token<S: Into<String>>(appid: S, secret: S, access_token: S, session: T) -> APIClient<T> {
        let appid = appid.into();
        let secret = secret.into();
        let client = Self::new(appid.clone(), secret, session);
        let token_key = format!("{}_access_token", appid);
        client.session.set(&token_key, access_token.into(), None);
        client
    }

    #[inline]
    pub fn access_token(&self) -> String {
        let token_key = format!("{}_access_token", self.appid);
        let expires_key = format!("{}_expires_at", self.appid);
        let token: String = self.session.get(&token_key, Some("".to_owned())).unwrap();
        let timestamp = time::get_time().sec;
        let expires_at: i64 = self.session.get(&expires_key, Some(timestamp)).unwrap();
        if expires_at <= timestamp {
            "".to_owned()
        } else {
            token
        }
    }

    pub fn request<D: Encodable>(&self, method: Method, url: &str, params: Vec<(&str, &str)>, data: &D) -> WeChatResult<Response> {
        let mut http_url = if !(url.starts_with("http://") || url.starts_with("https://")) {
            let mut url_string = "https://api.weixin.qq.com/cgi-bin/".to_owned();
            url_string = url_string + url;
            Url::parse(&url_string).unwrap()
        } else {
            Url::parse(url).unwrap()
        };
        let access_token = self.access_token();
        let mut querys = params.clone();
        if !access_token.is_empty() {
            debug!("Using access_token: {}", access_token);
            querys.push(("access_token", &access_token));
        }
        http_url.set_query_from_pairs(querys.into_iter());
        let body = match json::encode(data) {
            Ok(text) => text,
            Err(_) => "".to_owned(),
        };
        let client = Client::new();
        let req = if method == Method::Post {
            client.post(http_url).body(&body)
        } else {
            client.get(http_url)
        };
        let res = match req.send() {
            Ok(_res) => _res,
            Err(_) => {
                error!("Send request error");
                return Err(WeChatError::ClientError { errcode: -1, errmsg: "Send request error".to_owned() });
            }
        };
        if res.status != hyper::Ok {
            error!("Response status error");
            return Err(WeChatError::ClientError { errcode: -2, errmsg: "Response status error".to_owned() })
        }
        Ok(res)

    }

    fn _upload_file<R: Read>(&self, url: &str, params: Vec<(&str, &str)>, files: &mut HashMap<String, &mut R>) -> WeChatResult<Response> {
        let mut http_url = if !(url.starts_with("http://") || url.starts_with("https://")) {
            let mut url_string = "https://api.weixin.qq.com/cgi-bin/".to_owned();
            url_string = url_string + url;
            Url::parse(&url_string).unwrap()
        } else {
            Url::parse(url).unwrap()
        };
        let access_token = self.access_token();
        let mut querys = params.clone();
        if !access_token.is_empty() {
            debug!("Using access_token: {}", access_token);
            querys.push(("access_token", &access_token));
        }
        http_url.set_query_from_pairs(querys.into_iter());
        let request = Request::new(Method::Post, http_url).unwrap();
        let mut req = Multipart::from_request(request).unwrap();
        for (name, stream) in files.iter_mut() {
            req.write_stream(name, stream, None, None);
        }
        let res = match req.send() {
            Ok(_res) => _res,
            Err(_) => {
                error!("Send request error");
                return Err(WeChatError::ClientError { errcode: -1, errmsg: "Send request error".to_owned() });
            }
        };
        if res.status != hyper::Ok {
            error!("Response status error");
            return Err(WeChatError::ClientError { errcode: -2, errmsg: "Response status error".to_owned() })
        }
        Ok(res)
    }

    pub fn upload_file<R: Read>(&self, url: &str, params: Vec<(&str, &str)>, files: &mut HashMap<String, &mut R>) -> WeChatResult<Json> {
        if self.access_token().is_empty() {
            self.fetch_access_token();
        }
        let mut res = try!(self._upload_file(url, params.clone(), files));
        let data = match self.json_decode(&mut res) {
            Ok(_data) => _data,
            Err(err) => {
                if let WeChatError::ClientError { errcode, .. } = err {
                    if REFETCH_ACCESS_TOKEN_ERRCODES.contains(&errcode) {
                        // access_token expired, fetch a new one and retry request
                        self.fetch_access_token();
                        let mut res1 = try!(self._upload_file(url, params, files));
                        try!(self.json_decode(&mut res1))
                    } else {
                        return Err(err);
                    }
                } else {
                    return Err(err);
                }
            },
        };
        Ok(data)
    }

    #[inline]
    fn json_decode(&self, res: &mut Response) -> WeChatResult<Json> {
        let obj = match Json::from_reader(res) {
            Ok(decoded) => { decoded },
            Err(_) => {
                error!("Json decode error");
                return Err(WeChatError::ClientError { errcode: -3, errmsg: "Json decode error".to_owned() });
            }
        };
        match obj.find("errcode") {
            Some(code) => {
                let errcode = code.as_i64().unwrap();
                if errcode != 0 {
                    let errmsg = match obj.find("errmsg") {
                        Some(msg) => {
                            msg.as_string().unwrap()
                        },
                        None => { "" }
                    };
                    return Err(WeChatError::ClientError { errcode: errcode as i32, errmsg: errmsg.to_owned() });
                }
            },
            None => {},
        }
        Ok(obj)
    }

    #[inline]
    pub fn post<D: Encodable>(&self, url: &str, params: Vec<(&str, &str)>, data: &D) -> WeChatResult<Json> {
        if self.access_token().is_empty() {
            self.fetch_access_token();
        }
        let mut res = try!(self.request(Method::Post, url, params.clone(), data));
        let data = match self.json_decode(&mut res) {
            Ok(_data) => _data,
            Err(err) => {
                if let WeChatError::ClientError { errcode, .. } = err {
                    if REFETCH_ACCESS_TOKEN_ERRCODES.contains(&errcode) {
                        // access_token expired, fetch a new one and retry request
                        self.fetch_access_token();
                        let mut res1 = try!(self.request(Method::Post, url, params, data));
                        try!(self.json_decode(&mut res1))
                    } else {
                        return Err(err);
                    }
                } else {
                    return Err(err);
                }
            },
        };
        Ok(data)
    }

    #[inline]
    pub fn get(&self, url: &str, params: Vec<(&str, &str)>) -> WeChatResult<Json> {
        if self.access_token().is_empty() {
            self.fetch_access_token();
        }
        let mut res = try!(self.request(Method::Get, url, params.clone(), &Object::new()));
        let data = match self.json_decode(&mut res) {
            Ok(_data) => _data,
            Err(err) => {
                if let WeChatError::ClientError { errcode, .. } = err {
                    if REFETCH_ACCESS_TOKEN_ERRCODES.contains(&errcode) {
                        // access_token expired, fetch a new one and retry request
                        self.fetch_access_token();
                        let mut res1 = try!(self.request(Method::Get, url, params, &Object::new()));
                        try!(self.json_decode(&mut res1))
                    } else {
                        return Err(err);
                    }
                } else {
                    return Err(err);
                }
            },
        };
        Ok(data)
    }

    pub fn fetch_access_token(&self) -> Option<String> {
        let res = self.request(
            Method::Get,
            "token",
            vec![
                ("grant_type", "client_credential"),
                ("appid", &self.appid),
                ("secret", &self.secret),
            ],
            &Object::new()
        );
        let mut raw_data = match res {
            Ok(raw) => raw,
            Err(_) => { return None; },
        };
        let data = match self.json_decode(&mut raw_data) {
            Ok(data) => data,
            Err(_) => { return None; },
        };
        let token = match data.find("access_token") {
            Some(token) => token,
            None => { return None; }
        };
        let expires_in = match data.find("expires_in") {
            Some(expires) => expires.as_u64().unwrap() as usize,
            None => 7200usize,
        };
        let expires_at = time::get_time().sec + expires_in as i64;
        let token_str = match *token {
            Json::String(ref v) => {
                let token_key = format!("{}_access_token", self.appid);
                let expires_key = format!("{}_expires_at", self.appid);
                self.session.set(&token_key, v.to_owned(), Some(expires_in));
                self.session.set(&expires_key, expires_at, Some(expires_in));
                Some(format!("{}", v))
            },
            _ => None,
        };
        token_str
    }
}
<commit_msg>Update WeChatClient errors<commit_after>use std::io::Read;
use std::collections::HashMap;

use time;
use url::Url;
use hyper::{self, Client};
use hyper::client::{Request, Response};
use hyper::method::Method;
use rustc_serialize::json::{self, Json, Object};
use rustc_serialize::Encodable;
use multipart::client::Multipart;

use errors::WeChatError;
use types::WeChatResult;
use session::SessionStore;

const REFETCH_ACCESS_TOKEN_ERRCODES: [i32; 3] = [40001, 40014, 42001];

#[derive(Debug, Clone)]
pub struct APIClient<T: SessionStore> {
    pub appid: String,
    pub secret: String,
    pub session: T,
}

impl<T: SessionStore> APIClient<T> {

    #[inline]
    pub fn new<S: Into<String>>(appid: S, secret: S, session: T) -> APIClient<T> {
        APIClient {
            appid: appid.into(),
            secret: secret.into(),
            session: session,
        }
    }

    #[inline]
    pub fn with_access_token<S: Into<String>>(appid: S, secret: S, access_token: S, session: T) -> APIClient<T> {
        let appid = appid.into();
        let secret = secret.into();
        let client = Self::new(appid.clone(), secret, session);
        let token_key = format!("{}_access_token", appid);
        client.session.set(&token_key, access_token.into(), None);
        client
    }

    #[inline]
    pub fn access_token(&self) -> String {
        let token_key = format!("{}_access_token", self.appid);
        let expires_key = format!("{}_expires_at", self.appid);
        let token: String = self.session.get(&token_key, Some("".to_owned())).unwrap();
        let timestamp = time::get_time().sec;
        let expires_at: i64 = self.session.get(&expires_key, Some(timestamp)).unwrap();
        if expires_at <= timestamp {
            "".to_owned()
        } else {
            token
        }
    }

    pub fn request<D: Encodable>(&self, method: Method, url: &str, params: Vec<(&str, &str)>, data: &D) -> WeChatResult<Response> {
        let mut http_url = if !(url.starts_with("http://") || url.starts_with("https://")) {
            let mut url_string = "https://api.weixin.qq.com/cgi-bin/".to_owned();
            url_string = url_string + url;
            Url::parse(&url_string).unwrap()
        } else {
            Url::parse(url).unwrap()
        };
        let access_token = self.access_token();
        let mut querys = params.clone();
        if !access_token.is_empty() {
            debug!("Using access_token: {}", access_token);
            querys.push(("access_token", &access_token));
        }
        http_url.set_query_from_pairs(querys.into_iter());
        let body = match json::encode(data) {
            Ok(text) => text,
            Err(_) => "".to_owned(),
        };
        let client = Client::new();
        let req = if method == Method::Post {
            client.post(http_url).body(&body)
        } else {
            client.get(http_url)
        };
        let res = match req.send() {
            Ok(_res) => _res,
            Err(ref e) => {
                error!("Send request error");
                return Err(WeChatError::ClientError { errcode: -1, errmsg: format!("Send request error: {}", e) });
            }
        };
        if res.status != hyper::Ok {
            error!("Response status error");
            return Err(WeChatError::ClientError { errcode: -2, errmsg: "Response status error".to_owned() })
        }
        Ok(res)

    }

    fn _upload_file<R: Read>(&self, url: &str, params: Vec<(&str, &str)>, files: &mut HashMap<String, &mut R>) -> WeChatResult<Response> {
        let mut http_url = if !(url.starts_with("http://") || url.starts_with("https://")) {
            let mut url_string = "https://api.weixin.qq.com/cgi-bin/".to_owned();
            url_string = url_string + url;
            Url::parse(&url_string).unwrap()
        } else {
            Url::parse(url).unwrap()
        };
        let access_token = self.access_token();
        let mut querys = params.clone();
        if !access_token.is_empty() {
            debug!("Using access_token: {}", access_token);
            querys.push(("access_token", &access_token));
        }
        http_url.set_query_from_pairs(querys.into_iter());
        let request = Request::new(Method::Post, http_url).unwrap();
        let mut req = Multipart::from_request(request).unwrap();
        for (name, stream) in files.iter_mut() {
            req.write_stream(name, stream, None, None);
        }
        let res = match req.send() {
            Ok(_res) => _res,
            Err(ref e) => {
                error!("Send request error");
                return Err(WeChatError::ClientError { errcode: -1, errmsg: format!("Send request error: {}", e) });
            }
        };
        if res.status != hyper::Ok {
            error!("Response status error");
            return Err(WeChatError::ClientError { errcode: -2, errmsg: "Response status error".to_owned() })
        }
        Ok(res)
    }

    pub fn upload_file<R: Read>(&self, url: &str, params: Vec<(&str, &str)>, files: &mut HashMap<String, &mut R>) -> WeChatResult<Json> {
        if self.access_token().is_empty() {
            self.fetch_access_token();
        }
        let mut res = try!(self._upload_file(url, params.clone(), files));
        let data = match self.json_decode(&mut res) {
            Ok(_data) => _data,
            Err(err) => {
                if let WeChatError::ClientError { errcode, .. } = err {
                    if REFETCH_ACCESS_TOKEN_ERRCODES.contains(&errcode) {
                        // access_token expired, fetch a new one and retry request
                        self.fetch_access_token();
                        let mut res1 = try!(self._upload_file(url, params, files));
                        try!(self.json_decode(&mut res1))
                    } else {
                        return Err(err);
                    }
                } else {
                    return Err(err);
                }
            },
        };
        Ok(data)
    }

    #[inline]
    fn json_decode(&self, res: &mut Response) -> WeChatResult<Json> {
        let obj = match Json::from_reader(res) {
            Ok(decoded) => { decoded },
            Err(ref e) => {
                error!("Json decode error");
                return Err(WeChatError::ClientError { errcode: -3, errmsg: format!("Json decode error: {}", e) });
            }
        };
        match obj.find("errcode") {
            Some(code) => {
                let errcode = code.as_i64().unwrap();
                if errcode != 0 {
                    let errmsg = match obj.find("errmsg") {
                        Some(msg) => {
                            msg.as_string().unwrap()
                        },
                        None => { "" }
                    };
                    return Err(WeChatError::ClientError { errcode: errcode as i32, errmsg: errmsg.to_owned() });
                }
            },
            None => {},
        }
        Ok(obj)
    }

    #[inline]
    pub fn post<D: Encodable>(&self, url: &str, params: Vec<(&str, &str)>, data: &D) -> WeChatResult<Json> {
        if self.access_token().is_empty() {
            self.fetch_access_token();
        }
        let mut res = try!(self.request(Method::Post, url, params.clone(), data));
        let data = match self.json_decode(&mut res) {
            Ok(_data) => _data,
            Err(err) => {
                if let WeChatError::ClientError { errcode, .. } = err {
                    if REFETCH_ACCESS_TOKEN_ERRCODES.contains(&errcode) {
                        // access_token expired, fetch a new one and retry request
                        self.fetch_access_token();
                        let mut res1 = try!(self.request(Method::Post, url, params, data));
                        try!(self.json_decode(&mut res1))
                    } else {
                        return Err(err);
                    }
                } else {
                    return Err(err);
                }
            },
        };
        Ok(data)
    }

    #[inline]
    pub fn get(&self, url: &str, params: Vec<(&str, &str)>) -> WeChatResult<Json> {
        if self.access_token().is_empty() {
            self.fetch_access_token();
        }
        let mut res = try!(self.request(Method::Get, url, params.clone(), &Object::new()));
        let data = match self.json_decode(&mut res) {
            Ok(_data) => _data,
            Err(err) => {
                if let WeChatError::ClientError { errcode, .. } = err {
                    if REFETCH_ACCESS_TOKEN_ERRCODES.contains(&errcode) {
                        // access_token expired, fetch a new one and retry request
                        self.fetch_access_token();
                        let mut res1 = try!(self.request(Method::Get, url, params, &Object::new()));
                        try!(self.json_decode(&mut res1))
                    } else {
                        return Err(err);
                    }
                } else {
                    return Err(err);
                }
            },
        };
        Ok(data)
    }

    pub fn fetch_access_token(&self) -> Option<String> {
        let res = self.request(
            Method::Get,
            "token",
            vec![
                ("grant_type", "client_credential"),
                ("appid", &self.appid),
                ("secret", &self.secret),
            ],
            &Object::new()
        );
        let mut raw_data = match res {
            Ok(raw) => raw,
            Err(_) => { return None; },
        };
        let data = match self.json_decode(&mut raw_data) {
            Ok(data) => data,
            Err(_) => { return None; },
        };
        let token = match data.find("access_token") {
            Some(token) => token,
            None => { return None; }
        };
        let expires_in = match data.find("expires_in") {
            Some(expires) => expires.as_u64().unwrap() as usize,
            None => 7200usize,
        };
        let expires_at = time::get_time().sec + expires_in as i64;
        let token_str = match *token {
            Json::String(ref v) => {
                let token_key = format!("{}_access_token", self.appid);
                let expires_key = format!("{}_expires_at", self.appid);
                self.session.set(&token_key, v.to_owned(), Some(expires_in));
                self.session.set(&expires_key, expires_at, Some(expires_in));
                Some(format!("{}", v))
            },
            _ => None,
        };
        token_str
    }
}
<|endoftext|>


<commit_before>use std;
use std::ffi::{CString, CStr, OsStr};
use std::os::unix::ffi::OsStrExt;
use std::path::{Path, PathBuf};

use super::super::Error;

/// Find the mountpoint for the volume containing the (previously canonicalized) provided path.
///
/// This uses `libc::statfs`, and as a result is (partially) unsafe.
///
/// It presumes that you will be passing in fully-qualified canonical paths (to minimize allocation
/// overhead, because the mountpoint that gets returned is a slice of the path that was passed in).
#[cfg(target_os = "macos")]
pub fn find_mountpoint_pre_canonicalized(path: &Path) -> Result<&Path, Error> {
    extern crate libc;

    let cstr = CString::new(path.as_os_str().as_bytes())?;

    let raw_mountpoint = unsafe {
        let mut fs_stat: libc::statfs = std::mem::uninitialized();
        if libc::statfs(cstr.as_ptr(), &mut fs_stat) != 0 {
            return Err(Error::from(std::io::Error::last_os_error()));
        } else {
            // CStr::from_ptr uses `libc::strlen` to delimit the slice and `transmute` to cast.
            CStr::from_ptr(fs_stat.f_mntonname.as_ptr())
        }
    };

    // from_bytes comes from OsStrExt -- it would be nice to figure out a more direct way to go
    // from CStr to OsStr
    let mountpoint = OsStr::from_bytes(raw_mountpoint.to_bytes());

    // I may remove these later, but for now I want to verify that these invariants hold in the
    // wild.
    assert!(path.starts_with(mountpoint));
    assert!(mountpoint.len() > 0);

    Ok(&Path::new(mountpoint))
}

/// Find the mountpoint for the volume containing the provided path.
///
/// Canonicalizes the path before calling `find_mountpoint_pre_canonicalized`. Because
/// canonicalization produces a PathBuf, lifetime management requires returning an owned path,
/// hence returns a PathBuf instead of a reference to a Path.
#[cfg(target_os = "macos")]
pub fn find_mountpoint(path: &Path) -> Result<PathBuf, Error> {
    let canonicalized = path.canonicalize()?;
    let found = find_mountpoint_pre_canonicalized(canonicalized.as_path())?;
    Ok(found.to_path_buf())
}
<commit_msg>narrow scope of imports<commit_after>#[cfg(target_os = "macos")]
use std::path::{Path, PathBuf};

#[cfg(target_os = "macos")]
use super::super::Error;

/// Find the mountpoint for the volume containing the (previously canonicalized) provided path.
///
/// This uses `libc::statfs`, and as a result is (partially) unsafe.
///
/// It presumes that you will be passing in fully-qualified canonical paths (to minimize allocation
/// overhead, because the mountpoint that gets returned is a slice of the path that was passed in).
#[cfg(target_os = "macos")]
pub fn find_mountpoint_pre_canonicalized(path: &Path) -> Result<&Path, Error> {
    extern crate libc;

    use std;
    use std::ffi::{CString, CStr, OsStr};
    use std::os::unix::ffi::OsStrExt;

    let cstr = CString::new(path.as_os_str().as_bytes())?;

    let raw_mountpoint = unsafe {
        let mut fs_stat: libc::statfs = std::mem::uninitialized();
        if libc::statfs(cstr.as_ptr(), &mut fs_stat) != 0 {
            return Err(Error::from(std::io::Error::last_os_error()));
        } else {
            // CStr::from_ptr uses `libc::strlen` to delimit the slice and `transmute` to cast.
            CStr::from_ptr(fs_stat.f_mntonname.as_ptr())
        }
    };

    // from_bytes comes from OsStrExt -- it would be nice to figure out a more direct way to go
    // from CStr to OsStr
    let mountpoint = OsStr::from_bytes(raw_mountpoint.to_bytes());

    // I may remove these later, but for now I want to verify that these invariants hold in the
    // wild.
    assert!(path.starts_with(mountpoint));
    assert!(mountpoint.len() > 0);

    Ok(&Path::new(mountpoint))
}

/// Find the mountpoint for the volume containing the provided path.
///
/// Canonicalizes the path before calling `find_mountpoint_pre_canonicalized`. Because
/// canonicalization produces a PathBuf, lifetime management requires returning an owned path,
/// hence returns a PathBuf instead of a reference to a Path.
#[cfg(target_os = "macos")]
pub fn find_mountpoint(path: &Path) -> Result<PathBuf, Error> {
    let canonicalized = path.canonicalize()?;
    let found = find_mountpoint_pre_canonicalized(canonicalized.as_path())?;
    Ok(found.to_path_buf())
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#![feature(proc_macro)]

extern crate gtk;
#[macro_use]
extern crate mg;
extern crate mg_settings;
#[macro_use]
extern crate mg_settings_macros;

use gtk::{ContainerExt, Entry, Label, WidgetExt};
use gtk::Orientation::Vertical;
use mg::Application;

use AppCommand::*;
use SpecialCommand::*;

#[derive(Commands)]
enum AppCommand {
    #[completion(hidden)]
    Follow,
    Insert,
    Normal,
    Open(String),
    Quit,
}

special_commands!(SpecialCommand {
    BackwardSearch('?', always),
    Search('/', always),
});

fn main() {
    gtk::init().unwrap();

    let app = Application::new_with_config(hash! {
        "i" => "insert",
    });
    app.use_dark_theme();
    let item = app.add_statusbar_item();
    item.set_text("Item");
    let item2 = app.add_statusbar_item();
    item2.set_text("Test");
    item.set_text("Rightmost");
    if let Err(error) = app.parse_config("main.conf") {
        app.error(&error.to_string());
    }
    app.add_variable("url", || "http://duckduckgo.com/lite".to_string());
    app.set_window_title("First Mg Program");

    let vbox = gtk::Box::new(Vertical, 0);
    let label = Label::new(Some("Mg App"));
    vbox.add(&label);
    let entry = Entry::new();
    vbox.add(&entry);
    app.set_view(&vbox);

    app.connect_mode_changed(|mode| println!("{}", mode));

    {
        let mg_app = app.clone();
        app.connect_command(move |command| {
            match command {
                Follow => (),
                Insert => mg_app.set_mode("insert"),
                Normal => mg_app.set_mode("normal"),
                Open(url) => label.set_text(&format!("Opening URL {}", url)),
                Quit => gtk::main_quit(),
            }
        });
    }

    {
        app.connect_special_command(move |command| {
            match command {
                BackwardSearch(input) => println!("Searching backward for {}", input),
                Search(input) => println!("Searching for {}", input),
            }
        });
    }

    entry.grab_focus();

    gtk::main();
}
<commit_msg>Added command to example.<commit_after>/*
 * Copyright (c) 2016 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#![feature(proc_macro)]

extern crate gtk;
#[macro_use]
extern crate mg;
extern crate mg_settings;
#[macro_use]
extern crate mg_settings_macros;

use gtk::{ContainerExt, Entry, Label, WidgetExt};
use gtk::Orientation::Vertical;
use mg::Application;

use AppCommand::*;
use SpecialCommand::*;

#[derive(Commands)]
enum AppCommand {
    #[completion(hidden)]
    Follow,
    Insert,
    Normal,
    Open(String),
    Quit,
    WinOpen(String),
}

special_commands!(SpecialCommand {
    BackwardSearch('?', always),
    Search('/', always),
});

fn main() {
    gtk::init().unwrap();

    let app = Application::new_with_config(hash! {
        "i" => "insert",
    });
    app.use_dark_theme();
    let item = app.add_statusbar_item();
    item.set_text("Item");
    let item2 = app.add_statusbar_item();
    item2.set_text("Test");
    item.set_text("Rightmost");
    if let Err(error) = app.parse_config("main.conf") {
        app.error(&error.to_string());
    }
    app.add_variable("url", || "http://duckduckgo.com/lite".to_string());
    app.set_window_title("First Mg Program");

    let vbox = gtk::Box::new(Vertical, 0);
    let label = Label::new(Some("Mg App"));
    vbox.add(&label);
    let entry = Entry::new();
    vbox.add(&entry);
    app.set_view(&vbox);

    app.connect_mode_changed(|mode| println!("{}", mode));

    {
        let mg_app = app.clone();
        app.connect_command(move |command| {
            match command {
                Follow => (),
                Insert => mg_app.set_mode("insert"),
                Normal => mg_app.set_mode("normal"),
                Open(url) => label.set_text(&format!("Opening URL {}", url)),
                WinOpen(url) => label.set_text(&format!("Opening URL {} in new window", url)),
                Quit => gtk::main_quit(),
            }
        });
    }

    {
        app.connect_special_command(move |command| {
            match command {
                BackwardSearch(input) => println!("Searching backward for {}", input),
                Search(input) => println!("Searching for {}", input),
            }
        });
    }

    entry.grab_focus();

    gtk::main();
}
<|endoftext|>


<commit_before>//! This module defines the `Bits` and `Dibits` iterators as well as the wrapper types
//! `Bit` and `Dibit`, for working with sub-byte values.
//!
//! The wrapped values of `Bit` and `Dibit` are guaranteed to have only one or two bits,
//! respectively.

use std;

/// Iterate over individual bits of a byte source, MSB to LSB.
pub type Bits<T> = SubByteIter<BitParams, T>;
/// Iterate over the dibits of a byte source, MSB to LSB.
pub type Dibits<T> = SubByteIter<DibitParams, T>;

/// Defines parameters needed for (power of two) sub-byte iterators.
pub trait IterParams {
    /// Type to yield at each iteration.
    type IterType;

    /// Number of bits to consume at each iteration.
    fn bits() -> u8;
    /// Wrap the given bits in container type.
    fn wrap(bits: u8) -> Self::IterType;

    /// Number of iterations needed for each byte.
    fn iterations() -> u8 { 8 / Self::bits() }

    /// Verify the parameters are supported.
    fn validate() {
        // Only powers of two are valid because there can be no "leftovers."
        assert!(Self::bits().is_power_of_two());
    }
}

/// A single bit.
pub struct Bit(u8);

impl Bit {
    /// Construct a new `Bit` with the given bit in the LSB position.
    pub fn new(bits: u8) -> Bit {
        assert!(bits & 0b11111110 == 0);
        Bit(bits)
    }

    /// Get the wrapped bit value.
    pub fn bit(&self) -> u8 { self.0 }
}

/// Parameters for `Bits` iterator.
pub struct BitParams;

impl IterParams for BitParams {
    type IterType = Bit;
    fn bits() -> u8 { 1 }
    fn wrap(bits: u8) -> Bit { Bit::new(bits) }
}

#[derive(Debug)]
/// Two bits.
pub struct Dibit(u8);

impl Dibit {
    /// Construct a new `Dibit` with the two given bits in the LSB position.
    pub fn new(bits: u8) -> Dibit {
        assert!(bits & 0b11111100 == 0);
        Dibit(bits)
    }

    /// Get the wrapped dibit.
    pub fn bits(&self) -> u8 { self.0 }
}

/// Parameters for `Dibits` iterator.
pub struct DibitParams;

impl IterParams for DibitParams {
    type IterType = Dibit;
    fn bits() -> u8 { 2 }
    fn wrap(bits: u8) -> Dibit { Dibit::new(bits) }
}

/// An iterator for sub-byte (bit-level) values.
pub struct SubByteIter<P, T> where
    P: IterParams, T: Iterator<Item = u8>
{
    params: std::marker::PhantomData<P>,
    /// Source of bytes.
    src: T,
    /// Current bit-level index into the current byte.
    idx: u8,
    /// Current byte in the source.
    byte: u8,
}

impl<P, T> SubByteIter<P, T> where
    P: IterParams, T: Iterator<Item = u8>
{
    /// Construct a new `SubByteIter` over the given byte source. All bits are iterated
    /// over, so the number of bits must be a byte multiple.
    pub fn new(src: T) -> SubByteIter<P, T> {
        SubByteIter {
            params: std::marker::PhantomData,
            src: src,
            byte: 0,
            idx: 0,
        }
    }
}

impl<P, T> Iterator for SubByteIter<P, T> where
    P: IterParams, T: Iterator<Item = u8>
{
    type Item = P::IterType;

    fn next(&mut self) -> Option<Self::Item> {
        if self.idx == 0 {
            self.byte = match self.src.next() {
                Some(b) => b,
                None => return None,
            };
        }

        // Extract MSBs.
        let bits = self.byte >> (8 - P::bits());

        // Strip off the MSBs for the next iteration.
        self.byte <<= P::bits();

        // Move to the next item and reset after all have been visited.
        self.idx += 1;
        self.idx %= P::iterations();

        Some(P::wrap(bits))
    }
}

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

    #[test]
    fn validate_params() {
        BitParams::validate();
        DibitParams::validate();
    }

    #[test]
    fn test_bits() {
        const BITS: &'static [u8] = &[
            0b00011011,
            0b11001100,
        ];

        {
            let mut d = Dibits::new(BITS.iter().cloned());

            assert!(d.next().unwrap().0 == 0b00);
            assert!(d.next().unwrap().0 == 0b01);
            assert!(d.next().unwrap().0 == 0b10);
            assert!(d.next().unwrap().0 == 0b11);
            assert!(d.next().unwrap().0 == 0b11);
            assert!(d.next().unwrap().0 == 0b00);
            assert!(d.next().unwrap().0 == 0b11);
            assert!(d.next().unwrap().0 == 0b00);
            assert!(d.next().is_none());
        }

        {
            let mut b = Bits::new(BITS.iter().cloned());

            assert!(b.next().unwrap().0 == 0);
            assert!(b.next().unwrap().0 == 0);
            assert!(b.next().unwrap().0 == 0);
            assert!(b.next().unwrap().0 == 1);
            assert!(b.next().unwrap().0 == 1);
            assert!(b.next().unwrap().0 == 0);
            assert!(b.next().unwrap().0 == 1);
            assert!(b.next().unwrap().0 == 1);
            assert!(b.next().unwrap().0 == 1);
            assert!(b.next().unwrap().0 == 1);
            assert!(b.next().unwrap().0 == 0);
            assert!(b.next().unwrap().0 == 0);
        }
    }
}
<commit_msg>Derive Copy, Default, Debug, and Eq for Bit and Dibit<commit_after>//! This module defines the `Bits` and `Dibits` iterators as well as the wrapper types
//! `Bit` and `Dibit`, for working with sub-byte values.
//!
//! The wrapped values of `Bit` and `Dibit` are guaranteed to have only one or two bits,
//! respectively.

use std;

/// Iterate over individual bits of a byte source, MSB to LSB.
pub type Bits<T> = SubByteIter<BitParams, T>;
/// Iterate over the dibits of a byte source, MSB to LSB.
pub type Dibits<T> = SubByteIter<DibitParams, T>;

/// Defines parameters needed for (power of two) sub-byte iterators.
pub trait IterParams {
    /// Type to yield at each iteration.
    type IterType;

    /// Number of bits to consume at each iteration.
    fn bits() -> u8;
    /// Wrap the given bits in container type.
    fn wrap(bits: u8) -> Self::IterType;

    /// Number of iterations needed for each byte.
    fn iterations() -> u8 { 8 / Self::bits() }

    /// Verify the parameters are supported.
    fn validate() {
        // Only powers of two are valid because there can be no "leftovers."
        assert!(Self::bits().is_power_of_two());
    }
}

/// A single bit.
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
pub struct Bit(u8);

impl Bit {
    /// Construct a new `Bit` with the given bit in the LSB position.
    pub fn new(bits: u8) -> Bit {
        assert!(bits & 0b11111110 == 0);
        Bit(bits)
    }

    /// Get the wrapped bit value.
    pub fn bit(&self) -> u8 { self.0 }
}

/// Parameters for `Bits` iterator.
pub struct BitParams;

impl IterParams for BitParams {
    type IterType = Bit;
    fn bits() -> u8 { 1 }
    fn wrap(bits: u8) -> Bit { Bit::new(bits) }
}

/// Two bits.
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
pub struct Dibit(u8);

impl Dibit {
    /// Construct a new `Dibit` with the two given bits in the LSB position.
    pub fn new(bits: u8) -> Dibit {
        assert!(bits & 0b11111100 == 0);
        Dibit(bits)
    }

    /// Get the wrapped dibit.
    pub fn bits(&self) -> u8 { self.0 }
}

/// Parameters for `Dibits` iterator.
pub struct DibitParams;

impl IterParams for DibitParams {
    type IterType = Dibit;
    fn bits() -> u8 { 2 }
    fn wrap(bits: u8) -> Dibit { Dibit::new(bits) }
}

/// An iterator for sub-byte (bit-level) values.
pub struct SubByteIter<P, T> where
    P: IterParams, T: Iterator<Item = u8>
{
    params: std::marker::PhantomData<P>,
    /// Source of bytes.
    src: T,
    /// Current bit-level index into the current byte.
    idx: u8,
    /// Current byte in the source.
    byte: u8,
}

impl<P, T> SubByteIter<P, T> where
    P: IterParams, T: Iterator<Item = u8>
{
    /// Construct a new `SubByteIter` over the given byte source. All bits are iterated
    /// over, so the number of bits must be a byte multiple.
    pub fn new(src: T) -> SubByteIter<P, T> {
        SubByteIter {
            params: std::marker::PhantomData,
            src: src,
            byte: 0,
            idx: 0,
        }
    }
}

impl<P, T> Iterator for SubByteIter<P, T> where
    P: IterParams, T: Iterator<Item = u8>
{
    type Item = P::IterType;

    fn next(&mut self) -> Option<Self::Item> {
        if self.idx == 0 {
            self.byte = match self.src.next() {
                Some(b) => b,
                None => return None,
            };
        }

        // Extract MSBs.
        let bits = self.byte >> (8 - P::bits());

        // Strip off the MSBs for the next iteration.
        self.byte <<= P::bits();

        // Move to the next item and reset after all have been visited.
        self.idx += 1;
        self.idx %= P::iterations();

        Some(P::wrap(bits))
    }
}

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

    #[test]
    fn validate_params() {
        BitParams::validate();
        DibitParams::validate();
    }

    #[test]
    fn test_bits() {
        const BITS: &'static [u8] = &[
            0b00011011,
            0b11001100,
        ];

        {
            let mut d = Dibits::new(BITS.iter().cloned());

            assert!(d.next().unwrap().0 == 0b00);
            assert!(d.next().unwrap().0 == 0b01);
            assert!(d.next().unwrap().0 == 0b10);
            assert!(d.next().unwrap().0 == 0b11);
            assert!(d.next().unwrap().0 == 0b11);
            assert!(d.next().unwrap().0 == 0b00);
            assert!(d.next().unwrap().0 == 0b11);
            assert!(d.next().unwrap().0 == 0b00);
            assert!(d.next().is_none());
        }

        {
            let mut b = Bits::new(BITS.iter().cloned());

            assert!(b.next().unwrap().0 == 0);
            assert!(b.next().unwrap().0 == 0);
            assert!(b.next().unwrap().0 == 0);
            assert!(b.next().unwrap().0 == 1);
            assert!(b.next().unwrap().0 == 1);
            assert!(b.next().unwrap().0 == 0);
            assert!(b.next().unwrap().0 == 1);
            assert!(b.next().unwrap().0 == 1);
            assert!(b.next().unwrap().0 == 1);
            assert!(b.next().unwrap().0 == 1);
            assert!(b.next().unwrap().0 == 0);
            assert!(b.next().unwrap().0 == 0);
        }
    }
}
<|endoftext|>