<commit_before>#![deny(missing_docs)]
//! A SDL2 window back-end for the Piston game engine.

extern crate sdl2;
extern crate window;
extern crate input;
extern crate shader_version;
extern crate gl;

// External crates.
use window::{
    BuildFromWindowSettings,
    OpenGLWindow,
    ProcAddress,
    Window,
    AdvancedWindow,
    WindowSettings,
    Size,
};
use input::{
    keyboard,
    Button,
    MouseButton,
    Input,
    Motion,
    ControllerAxisArgs,
    ControllerButton
};

use std::vec::Vec;

pub use shader_version::OpenGL;

struct JoystickState {
    joysticks: Vec<sdl2::joystick::Joystick>,
    subsystem: sdl2::JoystickSubsystem,
}

impl JoystickState {
    fn new(subsystem: sdl2::JoystickSubsystem) -> Self {
        JoystickState {
            joysticks: Vec::new(),
            subsystem: subsystem,
        }
    }
}

/// A widow implemented by SDL2 back-end.
pub struct Sdl2Window {
    /// SDL window handle.
    pub window: sdl2::video::Window,
    /// Allow dead code because this keeps track of the OpenGL context.
    /// Will be released on drop.
    #[allow(dead_code)]
    pub context: sdl2::video::GLContext,
    /// SDL context.
    pub sdl_context: sdl2::Sdl,
    /// Video subsystem.
    pub video_subsystem: sdl2::VideoSubsystem,
    joystick_state: Option<JoystickState>,
    should_close: bool,
    mouse_relative: Option<(f64, f64)>,
    exit_on_esc: bool,
    title: String,
    size: Size,
    draw_size: Size,
}

impl Sdl2Window {
    /// Creates a new game window for SDL2. This will initialize SDL and the video subsystem.
    /// You can retrieve both via the public fields on the `Sdl2Window` struct.
    pub fn new(settings: WindowSettings) -> Result<Self, String> {
        let sdl = try!(sdl2::init().map_err(|e| format!("{}", e)));
        let video_subsystem = try!(sdl.video()
            .map_err(|e| format!("{}", e)));
        let mut window = try!(Self::with_subsystem(video_subsystem, settings));
        // Enable joysticks by default.
        try!(window.init_joysticks().map_err(|e| e));
        Ok(window)
    }

    /// Creates a window with the supplied SDL Video subsystem.
    pub fn with_subsystem(video_subsystem: sdl2::VideoSubsystem, settings: WindowSettings) -> Result<Self, String> {
        use sdl2::video::GLProfile;

        let sdl_context = video_subsystem.sdl();
        let opengl = settings.get_maybe_opengl().unwrap_or(OpenGL::V3_2);
        let (major, minor) = opengl.get_major_minor();

        {
            let gl_attr = video_subsystem.gl_attr();

            // Not all drivers default to 32bit color, so explicitly set it to 32bit color.
            gl_attr.set_red_size(8);
            gl_attr.set_green_size(8);
            gl_attr.set_blue_size(8);
            gl_attr.set_alpha_size(8);
            gl_attr.set_stencil_size(8);
            gl_attr.set_context_version(major as u8, minor as u8);
            gl_attr.set_framebuffer_srgb_compatible(settings.get_srgb());
        }

        if opengl >= OpenGL::V3_2 {
            video_subsystem.gl_attr().set_context_profile(GLProfile::Core);
        }
        if settings.get_samples() != 0 {
            let gl_attr = video_subsystem.gl_attr();
            gl_attr.set_multisample_buffers(1);
            gl_attr.set_multisample_samples(settings.get_samples());
        }

        let mut window_builder = video_subsystem.window(
            &settings.get_title(),
            settings.get_size().width as u32,
            settings.get_size().height as u32
        );

        let window_builder = window_builder.position_centered()
            .opengl()
            .resizable();

        let window_builder = if settings.get_fullscreen() {
            window_builder.fullscreen()
        } else {
            window_builder
        };

        let window = window_builder.build();

        let window = match window {
            Ok(w) => w,
            Err(_) =>
                if settings.get_samples() != 0 {
                    // Retry without requiring anti-aliasing.
                    let gl_attr = video_subsystem.gl_attr();
                    gl_attr.set_multisample_buffers(0);
                    gl_attr.set_multisample_samples(0);
                    try!(window_builder.build().map_err(|e| format!("{}", e)))
                } else {
                    try!(window.map_err(|e| format!("{}", e)))
                }
        };

        // Send text input events.
        video_subsystem.text_input().start();

        let context = try!(window.gl_create_context()
            .map_err(|e| format!("{}", e)));

        // Load the OpenGL function pointers.
        gl::load_with(|name| video_subsystem.gl_get_proc_address(name) as *const _);

        if settings.get_vsync() {
            video_subsystem.gl_set_swap_interval(1);
        } else {
            video_subsystem.gl_set_swap_interval(0);
        }

        let mut window = Sdl2Window {
            exit_on_esc: settings.get_exit_on_esc(),
            should_close: false,
            window: window,
            context: context,
            sdl_context: sdl_context,
            video_subsystem: video_subsystem,
            joystick_state: None,
            mouse_relative: None,
            title: settings.get_title() ,
            size: settings.get_size(),
            draw_size: settings.get_size(),
        };
        window.update_draw_size();
        Ok(window)
    }

    /// Initialize the joystick subsystem. Required before joystick input
    /// events will be returned. Returns the number available or error.
    pub fn init_joysticks(&mut self) -> Result<u32, String> {
        let subsystem = try!(self.sdl_context.joystick().map_err(|e| format!("{}", e)));
        let mut state = JoystickState::new(subsystem);
        let available = try!(state.subsystem.num_joysticks().map_err(|e| format!("{}", e)));

        // Open all the joysticks
        for id in 0..available {
            match state.subsystem.open(id) {
                Ok(c) => { state.joysticks.push(c) },
                Err(e) => return Err(format!("{}", e)),
            }
        }

        self.joystick_state = Some(state);

        Ok(available)
    }

    fn update_draw_size(&mut self) {
        let (w, h) = self.window.drawable_size();
        self.draw_size = Size { width: w as u32, height: h as u32 };
    }

    fn poll_event(&mut self) -> Option<Input> {
        use sdl2::event::{ Event, WindowEventId };

        // First check for a pending relative mouse move event.
        if let Some((x, y)) = self.mouse_relative {
            self.mouse_relative = None;
            return Some(Input::Move(Motion::MouseRelative(x, y)));
        }

        // Even though we create a new EventPump each time we poll an event
        // this should not be a problem since it only contains phantom data
        // and therefore should actually not have any overhead.
        let event = match self.sdl_context.event_pump().unwrap().poll_event() {
            Some( ev ) => ev,
            None => return None
        };
        match event {
            Event::Quit{..} => {
                self.should_close = true;
            }
            Event::TextInput { text, .. } => {
                return Some(Input::Text(text));
            }
            Event::KeyDown { keycode: Some(key), repeat, ..} => {
                // SDL2 repeats the key down event.
                // If the event is the same as last one, ignore it.
                if repeat {
                    return self.poll_event()
                }

                if self.exit_on_esc
                && key == sdl2::keyboard::Keycode::Escape {
                    self.should_close = true;
                } else {
                    return Some(Input::Press(Button::Keyboard(sdl2_map_key(key))));
                }
            }
            Event::KeyUp { keycode: Some(key), repeat, .. } => {
                if repeat {
                    return self.poll_event()
                }
                return Some(Input::Release(Button::Keyboard(sdl2_map_key(key))));
            }
            Event::MouseButtonDown { mouse_btn: button, .. } => {
                return Some(Input::Press(Button::Mouse(sdl2_map_mouse(button))));
            }
            Event::MouseButtonUp { mouse_btn: button, .. } => {
                return Some(Input::Release(Button::Mouse(sdl2_map_mouse(button))));
            }
            Event::MouseMotion { x, y, xrel: dx, yrel: dy, .. } => {
                // Send relative move movement next time.
                self.mouse_relative = Some((dx as f64, dy as f64));
                return Some(Input::Move(Motion::MouseCursor(x as f64, y as f64)));
            },
            Event::MouseWheel { x, y, .. } => {
                return Some(Input::Move(Motion::MouseScroll(x as f64, y as f64)));
            }
            Event::JoyAxisMotion{ which, axis_idx, value: val, .. } => {
                // Axis motion is an absolute value in the range
                // [-32768, 32767]. Normalize it down to a float.
                use std::i16::MAX;
                let normalized_value = val as f64 / MAX as f64;
                return Some(Input::Move(Motion::ControllerAxis(ControllerAxisArgs::new(which, axis_idx, normalized_value))));
            }
            Event::JoyButtonDown{ which, button_idx, .. } => {
                return Some(Input::Press(Button::Controller(ControllerButton::new(which, button_idx))))
            },
            Event::JoyButtonUp{ which, button_idx, .. } => {
                return Some(Input::Release(Button::Controller(ControllerButton::new(which, button_idx))))
            },
            Event::Window {
                win_event_id: sdl2::event::WindowEventId::Resized, data1: w, data2: h, .. } => {
                self.size.width = w as u32;
                self.size.height = h as u32;
                self.update_draw_size();
                return Some(Input::Resize(w as u32, h as u32));
            }
            Event::Window { win_event_id: WindowEventId::FocusGained, .. } => {
                return Some(Input::Focus(true));
            }
            Event::Window { win_event_id: WindowEventId::FocusLost, .. } => {
                return Some(Input::Focus(false));
            }
            Event::Window { win_event_id: WindowEventId::Enter, .. } => {
                return Some(Input::Cursor(true));
            }
            Event::Window { win_event_id: WindowEventId::Leave, .. } => {
                return Some(Input::Cursor(false));
            }
            _ => {}
        }
        None
    }
}

impl BuildFromWindowSettings for Sdl2Window {
    fn build_from_window_settings(settings: WindowSettings)
    -> Result<Self, String> {
        Sdl2Window::new(settings)
    }
}

impl Drop for Sdl2Window {
    fn drop(&mut self) {
        self.set_capture_cursor(false);
    }
}

impl Window for Sdl2Window {
    type Event = Input;

    fn should_close(&self) -> bool { self.should_close }
    fn set_should_close(&mut self, value: bool) { self.should_close = value; }
    fn swap_buffers(&mut self) { self.window.gl_swap_window(); }
    fn size(&self) -> Size { self.size }
    fn poll_event(&mut self) -> Option<Input> { self.poll_event() }
    fn draw_size(&self) -> Size { self.draw_size }
}

impl AdvancedWindow for Sdl2Window {
    fn get_title(&self) -> String {
        self.title.clone()
    }
    fn set_title(&mut self, value: String) {
        let _ = self.window.set_title(&value);
        self.title = value
    }
    fn get_exit_on_esc(&self) -> bool { self.exit_on_esc }
    fn set_exit_on_esc(&mut self, value: bool) { self.exit_on_esc = value; }
    fn set_capture_cursor(&mut self, value: bool) {
        self.sdl_context.mouse().set_relative_mouse_mode(value);
    }
}

impl OpenGLWindow for Sdl2Window {
    fn get_proc_address(&mut self, proc_name: &str) -> ProcAddress {
        self.video_subsystem.gl_get_proc_address(proc_name) as *const _
    }

    fn is_current(&self) -> bool {
        self.context.is_current()
    }

    fn make_current(&mut self) {
        self.window.gl_make_current(&self.context).unwrap();
    }
}

/// Maps a SDL2 key to piston-input key.
pub fn sdl2_map_key(keycode: sdl2::keyboard::Keycode) -> keyboard::Key {
    (keycode as u32).into()
}

