<commit_before>#![feature(box_syntax)]
#![feature(plugin)]

#![unstable]

#[plugin]
#[no_link]
extern crate compile_msg;

extern crate libc;

use std::ffi::{CString};
use std::sync::mpsc::{Sender};
use std::sync::Mutex;
use std::thread::Thread;

#[doc(hidden)]
pub mod ffi;

/// This static variable  will store the android_app* on creation, and set it back to 0 at
///  destruction.
/// Apart from this, the static is never written, so there is no risk of race condition.
static mut ANDROID_APP: *mut ffi::android_app = 0 as *mut ffi::android_app;

/// This is the structure that serves as user data in the android_app*
#[doc(hidden)]
struct Context {
    senders: Mutex<Vec<Sender<Event>>>,
}

/// An event triggered by the Android environment.
pub enum Event {
    EventUp,
    EventDown,
    EventMove(i32, i32),
}

impl Copy for Event {}

#[cfg(not(target_os = "android"))]
compile_note!("You are not compiling for Android");

#[macro_export]
macro_rules! android_start(
    ($main: ident) => (
        pub mod __android_start {
            extern crate android_glue;

            // this function is here because we are sure that it will be included by the linker
            // so we call app_dummy in it, in order to be sure that the native glue will be included
            #[start]
            pub fn start(_: int, _: *const *const u8) -> int {
                unsafe { android_glue::ffi::app_dummy() };
                1
            }

            #[no_mangle]
            #[inline(never)]
            #[allow(non_snake_case)]
            pub extern "C" fn android_main(app: *mut ()) {
                android_glue::android_main2(app, move|| super::$main());
            }
        }
    )
);

/// This is the function that must be called by `android_main`
#[doc(hidden)]
pub fn android_main2<F>(app: *mut (), main_function: F)
    where F: FnOnce(), F: Send
{
    use std::{mem, ptr};

    write_log("Entering android_main");

    unsafe { ANDROID_APP = std::mem::transmute(app) };
    let app: &mut ffi::android_app = unsafe { std::mem::transmute(app) };

    // creating the context that will be passed to the callback
    let context = Context { senders: Mutex::new(Vec::new()) };
    app.onAppCmd = commands_callback;
    app.onInputEvent = inputs_callback;
    app.userData = unsafe { std::mem::transmute(&context) };

    // executing the main function in parallel
    let g = Thread::spawn(move|| {
        std::io::stdio::set_stdout(box std::io::LineBufferedWriter::new(ToLogWriter));
        std::io::stdio::set_stderr(box std::io::LineBufferedWriter::new(ToLogWriter));
        main_function()
    });

    // polling for events forever
    // note that this must be done in the same thread as android_main because ALooper are
    //  thread-local
    unsafe {
        loop {
            let mut events = mem::uninitialized();
            let mut source = mem::uninitialized();

            // passing -1 means that we are blocking
            let ident = ffi::ALooper_pollAll(-1, ptr::null_mut(), &mut events,
                &mut source);

            // processing the event
            if !source.is_null() {
                let source: *mut ffi::android_poll_source = mem::transmute(source);
                ((*source).process)(ANDROID_APP, source);
            }
        }
    }

    // terminating the application
    unsafe { ANDROID_APP = 0 as *mut ffi::android_app };
}

/// Writer that will redirect what is written to it to the logs.
struct ToLogWriter;

impl Writer for ToLogWriter {
    fn write(&mut self, buf: &[u8]) -> std::io::IoResult<()> {
        let message = CString::from_slice(buf).as_slice_with_nul().as_ptr();
        let tag = b"RustAndroidGlueStdouterr";
        let tag = CString::from_slice(tag).as_slice_with_nul().as_ptr();
        unsafe { ffi::__android_log_write(3, tag, message) };
        Ok(())
    }
}

/// The callback for inputs.
pub extern fn inputs_callback(_: *mut ffi::android_app, event: *const ffi::AInputEvent)
    -> libc::int32_t
{
    fn send_event(event: Event) {
        let senders = get_context().senders.lock().ok().unwrap();
        for sender in senders.iter() {
            sender.send(event);
        }
    }
    fn get_xy(event: *const ffi::AInputEvent) -> (i32, i32) {
        let x = unsafe { ffi::AMotionEvent_getX(event, 0) };
        let y = unsafe { ffi::AMotionEvent_getY(event, 0) };
        (x as i32, y as i32)
    }
    let action = unsafe { ffi::AMotionEvent_getAction(event) };
    let action_code = action & ffi::AMOTION_EVENT_ACTION_MASK;
    match action_code {
        ffi::AMOTION_EVENT_ACTION_UP
            | ffi::AMOTION_EVENT_ACTION_OUTSIDE
            | ffi::AMOTION_EVENT_ACTION_CANCEL
            | ffi::AMOTION_EVENT_ACTION_POINTER_UP =>
        {
            send_event(Event::EventUp);
        },
        ffi::AMOTION_EVENT_ACTION_DOWN
            | ffi::AMOTION_EVENT_ACTION_POINTER_DOWN =>
        {
            let (x, y) = get_xy(event);
            send_event(Event::EventMove(x, y));
            send_event(Event::EventDown);
        },
        _ => {
            let (x, y) = get_xy(event);
            send_event(Event::EventMove(x, y));
        },
    }
    0
}

/// The callback for commands.
#[doc(hidden)]
pub extern fn commands_callback(_: *mut ffi::android_app, command: libc::int32_t) {
    let context = get_context();

    match command {
        ffi::APP_CMD_INIT_WINDOW => {

        },

        ffi::APP_CMD_SAVE_STATE => {

        },

        ffi::APP_CMD_TERM_WINDOW => {

        },

        ffi::APP_CMD_GAINED_FOCUS => {

        },

        ffi::APP_CMD_LOST_FOCUS => {

        },

        _ => ()
    }
}

/// Returns the current Context.
fn get_context() -> &'static Context {
    let context = unsafe { (*ANDROID_APP).userData };
    unsafe { std::mem::transmute(context) }
}

/// Adds a sender where events will be sent to.
pub fn add_sender(sender: Sender<Event>) {
    get_context().senders.lock().ok().unwrap().push(sender);
}

/// Returns a handle to the native window.
pub unsafe fn get_native_window() -> ffi::NativeWindowType {
    if ANDROID_APP.is_null() {
        panic!("The application was not initialized from android_main");
    }

    loop {
        let value = (*ANDROID_APP).window;
        if !value.is_null() {
            return value;
        }

        // spin-locking
        std::io::timer::sleep(std::time::Duration::milliseconds(10));
    }
}

///
pub fn write_log(message: &str) {
    let message = message.as_bytes();
    let message = CString::from_slice(message).as_slice_with_nul().as_ptr();
    let tag = b"RustAndroidGlueStdouterr";
    let tag = CString::from_slice(tag).as_slice_with_nul().as_ptr();
    unsafe { ffi::__android_log_write(3, tag, message) };
}

pub enum AssetError {
    AssetMissing,
    EmptyBuffer,
}

pub fn load_asset(filename: &str) -> Result<Vec<u8>, AssetError> {
    struct AssetCloser {
        asset: *const ffi::Asset,
    }

    impl Drop for AssetCloser {
        fn drop(&mut self) {
            unsafe {
                ffi::AAsset_close(self.asset)
            };
        }
    }

    unsafe fn get_asset_manager() -> *const ffi::AAssetManager {
        let app = &*ANDROID_APP;
        let activity = &*app.activity;
        activity.assetManager
    }

    let filename_c_str = CString::from_slice(filename.as_bytes())
        .as_slice_with_nul().as_ptr();
    let asset = unsafe {
        ffi::AAssetManager_open(
            get_asset_manager(), filename_c_str, ffi::MODE_STREAMING)
    };
    if asset.is_null() {
        return Err(AssetError::AssetMissing);
    }
    let _asset_closer = AssetCloser{asset: asset};
    let len = unsafe {
        ffi::AAsset_getLength(asset)
    };
    let buff = unsafe {
        ffi::AAsset_getBuffer(asset)
    };
    if buff.is_null() {
        return Err(AssetError::EmptyBuffer);
    }
    let vec = unsafe {
        Vec::from_raw_buf(buff as *const u8, len as usize)
    };
    Ok(vec)
}
<commit_msg>Remove keyword servo from android_start macro<commit_after>#![feature(box_syntax)]
#![feature(plugin)]

#![unstable]

#[plugin]
#[no_link]
extern crate compile_msg;

extern crate libc;

use std::ffi::{CString};
use std::sync::mpsc::{Sender};
use std::sync::Mutex;
use std::thread::Thread;

#[doc(hidden)]
pub mod ffi;

/// This static variable  will store the android_app* on creation, and set it back to 0 at
///  destruction.
/// Apart from this, the static is never written, so there is no risk of race condition.
static mut ANDROID_APP: *mut ffi::android_app = 0 as *mut ffi::android_app;

/// This is the structure that serves as user data in the android_app*
#[doc(hidden)]
struct Context {
    senders: Mutex<Vec<Sender<Event>>>,
}

/// An event triggered by the Android environment.
pub enum Event {
    EventUp,
    EventDown,
    EventMove(i32, i32),
}

impl Copy for Event {}

#[cfg(not(target_os = "android"))]
compile_note!("You are not compiling for Android");

#[macro_export]
macro_rules! android_start(
    ($main: ident) => (
        pub mod __android_start {
            extern crate android_glue;

            // this function is here because we are sure that it will be included by the linker
            // so we call app_dummy in it, in order to be sure that the native glue will be included
            #[start]
            pub fn start(_: int, _: *const *const u8) -> int {
                unsafe { android_glue::ffi::app_dummy() };
                1
            }

            #[no_mangle]
            #[inline(never)]
            #[allow(non_snake_case)]
            pub extern "C" fn android_main(app: *mut ()) {
                android_glue::android_main2(app, move|| ::$main());
            }
        }
    )
);

/// This is the function that must be called by `android_main`
#[doc(hidden)]
pub fn android_main2<F>(app: *mut (), main_function: F)
    where F: FnOnce(), F: Send
{
    use std::{mem, ptr};

    write_log("Entering android_main");

    unsafe { ANDROID_APP = std::mem::transmute(app) };
    let app: &mut ffi::android_app = unsafe { std::mem::transmute(app) };

    // creating the context that will be passed to the callback
    let context = Context { senders: Mutex::new(Vec::new()) };
    app.onAppCmd = commands_callback;
    app.onInputEvent = inputs_callback;
    app.userData = unsafe { std::mem::transmute(&context) };

    // executing the main function in parallel
    let g = Thread::spawn(move|| {
        std::io::stdio::set_stdout(box std::io::LineBufferedWriter::new(ToLogWriter));
        std::io::stdio::set_stderr(box std::io::LineBufferedWriter::new(ToLogWriter));
        main_function()
    });

    // polling for events forever
    // note that this must be done in the same thread as android_main because ALooper are
    //  thread-local
    unsafe {
        loop {
            let mut events = mem::uninitialized();
            let mut source = mem::uninitialized();

            // passing -1 means that we are blocking
            let ident = ffi::ALooper_pollAll(-1, ptr::null_mut(), &mut events,
                &mut source);

            // processing the event
            if !source.is_null() {
                let source: *mut ffi::android_poll_source = mem::transmute(source);
                ((*source).process)(ANDROID_APP, source);
            }
        }
    }

    // terminating the application
    unsafe { ANDROID_APP = 0 as *mut ffi::android_app };
}