/// Maps a SDL2 mouse button to piston-input button.
pub fn sdl2_map_mouse(button: sdl2::mouse::Mouse) -> MouseButton {
    match button {
        sdl2::mouse::Mouse::Left => MouseButton::Left,
        sdl2::mouse::Mouse::Right => MouseButton::Right,
        sdl2::mouse::Mouse::Middle => MouseButton::Middle,
        sdl2::mouse::Mouse::X1 => MouseButton::X1,
        sdl2::mouse::Mouse::X2 => MouseButton::X2,
        sdl2::mouse::Mouse::Unknown(_) => MouseButton::Unknown,
    }
}
<commit_msg>Fix Issue #225: Typo in Documentation for `Sdl2Window` Struct <commit_after>#![deny(missing_docs)]
//! A SDL2 window back-end for the Piston game engine.

extern crate sdl2;
extern crate window;
extern crate input;
extern crate shader_version;
extern crate gl;

// External crates.
use window::{
    BuildFromWindowSettings,
    OpenGLWindow,
    ProcAddress,
    Window,
    AdvancedWindow,
    WindowSettings,
    Size,
};
use input::{
    keyboard,
    Button,
    MouseButton,
    Input,
    Motion,
    ControllerAxisArgs,
    ControllerButton
};

use std::vec::Vec;

pub use shader_version::OpenGL;

struct JoystickState {
    joysticks: Vec<sdl2::joystick::Joystick>,
    subsystem: sdl2::JoystickSubsystem,
}

impl JoystickState {
    fn new(subsystem: sdl2::JoystickSubsystem) -> Self {
        JoystickState {
            joysticks: Vec::new(),
            subsystem: subsystem,
        }
    }
}

/// A window implemented by SDL2 back-end.
pub struct Sdl2Window {
    /// SDL window handle.
    pub window: sdl2::video::Window,
    /// Allow dead code because this keeps track of the OpenGL context.
    /// Will be released on drop.
    #[allow(dead_code)]
    pub context: sdl2::video::GLContext,
    /// SDL context.
    pub sdl_context: sdl2::Sdl,
    /// Video subsystem.
    pub video_subsystem: sdl2::VideoSubsystem,
    joystick_state: Option<JoystickState>,
    should_close: bool,
    mouse_relative: Option<(f64, f64)>,
    exit_on_esc: bool,
    title: String,
    size: Size,
    draw_size: Size,
}

impl Sdl2Window {
    /// Creates a new game window for SDL2. This will initialize SDL and the video subsystem.
    /// You can retrieve both via the public fields on the `Sdl2Window` struct.
    pub fn new(settings: WindowSettings) -> Result<Self, String> {
        let sdl = try!(sdl2::init().map_err(|e| format!("{}", e)));
        let video_subsystem = try!(sdl.video()
            .map_err(|e| format!("{}", e)));
        let mut window = try!(Self::with_subsystem(video_subsystem, settings));
        // Enable joysticks by default.
        try!(window.init_joysticks().map_err(|e| e));
        Ok(window)
    }

    /// Creates a window with the supplied SDL Video subsystem.
    pub fn with_subsystem(video_subsystem: sdl2::VideoSubsystem, settings: WindowSettings) -> Result<Self, String> {
        use sdl2::video::GLProfile;

        let sdl_context = video_subsystem.sdl();
        let opengl = settings.get_maybe_opengl().unwrap_or(OpenGL::V3_2);
        let (major, minor) = opengl.get_major_minor();

        {
            let gl_attr = video_subsystem.gl_attr();

            // Not all drivers default to 32bit color, so explicitly set it to 32bit color.
            gl_attr.set_red_size(8);
            gl_attr.set_green_size(8);
            gl_attr.set_blue_size(8);
            gl_attr.set_alpha_size(8);
            gl_attr.set_stencil_size(8);
            gl_attr.set_context_version(major as u8, minor as u8);
            gl_attr.set_framebuffer_srgb_compatible(settings.get_srgb());
        }

        if opengl >= OpenGL::V3_2 {
            video_subsystem.gl_attr().set_context_profile(GLProfile::Core);
        }
        if settings.get_samples() != 0 {
            let gl_attr = video_subsystem.gl_attr();
            gl_attr.set_multisample_buffers(1);
            gl_attr.set_multisample_samples(settings.get_samples());
        }

        let mut window_builder = video_subsystem.window(
            &settings.get_title(),
            settings.get_size().width as u32,
            settings.get_size().height as u32
        );

        let window_builder = window_builder.position_centered()
            .opengl()
            .resizable();

        let window_builder = if settings.get_fullscreen() {
            window_builder.fullscreen()
        } else {
            window_builder
        };

        let window = window_builder.build();

        let window = match window {
            Ok(w) => w,
            Err(_) =>
                if settings.get_samples() != 0 {
                    // Retry without requiring anti-aliasing.
                    let gl_attr = video_subsystem.gl_attr();
                    gl_attr.set_multisample_buffers(0);
                    gl_attr.set_multisample_samples(0);
                    try!(window_builder.build().map_err(|e| format!("{}", e)))
                } else {
                    try!(window.map_err(|e| format!("{}", e)))
                }
        };

        // Send text input events.
        video_subsystem.text_input().start();

        let context = try!(window.gl_create_context()
            .map_err(|e| format!("{}", e)));

        // Load the OpenGL function pointers.
        gl::load_with(|name| video_subsystem.gl_get_proc_address(name) as *const _);

        if settings.get_vsync() {
            video_subsystem.gl_set_swap_interval(1);
        } else {
            video_subsystem.gl_set_swap_interval(0);
        }

        let mut window = Sdl2Window {
            exit_on_esc: settings.get_exit_on_esc(),
            should_close: false,
            window: window,
            context: context,
            sdl_context: sdl_context,
            video_subsystem: video_subsystem,
            joystick_state: None,
            mouse_relative: None,
            title: settings.get_title() ,
            size: settings.get_size(),
            draw_size: settings.get_size(),
        };
        window.update_draw_size();
        Ok(window)
    }

    /// Initialize the joystick subsystem. Required before joystick input
    /// events will be returned. Returns the number available or error.
    pub fn init_joysticks(&mut self) -> Result<u32, String> {
        let subsystem = try!(self.sdl_context.joystick().map_err(|e| format!("{}", e)));
        let mut state = JoystickState::new(subsystem);
        let available = try!(state.subsystem.num_joysticks().map_err(|e| format!("{}", e)));

        // Open all the joysticks
        for id in 0..available {
            match state.subsystem.open(id) {
                Ok(c) => { state.joysticks.push(c) },
                Err(e) => return Err(format!("{}", e)),
            }
        }

        self.joystick_state = Some(state);

        Ok(available)
    }

    fn update_draw_size(&mut self) {
        let (w, h) = self.window.drawable_size();
        self.draw_size = Size { width: w as u32, height: h as u32 };
    }

    fn poll_event(&mut self) -> Option<Input> {
        use sdl2::event::{ Event, WindowEventId };

        // First check for a pending relative mouse move event.
        if let Some((x, y)) = self.mouse_relative {
            self.mouse_relative = None;
            return Some(Input::Move(Motion::MouseRelative(x, y)));
        }

        // Even though we create a new EventPump each time we poll an event
        // this should not be a problem since it only contains phantom data
        // and therefore should actually not have any overhead.
        let event = match self.sdl_context.event_pump().unwrap().poll_event() {
            Some( ev ) => ev,
            None => return None
        };
        match event {
            Event::Quit{..} => {
                self.should_close = true;
            }
            Event::TextInput { text, .. } => {
                return Some(Input::Text(text));
            }
            Event::KeyDown { keycode: Some(key), repeat, ..} => {
                // SDL2 repeats the key down event.
                // If the event is the same as last one, ignore it.
                if repeat {
                    return self.poll_event()
                }

                if self.exit_on_esc
                && key == sdl2::keyboard::Keycode::Escape {
                    self.should_close = true;
                } else {
                    return Some(Input::Press(Button::Keyboard(sdl2_map_key(key))));
                }
            }
            Event::KeyUp { keycode: Some(key), repeat, .. } => {
                if repeat {
                    return self.poll_event()
                }
                return Some(Input::Release(Button::Keyboard(sdl2_map_key(key))));
            }
            Event::MouseButtonDown { mouse_btn: button, .. } => {
                return Some(Input::Press(Button::Mouse(sdl2_map_mouse(button))));
            }
            Event::MouseButtonUp { mouse_btn: button, .. } => {
                return Some(Input::Release(Button::Mouse(sdl2_map_mouse(button))));
            }
            Event::MouseMotion { x, y, xrel: dx, yrel: dy, .. } => {
                // Send relative move movement next time.
                self.mouse_relative = Some((dx as f64, dy as f64));
                return Some(Input::Move(Motion::MouseCursor(x as f64, y as f64)));
            },
            Event::MouseWheel { x, y, .. } => {
                return Some(Input::Move(Motion::MouseScroll(x as f64, y as f64)));
            }
            Event::JoyAxisMotion{ which, axis_idx, value: val, .. } => {
                // Axis motion is an absolute value in the range
                // [-32768, 32767]. Normalize it down to a float.
                use std::i16::MAX;
                let normalized_value = val as f64 / MAX as f64;
                return Some(Input::Move(Motion::ControllerAxis(ControllerAxisArgs::new(which, axis_idx, normalized_value))));
            }
            Event::JoyButtonDown{ which, button_idx, .. } => {
                return Some(Input::Press(Button::Controller(ControllerButton::new(which, button_idx))))
            },
            Event::JoyButtonUp{ which, button_idx, .. } => {
                return Some(Input::Release(Button::Controller(ControllerButton::new(which, button_idx))))
            },
            Event::Window {
                win_event_id: sdl2::event::WindowEventId::Resized, data1: w, data2: h, .. } => {
                self.size.width = w as u32;
                self.size.height = h as u32;
                self.update_draw_size();
                return Some(Input::Resize(w as u32, h as u32));
            }
            Event::Window { win_event_id: WindowEventId::FocusGained, .. } => {
                return Some(Input::Focus(true));
            }
            Event::Window { win_event_id: WindowEventId::FocusLost, .. } => {
                return Some(Input::Focus(false));
            }
            Event::Window { win_event_id: WindowEventId::Enter, .. } => {
                return Some(Input::Cursor(true));
            }
            Event::Window { win_event_id: WindowEventId::Leave, .. } => {
                return Some(Input::Cursor(false));
            }
            _ => {}
        }
        None
    }
}

impl BuildFromWindowSettings for Sdl2Window {
    fn build_from_window_settings(settings: WindowSettings)
    -> Result<Self, String> {
        Sdl2Window::new(settings)
    }
}

impl Drop for Sdl2Window {
    fn drop(&mut self) {
        self.set_capture_cursor(false);
    }
}

impl Window for Sdl2Window {
    type Event = Input;

    fn should_close(&self) -> bool { self.should_close }
    fn set_should_close(&mut self, value: bool) { self.should_close = value; }
    fn swap_buffers(&mut self) { self.window.gl_swap_window(); }
    fn size(&self) -> Size { self.size }
    fn poll_event(&mut self) -> Option<Input> { self.poll_event() }
    fn draw_size(&self) -> Size { self.draw_size }
}

impl AdvancedWindow for Sdl2Window {
    fn get_title(&self) -> String {
        self.title.clone()
    }
    fn set_title(&mut self, value: String) {
        let _ = self.window.set_title(&value);
        self.title = value
    }
    fn get_exit_on_esc(&self) -> bool { self.exit_on_esc }
    fn set_exit_on_esc(&mut self, value: bool) { self.exit_on_esc = value; }
    fn set_capture_cursor(&mut self, value: bool) {
        self.sdl_context.mouse().set_relative_mouse_mode(value);
    }
}