/// Writer that will redirect what is written to it to the logs.
struct ToLogWriter;

impl Writer for ToLogWriter {
    fn write(&mut self, buf: &[u8]) -> std::io::IoResult<()> {
        let message = CString::from_slice(buf).as_slice_with_nul().as_ptr();
        let tag = b"RustAndroidGlueStdouterr";
        let tag = CString::from_slice(tag).as_slice_with_nul().as_ptr();
        unsafe { ffi::__android_log_write(3, tag, message) };
        Ok(())
    }
}

/// The callback for inputs.
pub extern fn inputs_callback(_: *mut ffi::android_app, event: *const ffi::AInputEvent)
    -> libc::int32_t
{
    fn send_event(event: Event) {
        let senders = get_context().senders.lock().ok().unwrap();
        for sender in senders.iter() {
            sender.send(event);
        }
    }
    fn get_xy(event: *const ffi::AInputEvent) -> (i32, i32) {
        let x = unsafe { ffi::AMotionEvent_getX(event, 0) };
        let y = unsafe { ffi::AMotionEvent_getY(event, 0) };
        (x as i32, y as i32)
    }
    let action = unsafe { ffi::AMotionEvent_getAction(event) };
    let action_code = action & ffi::AMOTION_EVENT_ACTION_MASK;
    match action_code {
        ffi::AMOTION_EVENT_ACTION_UP
            | ffi::AMOTION_EVENT_ACTION_OUTSIDE
            | ffi::AMOTION_EVENT_ACTION_CANCEL
            | ffi::AMOTION_EVENT_ACTION_POINTER_UP =>
        {
            send_event(Event::EventUp);
        },
        ffi::AMOTION_EVENT_ACTION_DOWN
            | ffi::AMOTION_EVENT_ACTION_POINTER_DOWN =>
        {
            let (x, y) = get_xy(event);
            send_event(Event::EventMove(x, y));
            send_event(Event::EventDown);
        },
        _ => {
            let (x, y) = get_xy(event);
            send_event(Event::EventMove(x, y));
        },
    }
    0
}

/// The callback for commands.
#[doc(hidden)]
pub extern fn commands_callback(_: *mut ffi::android_app, command: libc::int32_t) {
    let context = get_context();

    match command {
        ffi::APP_CMD_INIT_WINDOW => {

        },

        ffi::APP_CMD_SAVE_STATE => {

        },

        ffi::APP_CMD_TERM_WINDOW => {

        },

        ffi::APP_CMD_GAINED_FOCUS => {

        },

        ffi::APP_CMD_LOST_FOCUS => {

        },

        _ => ()
    }
}

/// Returns the current Context.
fn get_context() -> &'static Context {
    let context = unsafe { (*ANDROID_APP).userData };
    unsafe { std::mem::transmute(context) }
}

/// Adds a sender where events will be sent to.
pub fn add_sender(sender: Sender<Event>) {
    get_context().senders.lock().ok().unwrap().push(sender);
}

/// Returns a handle to the native window.
pub unsafe fn get_native_window() -> ffi::NativeWindowType {
    if ANDROID_APP.is_null() {
        panic!("The application was not initialized from android_main");
    }

    loop {
        let value = (*ANDROID_APP).window;
        if !value.is_null() {
            return value;
        }

        // spin-locking
        std::io::timer::sleep(std::time::Duration::milliseconds(10));
    }
}

///
pub fn write_log(message: &str) {
    let message = message.as_bytes();
    let message = CString::from_slice(message).as_slice_with_nul().as_ptr();
    let tag = b"RustAndroidGlueStdouterr";
    let tag = CString::from_slice(tag).as_slice_with_nul().as_ptr();
    unsafe { ffi::__android_log_write(3, tag, message) };
}

pub enum AssetError {
    AssetMissing,
    EmptyBuffer,
}

pub fn load_asset(filename: &str) -> Result<Vec<u8>, AssetError> {
    struct AssetCloser {
        asset: *const ffi::Asset,
    }

    impl Drop for AssetCloser {
        fn drop(&mut self) {
            unsafe {
                ffi::AAsset_close(self.asset)
            };
        }
    }

    unsafe fn get_asset_manager() -> *const ffi::AAssetManager {
        let app = &*ANDROID_APP;
        let activity = &*app.activity;
        activity.assetManager
    }

    let filename_c_str = CString::from_slice(filename.as_bytes())
        .as_slice_with_nul().as_ptr();
    let asset = unsafe {
        ffi::AAssetManager_open(
            get_asset_manager(), filename_c_str, ffi::MODE_STREAMING)
    };
    if asset.is_null() {
        return Err(AssetError::AssetMissing);
    }
    let _asset_closer = AssetCloser{asset: asset};
    let len = unsafe {
        ffi::AAsset_getLength(asset)
    };
    let buff = unsafe {
        ffi::AAsset_getBuffer(asset)
    };
    if buff.is_null() {
        return Err(AssetError::EmptyBuffer);
    }
    let vec = unsafe {
        Vec::from_raw_buf(buff as *const u8, len as usize)
    };
    Ok(vec)
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "cargo-clippy", allow(clone_on_ref_ptr))]
#![cfg_attr(feature = "cargo-clippy", allow(not_unsafe_ptr_arg_deref))]
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
#![warn(unused)]

extern crate cairo;
extern crate cairo_sys;
extern crate cssparser;
extern crate data_url;
extern crate downcast_rs;
extern crate encoding;
extern crate float_cmp;
extern crate gdk_pixbuf;
extern crate gdk_pixbuf_sys;
extern crate gio;
extern crate gio_sys;
extern crate glib;
extern crate glib_sys;
extern crate itertools;
extern crate language_tags;
extern crate libc;
extern crate locale_config;
extern crate nalgebra;
extern crate num_traits;
extern crate owning_ref;
extern crate pango;
extern crate pango_sys;
extern crate pangocairo;
extern crate rayon;
extern crate regex;
extern crate url;
extern crate xml as xml_rs;

#[macro_use]
extern crate lazy_static;

pub use color::{rsvg_css_parse_color, ColorKind, ColorSpec};

pub use handle::{
    rsvg_handle_rust_close,
    rsvg_handle_rust_free,
    rsvg_handle_rust_get_base_gfile,
    rsvg_handle_rust_get_base_url,
    rsvg_handle_rust_get_dimensions,
    rsvg_handle_rust_get_dimensions_sub,
    rsvg_handle_rust_get_dpi_x,
    rsvg_handle_rust_get_dpi_y,
    rsvg_handle_rust_get_flags,
    rsvg_handle_rust_get_geometry_sub,
    rsvg_handle_rust_get_pixbuf_sub,
    rsvg_handle_rust_get_position_sub,
    rsvg_handle_rust_has_sub,
    rsvg_handle_rust_new,
    rsvg_handle_rust_read_stream_sync,
    rsvg_handle_rust_render_cairo_sub,
    rsvg_handle_rust_set_base_url,
    rsvg_handle_rust_set_dpi_x,
    rsvg_handle_rust_set_dpi_y,
    rsvg_handle_rust_set_flags,
    rsvg_handle_rust_set_size_closure,
    rsvg_handle_rust_set_testing,
    rsvg_handle_rust_write,
};

pub use xml::rsvg_xml_state_error;

#[macro_use]
mod log;

#[macro_use]
mod coord_units;

#[macro_use]
mod float_eq_cairo;

#[macro_use]
mod property_macros;

mod allowed_url;
mod angle;
mod aspect_ratio;
mod attributes;
mod bbox;
mod clip_path;
mod color;
mod cond;
mod create_node;
mod croco;
mod css;
mod defs;
mod dpi;
mod drawing_ctx;
mod error;
pub mod filters;
mod font_props;
mod gradient;
mod handle;
mod image;
mod io;
mod iri;
mod length;
mod link;
mod load;
mod marker;
mod mask;
mod node;
mod paint_server;
mod parsers;
mod path_builder;
mod path_parser;
mod pattern;
mod property_bag;
mod rect;
mod shapes;
mod space;
pub mod srgb;
mod state;
mod stop;
mod structure;
mod style;
pub mod surface_utils;
mod svg;
mod text;
mod transform;
mod tree;
pub mod tree_utils;
mod unit_interval;
mod util;
mod viewbox;
mod viewport;
mod xml;
mod xml2;
mod xml2_load;
<commit_msg>dpi: export function to C<commit_after>#![cfg_attr(feature = "cargo-clippy", allow(clone_on_ref_ptr))]
#![cfg_attr(feature = "cargo-clippy", allow(not_unsafe_ptr_arg_deref))]
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
#![warn(unused)]

extern crate cairo;
extern crate cairo_sys;
extern crate cssparser;
extern crate data_url;
extern crate downcast_rs;
extern crate encoding;
extern crate float_cmp;
extern crate gdk_pixbuf;
extern crate gdk_pixbuf_sys;
extern crate gio;
extern crate gio_sys;
extern crate glib;
extern crate glib_sys;
extern crate itertools;
extern crate language_tags;
extern crate libc;
extern crate locale_config;
extern crate nalgebra;
extern crate num_traits;
extern crate owning_ref;
extern crate pango;
extern crate pango_sys;
extern crate pangocairo;
extern crate rayon;
extern crate regex;
extern crate url;
extern crate xml as xml_rs;

#[macro_use]
extern crate lazy_static;

pub use color::{rsvg_css_parse_color, ColorKind, ColorSpec};

pub use dpi::rsvg_rust_set_default_dpi_x_y;

pub use handle::{
    rsvg_handle_rust_close,
    rsvg_handle_rust_free,
    rsvg_handle_rust_get_base_gfile,
    rsvg_handle_rust_get_base_url,
    rsvg_handle_rust_get_dimensions,
    rsvg_handle_rust_get_dimensions_sub,
    rsvg_handle_rust_get_dpi_x,
    rsvg_handle_rust_get_dpi_y,
    rsvg_handle_rust_get_flags,
    rsvg_handle_rust_get_geometry_sub,
    rsvg_handle_rust_get_pixbuf_sub,
    rsvg_handle_rust_get_position_sub,
    rsvg_handle_rust_has_sub,
    rsvg_handle_rust_new,
    rsvg_handle_rust_read_stream_sync,
    rsvg_handle_rust_render_cairo_sub,
    rsvg_handle_rust_set_base_url,
    rsvg_handle_rust_set_dpi_x,
    rsvg_handle_rust_set_dpi_y,
    rsvg_handle_rust_set_flags,
    rsvg_handle_rust_set_size_closure,
    rsvg_handle_rust_set_testing,
    rsvg_handle_rust_write,
};

pub use xml::rsvg_xml_state_error;

#[macro_use]
mod log;

#[macro_use]
mod coord_units;

#[macro_use]
mod float_eq_cairo;

#[macro_use]
mod property_macros;