impl OpenGLWindow for Sdl2Window {
    fn get_proc_address(&mut self, proc_name: &str) -> ProcAddress {
        self.video_subsystem.gl_get_proc_address(proc_name) as *const _
    }

    fn is_current(&self) -> bool {
        self.context.is_current()
    }

    fn make_current(&mut self) {
        self.window.gl_make_current(&self.context).unwrap();
    }
}

/// Maps a SDL2 key to piston-input key.
pub fn sdl2_map_key(keycode: sdl2::keyboard::Keycode) -> keyboard::Key {
    (keycode as u32).into()
}

/// Maps a SDL2 mouse button to piston-input button.
pub fn sdl2_map_mouse(button: sdl2::mouse::Mouse) -> MouseButton {
    match button {
        sdl2::mouse::Mouse::Left => MouseButton::Left,
        sdl2::mouse::Mouse::Right => MouseButton::Right,
        sdl2::mouse::Mouse::Middle => MouseButton::Middle,
        sdl2::mouse::Mouse::X1 => MouseButton::X1,
        sdl2::mouse::Mouse::X2 => MouseButton::X2,
        sdl2::mouse::Mouse::Unknown(_) => MouseButton::Unknown,
    }
}
<|endoftext|>


<commit_before>extern crate nom_lua53;

use nom_lua53::{parse_all, ParseResult, Statement, Exp};
use nom_lua53::op::BinOp;

#[derive(Debug)]
pub enum LuaValue {
    Nil,
    Integer(isize),
    Float(f64),
    Boolean(bool),
    Str(String),
}

#[derive(Debug)]
pub enum LuaError {
    TypeError(String),
    ArithmeticError(String),
}

use LuaError::*;

type Result<T> = std::result::Result<T, LuaError>;

// What do we say? We say "Merci Basile!"
fn lit_to_string(string: &nom_lua53::string::StringLit) -> String {
    return String::from_utf8_lossy(&(string.0)).to_string();
}

fn eval_arithmetic(left_op: &Box<Exp>, right_op: &Box<Exp>,
                   integer: fn(isize, isize) -> Result<LuaValue>,
                   float: fn(f64, f64) -> Result<LuaValue>) -> Result<LuaValue> {

    let left_op = eval_expr(&left_op)?;
    let right_op = eval_expr(&right_op)?;

    match left_op {
        LuaValue::Integer(i) => match right_op {
            LuaValue::Integer(j) => integer(i, j),
            LuaValue::Float(j) => float(i as f64, j),
            _ => Err(TypeError("Trying to do arithmetic on non-numerical values.".to_owned()))
        },
        LuaValue::Float(i) => match right_op {
            LuaValue::Integer(j) => float(i, j as f64),
            LuaValue::Float(j) => float(i, j),
            _ => Err(TypeError("Trying to do arithmetic on non-numerical values.".to_owned()))
        },
        _ => Err(TypeError("Trying to do arithmetic on non-numerical values.".to_owned()))
    }
}

fn eval_binary_expr(left_op: &Box<Exp>, right_op: &Box<Exp>, operator: &BinOp) -> Result<LuaValue> {
    // We cannot yet evaluate the operands as some binary operators are used to shortcut
    // evaluation.
    match *operator {
        BinOp::Plus => eval_arithmetic(left_op, right_op,
                                       |i, j| Ok(LuaValue::Integer(i+j)),
                                       |i, j| Ok(LuaValue::Float(i+j))),
        BinOp::Minus => eval_arithmetic(left_op, right_op,
                                        |i, j| Ok(LuaValue::Integer(i-j)),
                                        |i, j| Ok(LuaValue::Float(i-j))),
        BinOp::Mul => eval_arithmetic(left_op, right_op,
                                      |i, j| Ok(LuaValue::Integer(i*j)),
                                      |i, j| Ok(LuaValue::Float(i*j))),
        BinOp::Pow => eval_arithmetic(left_op, right_op,
                                         |i, j| Ok(LuaValue::Float((i as f64).powf(j as f64))),
                                         |i, j| Ok(LuaValue::Float(i.powf(j)))),
        _ => Ok(LuaValue::Nil)
    }
}

fn eval_expr(expr: &Exp) -> Result<LuaValue> {
    match *expr {
        Exp::Nil => Ok(LuaValue::Nil),
        Exp::Bool(val) => Ok(LuaValue::Boolean(val)),
        Exp::Num(val) => Ok(match val {
            nom_lua53::num::Numeral::Float(fl) => LuaValue::Float(fl),
            nom_lua53::num::Numeral::Int(i) => LuaValue::Integer(i),
        }),
        Exp::BinExp(ref left, ref op, ref right) => eval_binary_expr(left, right, &op),
        Exp::Str(ref s) => Ok(LuaValue::Str(lit_to_string(s))),
        _ => Ok(LuaValue::Nil),
    }
}

pub fn eval_file(input: &[u8]) {
    match parse_all(input) {
        ParseResult::Done(blk) => {
            for stmt in blk.stmts {
                println!("{:?}", stmt);
                match stmt {
                    Statement::LVarAssign(ass) => {
                        let values = ass.vals.expect("There should be some values. Why isn't there any value?!");
                        for (var, val) in ass.vars.iter().zip(values.iter()) {
                            let computed_value = eval_expr(val);
                            println!("Assigning {:?} to {:?}", computed_value, var);
                        }
                    }
                    Statement::Assignment(ass) => {
                        println!("Assigning {:?} to {:?}", ass.vals, ass.vars);
                    }
                    _ => {}
                }
            }
        }

        ParseResult::Error(rest, ss) => {
            println!("Error. statements == {:#?}", ss);
            println!("rest == '{}'", String::from_utf8_lossy(rest));
        }
    }
}
<commit_msg>Implement all the division variations<commit_after>extern crate nom_lua53;

use nom_lua53::{parse_all, ParseResult, Statement, Exp};
use nom_lua53::op::BinOp;

#[derive(Debug)]
pub enum LuaValue {
    Nil,
    Integer(isize),
    Float(f64),
    Boolean(bool),
    Str(String),
}

#[derive(Debug)]
pub enum LuaError {
    TypeError(String),
    ArithmeticError(String),
}

use LuaError::*;

type Result<T> = std::result::Result<T, LuaError>;

// What do we say? We say "Merci Basile!"
fn lit_to_string(string: &nom_lua53::string::StringLit) -> String {
    return String::from_utf8_lossy(&(string.0)).to_string();
}

fn eval_arithmetic(left_op: &Box<Exp>, right_op: &Box<Exp>,
                   integer: fn(isize, isize) -> Result<LuaValue>,
                   float: fn(f64, f64) -> Result<LuaValue>) -> Result<LuaValue> {

    let left_op = eval_expr(&left_op)?;
    let right_op = eval_expr(&right_op)?;

    match left_op {
        LuaValue::Integer(i) => match right_op {
            LuaValue::Integer(j) => integer(i, j),
            LuaValue::Float(j) => float(i as f64, j),
            _ => Err(TypeError("Trying to do arithmetic on non-numerical values.".to_owned()))
        },
        LuaValue::Float(i) => match right_op {
            LuaValue::Integer(j) => float(i, j as f64),
            LuaValue::Float(j) => float(i, j),
            _ => Err(TypeError("Trying to do arithmetic on non-numerical values.".to_owned()))
        },
        _ => Err(TypeError("Trying to do arithmetic on non-numerical values.".to_owned()))
    }
}

fn eval_binary_expr(left_op: &Box<Exp>, right_op: &Box<Exp>, operator: &BinOp) -> Result<LuaValue> {
    // We cannot yet evaluate the operands as some binary operators are used to shortcut
    // evaluation.
    match *operator {
        BinOp::Plus => eval_arithmetic(left_op, right_op,
                                       |i, j| Ok(LuaValue::Integer(i+j)),
                                       |i, j| Ok(LuaValue::Float(i+j))),
        BinOp::Minus => eval_arithmetic(left_op, right_op,
                                        |i, j| Ok(LuaValue::Integer(i-j)),
                                        |i, j| Ok(LuaValue::Float(i-j))),
        BinOp::Mul => eval_arithmetic(left_op, right_op,
                                      |i, j| Ok(LuaValue::Integer(i*j)),
                                      |i, j| Ok(LuaValue::Float(i*j))),
        BinOp::Div => eval_arithmetic(left_op, right_op,
                                      |i, j| if j == 0 {
                                          Err(ArithmeticError("Dividing by 0".to_owned()))
                                      } else {
                                          Ok(LuaValue::Float((i as f64)/(j as f64)))
                                      },
                                      |i, j| if j == 0. {
                                          Err(ArithmeticError("Dividing by 0".to_owned()))
                                      } else {
                                          Ok(LuaValue::Float(i/j))
                                      }),
        BinOp::Mod => eval_arithmetic(left_op, right_op,
                                      |i, j| if j == 0 {
                                          Err(ArithmeticError("Dividing by 0".to_owned()))
                                      } else {
                                          Ok(LuaValue::Integer(i % j))
                                      },
                                      |i, j| if j == 0. {
                                          Err(ArithmeticError("Dividing by 0".to_owned()))
                                      } else {
                                          Ok(LuaValue::Float(i - (i/j).floor()*j))
                                      }),
        BinOp::IntDiv => eval_arithmetic(left_op, right_op,
                                         |i, j| if j == 0 {
                                             Err(ArithmeticError("Dividing by 0".to_owned()))
                                         } else {
                                             Ok(LuaValue::Integer(i/j))
                                         },
                                         |i, j| if j == 0. {
                                             Err(ArithmeticError("Dividing by 0".to_owned()))
                                         } else {
                                             Ok(LuaValue::Integer((i/j).floor() as isize))
                                         }),
        BinOp::Pow => eval_arithmetic(left_op, right_op,
                                         |i, j| Ok(LuaValue::Float((i as f64).powf(j as f64))),
                                         |i, j| Ok(LuaValue::Float(i.powf(j)))),
        _ => Ok(LuaValue::Nil)
    }
}

fn eval_expr(expr: &Exp) -> Result<LuaValue> {
    match *expr {
        Exp::Nil => Ok(LuaValue::Nil),
        Exp::Bool(val) => Ok(LuaValue::Boolean(val)),
        Exp::Num(val) => Ok(match val {
            nom_lua53::num::Numeral::Float(fl) => LuaValue::Float(fl),
            nom_lua53::num::Numeral::Int(i) => LuaValue::Integer(i),
        }),
        Exp::BinExp(ref left, ref op, ref right) => eval_binary_expr(left, right, &op),
        Exp::Str(ref s) => Ok(LuaValue::Str(lit_to_string(s))),
        _ => Ok(LuaValue::Nil),
    }
}

pub fn eval_file(input: &[u8]) {
    match parse_all(input) {
        ParseResult::Done(blk) => {
            for stmt in blk.stmts {
                println!("{:?}", stmt);
                match stmt {
                    Statement::LVarAssign(ass) => {
                        let values = ass.vals.expect("There should be some values. Why isn't there any value?!");
                        for (var, val) in ass.vars.iter().zip(values.iter()) {
                            let computed_value = eval_expr(val);
                            println!("Assigning {:?} to {:?}", computed_value, var);
                        }
                    }
                    Statement::Assignment(ass) => {
                        println!("Assigning {:?} to {:?}", ass.vals, ass.vars);
                    }
                    _ => {}
                }
            }
        }

        ParseResult::Error(rest, ss) => {
            println!("Error. statements == {:#?}", ss);
            println!("rest == '{}'", String::from_utf8_lossy(rest));
        }
    }
}
<|endoftext|>