mod allowed_url;
mod angle;
mod aspect_ratio;
mod attributes;
mod bbox;
mod clip_path;
mod color;
mod cond;
mod create_node;
mod croco;
mod css;
mod defs;
mod dpi;
mod drawing_ctx;
mod error;
pub mod filters;
mod font_props;
mod gradient;
mod handle;
mod image;
mod io;
mod iri;
mod length;
mod link;
mod load;
mod marker;
mod mask;
mod node;
mod paint_server;
mod parsers;
mod path_builder;
mod path_parser;
mod pattern;
mod property_bag;
mod rect;
mod shapes;
mod space;
pub mod srgb;
mod state;
mod stop;
mod structure;
mod style;
pub mod surface_utils;
mod svg;
mod text;
mod transform;
mod tree;
pub mod tree_utils;
mod unit_interval;
mod util;
mod viewbox;
mod viewport;
mod xml;
mod xml2;
mod xml2_load;
<|endoftext|>


<commit_before>use std::iter::Iterator;
use std::iter::Peekable;
use itertools::Itertools;

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Token {
  LParen,
  RParen,
  Arrow,
  Dot,
  Colon,
  Variable(String),
}

impl ToString for Token {
  fn to_string(&self) -> String {
    match *self {
      Token::LParen => "(".to_string(),
      Token::RParen => ")".to_string(),
      Token::Arrow => "->".to_string(),
      Token::Dot => ".".to_string(),
      Token::Colon => ":".to_string(),
      Token::Variable(ref name) => name.clone(),
    }
  }
}

pub struct Lexer<I>
  where I: Clone + Iterator<Item = char>
{
  iter: Peekable<I>,
}

impl<I: Clone + Iterator<Item = char>> Lexer<I> {
  fn new(iter: I) -> Lexer<I> {
    Lexer { iter: iter.peekable() }
  }
}

impl<I: Clone + Iterator<Item = char>> Iterator for Lexer<I> {
  type Item = Token;
  fn next(&mut self) -> Option<Token> {
    match *self.iter.peek().unwrap_or(&'\0') {
      '(' => {
        self.iter.next();
        Some(Token::LParen)
      }
      ')' => {
        self.iter.next();
        Some(Token::RParen)
      }
      ':' => {
        self.iter.next();
        Some(Token::Colon)
      }
      '.' => {
        self.iter.next();
        Some(Token::Dot)
      }
      '-' => {
        self.iter.next();
        if self.iter.peek().unwrap_or(&'\0') == &'>' {
          self.iter.next();
          Some(Token::Arrow)
        } else {
          None
        }
      }
      'A'...'Z' | 'a'...'z' | '_' => {
        Some(Token::Variable(self.iter
                                 .take_while_ref(|&c| {
                                   c.is_lowercase() || c.is_uppercase() ||
                                   c == '_'
                                 })
                                 .collect::<String>()))
      }
      '\0' => None,
      _ => {
        self.iter.next();
        self.next()
      }
    }
  }
}

pub fn lex<I: Clone + Iterator<Item = char>>(iter: I) -> Lexer<I> {
  Lexer::new(iter)
}

#[test]
fn test_to_string() {
  assert_eq!("(", Token::LParen.to_string());
  assert_eq!(")", Token::RParen.to_string());
  assert_eq!("->", Token::Arrow.to_string());
  assert_eq!(".", Token::Dot.to_string());
  assert_eq!(":", Token::Colon.to_string());
  assert_eq!("a", Token::Variable("a".to_string()).to_string());
}

#[test]
fn test_lex() {
  let mut l = lex("id : (a : data) -> a -> a.".chars());
  assert_eq!(l.next(), Some(Token::Variable("id".to_string())));
  assert_eq!(l.next(), Some(Token::Colon));
  assert_eq!(l.next(), Some(Token::LParen));
  assert_eq!(l.next(), Some(Token::Variable("a".to_string())));
  assert_eq!(l.next(), Some(Token::Colon));
  assert_eq!(l.next(), Some(Token::Variable("data".to_string())));
  assert_eq!(l.next(), Some(Token::RParen));
  assert_eq!(l.next(), Some(Token::Arrow));
  assert_eq!(l.next(), Some(Token::Variable("a".to_string())));
  assert_eq!(l.next(), Some(Token::Arrow));
  assert_eq!(l.next(), Some(Token::Variable("a".to_string())));
  assert_eq!(l.next(), Some(Token::Dot));
  assert_eq!(l.next(), None);
}
<commit_msg>Add = to lexable tokens.<commit_after>use std::iter::Iterator;
use std::iter::Peekable;
use itertools::Itertools;

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Token {
  LParen,
  RParen,
  Arrow,
  Dot,
  Colon,
  Equal,
  Variable(String),
}

impl ToString for Token {
  fn to_string(&self) -> String {
    match *self {
      Token::LParen => "(".to_string(),
      Token::RParen => ")".to_string(),
      Token::Arrow => "->".to_string(),
      Token::Dot => ".".to_string(),
      Token::Colon => ":".to_string(),
      Token::Equal => "=".to_string(),
      Token::Variable(ref name) => name.clone(),
    }
  }
}

pub struct Lexer<I>
  where I: Clone + Iterator<Item = char>
{
  iter: Peekable<I>,
}

impl<I: Clone + Iterator<Item = char>> Lexer<I> {
  fn new(iter: I) -> Lexer<I> {
    Lexer { iter: iter.peekable() }
  }
}

impl<I: Clone + Iterator<Item = char>> Iterator for Lexer<I> {
  type Item = Token;
  fn next(&mut self) -> Option<Token> {
    match *self.iter.peek().unwrap_or(&'\0') {
      '(' => {
        self.iter.next();
        Some(Token::LParen)
      }
      ')' => {
        self.iter.next();
        Some(Token::RParen)
      }
      ':' => {
        self.iter.next();
        Some(Token::Colon)
      }
      '.' => {
        self.iter.next();
        Some(Token::Dot)
      }
      '=' => {
        self.iter.next();
        Some(Token::Equal)
      }
      '-' => {
        self.iter.next();
        if self.iter.peek().unwrap_or(&'\0') == &'>' {
          self.iter.next();
          Some(Token::Arrow)
        } else {
          None
        }
      }
      'A'...'Z' | 'a'...'z' | '_' => {
        Some(Token::Variable(self.iter
                                 .take_while_ref(|&c| {
                                   c.is_lowercase() || c.is_uppercase() ||
                                   c == '_'
                                 })
                                 .collect::<String>()))
      }
      '\0' => None,
      _ => {
        self.iter.next();
        self.next()
      }
    }
  }
}

pub fn lex<I: Clone + Iterator<Item = char>>(iter: I) -> Lexer<I> {
  Lexer::new(iter)
}

#[test]
fn test_to_string() {
  assert_eq!("(", Token::LParen.to_string());
  assert_eq!(")", Token::RParen.to_string());
  assert_eq!("->", Token::Arrow.to_string());
  assert_eq!(".", Token::Dot.to_string());
  assert_eq!(":", Token::Colon.to_string());
  assert_eq!("=", Token::Equal.to_string());
  assert_eq!("a", Token::Variable("a".to_string()).to_string());
}

#[test]
fn test_lex() {
  let mut l = lex("type = id : (a : data) -> a -> a.".chars());
  assert_eq!(l.next(), Some(Token::Variable("type".to_string())));
  assert_eq!(l.next(), Some(Token::Equal));
  assert_eq!(l.next(), Some(Token::Variable("id".to_string())));
  assert_eq!(l.next(), Some(Token::Colon));
  assert_eq!(l.next(), Some(Token::LParen));
  assert_eq!(l.next(), Some(Token::Variable("a".to_string())));
  assert_eq!(l.next(), Some(Token::Colon));
  assert_eq!(l.next(), Some(Token::Variable("data".to_string())));
  assert_eq!(l.next(), Some(Token::RParen));
  assert_eq!(l.next(), Some(Token::Arrow));
  assert_eq!(l.next(), Some(Token::Variable("a".to_string())));
  assert_eq!(l.next(), Some(Token::Arrow));
  assert_eq!(l.next(), Some(Token::Variable("a".to_string())));
  assert_eq!(l.next(), Some(Token::Dot));
  assert_eq!(l.next(), None);
}
<|endoftext|>


<commit_before>use chrono::Utc;
use conduit_cookie::RequestSession;

use super::prelude::*;

use crate::middleware::log_request;
use crate::models::{ApiToken, User};
use crate::util::errors::{
    account_locked, forbidden, internal, AppError, AppResult, ChainError,
    InsecurelyGeneratedTokenRevoked,
};

#[derive(Debug)]
pub struct AuthenticatedUser {
    user: User,
    token_id: Option<i32>,
}

impl AuthenticatedUser {
    pub fn user_id(&self) -> i32 {
        self.user.id
    }

    pub fn api_token_id(&self) -> Option<i32> {
        self.token_id
    }

    pub fn user(self) -> User {
        self.user
    }
}

/// The Origin header (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin)
/// is sent with CORS requests and POST requests, and indicates where the request comes from.
/// We don't want to accept authenticated requests that originated from other sites, so this
/// function returns an error if the Origin header doesn't match what we expect "this site" to
/// be: https://crates.io in production, or http://localhost:port/ in development.
fn verify_origin(req: &dyn RequestExt) -> AppResult<()> {
    let headers = req.headers();
    let allowed_origins = &req.app().config.allowed_origins;

    let bad_origin = headers
        .get_all(header::ORIGIN)
        .iter()
        .filter_map(|value| value.to_str().ok())
        .find(|value| !allowed_origins.iter().any(|it| it == value));

    if let Some(bad_origin) = bad_origin {
        let error_message = format!(
            "only same-origin requests can be authenticated. got {:?}",
            bad_origin
        );
        return Err(internal(&error_message))
            .chain_error(|| Box::new(forbidden()) as Box<dyn AppError>);
    }
    Ok(())
}

fn authenticate_user(req: &dyn RequestExt) -> AppResult<AuthenticatedUser> {
    let conn = req.db_conn()?;

    let session = req.session();
    let user_id_from_session = session.get("user_id").and_then(|s| s.parse::<i32>().ok());

    if let Some(id) = user_id_from_session {
        let user = User::find(&conn, id)
            .chain_error(|| internal("user_id from cookie not found in database"))?;

        return Ok(AuthenticatedUser {
            user,
            token_id: None,
        });
    } else {
        // Otherwise, look for an `Authorization` header on the request
        let maybe_authorization = req
            .headers()
            .get(header::AUTHORIZATION)
            .and_then(|h| h.to_str().ok());

        if let Some(header_value) = maybe_authorization {
            let token = ApiToken::find_by_api_token(&conn, header_value).map_err(|e| {
                if e.is::<InsecurelyGeneratedTokenRevoked>() {
                    e
                } else {
                    e.chain(internal("invalid token")).chain(forbidden())
                }
            })?;

            let user = User::find(&conn, token.user_id)
                .chain_error(|| internal("user_id from token not found in database"))?;

            return Ok(AuthenticatedUser {
                user,
                token_id: Some(token.id),
            });
        } else {
            // Unable to authenticate the user
            return Err(internal("no cookie session or auth header found")).chain_error(forbidden);
        }
    }
}