<commit_before>#![feature(core)]
extern crate core;
use core::fmt::Debug;
use std::marker::PhantomData;

pub struct Expectation<Lhs: Debug>(Lhs);

pub struct To<Lhs: Debug>(Lhs);

pub trait Matcher<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool;
    fn fail_msg(&self, rhs: &Lhs) -> String;
}

trait WithLen {
    fn len(&self) -> usize;
    fn is_empty(&self) -> bool;
}

impl<T> WithLen for Vec<T> {
    fn len(&self) -> usize { self.len() }
    fn is_empty(&self) -> bool { self.is_empty() }
}

pub struct Empty;
impl<Lhs: Debug + WithLen> Matcher<Lhs> for Empty {
    fn matches(&self, rhs: &Lhs) -> bool {
        rhs.is_empty()
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("expected {:?} to be empty", rhs)
    }
}

pub struct Equal<Lhs: Debug>(Lhs);

impl<Lhs: Debug + PartialEq> Matcher<Lhs> for Equal<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool {
        &self.0 == rhs
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("expected {:?} to equal {:?}", rhs, self.0)
    }
}

pub struct Not<A, M>(M, PhantomData<A>) where A: Debug, M: Matcher<A>;

impl<Lhs: Debug, M: Matcher<Lhs>> Matcher<Lhs> for Not<Lhs, M> {
    fn matches(&self, rhs: &Lhs) -> bool {
        !self.0.matches(rhs)
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("not {}", self.0.fail_msg(rhs))
    }
}

impl<Lhs: Debug> Expectation<Lhs> {
    pub fn is<T>(&self, matcher: T) where T: Matcher<Lhs> {
        self.to(matcher)
    }

    pub fn to<T>(&self, matcher: T) where T: Matcher<Lhs> {
        if !matcher.matches(&self.0) {
            panic!(matcher.fail_msg(&self.0))
        }
    }
}

pub fn expect<T: Debug>(lhs: T) -> Expectation<T> {
    Expectation(lhs)
}

pub fn equal<T: Debug>(rhs: T) -> Equal<T> {
    Equal(rhs)
}

pub fn not<T: Debug, M: Matcher<T>>(rhs: M) -> Not<T, M> {
    Not(rhs, PhantomData)
}

pub fn empty() -> Empty {
    Empty
}

#[cfg(test)]
mod test {
    use super::{expect, equal, not, empty};

    #[test]
    fn test_expect_equality() {
        expect(1).to(equal(1));
    }

    #[test]
    #[should_panic(expected="expected 1 to equal 2")]
    fn test_expect_not_equality_to_fail() {
        expect(1).to(equal(2));
    }

    #[test]
    fn test_partial_eq_equality() {
        #[derive(PartialEq, Debug)]
        struct Foo { a: u16, b: String }

        expect(Foo{ a: 10u16, b: "Hello".to_string()})
            .to(equal(Foo{ a: 10u16, b: "Hello".to_string()}));
    }

    #[test]
    fn test_invert_equality() {
        expect(1).to(not(equal(2)));
    }

    #[test]
    fn test_invert_invert_equality() {
        expect(1).to(not(not(equal(1))));
    }

    #[test]
    #[should_panic(expected="not expected 1 to equal 1")]
    fn test_invert_equality_equal_to_fail() {
        expect(1).to(not(equal(1)));
    }

    #[test]
    fn test_empty() {
        let v: Vec<usize> = Vec::new();
        expect(v).is(empty());
    }

    #[test]
    fn test_not_empty() {
        let v = vec![1, 2, 3];
        expect(v).is(not(empty()));
    }
}
<commit_msg>Add `WithLen` impl for strings<commit_after>#![feature(core)]
extern crate core;
use core::fmt::Debug;
use std::marker::PhantomData;

pub struct Expectation<Lhs: Debug>(Lhs);

pub struct To<Lhs: Debug>(Lhs);

pub trait Matcher<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool;
    fn fail_msg(&self, rhs: &Lhs) -> String;
}

pub trait WithLen {
    fn len(&self) -> usize;
    fn is_empty(&self) -> bool;
}

impl<T> WithLen for Vec<T> {
    fn len(&self) -> usize { self.len() }
    fn is_empty(&self) -> bool { self.is_empty() }
}

impl WithLen for String {
    fn len(&self) -> usize { self.chars().count() }
    fn is_empty(&self) -> bool { self.chars().count() == 0 }
}

impl<'a> WithLen for &'a str {
    fn len(&self) -> usize { self.chars().count() }
    fn is_empty(&self) -> bool { self.chars().count() == 0 }
}

pub struct Empty;
impl<Lhs: Debug + WithLen> Matcher<Lhs> for Empty {
    fn matches(&self, rhs: &Lhs) -> bool {
        rhs.is_empty()
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("expected {:?} to be empty", rhs)
    }
}

pub struct Equal<Lhs: Debug>(Lhs);

impl<Lhs: Debug + PartialEq> Matcher<Lhs> for Equal<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool {
        &self.0 == rhs
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("expected {:?} to equal {:?}", rhs, self.0)
    }
}

pub struct Not<A, M>(M, PhantomData<A>) where A: Debug, M: Matcher<A>;

impl<Lhs: Debug, M: Matcher<Lhs>> Matcher<Lhs> for Not<Lhs, M> {
    fn matches(&self, rhs: &Lhs) -> bool {
        !self.0.matches(rhs)
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("not {}", self.0.fail_msg(rhs))
    }
}

impl<Lhs: Debug> Expectation<Lhs> {
    pub fn is<T>(&self, matcher: T) where T: Matcher<Lhs> {
        self.to(matcher)
    }

    pub fn to<T>(&self, matcher: T) where T: Matcher<Lhs> {
        if !matcher.matches(&self.0) {
            panic!(matcher.fail_msg(&self.0))
        }
    }
}

pub fn expect<T: Debug>(lhs: T) -> Expectation<T> {
    Expectation(lhs)
}

pub fn equal<T: Debug>(rhs: T) -> Equal<T> {
    Equal(rhs)
}

pub fn not<T: Debug, M: Matcher<T>>(rhs: M) -> Not<T, M> {
    Not(rhs, PhantomData)
}

pub fn empty() -> Empty {
    Empty
}

#[cfg(test)]
mod test {
    use super::{expect, equal, not, empty};

    #[test]
    fn test_expect_equality() {
        expect(1).to(equal(1));
    }

    #[test]
    #[should_panic(expected="expected 1 to equal 2")]
    fn test_expect_not_equality_to_fail() {
        expect(1).to(equal(2));
    }

    #[test]
    fn test_partial_eq_equality() {
        #[derive(PartialEq, Debug)]
        struct Foo { a: u16, b: String }

        expect(Foo{ a: 10u16, b: "Hello".to_string()})
            .to(equal(Foo{ a: 10u16, b: "Hello".to_string()}));
    }

    #[test]
    fn test_invert_equality() {
        expect(1).to(not(equal(2)));
    }

    #[test]
    fn test_invert_invert_equality() {
        expect(1).to(not(not(equal(1))));
    }

    #[test]
    #[should_panic(expected="not expected 1 to equal 1")]
    fn test_invert_equality_equal_to_fail() {
        expect(1).to(not(equal(1)));
    }

    #[test]
    fn test_empty() {
        let v: Vec<usize> = Vec::new();
        expect(v).is(empty());
    }

    #[test]
    fn test_not_empty() {
        let v = vec![1, 2, 3];
        expect(v).is(not(empty()));
    }

    #[test]
    fn test_empty_string() {
        expect("".to_string()).is(empty());
    }

    #[test]
    fn test_not_empty_string() {
        expect("not-empty".to_string()).is(not(empty()));
    }

    #[test]
    fn test_empty_str() {
        expect("").is(empty());
    }

    #[test]
    fn test_not_empty_str() {
        expect("not-empty").is(not(empty()));
    }
}
<|endoftext|>


<commit_before>//! A simple but effective sign library, written in Rust.
//!
//! Ported from [nobi](https://github.com/cyx/nobi),
//! which itself is a port of [itsdangerous](http://pythonhosted.org/itsdangerous/).
//!
//! # Possible use cases
//!
//! * Creating an activation link for users
//! * Creating a password reset link
//!
//! # Basic Example:
//!
//! ```rust
//! use nobsign::Signer;
//! let signer = Signer::new(b"my secret");
//!
//! // Let's say the user's ID is 101
//! let signed = signer.sign("101");
//!
//! // You can now email this url to your users!
//! let url = format!("http://yoursite.com/activate/?key={}", signed);
//!
//! // Later check the signature and get the value back
//! let unsigned = signer.unsign(&signed).unwrap();
//! ```
//!
//! # Example with timestamped signatures
//!
//! ```rust
//! use nobsign::TimestampSigner;
//! let signer = TimestampSigner::new(b"my secret");
//!
//! // Let's say the user's ID is 101
//! let signed = signer.sign("101");
//!
//! // You can now email this url to your users!
//! let url = format!("http://yoursite.com/activate/?key={}", signed);
//!
//! // In your code, you can verify the expiration:
//! signer.unsign(&signed, 86400).unwrap(); // 1 day expiration
//! ```
extern crate rustc_serialize;
extern crate ring;
extern crate time;
extern crate byteorder;

// Use same EPOCH as nobi, the Ruby implementation
const EPOCH : i32 = 1293840000;

use ring::{digest, hmac};
use rustc_serialize::base64::{ToBase64, FromBase64, URL_SAFE};
use byteorder::{ByteOrder, LittleEndian};

static ALGORITHM: &'static digest::Algorithm = &digest::SHA1;

#[derive(Debug,PartialEq)]
pub enum Error {
    BadData,
    BadSignature,
    BadTimeSignature,
    SignatureExpired,
}

pub struct Signer {
    separator: char,
    s_key: hmac::SigningKey,
    v_key: hmac::VerificationKey,
}

pub struct TimestampSigner {
    signer: Signer,
}

fn int_to_bytes(n: i32) -> [u8; 4] {
    let mut out = [0; 4];

    LittleEndian::write_i32(&mut out, n);
    out
}
fn bytes_to_int(n: &[u8]) -> i32 {
    assert!(n.len() == 4);
    LittleEndian::read_i32(n)
}

impl Signer {
    pub fn new(secret: &[u8]) -> Signer {
        let initial_key = hmac::SigningKey::new(ALGORITHM, secret);
        let derived_key = hmac::sign(&initial_key, b"nobi.Signer");

        Signer {
            separator: '.',
            s_key: hmac::SigningKey::new(ALGORITHM, derived_key.as_ref()),
            v_key: hmac::VerificationKey::new(ALGORITHM, derived_key.as_ref()),
        }
    }

    pub fn sign(&self, value: &str) -> String {
        format!("{}{}{}", value, self.separator, &self.signature(value))
    }

    pub fn unsign(&self, value: &str) -> Result<String, Error> {
        let mut splitted = value.rsplitn(2, |c| c == self.separator);

        let sig = match splitted.next() {
            Some(val) => val,
            None => return Err(Error::BadSignature),
        };
        let value = match splitted.next() {
            Some(val) => val,
            None => return Err(Error::BadSignature),
        };

        let sig = try!(sig.from_base64().map_err(|_| Error::BadSignature));
        try!(hmac::verify(&self.v_key, value.as_bytes(), &sig)
                .map_err(|_| Error::BadSignature));

        Ok(value.into())
    }