impl<'a> UserAuthenticationExt for dyn RequestExt + 'a {
    /// Obtain `AuthenticatedUser` for the request or return an `Forbidden` error
    fn authenticate(&mut self) -> AppResult<AuthenticatedUser> {
        verify_origin(self)?;

        let authenticated_user = authenticate_user(self)?;

        if let Some(reason) = &authenticated_user.user.account_lock_reason {
            let still_locked = if let Some(until) = authenticated_user.user.account_lock_until {
                until > Utc::now().naive_utc()
            } else {
                true
            };
            if still_locked {
                return Err(account_locked(
                    &reason,
                    authenticated_user.user.account_lock_until,
                ));
            }
        }

        log_request::add_custom_metadata(self, "uid", authenticated_user.user_id());
        if let Some(id) = authenticated_user.api_token_id() {
            log_request::add_custom_metadata(self, "tokenid", id);
        }

        Ok(authenticated_user)
    }
}
<commit_msg>controllers::util: Reduce nesting<commit_after>use chrono::Utc;
use conduit_cookie::RequestSession;

use super::prelude::*;

use crate::middleware::log_request;
use crate::models::{ApiToken, User};
use crate::util::errors::{
    account_locked, forbidden, internal, AppError, AppResult, ChainError,
    InsecurelyGeneratedTokenRevoked,
};

#[derive(Debug)]
pub struct AuthenticatedUser {
    user: User,
    token_id: Option<i32>,
}

impl AuthenticatedUser {
    pub fn user_id(&self) -> i32 {
        self.user.id
    }

    pub fn api_token_id(&self) -> Option<i32> {
        self.token_id
    }

    pub fn user(self) -> User {
        self.user
    }
}

/// The Origin header (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin)
/// is sent with CORS requests and POST requests, and indicates where the request comes from.
/// We don't want to accept authenticated requests that originated from other sites, so this
/// function returns an error if the Origin header doesn't match what we expect "this site" to
/// be: https://crates.io in production, or http://localhost:port/ in development.
fn verify_origin(req: &dyn RequestExt) -> AppResult<()> {
    let headers = req.headers();
    let allowed_origins = &req.app().config.allowed_origins;

    let bad_origin = headers
        .get_all(header::ORIGIN)
        .iter()
        .filter_map(|value| value.to_str().ok())
        .find(|value| !allowed_origins.iter().any(|it| it == value));

    if let Some(bad_origin) = bad_origin {
        let error_message = format!(
            "only same-origin requests can be authenticated. got {:?}",
            bad_origin
        );
        return Err(internal(&error_message))
            .chain_error(|| Box::new(forbidden()) as Box<dyn AppError>);
    }
    Ok(())
}

fn authenticate_user(req: &dyn RequestExt) -> AppResult<AuthenticatedUser> {
    let conn = req.db_conn()?;

    let session = req.session();
    let user_id_from_session = session.get("user_id").and_then(|s| s.parse::<i32>().ok());

    if let Some(id) = user_id_from_session {
        let user = User::find(&conn, id)
            .chain_error(|| internal("user_id from cookie not found in database"))?;

        return Ok(AuthenticatedUser {
            user,
            token_id: None,
        });
    }

    // Otherwise, look for an `Authorization` header on the request
    let maybe_authorization = req
        .headers()
        .get(header::AUTHORIZATION)
        .and_then(|h| h.to_str().ok());

    if let Some(header_value) = maybe_authorization {
        let token = ApiToken::find_by_api_token(&conn, header_value).map_err(|e| {
            if e.is::<InsecurelyGeneratedTokenRevoked>() {
                e
            } else {
                e.chain(internal("invalid token")).chain(forbidden())
            }
        })?;

        let user = User::find(&conn, token.user_id)
            .chain_error(|| internal("user_id from token not found in database"))?;

        return Ok(AuthenticatedUser {
            user,
            token_id: Some(token.id),
        });
    }

    // Unable to authenticate the user
    return Err(internal("no cookie session or auth header found")).chain_error(forbidden);
}

impl<'a> UserAuthenticationExt for dyn RequestExt + 'a {
    /// Obtain `AuthenticatedUser` for the request or return an `Forbidden` error
    fn authenticate(&mut self) -> AppResult<AuthenticatedUser> {
        verify_origin(self)?;

        let authenticated_user = authenticate_user(self)?;

        if let Some(reason) = &authenticated_user.user.account_lock_reason {
            let still_locked = if let Some(until) = authenticated_user.user.account_lock_until {
                until > Utc::now().naive_utc()
            } else {
                true
            };
            if still_locked {
                return Err(account_locked(
                    &reason,
                    authenticated_user.user.account_lock_until,
                ));
            }
        }

        log_request::add_custom_metadata(self, "uid", authenticated_user.user_id());
        if let Some(id) = authenticated_user.api_token_id() {
            log_request::add_custom_metadata(self, "tokenid", id);
        }

        Ok(authenticated_user)
    }
}
<|endoftext|>


<commit_before>use super::*;

use std;
use std::fmt::{Debug, Display, Formatter};
use std::ops::*;

/// Represents an element of ModInt field.
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
struct ModInt(i64);

impl ModInt {
    fn pow(self, e: i64) -> Self {
        pow(self.0, e).into()
    }
}

impl Debug for ModInt {
    fn fmt(&self, formatter: &mut Formatter) -> std::fmt::Result {
        formatter.write_fmt(format_args!("{:?}", self.0))
    }
}

impl Display for ModInt {
    fn fmt(&self, formatter: &mut Formatter) -> std::fmt::Result {
        formatter.write_fmt(format_args!("{}", self.0))
    }
}

impl From<i64> for ModInt {
    fn from(value: i64) -> Self {
        ModInt((value % P + P) % P)
    }
}

// Generate binary operation traits.
macro_rules! impl_binary_op_for_modint {
    ($op_trait:ident, $op:ident, $assign_trait:ident, $assign:ident $(, $f:ident)*) => {
        $(impl $op_trait<ModInt> for ModInt {
            type Output = Self;

            fn $op(self, other: Self) -> Self {
                ModInt::from((self.0).$f(other.0))
            }
        })*

        impl $op_trait<i64> for ModInt {
            type Output = Self;

            fn $op(self, other: i64) -> Self {
                self.$op(ModInt::from(other))
            }
        }

        impl $assign_trait<ModInt> for ModInt {
            fn $assign(&mut self, other: Self) {
                *self = self.$op(other)
            }
        }

        impl $assign_trait<i64> for ModInt {
            fn $assign(&mut self, other: i64) {
                *self = self.$op(other)
            }
        }
    };
}

impl_binary_op_for_modint! {Add, add, AddAssign, add_assign, add}
impl_binary_op_for_modint! {Sub, sub, SubAssign, sub_assign, sub}
impl_binary_op_for_modint! {Mul, mul, MulAssign, mul_assign, mul}
impl_binary_op_for_modint! {Div, div, DivAssign, div_assign}

impl Div<ModInt> for ModInt {
    type Output = ModInt;

    fn div(self, other: Self) -> Self {
        self * other.pow(P - 2)
    }
}

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

    #[test]
    fn test_ops() {
        let x = ModInt::from(P + 2);

        // `from` should normalize the value.
        assert_eq!(x.0, 2);

        // Operations.
        assert_eq!(x + 7, (2 + 7).into());
        assert_eq!(x - 7, (P + (2 - 7)).into());
        assert_eq!(x * 3, (2 * 3).into());
        assert_eq!((x / 11) * 11, 2.into());

        assert_eq!(x + ModInt::from(7), (2 + 7).into());
        assert_eq!(x - ModInt::from(7), (P + (2 - 7)).into());
        assert_eq!(x * ModInt::from(3), (2 * 3).into());
        assert_eq!((x / ModInt::from(11)) * 11, 2.into());

        let mut x = x;
        x += 7;
        assert_eq!(x, 9.into());
        x -= 5;
        assert_eq!(x, 4.into());
        x *= 6;
        assert_eq!(x, 24.into());
        x /= 3;
        assert_eq!(x, 8.into());
    }

    #[test]
    fn test_fmt() {
        assert_eq!(format!("{:?}", ModInt::from(2)), "2");
        assert_eq!(format!("{}", ModInt::from(2)), "2");
    }
}
<commit_msg>fix: Fix typo<commit_after>use super::*;

use std;
use std::fmt::{Debug, Display, Formatter};
use std::ops::*;

/// Represents an element of finite field.
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
struct ModInt(i64);

impl ModInt {
    fn pow(self, e: i64) -> Self {
        pow(self.0, e).into()
    }
}

impl Debug for ModInt {
    fn fmt(&self, formatter: &mut Formatter) -> std::fmt::Result {
        formatter.write_fmt(format_args!("{:?}", self.0))
    }
}

impl Display for ModInt {
    fn fmt(&self, formatter: &mut Formatter) -> std::fmt::Result {
        formatter.write_fmt(format_args!("{}", self.0))
    }
}

impl From<i64> for ModInt {
    fn from(value: i64) -> Self {
        ModInt((value % P + P) % P)
    }
}

// Generate binary operation traits.
macro_rules! impl_binary_op_for_modint {
    ($op_trait:ident, $op:ident, $assign_trait:ident, $assign:ident $(, $f:ident)*) => {
        $(impl $op_trait<ModInt> for ModInt {
            type Output = Self;

            fn $op(self, other: Self) -> Self {
                ModInt::from((self.0).$f(other.0))
            }
        })*

        impl $op_trait<i64> for ModInt {
            type Output = Self;

            fn $op(self, other: i64) -> Self {
                self.$op(ModInt::from(other))
            }
        }

        impl $assign_trait<ModInt> for ModInt {
            fn $assign(&mut self, other: Self) {
                *self = self.$op(other)
            }
        }

        impl $assign_trait<i64> for ModInt {
            fn $assign(&mut self, other: i64) {
                *self = self.$op(other)
            }
        }
    };
}

impl_binary_op_for_modint! {Add, add, AddAssign, add_assign, add}
impl_binary_op_for_modint! {Sub, sub, SubAssign, sub_assign, sub}
impl_binary_op_for_modint! {Mul, mul, MulAssign, mul_assign, mul}
impl_binary_op_for_modint! {Div, div, DivAssign, div_assign}

impl Div<ModInt> for ModInt {
    type Output = ModInt;

    fn div(self, other: Self) -> Self {
        self * other.pow(P - 2)
    }
}

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

    #[test]
    fn test_ops() {
        let x = ModInt::from(P + 2);

        // `from` should normalize the value.
        assert_eq!(x.0, 2);

        // Operations.
        assert_eq!(x + 7, (2 + 7).into());
        assert_eq!(x - 7, (P + (2 - 7)).into());
        assert_eq!(x * 3, (2 * 3).into());
        assert_eq!((x / 11) * 11, 2.into());

        assert_eq!(x + ModInt::from(7), (2 + 7).into());
        assert_eq!(x - ModInt::from(7), (P + (2 - 7)).into());
        assert_eq!(x * ModInt::from(3), (2 * 3).into());
        assert_eq!((x / ModInt::from(11)) * 11, 2.into());

        let mut x = x;
        x += 7;
        assert_eq!(x, 9.into());
        x -= 5;
        assert_eq!(x, 4.into());
        x *= 6;
        assert_eq!(x, 24.into());
        x /= 3;
        assert_eq!(x, 8.into());
    }

    #[test]
    fn test_fmt() {
        assert_eq!(format!("{:?}", ModInt::from(2)), "2");
        assert_eq!(format!("{}", ModInt::from(2)), "2");
    }
}
<|endoftext|>