    fn signature(&self, value: &str) -> String {
        let sig = hmac::sign(&self.s_key, value.as_bytes());
        sig.as_ref().to_base64(URL_SAFE)
    }
}

impl TimestampSigner {
    pub fn new(secret: &[u8]) -> TimestampSigner {
        TimestampSigner { signer: Signer::new(secret) }
    }

    fn get_timestamp(&self) -> i32 {
        let now = time::now_utc().to_timespec();
        now.sec as i32 - EPOCH
    }

    pub fn sign(&self, value: &str) -> String {
        let timestamp = self.get_timestamp();
        let timestamp = int_to_bytes(timestamp);
        let timestamp = timestamp.to_base64(URL_SAFE);
        let value = format!("{}{}{}", value, self.signer.separator, timestamp);

        format!("{}{}{}",
                value,
                self.signer.separator,
                &self.signature(&value))
    }

    pub fn unsign(&self, value: &str, max_age: u32) -> Result<String, Error> {
        let result = try!(self.signer.unsign(value));

        if !result.contains(self.signer.separator) {
            return Err(Error::BadTimeSignature);
        }

        let mut splitted = result.rsplitn(2, |c| c == self.signer.separator);

        let timestamp = match splitted.next() {
            Some(val) => val,
            None => return Err(Error::BadSignature),
        };
        let value = match splitted.next() {
            Some(val) => val,
            None => return Err(Error::BadSignature),
        };

        let timestamp = match timestamp.from_base64() {
            Err(_) => return Err(Error::BadTimeSignature),
            Ok(timestamp) => timestamp,
        };
        if timestamp.len() != 4 {
            return Err(Error::BadTimeSignature);
        }
        let timestamp = bytes_to_int(&timestamp);
        let age = self.get_timestamp() - timestamp;

        if age > max_age as i32 {
            return Err(Error::SignatureExpired);
        }

        Ok(value.into())
    }

    fn signature(&self, value: &str) -> String {
        self.signer.signature(value)
    }
}

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

    #[test]
    fn signs() {
        let signer = Signer::new(b"my-key");

        let signed = signer.sign("value");
        assert_eq!("value.EWkF3-80sipsPgLQ01NuTuPb0jQ".to_owned(), signed);

        assert_eq!("value".to_owned(), signer.unsign(&signed).unwrap());
    }

    #[test]
    fn bad_unsign() {
        let signer = Signer::new(b"my-key");

        let signed = "value.ABCDEF";
        assert_eq!(Err(Error::BadSignature), signer.unsign(&signed));
    }

    #[test]
    fn signs_with_timestamp() {
        let signer = TimestampSigner::new(b"my-key");

        let signed = signer.sign("value");

        assert_eq!("value".to_owned(), signer.unsign(&signed, 100).unwrap());
    }

    #[test]
    fn bad_unsign_with_timestamp() {
        let signer = TimestampSigner::new(b"my-key");

        let signed = "value.ABCDEF";
        assert_eq!(Err(Error::BadSignature), signer.unsign(&signed, 10));

        let signed = "value.EWkF3-80sipsPgLQ01NuTuPb0jQ";
        assert_eq!(Err(Error::BadTimeSignature), signer.unsign(&signed, 10));

        let signed = "value.AB.HHdWpuF7QVDZ_02wvECHvtV8vIc";
        assert_eq!(Err(Error::BadTimeSignature), signer.unsign(&signed, 10));
    }

    #[test]
    fn unsign_expired() {
        use std::thread::sleep_ms;
        let signer = TimestampSigner::new(b"my-key");
        let signed = signer.sign("value");
        sleep_ms(1000);
        assert_eq!(Err(Error::SignatureExpired), signer.unsign(&signed, 0));
    }

    #[test]
    fn with_secure_secret() {
        use ring::rand;
        let mut key = vec![0u8; ALGORITHM.digest_len];
        rand::fill_secure_random(&mut key).unwrap();

        let signer = Signer::new(&key);
        let signed = signer.sign("Hello world!");

        assert_eq!("Hello world!", signer.unsign(&signed).unwrap());
    }
}
<commit_msg>refactor: Replace deprecated API usage<commit_after>//! A simple but effective sign library, written in Rust.
//!
//! Ported from [nobi](https://github.com/cyx/nobi),
//! which itself is a port of [itsdangerous](http://pythonhosted.org/itsdangerous/).
//!
//! # Possible use cases
//!
//! * Creating an activation link for users
//! * Creating a password reset link
//!
//! # Basic Example:
//!
//! ```rust
//! use nobsign::Signer;
//! let signer = Signer::new(b"my secret");
//!
//! // Let's say the user's ID is 101
//! let signed = signer.sign("101");
//!
//! // You can now email this url to your users!
//! let url = format!("http://yoursite.com/activate/?key={}", signed);
//!
//! // Later check the signature and get the value back
//! let unsigned = signer.unsign(&signed).unwrap();
//! ```
//!
//! # Example with timestamped signatures
//!
//! ```rust
//! use nobsign::TimestampSigner;
//! let signer = TimestampSigner::new(b"my secret");
//!
//! // Let's say the user's ID is 101
//! let signed = signer.sign("101");
//!
//! // You can now email this url to your users!
//! let url = format!("http://yoursite.com/activate/?key={}", signed);
//!
//! // In your code, you can verify the expiration:
//! signer.unsign(&signed, 86400).unwrap(); // 1 day expiration
//! ```
extern crate rustc_serialize;
extern crate ring;
extern crate time;
extern crate byteorder;

// Use same EPOCH as nobi, the Ruby implementation
const EPOCH : i32 = 1293840000;

use ring::{digest, hmac};
use rustc_serialize::base64::{ToBase64, FromBase64, URL_SAFE};
use byteorder::{ByteOrder, LittleEndian};

static ALGORITHM: &'static digest::Algorithm = &digest::SHA1;

#[derive(Debug,PartialEq)]
pub enum Error {
    BadData,
    BadSignature,
    BadTimeSignature,
    SignatureExpired,
}

pub struct Signer {
    separator: char,
    s_key: hmac::SigningKey,
    v_key: hmac::VerificationKey,
}

pub struct TimestampSigner {
    signer: Signer,
}

fn int_to_bytes(n: i32) -> [u8; 4] {
    let mut out = [0; 4];

    LittleEndian::write_i32(&mut out, n);
    out
}
fn bytes_to_int(n: &[u8]) -> i32 {
    assert!(n.len() == 4);
    LittleEndian::read_i32(n)
}

impl Signer {
    pub fn new(secret: &[u8]) -> Signer {
        let initial_key = hmac::SigningKey::new(ALGORITHM, secret);
        let derived_key = hmac::sign(&initial_key, b"nobi.Signer");

        Signer {
            separator: '.',
            s_key: hmac::SigningKey::new(ALGORITHM, derived_key.as_ref()),
            v_key: hmac::VerificationKey::new(ALGORITHM, derived_key.as_ref()),
        }
    }

    pub fn sign(&self, value: &str) -> String {
        format!("{}{}{}", value, self.separator, &self.signature(value))
    }

    pub fn unsign(&self, value: &str) -> Result<String, Error> {
        let mut splitted = value.rsplitn(2, |c| c == self.separator);

        let sig = match splitted.next() {
            Some(val) => val,
            None => return Err(Error::BadSignature),
        };
        let value = match splitted.next() {
            Some(val) => val,
            None => return Err(Error::BadSignature),
        };

        let sig = try!(sig.from_base64().map_err(|_| Error::BadSignature));
        try!(hmac::verify(&self.v_key, value.as_bytes(), &sig)
                .map_err(|_| Error::BadSignature));

        Ok(value.into())
    }

    fn signature(&self, value: &str) -> String {
        let sig = hmac::sign(&self.s_key, value.as_bytes());
        sig.as_ref().to_base64(URL_SAFE)
    }
}

impl TimestampSigner {
    pub fn new(secret: &[u8]) -> TimestampSigner {
        TimestampSigner { signer: Signer::new(secret) }
    }

    fn get_timestamp(&self) -> i32 {
        let now = time::now_utc().to_timespec();
        now.sec as i32 - EPOCH
    }

    pub fn sign(&self, value: &str) -> String {
        let timestamp = self.get_timestamp();
        let timestamp = int_to_bytes(timestamp);
        let timestamp = timestamp.to_base64(URL_SAFE);
        let value = format!("{}{}{}", value, self.signer.separator, timestamp);

        format!("{}{}{}",
                value,
                self.signer.separator,
                &self.signature(&value))
    }

    pub fn unsign(&self, value: &str, max_age: u32) -> Result<String, Error> {
        let result = try!(self.signer.unsign(value));

        if !result.contains(self.signer.separator) {
            return Err(Error::BadTimeSignature);
        }

        let mut splitted = result.rsplitn(2, |c| c == self.signer.separator);

        let timestamp = match splitted.next() {
            Some(val) => val,
            None => return Err(Error::BadSignature),
        };
        let value = match splitted.next() {
            Some(val) => val,
            None => return Err(Error::BadSignature),
        };

        let timestamp = match timestamp.from_base64() {
            Err(_) => return Err(Error::BadTimeSignature),
            Ok(timestamp) => timestamp,
        };
        if timestamp.len() != 4 {
            return Err(Error::BadTimeSignature);
        }
        let timestamp = bytes_to_int(&timestamp);
        let age = self.get_timestamp() - timestamp;

        if age > max_age as i32 {
            return Err(Error::SignatureExpired);
        }

        Ok(value.into())
    }

    fn signature(&self, value: &str) -> String {
        self.signer.signature(value)
    }
}

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

    #[test]
    fn signs() {
        let signer = Signer::new(b"my-key");

        let signed = signer.sign("value");
        assert_eq!("value.EWkF3-80sipsPgLQ01NuTuPb0jQ".to_owned(), signed);

        assert_eq!("value".to_owned(), signer.unsign(&signed).unwrap());
    }

    #[test]
    fn bad_unsign() {
        let signer = Signer::new(b"my-key");

        let signed = "value.ABCDEF";
        assert_eq!(Err(Error::BadSignature), signer.unsign(&signed));
    }

    #[test]
    fn signs_with_timestamp() {
        let signer = TimestampSigner::new(b"my-key");

        let signed = signer.sign("value");

        assert_eq!("value".to_owned(), signer.unsign(&signed, 100).unwrap());
    }

    #[test]
    fn bad_unsign_with_timestamp() {
        let signer = TimestampSigner::new(b"my-key");

        let signed = "value.ABCDEF";
        assert_eq!(Err(Error::BadSignature), signer.unsign(&signed, 10));

        let signed = "value.EWkF3-80sipsPgLQ01NuTuPb0jQ";
        assert_eq!(Err(Error::BadTimeSignature), signer.unsign(&signed, 10));

        let signed = "value.AB.HHdWpuF7QVDZ_02wvECHvtV8vIc";
        assert_eq!(Err(Error::BadTimeSignature), signer.unsign(&signed, 10));
    }

    #[test]
    fn unsign_expired() {
        use std::thread;
        use std::time::Duration;

        let signer = TimestampSigner::new(b"my-key");
        let signed = signer.sign("value");
        thread::sleep(Duration::from_secs(1));
        assert_eq!(Err(Error::SignatureExpired), signer.unsign(&signed, 0));
    }

    #[test]
    fn with_secure_secret() {
        use ring::rand;
        let mut key = vec![0u8; ALGORITHM.digest_len];
        rand::fill_secure_random(&mut key).unwrap();

        let signer = Signer::new(&key);
        let signed = signer.sign("Hello world!");

        assert_eq!("Hello world!", signer.unsign(&signed).unwrap());
    }
}
<|endoftext|>