<commit_before>use std::time::Duration;

use futures::{Future, IntoFuture, Poll, Async};
use futures::sync::oneshot::spawn;
use tokio::runtime::Runtime;

use super::credential::CredentialsError;
use super::client::{TimeoutFuture, SignAndDispatchError};
use super::request::{HttpResponse, HttpDispatchError};

lazy_static! {
    static ref FALLBACK_RUNTIME: Runtime = Runtime::new().unwrap();
}

/// Future that is returned from all rusoto service APIs.
pub struct RusotoFuture<T, E> {
    state: Option<RusotoFutureState<T, E>>
}

pub fn new<T, E>(
        future: Box<TimeoutFuture<Item=HttpResponse, Error=SignAndDispatchError> + Send>,
        handler: fn(HttpResponse) -> Box<Future<Item=T, Error=E> + Send>
    ) -> RusotoFuture<T, E>
{
    RusotoFuture { state: Some(RusotoFutureState::SignAndDispatch { future, handler }) }
}

impl<T, E> RusotoFuture<T, E> {
    /// Set the timeout on the future to the provided duration.
    ///
    /// Unlike `set_timeout` this method can be easily chained:
    ///
    /// ```rust,ignore
    /// let future = s3.head_object(...)
    ///     .with_timeout(Duration::from_secs(10));
    /// ```
    ///
    /// This is only guaranteed to take effect when called before the future
    /// is polled for the first time.
    pub fn with_timeout(mut self, timeout: Duration) -> Self {
        self.set_timeout(timeout);
        self
    }

    /// Set the timeout on the future to the provided duration.
    ///
    /// This is only guaranteed to take effect when called before the future
    /// is polled for the first time.
    pub fn set_timeout(&mut self, timeout: Duration) {
        if let Some(RusotoFutureState::SignAndDispatch { ref mut future, .. }) = self.state {
            future.set_timeout(timeout);
        }
    }

    /// Clear the timeout on the future.
    ///
    /// This is only guaranteed to take effect when called before the future
    /// is polled for the first time.
    pub fn clear_timeout(&mut self) {
        if let Some(RusotoFutureState::SignAndDispatch { ref mut future, .. }) = self.state {
            future.clear_timeout();
        }
    }

    /// Blocks the current thread until the future has resolved.
    ///
    /// This is meant to provide a simple way for non-async consumers
    /// to work with rusoto.
    pub fn sync(self) -> Result<T, E>
        where T: Send + 'static,
              E: From<CredentialsError> + From<HttpDispatchError> + Send + 'static
    {
        spawn(self, &FALLBACK_RUNTIME.executor()).wait()
    }
}

impl<T, E> Future for RusotoFuture<T, E>
    where E: From<CredentialsError> + From<HttpDispatchError>
{
    type Item = T;
    type Error = E;

    fn poll(&mut self) -> Poll<T, E> {
        match self.state.take().unwrap() {
            RusotoFutureState::SignAndDispatch { mut future, handler } => {
                match future.poll() {
                    Err(SignAndDispatchError::Credentials(err)) => Err(err.into()),
                    Err(SignAndDispatchError::Dispatch(err)) => Err(err.into()),
                    Ok(Async::Ready(response)) => {
                        self.state = Some(RusotoFutureState::RunningResponseHandler(handler(response)));
                        self.poll()
                    },
                    Ok(Async::NotReady) => {
                        self.state = Some(RusotoFutureState::SignAndDispatch { future, handler });
                        Ok(Async::NotReady)
                    }
                }
            },
            RusotoFutureState::RunningResponseHandler(mut future) => {
                match future.poll()? {
                    Async::Ready(value) => Ok(Async::Ready(value)),
                    Async::NotReady => {
                        self.state = Some(RusotoFutureState::RunningResponseHandler(future));
                        Ok(Async::NotReady)
                    }
                }
            }
        }
    }
}

enum RusotoFutureState<T, E> {
    SignAndDispatch {
        future: Box<TimeoutFuture<Item=HttpResponse, Error=SignAndDispatchError> + Send>,
        handler: fn(HttpResponse) -> Box<Future<Item=T, Error=E> + Send>
    },
    RunningResponseHandler(Box<Future<Item=T, Error=E> + Send>)
}

impl<T: Send + 'static, E: Send + 'static> From<Result<T, E>> for RusotoFuture<T, E> {
    fn from(value: Result<T, E>) -> Self {
        let fut = value.into_future();
        RusotoFuture {
            state: Some(RusotoFutureState::RunningResponseHandler(Box::new(fut))),
        }
    }
}

#[test]
fn rusoto_future_is_send() {
    fn is_send<T: Send>() {}

    is_send::<RusotoFuture<(), ()>>();
}

#[test]
fn rusuto_future_from_ok() {
    use std::error::Error;
    let fut: RusotoFuture<i32, Box<Error + Send + Sync>> = RusotoFuture::from(Ok(42));
    assert_eq!(fut.sync().unwrap(), 42);
}

#[test]
fn rusuto_future_from_err() {
    use std::error::Error;
    let fut: RusotoFuture<i32, Box<Error + Send + Sync>> =
        RusotoFuture::from("ab".parse::<i32>().map_err(|e| e.into()));
    assert!(fut.sync().is_err());
}
<commit_msg>Add an example mocking RusotoFuture.<commit_after>use std::time::Duration;

use futures::{Future, IntoFuture, Poll, Async};
use futures::sync::oneshot::spawn;
use tokio::runtime::Runtime;

use super::credential::CredentialsError;
use super::client::{TimeoutFuture, SignAndDispatchError};
use super::request::{HttpResponse, HttpDispatchError};

lazy_static! {
    static ref FALLBACK_RUNTIME: Runtime = Runtime::new().unwrap();
}

/// Future that is returned from all rusoto service APIs.
///
/// ## Mocking
///
/// To mock service traits, you can use the `From` implementation to create `RusotoFuture`
/// instance.
///
/// ```rust,ignore
/// use rusoto_core::RusotoFuture;
/// use rusoto_s3::*;
///
/// pub struct S3Mock;
///
/// impl S3 for S3Mock {
///     fn abort_multipart_upload(
///         &self,
///         _input: AbortMultipartUploadRequest,
///     ) -> RusotoFuture<AbortMultipartUploadOutput, AbortMultipartUploadError> {
///         unimplemented!();
///     }
///
///     ...
///
///     fn put_object(&self, input: PutObjectRequest) -> RusotoFuture<PutObjectOutput, PutObjectError> {
///         if input.bucket == "foo" {
///             Ok(PutObjectOutput {
///                 ..Default::default()
///             }).into()
///         } else {
///             Err(PutObjectError::Validation("Invalid bucket".to_string())).into()
///         }
///     }
///
///     ...
/// }
/// ```
pub struct RusotoFuture<T, E> {
    state: Option<RusotoFutureState<T, E>>
}

pub fn new<T, E>(
        future: Box<TimeoutFuture<Item=HttpResponse, Error=SignAndDispatchError> + Send>,
        handler: fn(HttpResponse) -> Box<Future<Item=T, Error=E> + Send>
    ) -> RusotoFuture<T, E>
{
    RusotoFuture { state: Some(RusotoFutureState::SignAndDispatch { future, handler }) }
}

impl<T, E> RusotoFuture<T, E> {
    /// Set the timeout on the future to the provided duration.
    ///
    /// Unlike `set_timeout` this method can be easily chained:
    ///
    /// ```rust,ignore
    /// let future = s3.head_object(...)
    ///     .with_timeout(Duration::from_secs(10));
    /// ```
    ///
    /// This is only guaranteed to take effect when called before the future
    /// is polled for the first time.
    pub fn with_timeout(mut self, timeout: Duration) -> Self {
        self.set_timeout(timeout);
        self
    }

    /// Set the timeout on the future to the provided duration.
    ///
    /// This is only guaranteed to take effect when called before the future
    /// is polled for the first time.
    pub fn set_timeout(&mut self, timeout: Duration) {
        if let Some(RusotoFutureState::SignAndDispatch { ref mut future, .. }) = self.state {
            future.set_timeout(timeout);
        }
    }

    /// Clear the timeout on the future.
    ///
    /// This is only guaranteed to take effect when called before the future
    /// is polled for the first time.
    pub fn clear_timeout(&mut self) {
        if let Some(RusotoFutureState::SignAndDispatch { ref mut future, .. }) = self.state {
            future.clear_timeout();
        }
    }

    /// Blocks the current thread until the future has resolved.
    ///
    /// This is meant to provide a simple way for non-async consumers
    /// to work with rusoto.
    pub fn sync(self) -> Result<T, E>
        where T: Send + 'static,
              E: From<CredentialsError> + From<HttpDispatchError> + Send + 'static
    {
        spawn(self, &FALLBACK_RUNTIME.executor()).wait()
    }
}

impl<T, E> Future for RusotoFuture<T, E>
    where E: From<CredentialsError> + From<HttpDispatchError>
{
    type Item = T;
    type Error = E;

    fn poll(&mut self) -> Poll<T, E> {
        match self.state.take().unwrap() {
            RusotoFutureState::SignAndDispatch { mut future, handler } => {
                match future.poll() {
                    Err(SignAndDispatchError::Credentials(err)) => Err(err.into()),
                    Err(SignAndDispatchError::Dispatch(err)) => Err(err.into()),
                    Ok(Async::Ready(response)) => {
                        self.state = Some(RusotoFutureState::RunningResponseHandler(handler(response)));
                        self.poll()
                    },
                    Ok(Async::NotReady) => {
                        self.state = Some(RusotoFutureState::SignAndDispatch { future, handler });
                        Ok(Async::NotReady)
                    }
                }
            },
            RusotoFutureState::RunningResponseHandler(mut future) => {
                match future.poll()? {
                    Async::Ready(value) => Ok(Async::Ready(value)),
                    Async::NotReady => {
                        self.state = Some(RusotoFutureState::RunningResponseHandler(future));
                        Ok(Async::NotReady)
                    }
                }
            }
        }
    }
}

enum RusotoFutureState<T, E> {
    SignAndDispatch {
        future: Box<TimeoutFuture<Item=HttpResponse, Error=SignAndDispatchError> + Send>,
        handler: fn(HttpResponse) -> Box<Future<Item=T, Error=E> + Send>
    },
    RunningResponseHandler(Box<Future<Item=T, Error=E> + Send>)
}

impl<T: Send + 'static, E: Send + 'static> From<Result<T, E>> for RusotoFuture<T, E> {
    fn from(value: Result<T, E>) -> Self {
        let fut = value.into_future();
        RusotoFuture {
            state: Some(RusotoFutureState::RunningResponseHandler(Box::new(fut))),
        }
    }
}

#[test]
fn rusoto_future_is_send() {
    fn is_send<T: Send>() {}

    is_send::<RusotoFuture<(), ()>>();
}