<commit_before>mod blueprint;

pub use blueprint::Blueprint;

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

  #[test]
  fn test() {
    println!("{:?}", Blueprint{})
  }
}
<commit_msg>Update `lib`<commit_after>//! A fuzzy inference engine library.
//!
//! This crate aims to offer a simple declarative API to build fuzzy inference engines.
//!
//! ## Examples
//!
//! Start by defining a `Blueprint` inference engine:
//!
//! ```rust
//! # #![allow(unused_variables)]
//! use fiers::blueprint::MaxMin;
//!
//! let blueprint = MaxMin::default();
//! ```

#![warn(missing_docs)]

pub mod fuzzy;
pub mod blueprint;
pub mod util;

pub use blueprint::Blueprint;

#[cfg(test)]
mod tests {
  use super::blueprint::{MaxMin};

  #[test]
  fn test() {
    println!("{:?}", MaxMin::default());
  }
}
<|endoftext|>


<commit_before>#![feature(plugin_registrar, macro_rules)]

extern crate rustc;
extern crate syntax;

use std::dynamic_lib::DynamicLibrary;
use std::gc::Gc;
use std::io::{fs, Command};
use std::os;
use std::str;
use std::sync::{Once, ONCE_INIT};

use rustc::plugin::Registry;
use syntax::abi;
use syntax::ast;
use syntax::attr;
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, DummyResult, MacroDef};
use syntax::ext::base::MacResult;
use syntax::ext::build::AstBuilder;
use syntax::fold::Folder;
use syntax::parse::parser::Parser;
use syntax::parse::token;
use syntax::parse::token::{special_idents, InternedString};
use syntax::print::pprust;
use syntax::util::small_vector::SmallVector;

struct LibInfo {
    lib: String,
    state: State,
    deps: Vec<(String, bool)>, // (name, static)
    locs: Vec<Path>,
}

struct MacItems {
    items: Vec<Gc<ast::Item>>,
}

enum State { Dynamic, Static(SystemDeps) }
enum SystemDeps { SystemDynamic, SystemStatic }
enum Favor { FavorDynamic, FavorStatic }

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("link_config", expand_link_config);
}

fn expand_link_config(ecx: &mut ExtCtxt, span: Span,
                      tts: &[ast::TokenTree]) -> Box<MacResult> {
    macro_rules! try_dummy( ($e:expr) => (
        match $e { Ok(s) => s, Err(()) => return DummyResult::any(span) }
    ) )

    let mut parser = ecx.new_parser_from_tts(tts);
    let (pkg, sp) = try_dummy!(parse_string(ecx, &mut parser));
    let mut favor_dynamic = FavorDynamic;
    let mut dylib_state = Some(Dynamic);
    let mut static_state = Some(Static(SystemDynamic));
    if parser.eat(&token::COMMA) && parser.eat(&token::LBRACKET) {
        while !parser.eat(&token::RBRACKET) {
            parser.eat(&token::COMMA);
            let (modifier, sp) = try_dummy!(parse_string(ecx, &mut parser));
            match modifier.as_slice() {
                "only_static" => {
                    dylib_state = None;
                    favor_dynamic = FavorStatic;
                }
                "only_dylib" => {
                    static_state = None;
                    favor_dynamic = FavorDynamic;
                }
                "system_static" => static_state = Some(Static(SystemStatic)),
                "favor_static" => favor_dynamic = FavorStatic,
                s => ecx.span_err(sp, format!("unknown modifier: `{}`",
                                              s).as_slice()),
            }
        }
    }
    if !parser.eat(&token::EOF) {
        ecx.span_err(parser.span, "only one string literal allowed");
        return DummyResult::any(span);
    }

    let dyn = try_dummy!(system_pkgconfig(ecx, sp, pkg.as_slice(), dylib_state));
    let statik = try_dummy!(system_pkgconfig(ecx, sp, pkg.as_slice(), static_state));

    let mut items = Vec::new();
    match dyn {
        Some(info) => items.push(block(ecx, sp, &info, favor_dynamic)),
        None => {}
    }
    match statik {
        Some(info) => items.push(block(ecx, sp, &info, favor_dynamic)),
        None => {}
    }
    box MacItems { items: items } as Box<MacResult>
}

fn system_pkgconfig(ecx: &mut ExtCtxt, sp: Span, pkg: &str,
                    state: Option<State>) -> Result<Option<LibInfo>, ()> {
    let state = match state {
        Some(state) => state,
        None => return Ok(None),
    };
    add_cargo_pkg_config_paths();

    let mut cmd = Command::new("pkg-config");
    cmd.arg(pkg).arg("--libs").env("PKG_CONFIG_ALLOW_SYSTEM_LIBS", "1");
    match state {
        Static(..) => { cmd.arg("--static"); }
        Dynamic => {}
    }
    let out = match cmd.output() {
        Ok(out) => out,
        Err(e) => {
            ecx.span_err(sp, format!("could not run pkg-config: {}", e).as_slice());
            return Err(())
        }
    };
    let stdout = str::from_utf8(out.output.as_slice()).unwrap();
    let stderr = str::from_utf8(out.error.as_slice()).unwrap();
    if !out.status.success() {
        let mut msg = format!("pkg-config did not exit successfully: {}",
                              out.status);
        if stdout.len() > 0 {
            msg.push_str("\n--- stdout\n");
            msg.push_str(stdout);
        }
        if stderr.len() > 0 {
            msg.push_str("\n--- stderr\n");
            msg.push_str(stderr);
        }
        ecx.span_err(sp, msg.as_slice());
        return Err(())
    }

    let mut libs = Vec::new();
    let mut locs = Vec::new();
    for arg in stdout.split(' ').filter(|l| !l.is_empty()) {
        if arg.starts_with("-l") {
            libs.push(arg.slice_from(2));
        } else if arg.starts_with("-L") {
            locs.push(Path::new(arg.slice_from(2).to_string()));
        }
    }

    let allow_static = match state {
        Static(..) => true,
        _ => false,
    };
    let allow_static_system = match state {
        Static(SystemStatic) => true,
        _ => false,
    };

    let cargo_locs = cargo_native_dirs();
    let libs = libs.move_iter().map(|lib| {
        let mut candidates = cargo_locs.iter().chain(locs.iter());
        (lib.to_string(), allow_static && candidates.any(|base| {
            (allow_static_system || !base.as_vec().starts_with(b"/usr")) &&
                (base.join(format!("lib{}.a", lib)).exists() ||
                 base.join(format!("{}.lib", lib)).exists() ||
                 base.join(format!("lib{}.lib", lib)).exists())
        }))
    }).collect();
    Ok(Some(LibInfo {
        lib: pkg.to_string(),
        deps: libs,
        locs: locs,
        state: state,
    }))
}

fn block(ecx: &mut ExtCtxt, sp: Span, info: &LibInfo,
         favor: Favor) -> Gc<ast::Item> {
    let lib = token::intern_and_get_ident(info.lib.as_slice());
    let s = match favor {
        FavorDynamic => InternedString::new("statik"),
        FavorStatic => InternedString::new("dylib"),
    };
    let cfg = ecx.meta_name_value(sp, s, ast::LitStr(lib, ast::CookedStr));
    let cfg = match (info.state, favor) {
        (Static(..), FavorDynamic) |
        (Dynamic, FavorStatic) => cfg,
        (Dynamic, FavorDynamic) |
        (Static(..), FavorStatic) => {
            ecx.meta_list(sp, InternedString::new("not"), vec![cfg])
        }
    };
    let cfg = ecx.meta_list(sp, InternedString::new("cfg"), vec![cfg]);

    let attrs = vec![ecx.attribute(sp, cfg)].move_iter();
    let attrs = attrs.chain(info.deps.iter().map(|&(ref l, statik)| {
        // Build #[link(name = <l>)]
        let l = token::intern_and_get_ident(l.as_slice());
        let mut items = Vec::new();
        items.push(ecx.meta_name_value(sp, InternedString::new("name"),
                                       ast::LitStr(l, ast::CookedStr)));
        if statik {
            let l = InternedString::new("static");
            items.push(ecx.meta_name_value(sp, InternedString::new("kind"),
                                           ast::LitStr(l, ast::CookedStr)));
        }
        let list = ecx.meta_list(sp, InternedString::new("link"), items);
        ecx.attribute(sp, list)
    }));
    let attrs = attrs.chain(info.locs.iter().map(|l| {
        let l = token::intern_and_get_ident(format!("-L{}", l.display()).as_slice());
        let args = ecx.meta_name_value(sp, InternedString::new("link_args"),
                                       ast::LitStr(l, ast::CookedStr));
        ecx.attribute(sp, args)
    }));
    let mut attrs = attrs.map(|attr| {
        attr::mark_used(&attr);
        attr
    });

    ecx.item(sp, special_idents::invalid, attrs.collect(),
             ast::ItemForeignMod(ast::ForeignMod {
        abi: abi::C,
        view_items: Vec::new(),
        items: Vec::new(),
    }))
}

fn parse_string(ecx: &mut ExtCtxt,
                parser: &mut Parser) -> Result<(String, Span), ()> {
    let entry = ecx.expander().fold_expr(parser.parse_expr());
    match entry.node {
        ast::ExprLit(lit) => {
            match lit.node {
                ast::LitStr(ref s, _) => return Ok((s.to_string(), entry.span)),
                _ => {}
            }
        }
        _ => {}
    }
    ecx.span_err(entry.span, format!(
        "expected string literal but got `{}`",
        pprust::expr_to_string(&*entry)).as_slice());
    Err(())
}

impl MacResult for MacItems {
    fn make_items(&self) -> Option<SmallVector<Gc<ast::Item>>> {
        Some(self.items.iter().map(|a| a.clone()).collect())
    }
    fn make_stmt(&self) -> Option<Gc<ast::Stmt>> { None }
    fn make_def(&self) -> Option<MacroDef> { None }
    fn make_expr(&self) -> Option<Gc<ast::Expr>> { None }
    fn make_pat(&self) -> Option<Gc<ast::Pat>> { None }
}

// lol hax
fn cargo_native_dirs() -> Vec<Path> {
    match rustc::driver::handle_options(os::args()) {
        Some(matches) => {
            matches.opt_strs("L").move_iter().filter_map(|s| {
                if s.as_slice().contains("native") {
                    Some(Path::new(s))
                } else {
                    None
                }
            }).collect()
        }
        None => Vec::new()
    }
}

fn add_cargo_pkg_config_paths() {
    static mut DONE: Once = ONCE_INIT;
    unsafe { DONE.doit(add_cargo_pkg_config_paths) }

    fn add_cargo_pkg_config_paths() {
        let path = os::getenv_as_bytes("PKG_CONFIG_PATH").unwrap_or(Vec::new());
        let mut pkg_config_path = os::split_paths(path.as_slice());
        pkg_config_path.push_all(cargo_native_dirs().as_slice());
        let pkg_config_path = os::join_paths(pkg_config_path.as_slice())
                                 .unwrap();
        os::setenv("PKG_CONFIG_PATH", pkg_config_path.as_slice());
    }
}
<commit_msg>Fix build break due to generalized object bounds<commit_after>#![feature(plugin_registrar, macro_rules)]

extern crate rustc;
extern crate syntax;

use std::dynamic_lib::DynamicLibrary;
use std::gc::Gc;
use std::io::{fs, Command};
use std::os;
use std::str;
use std::sync::{Once, ONCE_INIT};