#[test]
fn rusuto_future_from_ok() {
    use std::error::Error;
    let fut: RusotoFuture<i32, Box<Error + Send + Sync>> = RusotoFuture::from(Ok(42));
    assert_eq!(fut.sync().unwrap(), 42);
}

#[test]
fn rusuto_future_from_err() {
    use std::error::Error;
    let fut: RusotoFuture<i32, Box<Error + Send + Sync>> =
        RusotoFuture::from("ab".parse::<i32>().map_err(|e| e.into()));
    assert!(fut.sync().is_err());
}
<|endoftext|>


<commit_before>// Copyright 2017 Google Inc. All rights reserved.
//
// 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.

#![feature(test)]

extern crate test;
extern crate xi_rope;

use test::Bencher;
use xi_rope::tree::*;

fn build_triangle(n: usize) -> String {
    let mut s = String::new();
    let mut line = String::new();
    for _ in 0..n {
        s += &line;
        s += "\n";
        line += "a";
    }
    s
}

fn build_short_lines(n: usize) -> String {
    let line = "match s.as_bytes()[minsplit - 1..splitpoint].iter().rposition(|&c| c == b'\n') {";
    let mut s = String::new();
    for _ in 0..n {
        s += line;
    }
    s
}

fn build_few_big_lines(size: usize) -> String {
    let mut s = String::with_capacity(size * 10 + 20);
    for _ in 0..10 {
        for _ in 0..size {
            s += "a";
        }
        s += "\n";
    }
    s
}

#[bench]
fn build_tree_triangle(b: &mut Bencher) {
    let mut t = TreeBuilder::new();
    b.iter(|| t.push_str(&build_triangle(500)));
}

#[bench]
fn build_tree_short_lines(b: &mut Bencher) {
    let mut t = TreeBuilder::new();
    b.iter(|| t.push_str(&build_short_lines(1_000)));
}

#[bench]
fn build_tree_few_big_lines(b: &mut Bencher) {
    let mut t = TreeBuilder::new();
    b.iter(|| t.push_str(&build_few_big_lines(1_000)));
}

#[bench]
fn build_tree_triangle_stack(b: &mut Bencher) {
    let mut t = TreeBuilder::new();
    b.iter(|| t.push_str_stacked(&build_triangle(500)));
}

#[bench]
fn build_tree_short_lines_stack(b: &mut Bencher) {
    let mut t = TreeBuilder::new();
    b.iter(|| t.push_str_stacked(&build_short_lines(1_000)));
}

#[bench]
fn build_tree_few_big_lines_stack(b: &mut Bencher) {
    let mut t = TreeBuilder::new();
    b.iter(|| t.push_str_stacked(&build_few_big_lines(1_000)));
}
<commit_msg>Change copyright message<commit_after>// Copyright 2017 The xi-editor 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.

#![feature(test)]

extern crate test;
extern crate xi_rope;

use test::Bencher;
use xi_rope::tree::*;

fn build_triangle(n: usize) -> String {
    let mut s = String::new();
    let mut line = String::new();
    for _ in 0..n {
        s += &line;
        s += "\n";
        line += "a";
    }
    s
}

fn build_short_lines(n: usize) -> String {
    let line = "match s.as_bytes()[minsplit - 1..splitpoint].iter().rposition(|&c| c == b'\n') {";
    let mut s = String::new();
    for _ in 0..n {
        s += line;
    }
    s
}

fn build_few_big_lines(size: usize) -> String {
    let mut s = String::with_capacity(size * 10 + 20);
    for _ in 0..10 {
        for _ in 0..size {
            s += "a";
        }
        s += "\n";
    }
    s
}

#[bench]
fn build_tree_triangle(b: &mut Bencher) {
    let mut t = TreeBuilder::new();
    b.iter(|| t.push_str(&build_triangle(500)));
}

#[bench]
fn build_tree_short_lines(b: &mut Bencher) {
    let mut t = TreeBuilder::new();
    b.iter(|| t.push_str(&build_short_lines(1_000)));
}

#[bench]
fn build_tree_few_big_lines(b: &mut Bencher) {
    let mut t = TreeBuilder::new();
    b.iter(|| t.push_str(&build_few_big_lines(1_000)));
}

#[bench]
fn build_tree_triangle_stack(b: &mut Bencher) {
    let mut t = TreeBuilder::new();
    b.iter(|| t.push_str_stacked(&build_triangle(500)));
}

#[bench]
fn build_tree_short_lines_stack(b: &mut Bencher) {
    let mut t = TreeBuilder::new();
    b.iter(|| t.push_str_stacked(&build_short_lines(1_000)));
}

#[bench]
fn build_tree_few_big_lines_stack(b: &mut Bencher) {
    let mut t = TreeBuilder::new();
    b.iter(|| t.push_str_stacked(&build_few_big_lines(1_000)));
}
<|endoftext|>


<commit_before>//! Error types.

use std::error;
use std::fmt;

use cssparser::{BasicParseError, BasicParseErrorKind, ParseErrorKind, ToCss};
use markup5ever::QualName;

use crate::allowed_url::Fragment;
use crate::node::Node;

/// A short-lived error.
///
/// The lifetime of the error is the same as the `cssparser::ParserInput` that
/// was used to create a `cssparser::Parser`.  That is, it is the lifetime of
/// the string data that is being parsed.
///
/// The code flow will sometimes require preserving this error as a long-lived struct;
/// see the `impl<'i, O> AttributeResultExt<O> for Result<O, ParseError<'i>>` for that
/// purpose.
pub type ParseError<'i> = cssparser::ParseError<'i, ValueErrorKind>;

/// A simple error which refers to an attribute's value
#[derive(Debug, Clone, PartialEq)]
pub enum ValueErrorKind {
    /// A property with the specified name was not found
    UnknownProperty,

    /// The value could not be parsed
    Parse(String),

    // The value could be parsed, but is invalid
    Value(String),
}

impl ValueErrorKind {
    pub fn parse_error(s: &str) -> ValueErrorKind {
        ValueErrorKind::Parse(s.to_string())
    }

    pub fn value_error(s: &str) -> ValueErrorKind {
        ValueErrorKind::Value(s.to_string())
    }
}

impl fmt::Display for ValueErrorKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            ValueErrorKind::UnknownProperty => write!(f, "unknown property name"),

            ValueErrorKind::Parse(ref s) => write!(f, "parse error: {}", s),

            ValueErrorKind::Value(ref s) => write!(f, "invalid value: {}", s),
        }
    }
}

impl<'a> From<BasicParseError<'a>> for ValueErrorKind {
    fn from(e: BasicParseError<'_>) -> ValueErrorKind {
        let BasicParseError { kind, .. } = e;

        let msg = match kind {
            BasicParseErrorKind::UnexpectedToken(_) => "unexpected token",
            BasicParseErrorKind::EndOfInput => "unexpected end of input",
            BasicParseErrorKind::AtRuleInvalid(_) => "invalid @-rule",
            BasicParseErrorKind::AtRuleBodyInvalid => "invalid @-rule body",
            BasicParseErrorKind::QualifiedRuleInvalid => "invalid qualified rule",
        };

        ValueErrorKind::parse_error(msg)
    }
}

/// A complete error for an attribute and its erroneous value
#[derive(Debug, Clone, PartialEq)]
pub struct ElementError {
    pub attr: QualName,
    pub err: ValueErrorKind,
}

impl error::Error for ElementError {
    fn description(&self) -> &str {
        match self.err {
            ValueErrorKind::UnknownProperty => "unknown property",
            ValueErrorKind::Parse(_) => "parse error",
            ValueErrorKind::Value(_) => "invalid attribute value",
        }
    }
}

impl fmt::Display for ElementError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}: {}", self.attr.expanded(), self.err)
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum DefsLookupErrorKind {
    HrefError(HrefError),
    CannotLookupExternalReferences,
    NotFound,
}

#[derive(Debug, Clone, PartialEq)]
pub enum RenderingError {
    Cairo(cairo::Status),
    CircularReference,
    InstancingLimit,
    InvalidId(DefsLookupErrorKind),
    InvalidHref,
    OutOfMemory,
    HandleIsNotLoaded,
}

impl error::Error for RenderingError {}

impl fmt::Display for RenderingError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            RenderingError::CircularReference => write!(f, "circular reference"),
            RenderingError::InstancingLimit => write!(f, "instancing limit"),
            RenderingError::InvalidHref => write!(f, "invalid href"),
            RenderingError::OutOfMemory => write!(f, "out of memory"),
            RenderingError::HandleIsNotLoaded => write!(f, "SVG data is not loaded into handle"),
            RenderingError::Cairo(ref status) => write!(f, "cairo error: {:?}", status),
            RenderingError::InvalidId(ref id) => write!(f, "invalid id: {:?}", id),
        }
    }
}

impl From<cairo::Status> for RenderingError {
    fn from(e: cairo::Status) -> RenderingError {
        assert!(e != cairo::Status::Success);

        RenderingError::Cairo(e)
    }
}

pub enum AcquireError {
    LinkNotFound(Fragment),
    InvalidLinkType(Fragment),
    CircularReference(Node),
    MaxReferencesExceeded,
}

impl fmt::Display for AcquireError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            AcquireError::LinkNotFound(ref frag) => write!(f, "link not found: {}", frag),

            AcquireError::InvalidLinkType(ref frag) => {
                write!(f, "link {} is to object of invalid type", frag)
            }

            AcquireError::CircularReference(ref node) => {
                write!(f, "circular reference in node {}", node)
            }

            AcquireError::MaxReferencesExceeded => {
                write!(f, "maximum number of references exceeded")
            }
        }
    }
}

/// Helper for converting `Result<O, E>` into `Result<O, ElementError>`
///
/// A `ElementError` requires a `QualName` that corresponds to the attribute to which the
/// error refers, plus the actual `ValueErrorKind` that describes the error.  However,
/// parsing functions for attribute value types will want to return their own kind of
/// error, instead of `ValueErrorKind`.  If that particular error type has an `impl
/// From<FooError> for ValueErrorKind`, then this trait helps assign attribute values in
/// `set_atts()` methods as follows:
///
/// ```ignore
/// use error::AttributeResultExt;
///
/// // fn parse_foo(...) -> Result<Foo, FooError>
///
/// // It is assumed that there is an impl From<FooError> for ValueErrorKind
///
/// self.foo = parse_foo(value).attribute(local_name!("foo"))?;
/// ```
///
/// The call to `.attribute(attr)` converts the `Result` from `parse_foo()` into a full
/// `ElementError` with the provided `attr`.
pub trait AttributeResultExt<O> {
    fn attribute(self, attr: QualName) -> Result<O, ElementError>;
}

impl<O, E: Into<ValueErrorKind>> AttributeResultExt<O> for Result<O, E> {
    fn attribute(self, attr: QualName) -> Result<O, ElementError> {
        self.map_err(|e| e.into())
            .map_err(|err| ElementError { attr, err })
    }
}