use rustc::plugin::Registry;
use syntax::abi;
use syntax::ast;
use syntax::attr;
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, DummyResult, MacroDef};
use syntax::ext::base::MacResult;
use syntax::ext::build::AstBuilder;
use syntax::fold::Folder;
use syntax::parse::parser::Parser;
use syntax::parse::token;
use syntax::parse::token::{special_idents, InternedString};
use syntax::print::pprust;
use syntax::util::small_vector::SmallVector;

struct LibInfo {
    lib: String,
    state: State,
    deps: Vec<(String, bool)>, // (name, static)
    locs: Vec<Path>,
}

struct MacItems {
    items: Vec<Gc<ast::Item>>,
}

enum State { Dynamic, Static(SystemDeps) }
enum SystemDeps { SystemDynamic, SystemStatic }
enum Favor { FavorDynamic, FavorStatic }

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("link_config", expand_link_config);
}

fn expand_link_config(ecx: &mut ExtCtxt, span: Span,
                      tts: &[ast::TokenTree]) -> Box<MacResult+'static> {
    macro_rules! try_dummy( ($e:expr) => (
        match $e { Ok(s) => s, Err(()) => return DummyResult::any(span) }
    ) )

    let mut parser = ecx.new_parser_from_tts(tts);
    let (pkg, sp) = try_dummy!(parse_string(ecx, &mut parser));
    let mut favor_dynamic = FavorDynamic;
    let mut dylib_state = Some(Dynamic);
    let mut static_state = Some(Static(SystemDynamic));
    if parser.eat(&token::COMMA) && parser.eat(&token::LBRACKET) {
        while !parser.eat(&token::RBRACKET) {
            parser.eat(&token::COMMA);
            let (modifier, sp) = try_dummy!(parse_string(ecx, &mut parser));
            match modifier.as_slice() {
                "only_static" => {
                    dylib_state = None;
                    favor_dynamic = FavorStatic;
                }
                "only_dylib" => {
                    static_state = None;
                    favor_dynamic = FavorDynamic;
                }
                "system_static" => static_state = Some(Static(SystemStatic)),
                "favor_static" => favor_dynamic = FavorStatic,
                s => ecx.span_err(sp, format!("unknown modifier: `{}`",
                                              s).as_slice()),
            }
        }
    }
    if !parser.eat(&token::EOF) {
        ecx.span_err(parser.span, "only one string literal allowed");
        return DummyResult::any(span);
    }

    let dyn = try_dummy!(system_pkgconfig(ecx, sp, pkg.as_slice(), dylib_state));
    let statik = try_dummy!(system_pkgconfig(ecx, sp, pkg.as_slice(), static_state));

    let mut items = Vec::new();
    match dyn {
        Some(info) => items.push(block(ecx, sp, &info, favor_dynamic)),
        None => {}
    }
    match statik {
        Some(info) => items.push(block(ecx, sp, &info, favor_dynamic)),
        None => {}
    }
    box MacItems { items: items } as Box<MacResult>
}

fn system_pkgconfig(ecx: &mut ExtCtxt, sp: Span, pkg: &str,
                    state: Option<State>) -> Result<Option<LibInfo>, ()> {
    let state = match state {
        Some(state) => state,
        None => return Ok(None),
    };
    add_cargo_pkg_config_paths();

    let mut cmd = Command::new("pkg-config");
    cmd.arg(pkg).arg("--libs").env("PKG_CONFIG_ALLOW_SYSTEM_LIBS", "1");
    match state {
        Static(..) => { cmd.arg("--static"); }
        Dynamic => {}
    }
    let out = match cmd.output() {
        Ok(out) => out,
        Err(e) => {
            ecx.span_err(sp, format!("could not run pkg-config: {}", e).as_slice());
            return Err(())
        }
    };
    let stdout = str::from_utf8(out.output.as_slice()).unwrap();
    let stderr = str::from_utf8(out.error.as_slice()).unwrap();
    if !out.status.success() {
        let mut msg = format!("pkg-config did not exit successfully: {}",
                              out.status);
        if stdout.len() > 0 {
            msg.push_str("\n--- stdout\n");
            msg.push_str(stdout);
        }
        if stderr.len() > 0 {
            msg.push_str("\n--- stderr\n");
            msg.push_str(stderr);
        }
        ecx.span_err(sp, msg.as_slice());
        return Err(())
    }

    let mut libs = Vec::new();
    let mut locs = Vec::new();
    for arg in stdout.split(' ').filter(|l| !l.is_empty()) {
        if arg.starts_with("-l") {
            libs.push(arg.slice_from(2));
        } else if arg.starts_with("-L") {
            locs.push(Path::new(arg.slice_from(2).to_string()));
        }
    }

    let allow_static = match state {
        Static(..) => true,
        _ => false,
    };
    let allow_static_system = match state {
        Static(SystemStatic) => true,
        _ => false,
    };

    let cargo_locs = cargo_native_dirs();
    let libs = libs.move_iter().map(|lib| {
        let mut candidates = cargo_locs.iter().chain(locs.iter());
        (lib.to_string(), allow_static && candidates.any(|base| {
            (allow_static_system || !base.as_vec().starts_with(b"/usr")) &&
                (base.join(format!("lib{}.a", lib)).exists() ||
                 base.join(format!("{}.lib", lib)).exists() ||
                 base.join(format!("lib{}.lib", lib)).exists())
        }))
    }).collect();
    Ok(Some(LibInfo {
        lib: pkg.to_string(),
        deps: libs,
        locs: locs,
        state: state,
    }))
}

fn block(ecx: &mut ExtCtxt, sp: Span, info: &LibInfo,
         favor: Favor) -> Gc<ast::Item> {
    let lib = token::intern_and_get_ident(info.lib.as_slice());
    let s = match favor {
        FavorDynamic => InternedString::new("statik"),
        FavorStatic => InternedString::new("dylib"),
    };
    let cfg = ecx.meta_name_value(sp, s, ast::LitStr(lib, ast::CookedStr));
    let cfg = match (info.state, favor) {
        (Static(..), FavorDynamic) |
        (Dynamic, FavorStatic) => cfg,
        (Dynamic, FavorDynamic) |
        (Static(..), FavorStatic) => {
            ecx.meta_list(sp, InternedString::new("not"), vec![cfg])
        }
    };
    let cfg = ecx.meta_list(sp, InternedString::new("cfg"), vec![cfg]);

    let attrs = vec![ecx.attribute(sp, cfg)].move_iter();
    let attrs = attrs.chain(info.deps.iter().map(|&(ref l, statik)| {
        // Build #[link(name = <l>)]
        let l = token::intern_and_get_ident(l.as_slice());
        let mut items = Vec::new();
        items.push(ecx.meta_name_value(sp, InternedString::new("name"),
                                       ast::LitStr(l, ast::CookedStr)));
        if statik {
            let l = InternedString::new("static");
            items.push(ecx.meta_name_value(sp, InternedString::new("kind"),
                                           ast::LitStr(l, ast::CookedStr)));
        }
        let list = ecx.meta_list(sp, InternedString::new("link"), items);
        ecx.attribute(sp, list)
    }));
    let attrs = attrs.chain(info.locs.iter().map(|l| {
        let l = token::intern_and_get_ident(format!("-L{}", l.display()).as_slice());
        let args = ecx.meta_name_value(sp, InternedString::new("link_args"),
                                       ast::LitStr(l, ast::CookedStr));
        ecx.attribute(sp, args)
    }));
    let mut attrs = attrs.map(|attr| {
        attr::mark_used(&attr);
        attr
    });

    ecx.item(sp, special_idents::invalid, attrs.collect(),
             ast::ItemForeignMod(ast::ForeignMod {
        abi: abi::C,
        view_items: Vec::new(),
        items: Vec::new(),
    }))
}

fn parse_string(ecx: &mut ExtCtxt,
                parser: &mut Parser) -> Result<(String, Span), ()> {
    let entry = ecx.expander().fold_expr(parser.parse_expr());
    match entry.node {
        ast::ExprLit(lit) => {
            match lit.node {
                ast::LitStr(ref s, _) => return Ok((s.to_string(), entry.span)),
                _ => {}
            }
        }
        _ => {}
    }
    ecx.span_err(entry.span, format!(
        "expected string literal but got `{}`",
        pprust::expr_to_string(&*entry)).as_slice());
    Err(())
}

impl MacResult for MacItems {
    fn make_items(&self) -> Option<SmallVector<Gc<ast::Item>>> {
        Some(self.items.iter().map(|a| a.clone()).collect())
    }
    fn make_stmt(&self) -> Option<Gc<ast::Stmt>> { None }
    fn make_def(&self) -> Option<MacroDef> { None }
    fn make_expr(&self) -> Option<Gc<ast::Expr>> { None }
    fn make_pat(&self) -> Option<Gc<ast::Pat>> { None }
}

// lol hax
fn cargo_native_dirs() -> Vec<Path> {
    match rustc::driver::handle_options(os::args()) {
        Some(matches) => {
            matches.opt_strs("L").move_iter().filter_map(|s| {
                if s.as_slice().contains("native") {
                    Some(Path::new(s))
                } else {
                    None
                }
            }).collect()
        }
        None => Vec::new()
    }
}

fn add_cargo_pkg_config_paths() {
    static mut DONE: Once = ONCE_INIT;
    unsafe { DONE.doit(add_cargo_pkg_config_paths) }

    fn add_cargo_pkg_config_paths() {
        let path = os::getenv_as_bytes("PKG_CONFIG_PATH").unwrap_or(Vec::new());
        let mut pkg_config_path = os::split_paths(path.as_slice());
        pkg_config_path.push_all(cargo_native_dirs().as_slice());
        let pkg_config_path = os::join_paths(pkg_config_path.as_slice())
                                 .unwrap();
        os::setenv("PKG_CONFIG_PATH", pkg_config_path.as_slice());
    }
}
<|endoftext|>


<commit_before>#![recursion_limit = "150"]

#[macro_use]
extern crate nom;

pub use self::common::{FieldExpression, Operator, TableKey};
pub use self::column::{Column, FunctionExpression};
pub use self::condition::{ConditionBase, ConditionExpression, ConditionTree};
pub use self::create::CreateTableStatement;
pub use self::insert::InsertStatement;
pub use self::parser::*;
pub use self::select::{SelectStatement, GroupByClause, JoinClause, LimitClause, OrderClause,
                       OrderType};
pub use self::table::Table;

pub mod parser;

#[macro_use]
mod caseless_tag;
mod keywords;
mod column;
mod common;
mod condition;
mod create;
mod insert;
mod join;
mod select;
mod table;
<commit_msg>Publicly export more join structs/enums<commit_after>#![recursion_limit = "150"]

#[macro_use]
extern crate nom;

pub use self::common::{FieldExpression, Operator, TableKey};
pub use self::column::{Column, FunctionExpression};
pub use self::condition::{ConditionBase, ConditionExpression, ConditionTree};
pub use self::create::CreateTableStatement;
pub use self::insert::InsertStatement;
pub use self::join::{JoinConstraint, JoinOperator, JoinRightSide};
pub use self::parser::*;
pub use self::select::{SelectStatement, GroupByClause, JoinClause, LimitClause, OrderClause,
                       OrderType};
pub use self::table::Table;

pub mod parser;

#[macro_use]
mod caseless_tag;
mod keywords;
mod column;
mod common;
mod condition;
mod create;
mod insert;
mod join;
mod select;
mod table;
<|endoftext|>


<commit_before>#![feature(macro_rules)]
#![allow(unused_variable)]
#![allow(dead_code)]

extern crate serialize;
extern crate url;
extern crate time;

use std::iter::Peekable;
use std::vec::MoveItems;