/// Turns a short-lived `ParseError` into a long-lived `ElementError`
impl<'i, O> AttributeResultExt<O> for Result<O, ParseError<'i>> {
    fn attribute(self, attr: QualName) -> Result<O, ElementError> {
        self.map_err(|e| {
            // FIXME: eventually, here we'll want to preserve the location information

            let ParseError {
                kind,
                location: _location,
            } = e;

            match kind {
                ParseErrorKind::Basic(BasicParseErrorKind::UnexpectedToken(tok)) => {
                    let mut s = String::from("unexpected token '");
                    tok.to_css(&mut s).unwrap(); // FIXME: what do we do with a fmt::Error?
                    s.push_str("'");

                    ElementError {
                        attr,
                        err: ValueErrorKind::Parse(s),
                    }
                }

                ParseErrorKind::Basic(BasicParseErrorKind::EndOfInput) => ElementError {
                    attr,
                    err: ValueErrorKind::parse_error("unexpected end of input"),
                },

                ParseErrorKind::Basic(_) => {
                    unreachable!("attribute parsers should not return errors for CSS rules")
                }

                ParseErrorKind::Custom(err) => ElementError { attr, err },
            }
        })
    }
}

/// Errors returned when creating an `Href` out of a string
#[derive(Debug, Clone, PartialEq)]
pub enum HrefError {
    /// The href is an invalid URI or has empty components.
    ParseError,

    /// A fragment identifier ("`#foo`") is not allowed here
    ///
    /// For example, the SVG `<image>` element only allows referencing
    /// resources without fragment identifiers like
    /// `xlink:href="foo.png"`.
    FragmentForbidden,

    /// A fragment identifier ("`#foo`") was required but not found.  For example,
    /// the SVG `<use>` element requires one, as in `<use xlink:href="foo.svg#bar">`.
    FragmentRequired,
}

impl From<HrefError> for ValueErrorKind {
    fn from(e: HrefError) -> ValueErrorKind {
        match e {
            HrefError::ParseError => ValueErrorKind::parse_error("url parse error"),
            HrefError::FragmentForbidden => {
                ValueErrorKind::value_error("fragment identifier not allowed")
            }
            HrefError::FragmentRequired => {
                ValueErrorKind::value_error("fragment identifier required")
            }
        }
    }
}

/// Errors that can happen while loading an SVG document.
///
/// All of these codes are for unrecoverable errors that keep an SVG document from being
/// fully loaded and parsed.  Note that SVG is very lenient with respect to document
/// structure and the syntax of CSS property values; most errors there will not lead to a
/// `LoadingError`.  To see those errors, you may want to set the `RSVG_LOG=1` environment
/// variable.
///
/// I/O errors get reported in the `Glib` variant, since librsvg uses GIO internally for
/// all input/output.
#[derive(Debug, Clone)]
pub enum LoadingError {
    // FIXME: C API only
    NoDataPassedToParser,

    /// XML syntax error.
    XmlParseError(String),

    // FIXME: this is OOM in libxml2; we shouldn't expose it.
    CouldNotCreateXmlParser,

    /// A malformed or disallowed URL was used.
    BadUrl,

    /// A `data:` URL could not be decoded.
    BadDataUrl,

    // FIXME: used only if XML processing instruction cannot find the stylesheet.
    BadStylesheet,

    /// An invalid stylesheet was used.
    BadCss,

    /// A Cairo error happened during loading.
    Cairo(cairo::Status),

    // FIXME: only used in load_image()
    EmptyData,

    /// There are no SVG elements in the document.
    SvgHasNoElements,

    /// The outermost element in the document is not `<svg>`.
    RootElementIsNotSvg,

    /// Generally an I/O error, or another error from GIO.
    Glib(glib::Error),

    // FIXME: only used internally when loading pixbufs, and temporarily in c_api.
    Unknown,
}

impl error::Error for LoadingError {}

impl fmt::Display for LoadingError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            LoadingError::NoDataPassedToParser => write!(f, "no data passed to parser"),
            LoadingError::XmlParseError(ref s) => write!(f, "XML parse error: {}", s),
            LoadingError::CouldNotCreateXmlParser => write!(f, "could not create XML parser"),
            LoadingError::BadUrl => write!(f, "invalid URL"),
            LoadingError::BadDataUrl => write!(f, "invalid data: URL"),
            LoadingError::BadStylesheet => write!(f, "invalid stylesheet"),
            LoadingError::BadCss => write!(f, "invalid CSS"),
            LoadingError::Cairo(status) => write!(f, "cairo error: {:?}", status),
            LoadingError::EmptyData => write!(f, "empty data"),
            LoadingError::SvgHasNoElements => write!(f, "SVG has no elements"),
            LoadingError::RootElementIsNotSvg => write!(f, "root element is not <svg>"),
            LoadingError::Glib(ref e) => e.fmt(f),
            LoadingError::Unknown => write!(f, "unknown error"),
        }
    }
}

impl From<cairo::Status> for LoadingError {
    fn from(e: cairo::Status) -> LoadingError {
        assert!(e != cairo::Status::Success);

        LoadingError::Cairo(e)
    }
}

impl From<glib::Error> for LoadingError {
    fn from(e: glib::Error) -> LoadingError {
        LoadingError::Glib(e)
    }
}
<commit_msg>First try at documenting RenderingError<commit_after>//! Error types.

use std::error;
use std::fmt;

use cssparser::{BasicParseError, BasicParseErrorKind, ParseErrorKind, ToCss};
use markup5ever::QualName;

use crate::allowed_url::Fragment;
use crate::node::Node;

/// A short-lived error.
///
/// The lifetime of the error is the same as the `cssparser::ParserInput` that
/// was used to create a `cssparser::Parser`.  That is, it is the lifetime of
/// the string data that is being parsed.
///
/// The code flow will sometimes require preserving this error as a long-lived struct;
/// see the `impl<'i, O> AttributeResultExt<O> for Result<O, ParseError<'i>>` for that
/// purpose.
pub type ParseError<'i> = cssparser::ParseError<'i, ValueErrorKind>;

/// A simple error which refers to an attribute's value
#[derive(Debug, Clone, PartialEq)]
pub enum ValueErrorKind {
    /// A property with the specified name was not found
    UnknownProperty,

    /// The value could not be parsed
    Parse(String),

    // The value could be parsed, but is invalid
    Value(String),
}

impl ValueErrorKind {
    pub fn parse_error(s: &str) -> ValueErrorKind {
        ValueErrorKind::Parse(s.to_string())
    }

    pub fn value_error(s: &str) -> ValueErrorKind {
        ValueErrorKind::Value(s.to_string())
    }
}

impl fmt::Display for ValueErrorKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            ValueErrorKind::UnknownProperty => write!(f, "unknown property name"),

            ValueErrorKind::Parse(ref s) => write!(f, "parse error: {}", s),

            ValueErrorKind::Value(ref s) => write!(f, "invalid value: {}", s),
        }
    }
}

impl<'a> From<BasicParseError<'a>> for ValueErrorKind {
    fn from(e: BasicParseError<'_>) -> ValueErrorKind {
        let BasicParseError { kind, .. } = e;

        let msg = match kind {
            BasicParseErrorKind::UnexpectedToken(_) => "unexpected token",
            BasicParseErrorKind::EndOfInput => "unexpected end of input",
            BasicParseErrorKind::AtRuleInvalid(_) => "invalid @-rule",
            BasicParseErrorKind::AtRuleBodyInvalid => "invalid @-rule body",
            BasicParseErrorKind::QualifiedRuleInvalid => "invalid qualified rule",
        };

        ValueErrorKind::parse_error(msg)
    }
}

/// A complete error for an attribute and its erroneous value
#[derive(Debug, Clone, PartialEq)]
pub struct ElementError {
    pub attr: QualName,
    pub err: ValueErrorKind,
}

impl error::Error for ElementError {
    fn description(&self) -> &str {
        match self.err {
            ValueErrorKind::UnknownProperty => "unknown property",
            ValueErrorKind::Parse(_) => "parse error",
            ValueErrorKind::Value(_) => "invalid attribute value",
        }
    }
}

impl fmt::Display for ElementError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}: {}", self.attr.expanded(), self.err)
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum DefsLookupErrorKind {
    HrefError(HrefError),
    CannotLookupExternalReferences,
    NotFound,
}

/// Errors that can happen while rendering or measuring an SVG document.
#[derive(Debug, Clone, PartialEq)]
pub enum RenderingError {
    /// A Cairo error happened during rendering.
    Cairo(cairo::Status),

    /// There is a circular reference between elements.
    // FIXME: should be internal only.
    CircularReference,

    /// The maximum number of rendered objects was reached.
    ///
    /// Librsvg has a limit on the number of rendered objects, so that malicious
    /// files cannot consume CPU time arbitrarily.
    InstancingLimit,

    /// Tried to reference an SVG element from a fragment identifier that is incorrect.
    InvalidId(DefsLookupErrorKind),

    // FIXME: unused.
    InvalidHref,

    /// Not enough memory was available for rendering.
    // FIXME: right now this is only returned from pixbuf_utils.rs
    OutOfMemory,

    /// Cannot occur from librsvg_crate; this is just for the C API.
    HandleIsNotLoaded,
}

impl error::Error for RenderingError {}

impl fmt::Display for RenderingError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            RenderingError::CircularReference => write!(f, "circular reference"),
            RenderingError::InstancingLimit => write!(f, "instancing limit"),
            RenderingError::InvalidHref => write!(f, "invalid href"),
            RenderingError::OutOfMemory => write!(f, "out of memory"),
            RenderingError::HandleIsNotLoaded => write!(f, "SVG data is not loaded into handle"),
            RenderingError::Cairo(ref status) => write!(f, "cairo error: {:?}", status),
            RenderingError::InvalidId(ref id) => write!(f, "invalid id: {:?}", id),
        }
    }
}

impl From<cairo::Status> for RenderingError {
    fn from(e: cairo::Status) -> RenderingError {
        assert!(e != cairo::Status::Success);

        RenderingError::Cairo(e)
    }
}

pub enum AcquireError {
    LinkNotFound(Fragment),
    InvalidLinkType(Fragment),
    CircularReference(Node),
    MaxReferencesExceeded,
}

impl fmt::Display for AcquireError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            AcquireError::LinkNotFound(ref frag) => write!(f, "link not found: {}", frag),

            AcquireError::InvalidLinkType(ref frag) => {
                write!(f, "link {} is to object of invalid type", frag)
            }

            AcquireError::CircularReference(ref node) => {
                write!(f, "circular reference in node {}", node)
            }

            AcquireError::MaxReferencesExceeded => {
                write!(f, "maximum number of references exceeded")
            }
        }
    }
}

/// Helper for converting `Result<O, E>` into `Result<O, ElementError>`
///
/// A `ElementError` requires a `QualName` that corresponds to the attribute to which the
/// error refers, plus the actual `ValueErrorKind` that describes the error.  However,
/// parsing functions for attribute value types will want to return their own kind of
/// error, instead of `ValueErrorKind`.  If that particular error type has an `impl
/// From<FooError> for ValueErrorKind`, then this trait helps assign attribute values in
/// `set_atts()` methods as follows:
///
/// ```ignore
/// use error::AttributeResultExt;
///
/// // fn parse_foo(...) -> Result<Foo, FooError>
///
/// // It is assumed that there is an impl From<FooError> for ValueErrorKind
///
/// self.foo = parse_foo(value).attribute(local_name!("foo"))?;
/// ```
///
/// The call to `.attribute(attr)` converts the `Result` from `parse_foo()` into a full
/// `ElementError` with the provided `attr`.
pub trait AttributeResultExt<O> {
    fn attribute(self, attr: QualName) -> Result<O, ElementError>;
}

impl<O, E: Into<ValueErrorKind>> AttributeResultExt<O> for Result<O, E> {
    fn attribute(self, attr: QualName) -> Result<O, ElementError> {
        self.map_err(|e| e.into())
            .map_err(|err| ElementError { attr, err })
    }
}

/// Turns a short-lived `ParseError` into a long-lived `ElementError`
impl<'i, O> AttributeResultExt<O> for Result<O, ParseError<'i>> {
    fn attribute(self, attr: QualName) -> Result<O, ElementError> {
        self.map_err(|e| {
            // FIXME: eventually, here we'll want to preserve the location information

            let ParseError {
                kind,
                location: _location,
            } = e;

            match kind {
                ParseErrorKind::Basic(BasicParseErrorKind::UnexpectedToken(tok)) => {
                    let mut s = String::from("unexpected token '");
                    tok.to_css(&mut s).unwrap(); // FIXME: what do we do with a fmt::Error?
                    s.push_str("'");

                    ElementError {
                        attr,
                        err: ValueErrorKind::Parse(s),
                    }
                }

                ParseErrorKind::Basic(BasicParseErrorKind::EndOfInput) => ElementError {
                    attr,
                    err: ValueErrorKind::parse_error("unexpected end of input"),
                },

                ParseErrorKind::Basic(_) => {
                    unreachable!("attribute parsers should not return errors for CSS rules")
                }

                ParseErrorKind::Custom(err) => ElementError { attr, err },
            }
        })
    }
}

/// Errors returned when creating an `Href` out of a string
#[derive(Debug, Clone, PartialEq)]
pub enum HrefError {
    /// The href is an invalid URI or has empty components.
    ParseError,

    /// A fragment identifier ("`#foo`") is not allowed here
    ///
    /// For example, the SVG `<image>` element only allows referencing
    /// resources without fragment identifiers like
    /// `xlink:href="foo.png"`.
    FragmentForbidden,

    /// A fragment identifier ("`#foo`") was required but not found.  For example,
    /// the SVG `<use>` element requires one, as in `<use xlink:href="foo.svg#bar">`.
    FragmentRequired,
}

impl From<HrefError> for ValueErrorKind {
    fn from(e: HrefError) -> ValueErrorKind {
        match e {
            HrefError::ParseError => ValueErrorKind::parse_error("url parse error"),
            HrefError::FragmentForbidden => {
                ValueErrorKind::value_error("fragment identifier not allowed")
            }
            HrefError::FragmentRequired => {
                ValueErrorKind::value_error("fragment identifier required")
            }
        }
    }
}

/// Errors that can happen while loading an SVG document.
///
/// All of these codes are for unrecoverable errors that keep an SVG document from being
/// fully loaded and parsed.  Note that SVG is very lenient with respect to document
/// structure and the syntax of CSS property values; most errors there will not lead to a
/// `LoadingError`.  To see those errors, you may want to set the `RSVG_LOG=1` environment
/// variable.
///
/// I/O errors get reported in the `Glib` variant, since librsvg uses GIO internally for
/// all input/output.
#[derive(Debug, Clone)]
pub enum LoadingError {
    // FIXME: C API only
    NoDataPassedToParser,

    /// XML syntax error.
    XmlParseError(String),

    // FIXME: this is OOM in libxml2; we shouldn't expose it.
    CouldNotCreateXmlParser,

    /// A malformed or disallowed URL was used.
    BadUrl,

    /// A `data:` URL could not be decoded.
    BadDataUrl,

    // FIXME: used only if XML processing instruction cannot find the stylesheet.
    BadStylesheet,

    /// An invalid stylesheet was used.
    BadCss,

    /// A Cairo error happened during loading.
    Cairo(cairo::Status),

    // FIXME: only used in load_image()
    EmptyData,

    /// There are no SVG elements in the document.
    SvgHasNoElements,

    /// The outermost element in the document is not `<svg>`.
    RootElementIsNotSvg,

    /// Generally an I/O error, or another error from GIO.
    Glib(glib::Error),

    // FIXME: only used internally when loading pixbufs, and temporarily in c_api.
    Unknown,
}

impl error::Error for LoadingError {}

impl fmt::Display for LoadingError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            LoadingError::NoDataPassedToParser => write!(f, "no data passed to parser"),
            LoadingError::XmlParseError(ref s) => write!(f, "XML parse error: {}", s),
            LoadingError::CouldNotCreateXmlParser => write!(f, "could not create XML parser"),
            LoadingError::BadUrl => write!(f, "invalid URL"),
            LoadingError::BadDataUrl => write!(f, "invalid data: URL"),
            LoadingError::BadStylesheet => write!(f, "invalid stylesheet"),
            LoadingError::BadCss => write!(f, "invalid CSS"),
            LoadingError::Cairo(status) => write!(f, "cairo error: {:?}", status),
            LoadingError::EmptyData => write!(f, "empty data"),
            LoadingError::SvgHasNoElements => write!(f, "SVG has no elements"),
            LoadingError::RootElementIsNotSvg => write!(f, "root element is not <svg>"),
            LoadingError::Glib(ref e) => e.fmt(f),
            LoadingError::Unknown => write!(f, "unknown error"),
        }
    }
}

impl From<cairo::Status> for LoadingError {
    fn from(e: cairo::Status) -> LoadingError {
        assert!(e != cairo::Status::Success);

        LoadingError::Cairo(e)
    }
}

impl From<glib::Error> for LoadingError {
    fn from(e: glib::Error) -> LoadingError {
        LoadingError::Glib(e)
    }
}
<|endoftext|>


<commit_before>pub fn annotate(minefield: &[&str]) -> Vec<String> {
    let mut annotated: Vec<String> = Vec::new();
    let mut field: Vec<Vec<char>> = Vec::new();

    for row in minefield {
        field.push(row.chars().collect());
    }

    for (y, row) in field.iter().enumerate() {
        let mut annotated_row = String::new();
        for (x, token) in row.iter().enumerate() {
            match token {
                '*' => annotated_row.push('*'),
                ' ' => {
                    let num = num_neighbor_mines(&field, y as u32, x as u32);
                    if num == 0 {
                        annotated_row.push(' ')
                    } else {
                        annotated_row.push_str(&num.to_string())
                    }
                }
                _ => panic!("unsupported token"),
            }
        }
        annotated.push(annotated_row)
    }

    println!("{:?}", field);

    // annotated.iter().map(|row| row.iter().collect()).collect()
    annotated
}

fn num_neighbor_mines(field: &Vec<Vec<char>>, y: u32, x: u32) -> u8 {
    let neighbors = get_neighbors(field, y, x);
    let mut result = 0;

    for neighbor in neighbors {
        if neighbor == '*' {
            result += 1
        }
    }
    result
}

fn get_neighbors(field: &Vec<Vec<char>>, y: u32, x: u32) -> Vec<char> {
    let mut neighbors = Vec::new();
    let y = y as i32;
    let x = x as i32;

    let delta_ys: Vec<i32> = (-1..=1).collect();
    for delta_y in delta_ys {
        let delta_xs: Vec<i32> = (-1..=1).collect();
        for delta_x in delta_xs {
            if delta_y == 0 && delta_x == 0 {
                continue;
            }
            if y + delta_y < 0 || y + delta_y >= field.len() as i32 {
                continue;
            }
            if x + delta_x < 0 || x + delta_x >= field[0].len() as i32 {
                continue;
            }
            println!("{} {}", y + delta_y, x + delta_x);
            let neighbor = field[(y + delta_y) as usize][(x + delta_x) as usize];
            neighbors.push(neighbor)
        }
    }

    neighbors
}
<commit_msg>Extract split()<commit_after>pub fn annotate(minefield: &[&str]) -> Vec<String> {
    let field = split(minefield);
    let mut annotated: Vec<String> = Vec::new();

    for (y, row) in field.iter().enumerate() {
        let mut annotated_row = String::new();
        for (x, token) in row.iter().enumerate() {
            match token {
                '*' => annotated_row.push('*'),
                ' ' => {
                    let num = num_neighbor_mines(&field, y as u32, x as u32);
                    if num == 0 {
                        annotated_row.push(' ')
                    } else {
                        annotated_row.push_str(&num.to_string())
                    }
                }
                _ => panic!("unsupported token"),
            }
        }
        annotated.push(annotated_row)
    }

    println!("{:?}", field);

    annotated
}

fn split(minefield: &[&str]) -> Vec<Vec<char>> {
    let mut field: Vec<Vec<char>> = Vec::new();

    for row in minefield {
        field.push(row.chars().collect());
    }
    field
}

fn num_neighbor_mines(field: &Vec<Vec<char>>, y: u32, x: u32) -> u8 {
    let neighbors = get_neighbors(field, y, x);
    let mut result = 0;

    for neighbor in neighbors {
        if neighbor == '*' {
            result += 1
        }
    }
    result
}

fn get_neighbors(field: &Vec<Vec<char>>, y: u32, x: u32) -> Vec<char> {
    let mut neighbors = Vec::new();
    let y = y as i32;
    let x = x as i32;

    let delta_ys: Vec<i32> = (-1..=1).collect();
    for delta_y in delta_ys {
        let delta_xs: Vec<i32> = (-1..=1).collect();
        for delta_x in delta_xs {
            if delta_y == 0 && delta_x == 0 {
                continue;
            }
            if y + delta_y < 0 || y + delta_y >= field.len() as i32 {
                continue;
            }
            if x + delta_x < 0 || x + delta_x >= field[0].len() as i32 {
                continue;
            }
            println!("{} {}", y + delta_y, x + delta_x);
            let neighbor = field[(y + delta_y) as usize][(x + delta_x) as usize];
            neighbors.push(neighbor)
        }
    }

    neighbors
}
<|endoftext|>


<commit_before>fn foo(x: &int) -> int {
    println!("{} {} {}", x, (*x) *3, (*x) * 5);
    *x
}

fn main() {
    {
        let mut x = 5i;

        {
            let y = &x;
            let z = &x;
            println!("1. y *{:p} -> {}", y, y);
            println!("1. z *{:p} -> {}", z, z);
        }

        {
            let i = &mut x;
            *i = *i * 2;
        }

        {
            let y = &x;
            let z = &x;
            printlnl!("2. y *{:p} -> {}", y, y);
            println!("2. z *{:p} -> {}", z, z);
        }

        foo(&x);

    }
}
<commit_msg>fix int types<commit_after>fn foo(x: &i32) -> i32 {
    println!("{} {} {}", x, (*x) *3, (*x) * 5);
    *x
}

fn main() {
    {
        let mut x = 5i32;

        {
            let y = &x;
            let z = &x;
            println!("1. y *{:p} -> {}", y, y);
            println!("1. z *{:p} -> {}", z, z);
        }

        {
            let i = &mut x;
            *i = *i * 2;
        }

        {
            let y = &x;
            let z = &x;
            println!("2. y *{:p} -> {}", y, y);
            println!("2. z *{:p} -> {}", z, z);
        }

        foo(&x);

    }
}
<|endoftext|>