use self::client::{JsonClient, Client, JsonResult};
use self::sub::Subreddit;
use self::user::{User, Message};

use self::time::{Timespec, Tm, at_utc};
use self::url::Url;

mod client;
pub mod user;
pub mod sub;
pub mod post;

pub static BASE_URL: &'static str = "https://www.reddit.com/";

pub type RedditResult<T> = Result<T, RedditError>;

static CLIENT: Client = self::client::Client;

#[deriving(Show)]
pub enum RedditError {
    /// Authentication failed. Possibly because of an invalid username/password combo,
    /// or an expired session cookie. Contains exact error message from the reddit API.
    AuthError(String),
    /// The user is not allowed to access that resource (HTTP 403).
    PermissionDenied,
    /// The requested resource was not found (HTTP 404).
    NotFound,
    /// This API call requires a modhash
    NeedModhash,
    /// The submission failed because reddit is requiring the user to solve a captcha.
    NeedCaptcha,
}

// Sucks we can't init this
local_data_key!(batch_size: u32)

/// Get the batch size or a sensible default
pub fn get_batch_size() -> u32 {
    batch_size.get().map_or(50u32, |val| *val)
}

pub fn set_batch_size(val: u32) {
    batch_size.replace(Some(50));
}

/// Login to reddit. Returns `Ok(Session)` on success, `Err(AuthError("reason"))` on failure.
pub fn login(user: &str, pass: &str, remain: bool) -> RedditResult<Session> {
    let params = params! {
        "user": user,
        "pass": pass,
        "rem": remain,
    };

    unimplemented!();
}

/// Resume a session with the given cookie string; does not make a request
pub fn resume_session(cookie: &str) -> Session {
    Session {
        cookie: cookie.into_string(),
    }
}

/// Find the subreddit with the given /r/ value
pub fn sub(sub: &str) -> RedditResult<Subreddit> {
    let url = {
        let url = format!("{}r/{}/about.json", BASE_URL, sub);
        Url::parse(url.as_slice()).unwrap()
    };

    let data = CLIENT.get(&url);

    println!("{}", data);

    unimplemented!();

}

/// Find a user with the given /u/ value
pub fn user(user: &str) -> RedditResult<User> {
    unimplemented!();
}

/// Struct representing an authenticated user session;
/// required by any API endpoint that submits changes to reddit, such as posting to subreddits, replying to comments, etc.
pub struct Session {
    cookie: String,
}

impl Session {
    /// Return info about the current user, retaining the modhash on `self`.
    pub fn me(&self) -> User {
        unimplemented!();
    }

    /// Get the session cookie to be restored later
    /// This consumes the Session
    pub fn cookie(self) -> String {
        self.cookie
    }

    pub fn inbox(&self) -> BatchedIter<Message> {
        unimplemented!();
    }

    pub fn unread(&self) -> BatchedIter<Message> {
        unimplemented!();
    }

    pub fn sent(&self) -> BatchedIter<Message> {
        unimplemented!();
    }

    pub fn needs_captcha(&self) -> bool {
        unimplemented!();
    }
}

/// An iterator that fetches items in batches from an underlying data source.
/// Its item type must implement `Batched`.
pub struct BatchedIter<T> {
    size: u32,
    current: Peekable<T, MoveItems<T>>,
}

impl<T: Batched> Iterator<T> for BatchedIter<T> {
    fn next(&mut self) -> Option<T> {
        let next = self.current.next();

        if self.current.peek().is_none() {
            let batch = Batched::batch(next.as_ref(), self.size);

            if !batch.is_empty() {
                self.current = batch.move_iter().peekable();
            }
        }

        next
    }
}

/// A trait for data types that should be fetched in batches, if possible.
pub trait Batched {
    /// Get the next batch of length `size` or smaller,
    /// starting after `last` if provided, the beginning if not.
    /// If no (more) results are available, return an empty vector.
    fn batch(last: Option<&Self>, size: u32) -> Vec<Self>;
}

/// Convert POSIX time (seconds since January 1, 1970 12:00 AM)
/// to Tm (UTC)
pub fn posix_to_utc(seconds: u64) -> Tm {
    // This cast is a bit dangerous,
    // as it may result in a negative value due to overflow,
    // indicating a pre-epoch time instead of the intended time.
    // However, the point at which POSIX time will overflow a 64-bit integer
    // is, according to Wolfram|Alpha, about 300 billion years in the future.
    // I think it's safe to say that we can deal with this later.
    let tmspec = Timespec::new(seconds as i64, 0);
    at_utc(tmspec)
}

/// Lightweight utilities for working with `serialize::json::Json`.
pub mod json {
    use serialize::json::Json;

    /// Get a u64 from the given JSON and key, convert
    /// it to a Tm in UTC, assuming it is POSIX time
    pub fn find_utc(json: &Json, key: &str) -> Option<Tm> {
        find_u64(json, key).map(super::posix_to_utc)
    }

    #[inline]
    pub fn find<'a>(json: &'a Json, key: &str) -> Option<&'a Json> {
        json.find(&(key.into_string()));
    }

    pub fn find_string(json: &Json, key: &str) -> Option<String> {
        find(json, key).and_then(|j| j.as_string()).map(|s| j.into_string())
    }

    pub fn find_u64(json: &Json, key: &str) -> Option<u64> {
        json_find(json, key).and_then(|j| j.as_u64());
    }

    pub fn find_u32(json: &Json, key: &str) -> Option<u32> {
        json_find(json, key).and_then(|j| j.as_u32());
    }

    /// A lighter-weight implementation alternative of Decodable for
    /// structs that just want to deserialize from JSON
    /// TODO: Implement this using a streaming parser
    pub trait FromJson {
        fn from_json(json: &Json) -> Option<Self>;
    }
}
#[test]
fn it_works() {
}
<commit_msg>Minor edits<commit_after>#![feature(macro_rules)]
#![allow(unused_variable)]
#![allow(dead_code)]

extern crate serialize;
extern crate url;
extern crate time;

use std::iter::Peekable;
use std::vec::MoveItems;

use self::client::{JsonClient, Client, JsonResult};
use self::sub::Subreddit;
use self::user::{User, Message};

use self::time::{Timespec, Tm, at_utc};
use self::url::Url;

mod client;
pub mod user;
pub mod sub;
pub mod post;

pub static BASE_URL: &'static str = "https://www.reddit.com/";

pub type RedditResult<T> = Result<T, RedditError>;

static CLIENT: Client = self::client::Client;

#[deriving(Show)]
pub enum RedditError {
    /// Authentication failed. Possibly because of an invalid username/password combo,
    /// or an expired session cookie. Contains exact error message from the reddit API.
    AuthError(String),
    /// The user is not allowed to access that resource (HTTP 403).
    PermissionDenied,
    /// The requested resource was not found (HTTP 404).
    NotFound,
    /// This API call requires a modhash
    NeedModhash,
    /// The submission failed because reddit is requiring the user to solve a captcha.
    NeedCaptcha,
}

// Sucks we can't init this
local_data_key!(batch_size: u32)

/// Get the batch size or a sensible default
pub fn get_batch_size() -> u32 {
    batch_size.get().map_or(50u32, |val| *val)
}

pub fn set_batch_size(val: u32) {
    batch_size.replace(Some(val));
}

/// Login to reddit. Returns `Ok(Session)` on success, `Err(AuthError("reason"))` on failure.
pub fn login(user: &str, pass: &str, remain: bool) -> RedditResult<Session> {
    let params = params! {
        "user": user,
        "pass": pass,
        "rem": remain,
    };

    unimplemented!();
}

/// Resume a session with the given cookie string; does not make a request
pub fn resume_session(cookie: &str) -> Session {
    Session {
        cookie: cookie.into_string(),
    }
}

/// Find the subreddit with the given /r/ value
pub fn sub(sub: &str) -> RedditResult<Subreddit> {
    let url = {
        let url = format!("{}r/{}/about.json", BASE_URL, sub);
        Url::parse(url.as_slice()).unwrap()
    };

    let data = CLIENT.get(&url);

    println!("{}", data);

    unimplemented!();
}

/// Find a user with the given /u/ value
pub fn user(user: &str) -> RedditResult<User> {
    unimplemented!();
}

/// Struct representing an authenticated user session;
/// required by any API endpoint that submits changes to reddit, such as posting to subreddits, replying to comments, etc.
pub struct Session {
    cookie: String,
}

impl Session {
    /// Return info about the current user.
    pub fn me(&self) -> User {
        unimplemented!();
    }

    /// Get the session cookie to be restored later
    /// This consumes the Session
    pub fn cookie(self) -> String {
        self.cookie
    }

    pub fn inbox(&self) -> BatchedIter<Message> {
        unimplemented!();
    }

    pub fn unread(&self) -> BatchedIter<Message> {
        unimplemented!();
    }

    pub fn sent(&self) -> BatchedIter<Message> {
        unimplemented!();
    }

    pub fn needs_captcha(&self) -> bool {
        unimplemented!();
    }
}

/// An iterator that fetches items in batches from an underlying data source.
/// Its item type must implement `Batched`.
pub struct BatchedIter<T> {
    size: u32,
    current: Peekable<T, MoveItems<T>>,
}

impl<T: Batched> Iterator<T> for BatchedIter<T> {
    fn next(&mut self) -> Option<T> {
        let next = self.current.next();

        if self.current.peek().is_none() {
            let batch = Batched::batch(next.as_ref(), self.size);

            if !batch.is_empty() {
                self.current = batch.move_iter().peekable();
            }
        }

        next
    }
}

/// A trait for data types that should be fetched in batches, if possible.
pub trait Batched {
    /// Get the next batch of length `size` or smaller,
    /// starting after `last` if provided, the beginning if not.
    /// If no (more) results are available, return an empty vector.
    fn batch(last: Option<&Self>, size: u32) -> Vec<Self>;
}

/// Convert POSIX time (seconds since January 1, 1970 12:00 AM)
/// to Tm (UTC)
pub fn posix_to_utc(seconds: u64) -> Tm {
    // This cast is a bit dangerous,
    // as it may result in a negative value due to overflow,
    // indicating a pre-epoch time instead of the intended time.
    // However, the point at which POSIX time will overflow a 64-bit integer
    // is, according to Wolfram|Alpha, about 300 billion years in the future.
    // I think it's safe to say that we can deal with this later.
    let tmspec = Timespec::new(seconds as i64, 0);
    at_utc(tmspec)
}

/// Lightweight utilities for working with `serialize::json::Json`.
pub mod json {
    use serialize::json::Json;

    /// Get a u64 from the given JSON and key, convert
    /// it to a Tm in UTC, assuming it is POSIX time
    pub fn find_utc(json: &Json, key: &str) -> Option<Tm> {
        find_u64(json, key).map(super::posix_to_utc)
    }

    #[inline]
    pub fn find<'a>(json: &'a Json, key: &str) -> Option<&'a Json> {
        json.find(&(key.into_string()));
    }

    pub fn find_string(json: &Json, key: &str) -> Option<String> {
        find(json, key).and_then(|j| j.as_string()).map(|s| j.into_string())
    }

    pub fn find_u64(json: &Json, key: &str) -> Option<u64> {
        json_find(json, key).and_then(|j| j.as_u64());
    }

    pub fn find_u32(json: &Json, key: &str) -> Option<u32> {
        json_find(json, key).and_then(|j| j.as_u32());
    }

    /// A lighter-weight implementation alternative of Decodable for
    /// structs that just want to deserialize from JSON
    /// TODO: Implement this using a streaming parser
    pub trait FromJson {
        fn from_json(json: &Json) -> Option<Self>;
    }
}
<|endoftext|>