<commit_before>#![deny(missing_docs)]

//! A SDL2 window back-end for the Piston game engine.

extern crate sdl2;
extern crate piston;
extern crate shader_version;
extern crate gl;
extern crate num;

// External crates.
use std::mem::transmute;
use piston::window::{
    OpenGLWindow,
    ProcAddress,
    Window,
    AdvancedWindow,
    WindowSettings,
    Size,
};
use piston::input::{ keyboard, Button, MouseButton, Input, Motion };

pub use shader_version::OpenGL;

/// 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,
    should_close: bool,
    mouse_relative: Option<(f64, f64)>,
    exit_on_esc: bool,
}

impl Sdl2Window {
    /// Creates a new game window for SDL2.
    pub fn new(opengl: OpenGL, settings: WindowSettings) -> Sdl2Window {
        let sdl_context = sdl2::init(sdl2::INIT_EVERYTHING).unwrap();

        // Not all drivers default to 32bit color, so explicitly set it to 32bit color.
        sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLRedSize, 8);
        sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLGreenSize, 8);
        sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLBlueSize, 8);
        sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLAlphaSize, 8);

        let (major, minor) = opengl.get_major_minor();
        sdl2::video::gl_set_attribute(
            sdl2::video::GLAttr::GLContextMajorVersion,
            major as i32
        );
        sdl2::video::gl_set_attribute(
            sdl2::video::GLAttr::GLContextMinorVersion,
            minor as i32
        );
        sdl2::video::gl_set_attribute(
            sdl2::video::GLAttr::GLContextProfileMask,
            sdl2::video::GLProfile::GLCoreProfile as i32
        );
        if settings.get_samples() != 0 {
            sdl2::video::gl_set_attribute(
                sdl2::video::GLAttr::GLMultiSampleBuffers,
                1
            );
            sdl2::video::gl_set_attribute(
                sdl2::video::GLAttr::GLMultiSampleSamples,
                settings.get_samples() as i32
            );
        }

        let window = sdl2::video::Window::new(
            &settings.get_title(),
            sdl2::video::WindowPos::PosCentered,
            sdl2::video::WindowPos::PosCentered,
            settings.get_size().width as i32,
            settings.get_size().height as i32,
            sdl2::video::OPENGL| sdl2::video::RESIZABLE
        );
        let window = match window {
            Ok(w) => w,
            Err(_) =>
                if settings.get_samples() != 0 {
                    // Retry without requiring anti-aliasing.
                    sdl2::video::gl_set_attribute(
                        sdl2::video::GLAttr::GLMultiSampleBuffers,
                        0
                            );
                    sdl2::video::gl_set_attribute(
                        sdl2::video::GLAttr::GLMultiSampleSamples,
                        0
                            );
                    sdl2::video::Window::new(
                        &settings.get_title(),
                        sdl2::video::WindowPos::PosCentered,
                        sdl2::video::WindowPos::PosCentered,
                        settings.get_size().width as i32,
                        settings.get_size().height as i32,
                        sdl2::video::OPENGL| sdl2::video::RESIZABLE
                            ).unwrap()
                } else {
                    window.unwrap() // Panic.
                }
        };
        if settings.get_fullscreen() {
            window.set_fullscreen(sdl2::video::FullscreenType::FTTrue);
        }

        // Send text input events.
        sdl2::keyboard::start_text_input();

        let context = window.gl_create_context().unwrap();

        // Load the OpenGL function pointers.
        gl::load_with(|s| unsafe {
            transmute(sdl2::video::gl_get_proc_address(s))
        });

        Sdl2Window {
            exit_on_esc: settings.get_exit_on_esc(),
            should_close: false,
            window: window,
            context: context,
            sdl_context: sdl_context,
            mouse_relative: None,
        }
    }

    fn poll_event(&mut self) -> Option<Input> {
        // First check for a pending relative mouse move event.
        match self.mouse_relative {
            Some((x, y)) => {
                self.mouse_relative = None;
                return Some(Input::Move(Motion::MouseRelative(x, y)));
            }
            None => {}
        }

        // 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().poll_event() {
            Some( ev ) => ev,
            None => return None
        };
        match event {
            sdl2::event::Event::Quit{..} => {
                self.should_close = true;
            }
            sdl2::event::Event::TextInput { text, .. } => {
                return Some(Input::Text(text));
            }
            sdl2::event::Event::KeyDown { keycode: 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::keycode::KeyCode::Escape {
                    self.should_close = true;
                } else {
                    return Some(Input::Press(Button::Keyboard(sdl2_map_key(key))));
                }
            }
            sdl2::event::Event::KeyUp { keycode: key, repeat, .. } => {
                if repeat {
                    return self.poll_event()
                }
                return Some(Input::Release(Button::Keyboard(sdl2_map_key(key))));
            }
            sdl2::event::Event::MouseButtonDown { mouse_btn: button, .. } => {
                return Some(Input::Press(Button::Mouse(sdl2_map_mouse(button))));
            }
            sdl2::event::Event::MouseButtonUp { mouse_btn: button, .. } => {
                return Some(Input::Release(Button::Mouse(sdl2_map_mouse(button))));
            }
            sdl2::event::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)));
            },
            sdl2::event::Event::MouseWheel { x, y, .. } => {
                return Some(Input::Move(Motion::MouseScroll(x as f64, y as f64)));
            }
            sdl2::event::Event::Window {
                win_event_id: sdl2::event::WindowEventId::Resized, data1: w, data2: h, .. } => {
                return Some(Input::Resize(w as u32, h as u32));
            }
            sdl2::event::Event::Window { win_event_id: sdl2::event::WindowEventId::FocusGained, .. } => {
                return Some(Input::Focus(true));
            }
            sdl2::event::Event::Window { win_event_id: sdl2::event::WindowEventId::FocusLost, .. } => {
                return Some(Input::Focus(false));
            }
            _ => {}
        }
        None
    }
}

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 swap_buffers(&mut self) { self.window.gl_swap_window(); }
    fn size(&self) -> Size {
        let (w, h) = self.window.get_size();
        Size { width: w as u32, height: h as u32 }
    }
    fn poll_event(&mut self) -> Option<Input> { self.poll_event() }
    fn draw_size(&self) -> Size {
        let (w, h) = self.window.get_size();
        Size { width: w as u32, height: h as u32 }
    }
}

impl AdvancedWindow for Sdl2Window {
    fn get_title(&self) -> String { self.window.get_title() }
    fn set_title(&mut self, value: String) { let _ = self.window.set_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) {
        sdl2::mouse::set_relative_mouse_mode(value);
    }
}

impl OpenGLWindow for Sdl2Window {
    fn get_proc_address(&mut self, proc_name: &str) -> ProcAddress {
        unsafe {
            transmute(sdl2::video::gl_get_proc_address(proc_name))
        }
    }

    fn is_current(&self) -> bool {
        unsafe {
            let this_context = self.context.raw();
            let current_context = sdl2::video::gl_get_current_context().unwrap().raw();

            this_context == current_context
        }
    }

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

/// Maps a SDL2 key to piston-input key.
pub fn sdl2_map_key(keycode: sdl2::keycode::KeyCode) -> keyboard::Key {
    use num::FromPrimitive;
    FromPrimitive::from_u64(keycode as u64).unwrap()
}

/// 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>Enable OpenGL Core Profile only if version >= 3.2<commit_after>#![deny(missing_docs)]

//! A SDL2 window back-end for the Piston game engine.

extern crate sdl2;
extern crate piston;
extern crate shader_version;
extern crate gl;
extern crate num;

// External crates.
use std::mem::transmute;
use piston::window::{
    OpenGLWindow,
    ProcAddress,
    Window,
    AdvancedWindow,
    WindowSettings,
    Size,
};
use piston::input::{ keyboard, Button, MouseButton, Input, Motion };

pub use shader_version::OpenGL;

/// 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,
    should_close: bool,
    mouse_relative: Option<(f64, f64)>,
    exit_on_esc: bool,
}

impl Sdl2Window {
    /// Creates a new game window for SDL2.
    pub fn new(opengl: OpenGL, settings: WindowSettings) -> Sdl2Window {
        let sdl_context = sdl2::init(sdl2::INIT_EVERYTHING).unwrap();

        // Not all drivers default to 32bit color, so explicitly set it to 32bit color.
        sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLRedSize, 8);
        sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLGreenSize, 8);
        sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLBlueSize, 8);
        sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLAlphaSize, 8);

        let (major, minor) = opengl.get_major_minor();
        sdl2::video::gl_set_attribute(
            sdl2::video::GLAttr::GLContextMajorVersion,
            major as i32
        );
        sdl2::video::gl_set_attribute(
            sdl2::video::GLAttr::GLContextMinorVersion,
            minor as i32
        );
        if opengl >= OpenGL::_3_2 {
            sdl2::video::gl_set_attribute(
                sdl2::video::GLAttr::GLContextProfileMask,
                sdl2::video::GLProfile::GLCoreProfile as i32
            );
        }
        if settings.get_samples() != 0 {
            sdl2::video::gl_set_attribute(
                sdl2::video::GLAttr::GLMultiSampleBuffers,
                1
            );
            sdl2::video::gl_set_attribute(
                sdl2::video::GLAttr::GLMultiSampleSamples,
                settings.get_samples() as i32
            );
        }

        let window = sdl2::video::Window::new(
            &settings.get_title(),
            sdl2::video::WindowPos::PosCentered,
            sdl2::video::WindowPos::PosCentered,
            settings.get_size().width as i32,
            settings.get_size().height as i32,
            sdl2::video::OPENGL| sdl2::video::RESIZABLE
        );
        let window = match window {
            Ok(w) => w,
            Err(_) =>
                if settings.get_samples() != 0 {
                    // Retry without requiring anti-aliasing.
                    sdl2::video::gl_set_attribute(
                        sdl2::video::GLAttr::GLMultiSampleBuffers,
                        0
                            );
                    sdl2::video::gl_set_attribute(
                        sdl2::video::GLAttr::GLMultiSampleSamples,
                        0
                            );
                    sdl2::video::Window::new(
                        &settings.get_title(),
                        sdl2::video::WindowPos::PosCentered,
                        sdl2::video::WindowPos::PosCentered,
                        settings.get_size().width as i32,
                        settings.get_size().height as i32,
                        sdl2::video::OPENGL| sdl2::video::RESIZABLE
                            ).unwrap()
                } else {
                    window.unwrap() // Panic.
                }
        };
        if settings.get_fullscreen() {
            window.set_fullscreen(sdl2::video::FullscreenType::FTTrue);
        }

        // Send text input events.
        sdl2::keyboard::start_text_input();

        let context = window.gl_create_context().unwrap();

        // Load the OpenGL function pointers.
        gl::load_with(|s| unsafe {
            transmute(sdl2::video::gl_get_proc_address(s))
        });

        Sdl2Window {
            exit_on_esc: settings.get_exit_on_esc(),
            should_close: false,
            window: window,
            context: context,
            sdl_context: sdl_context,
            mouse_relative: None,
        }
    }

    fn poll_event(&mut self) -> Option<Input> {
        // First check for a pending relative mouse move event.
        match self.mouse_relative {
            Some((x, y)) => {
                self.mouse_relative = None;
                return Some(Input::Move(Motion::MouseRelative(x, y)));
            }
            None => {}
        }

        // 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().poll_event() {
            Some( ev ) => ev,
            None => return None
        };
        match event {
            sdl2::event::Event::Quit{..} => {
                self.should_close = true;
            }
            sdl2::event::Event::TextInput { text, .. } => {
                return Some(Input::Text(text));
            }
            sdl2::event::Event::KeyDown { keycode: 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::keycode::KeyCode::Escape {
                    self.should_close = true;
                } else {
                    return Some(Input::Press(Button::Keyboard(sdl2_map_key(key))));
                }
            }
            sdl2::event::Event::KeyUp { keycode: key, repeat, .. } => {
                if repeat {
                    return self.poll_event()
                }
                return Some(Input::Release(Button::Keyboard(sdl2_map_key(key))));
            }
            sdl2::event::Event::MouseButtonDown { mouse_btn: button, .. } => {
                return Some(Input::Press(Button::Mouse(sdl2_map_mouse(button))));
            }
            sdl2::event::Event::MouseButtonUp { mouse_btn: button, .. } => {
                return Some(Input::Release(Button::Mouse(sdl2_map_mouse(button))));
            }
            sdl2::event::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)));
            },
            sdl2::event::Event::MouseWheel { x, y, .. } => {
                return Some(Input::Move(Motion::MouseScroll(x as f64, y as f64)));
            }
            sdl2::event::Event::Window {
                win_event_id: sdl2::event::WindowEventId::Resized, data1: w, data2: h, .. } => {
                return Some(Input::Resize(w as u32, h as u32));
            }
            sdl2::event::Event::Window { win_event_id: sdl2::event::WindowEventId::FocusGained, .. } => {
                return Some(Input::Focus(true));
            }
            sdl2::event::Event::Window { win_event_id: sdl2::event::WindowEventId::FocusLost, .. } => {
                return Some(Input::Focus(false));
            }
            _ => {}
        }
        None
    }
}

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 swap_buffers(&mut self) { self.window.gl_swap_window(); }
    fn size(&self) -> Size {
        let (w, h) = self.window.get_size();
        Size { width: w as u32, height: h as u32 }
    }
    fn poll_event(&mut self) -> Option<Input> { self.poll_event() }
    fn draw_size(&self) -> Size {
        let (w, h) = self.window.get_size();
        Size { width: w as u32, height: h as u32 }
    }
}

impl AdvancedWindow for Sdl2Window {
    fn get_title(&self) -> String { self.window.get_title() }
    fn set_title(&mut self, value: String) { let _ = self.window.set_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) {
        sdl2::mouse::set_relative_mouse_mode(value);
    }
}

impl OpenGLWindow for Sdl2Window {
    fn get_proc_address(&mut self, proc_name: &str) -> ProcAddress {
        unsafe {
            transmute(sdl2::video::gl_get_proc_address(proc_name))
        }
    }

    fn is_current(&self) -> bool {
        unsafe {
            let this_context = self.context.raw();
            let current_context = sdl2::video::gl_get_current_context().unwrap().raw();

            this_context == current_context
        }
    }

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

/// Maps a SDL2 key to piston-input key.
pub fn sdl2_map_key(keycode: sdl2::keycode::KeyCode) -> keyboard::Key {
    use num::FromPrimitive;
    FromPrimitive::from_u64(keycode as u64).unwrap()
}

/// 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>//! An implementation of Google Protobuf's Variable-Length Integers

use std::collections::VecDeque;

/// The maximum number of bytes used by a 32-bit Varint
pub const VARINT_32_MAX_BYTES: usize = 5;

/// The maximum number of bytes used by a 32-bit Varint
pub const VARINT_64_MAX_BYTES: usize = 10;

/// Checks to see if the most signifigant bit exists in the specified byte
pub fn most_signifigant_bit_exists(input: u8) -> bool {
    input & 0b10000000 != 0
}

/// A struct defining a variable-length integer
#[derive(Clone, Debug)]
pub struct Varint {

    /// The internal data representation
    pub data: VecDeque<u8>

}

impl Varint {

    /// Gets the number of bytes currently contained by this Varint
    pub fn number_of_bytes(&self) -> usize {
        self.data.len()
    }

}

/// Transforms a signed int to an unsigned int via zig-zag transformation
pub fn zigzag_signed_int(input: i32) -> u32 {
    ((input << 1) ^ (input >> 31)) as u32
}

/// Transforms a signed long to an unsigned long via zig-zag transformation
pub fn zigzag_signed_long(input: i64) -> u64 {
    ((input << 1) ^ (input >> 63)) as u64
}

/// Transforms an unsigned int to a signed int via zig-zag transformation
pub fn zigzag_unsigned_int(input: u32) -> i32 {
    ((input >> 1) as i32) ^ (-((input & 1) as i32))
}

/// Transforms an unsignigned long to a signed long via zig-zag transformation
pub fn zigzag_unsigned_long(input: u64) -> i64 {
    ((input >> 1) as i64) ^ (-((input & 1) as i64))
}

/// Encodes a signed i32 as a Varint
pub fn encode_signed_varint32(input: i32) -> Varint {
    encode_unsigned_varint32(zigzag_signed_int(input))
}

/// Encodes a signed i64 as a Varint
pub fn encode_signed_varint64(input: i64) -> Varint {
    encode_unsigned_varint64(zigzag_signed_long(input))
}

/// Encodes an unsigned u32 as a Varint.
pub fn encode_unsigned_varint32(input: u32) -> Varint {

    let mut returnable: Varint = Varint { data: VecDeque::<u8>::new() };

    let mut value: u32 = input;

    if value == 0 {
        returnable.data.push_back(0);
        return returnable;
    } else {

        while value >= 1 {
            let mut next_byte: u8 = (value & 0b01111111) as u8;

            value >>= 7;

            if value >= 1 {
                next_byte |= 0b10000000;
            }

            returnable.data.push_back(next_byte);
        }

        return returnable;
    }

}

/// Encodes an unsigned u64 as a Varint.
pub fn encode_unsigned_varint64(input: u64) -> Varint {

    let mut returnable: Varint = Varint { data: VecDeque::<u8>::new() };

    let mut value: u64 = input;

    if value == 0 {
        returnable.data.push_back(0);
        return returnable;
    } else {

        while value >= 1 {
            let mut next_byte: u8 = (value & 0b01111111) as u8;

            value >>= 7;

            if value >= 1 {
                next_byte |= 0b10000000;
            }

            returnable.data.push_back(next_byte);
        }

        return returnable;
    }

}

/// Decodes an unsigned varint32, returning a result of either a u32 or a string explaining the error
pub fn decode_unsigned_varint32(input: &mut Varint) -> Result<u32, &'static str> {
    if input.number_of_bytes() == 0 {
        return Err("Varint somehow has zero bytes! Are you decoding something you wrote?");
    } else if input.number_of_bytes() > VARINT_32_MAX_BYTES {
        return Err("Varint is larger than VARINT_32_MAX_BYTES");
    } else if input.number_of_bytes() == 1 {
        let returnable = input.data.pop_front();

        if returnable.is_none() {
            return Err("Only byte contained in a VecDeque is a byte but is also None. You might want to run memtest");
        } else {
            return Ok(returnable.unwrap() as u32);
        }
    } else {
        let mut shift_amount: u32 = 0;
        let mut decoded_value: u32 = 0;
        while input.number_of_bytes() >= 1 {
            let byte_result = input.data.pop_front();

            if byte_result.is_none() {
                return Err("Byte contained in a VecDeque is a byte that is also None. Run memtest, please");
            } else {
                let byte_value = byte_result.unwrap();

                decoded_value |= ((byte_value & 0b01111111) as u32) << shift_amount; //<< 0 for first byte

                if (decoded_value & 0b10000000) == 0 {
                    return Ok(decoded_value);
                } else {
                    shift_amount += 7;
                }
            }
        }

        Err("No bytes were marked as the end byte. Check your numbers or run a memtest")
    }
}

/// Decodes an unsigned varint64, returning a result of either a u64 or a string explaining the error
pub fn decode_unsigned_varint64(input: &mut Varint) -> Result<u64, &'static str> {
    if input.number_of_bytes() == 0 {
        return Err("Varint somehow has zero bytes! Are you decoding something you wrote?");
    } else if input.number_of_bytes() > VARINT_64_MAX_BYTES {
        return Err("Varint is larger than VARINT_64_MAX_BYTES");
    } else if input.number_of_bytes() == 1 {
        let returnable = input.data.pop_front();

        if returnable.is_none() {
            return Err("Only byte contained in a VecDeque is a byte but is also None. You might want to run memtest");
        } else {
            return Ok(returnable.unwrap() as u64);
        }
    } else {
        let mut shift_amount: u64 = 0;
        let mut decoded_value: u64 = 0;
        while input.number_of_bytes() >= 1 {
            let byte_result = input.data.pop_front();

            if byte_result.is_none() {
                return Err("Byte contained in a VecDeque is a byte that is also None. Run memtest, please");
            } else {
                let byte_value = byte_result.unwrap();

                decoded_value |= ((byte_value & 0b01111111) as u64) << shift_amount; //<< 0 for first byte

                if (decoded_value & 0b10000000) == 0 {
                    return Ok(decoded_value);
                } else {
                    shift_amount += 7;
                }
            }
        }

        Err("No bytes were marked as the end byte. Check your numbers or run a memtest")
    }
}

#[cfg(test)]
mod test {

    use super::*;

    use std::collections::VecDeque;

    #[test]
    fn test_zigzag_unsigned_value() {
        let mut unsigned: u32 = 0;

        assert_eq!(unsigned, zigzag_unsigned_int(unsigned) as u32);

        unsigned = 1;

        assert_eq!(-1, zigzag_unsigned_int(unsigned));

        unsigned = 2;

        assert_eq!(1, zigzag_unsigned_int(unsigned));

        let unsigned: u64 = 18446744073709551612;

        assert_eq!(9223372036854775806, zigzag_unsigned_long(unsigned));
    }

    #[test]
    fn test_zigzag_signed_value() {
        let mut signed: i32 = 0;

        assert_eq!(signed, zigzag_signed_int(signed) as i32);

        signed = -1;

        assert_eq!(1, zigzag_signed_int(signed));

        signed = 1;

        assert_eq!(2, zigzag_signed_int(signed));

        signed = -2;

        assert_eq!(3, zigzag_signed_int(signed));

        let mut signed: i64 = 9223372036854775806;

        assert_eq!(18446744073709551612, zigzag_signed_long(signed));

        signed = -9223372036854775808;

        assert_eq!(18446744073709551615, zigzag_signed_long(signed));
    }

    #[test]
    fn test_new_varint_has_no_bytes() {

        let abc: Varint = Varint { data: VecDeque::<u8>::new() };

        assert_eq!(0, abc.number_of_bytes());

    }

    #[test]
    fn test_most_signifigant_bit() {
        let mut value: u8 = 1;

        assert!(most_signifigant_bit_exists(value) == false);

        value = 120;

        assert!(most_signifigant_bit_exists(value) == false);

        value = 128;

        assert!(most_signifigant_bit_exists(value) == true);

        value = 129;

        assert!(most_signifigant_bit_exists(value) == true);
    }

}<commit_msg>Fix encoding and decoding, it *APPEARS* to be working according to the tests.<commit_after>//! An implementation of Google Protobuf's Variable-Length Integers

use std::collections::VecDeque;

/// The maximum number of bytes used by a 32-bit Varint
pub const VARINT_32_MAX_BYTES: usize = 5;

/// The maximum number of bytes used by a 32-bit Varint
pub const VARINT_64_MAX_BYTES: usize = 10;

/// Checks to see if the most signifigant bit exists in the specified byte
pub fn most_signifigant_bit_exists(input: u8) -> bool {
    input & 0b10000000 != 0
}

/// A struct defining a variable-length integer
#[derive(Clone, Debug)]
pub struct Varint {

    /// The internal data representation
    pub data: VecDeque<u8>

}

impl Varint {

    /// Gets the number of bytes currently contained by this Varint
    pub fn number_of_bytes(&self) -> usize {
        self.data.len()
    }

}

/// Transforms a signed int to an unsigned int via zig-zag transformation
pub fn zigzag_signed_int(input: i32) -> u32 {
    ((input << 1) ^ (input >> 31)) as u32
}

/// Transforms a signed long to an unsigned long via zig-zag transformation
pub fn zigzag_signed_long(input: i64) -> u64 {
    ((input << 1) ^ (input >> 63)) as u64
}

/// Transforms an unsigned int to a signed int via zig-zag transformation
pub fn zigzag_unsigned_int(input: u32) -> i32 {
    ((input >> 1) as i32) ^ (-((input & 1) as i32))
}

/// Transforms an unsignigned long to a signed long via zig-zag transformation
pub fn zigzag_unsigned_long(input: u64) -> i64 {
    ((input >> 1) as i64) ^ (-((input & 1) as i64))
}

/// Encodes a signed i32 as a Varint
pub fn encode_signed_varint32(input: i32) -> Varint {
    encode_unsigned_varint32(zigzag_signed_int(input))
}

/// Encodes a signed i64 as a Varint
pub fn encode_signed_varint64(input: i64) -> Varint {
    encode_unsigned_varint64(zigzag_signed_long(input))
}

/// Encodes an unsigned u32 as a Varint, returning the Varint.
pub fn encode_unsigned_varint32(input: u32) -> Varint {

    let mut returnable: Varint = Varint { data: VecDeque::<u8>::new() };

    let mut value: u32 = input;

    if value == 0 {
        returnable.data.push_back(0);
        return returnable;
    } else {

        while value >= 0b10000000 {
            let next_byte: u8 = ((value & 0b01111111) as u8) | 0b10000000;

            value = value >> 7;

            returnable.data.push_back(next_byte);
        }

        returnable.data.push_back((value & 0b01111111) as u8);

        return returnable;
    }

}

/// Encodes an unsigned u64 as a Varint, returning the Varint
pub fn encode_unsigned_varint64(input: u64) -> Varint {

    let mut returnable: Varint = Varint { data: VecDeque::<u8>::new() };

    let mut value: u64 = input;

    if value == 0 {
        returnable.data.push_back(0);
        return returnable;
    } else {

        while value >= 0b10000000 {
            let next_byte: u8 = ((value & 0b01111111) as u8) | 0b10000000;

            value = value >> 7;

            returnable.data.push_back(next_byte);
        }

        returnable.data.push_back((value & 0b01111111) as u8);

        return returnable;
    }

}

/// Decodes an unsigned varint32, returning a result of either a u32 or a string explaining the error
pub fn decode_unsigned_varint32(original_input: &Varint) -> Result<u32, &'static str> {

    let mut input = original_input.clone();

    if input.number_of_bytes() == 0 {
        return Err("Varint somehow has zero bytes! Are you decoding something you wrote?");
    } else if input.number_of_bytes() > VARINT_32_MAX_BYTES {
        return Err("Varint is larger than VARINT_32_MAX_BYTES");
    } else if input.number_of_bytes() == 1 {
        let returnable = input.data.pop_front();

        if returnable.is_none() {
            return Err("Only byte contained in a VecDeque is a byte but is also None. You might want to run memtest");
        } else {
            return Ok(returnable.unwrap() as u32);
        }
    } else {
        let mut shift_amount: u32 = 0;
        let mut decoded_value: u32 = 0;
        while input.number_of_bytes() >= 1 {
            let byte_result = input.data.pop_front();

            if byte_result.is_none() {
                return Err("Byte contained in a VecDeque is a byte that is also None. Run memtest, please");
            } else {
                let byte_value = byte_result.unwrap();

                decoded_value |= ((byte_value & 0b01111111) as u32) << shift_amount; //<< 0 for first byte

                if (byte_value & 0b10000000) == 0 {
                    return Ok(decoded_value);
                } else {
                    shift_amount += 7;
                }
            }
        }

        Err("No bytes were marked as the end byte. Check your numbers or run a memtest")
    }
}

/// Decodes an unsigned varint64, returning a result of either a u64 or a string explaining the error
pub fn decode_unsigned_varint64(original_input: &Varint) -> Result<u64, &'static str> {

    let mut input = original_input.clone();

    if input.number_of_bytes() == 0 {
        return Err("Varint somehow has zero bytes! Are you decoding something you wrote?");
    } else if input.number_of_bytes() > VARINT_64_MAX_BYTES {
        return Err("Varint is larger than VARINT_64_MAX_BYTES");
    } else if input.number_of_bytes() == 1 {
        let returnable = input.data.pop_front();

        if returnable.is_none() {
            return Err("Only byte contained in a VecDeque is a byte but is also None. You might want to run memtest");
        } else {
            return Ok(returnable.unwrap() as u64);
        }
    } else {
        let mut shift_amount: u64 = 0;
        let mut decoded_value: u64 = 0;
        while input.number_of_bytes() >= 1 {
            let byte_result = input.data.pop_front();

            if byte_result.is_none() {
                return Err("Byte contained in a VecDeque is a byte that is also None. Run memtest, please");
            } else {
                let byte_value = byte_result.unwrap();

                decoded_value |= ((byte_value & 0b01111111) as u64) << shift_amount; //<< 0 for first byte

                if (byte_value & 0b10000000) == 0 {
                    return Ok(decoded_value);
                } else {
                    shift_amount += 7;
                }
            }
        }

        Err("No bytes were marked as the end byte. Check your numbers or run a memtest")
    }
}

#[cfg(test)]
mod test {

    use super::*;

    use std::collections::VecDeque;

    #[test]
    fn test_endecoding_zero() {
        let value = 0;

        assert_eq!(value, value); //Congratulations. You've sucessfully switched to a parallel universe where 0 is actually 1

        let encoded: Varint = encode_unsigned_varint32(value);

        assert_eq!(1, encoded.number_of_bytes());

        let result = decode_unsigned_varint32(&encoded);

        if result.is_ok() {
            let result = result.unwrap();

            assert_eq!(value, result);
        } else {
            assert_eq!(0, 1); //You're still in that alternate universe, bro
        }
    }

    #[test]
    fn test_endecoding_one() {
        let value = 1;

        assert_eq!(value, value); //Congratulations. You've sucessfully switched to a parallel universe where 0 is actually 1

        let encoded: Varint = encode_unsigned_varint32(value);

        assert_eq!(1, encoded.number_of_bytes());

        let result = decode_unsigned_varint32(&encoded);

        if result.is_ok() {
            let result = result.unwrap();

            assert_eq!(value, result);
        } else {
            assert_eq!(0, 1); //You're still in that alternate universe, bro
        }
    }

    #[test]
    fn test_endecoding_trillion() {
        let value = 1_000_000_000_000;

        assert_eq!(value, value); //Congratulations. You've sucessfully switched to a parallel universe where 0 is actually 1

        let encoded: Varint = encode_unsigned_varint64(value);

        assert_eq!(6, encoded.number_of_bytes());

        let result = decode_unsigned_varint64(&encoded);

        if result.is_ok() {
            let result = result.unwrap();

            assert_eq!(value, result);
        } else {
            assert_eq!(0, 1); //You're still in that alternate universe, bro
        }
    }

    #[test]
    fn test_endecoding_minus_one() {
        let value = -1;

        assert_eq!(value, value); //Congratulations. You've sucessfully switched to a parallel universe where 0 is actually 1

        let encoded: Varint = encode_signed_varint32(value);

        assert_eq!(1, encoded.number_of_bytes());

        let result = decode_unsigned_varint32(&encoded);

        if result.is_ok() {
            let result = result.unwrap();

            assert_eq!(value, zigzag_unsigned_int(result));
        } else {
            assert_eq!(0, 1); //You're still in that alternate universe, bro
        }
    }

    #[test]
    fn test_endecoding_minus_one_fifty() {
        let value = -150;

        assert_eq!(value, value); //Congratulations. You've sucessfully switched to a parallel universe where 0 is actually 1

        let encoded: Varint = encode_signed_varint32(value);

        assert_eq!(2, encoded.number_of_bytes());

        let result = decode_unsigned_varint32(&encoded);

        if result.is_ok() {
            let result = result.unwrap();

            assert_eq!(value, zigzag_unsigned_int(result));
        } else {
            assert_eq!(0, 1); //You're still in that alternate universe, bro
        }
    }

    #[test]
    fn test_endecoding_minus_three_hundred() {
        let value = -300;

        assert_eq!(value, value); //Congratulations. You've sucessfully switched to a parallel universe where 0 is actually 1

        let encoded: Varint = encode_signed_varint32(value);

        assert_eq!(2, encoded.number_of_bytes());

        let result = decode_unsigned_varint32(&encoded);

        if result.is_ok() {
            let result = result.unwrap();

            assert_eq!(value, zigzag_unsigned_int(result));
        } else {
            assert_eq!(0, 1); //You're still in that alternate universe, bro
        }
    }

    #[test]
    fn test_endecoding_minus_one_hundred_trillion() {
        let value = -100_000_000_000_000;

        assert_eq!(value, value); //Congratulations. You've sucessfully switched to a parallel universe where 0 is actually 1

        let encoded: Varint = encode_signed_varint64(value);

        assert_eq!(7, encoded.number_of_bytes());

        let result = decode_unsigned_varint64(&encoded);

        if result.is_ok() {
            let result = result.unwrap();

            assert_eq!(value, zigzag_unsigned_long(result));
        } else {
            assert_eq!(0, 1); //You're still in that alternate universe, bro
        }
    }

    #[test]
    fn test_zigzag_unsigned_value() {
        let mut unsigned: u32 = 0;

        assert_eq!(unsigned, zigzag_unsigned_int(unsigned) as u32);

        unsigned = 1;

        assert_eq!(-1, zigzag_unsigned_int(unsigned));

        unsigned = 2;

        assert_eq!(1, zigzag_unsigned_int(unsigned));

        let unsigned: u64 = 18446744073709551612;

        assert_eq!(9223372036854775806, zigzag_unsigned_long(unsigned));
    }

    #[test]
    fn test_zigzag_signed_value() {
        let mut signed: i32 = 0;

        assert_eq!(signed, zigzag_signed_int(signed) as i32);

        signed = -1;

        assert_eq!(1, zigzag_signed_int(signed));

        signed = 1;

        assert_eq!(2, zigzag_signed_int(signed));

        signed = -2;

        assert_eq!(3, zigzag_signed_int(signed));

        let mut signed: i64 = 9223372036854775806;

        assert_eq!(18446744073709551612, zigzag_signed_long(signed));

        signed = -9223372036854775808;

        assert_eq!(18446744073709551615, zigzag_signed_long(signed));
    }

    #[test]
    fn test_new_varint_has_no_bytes() {

        let abc: Varint = Varint { data: VecDeque::<u8>::new() };

        assert_eq!(0, abc.number_of_bytes());

    }

    #[test]
    fn test_most_signifigant_bit() {
        let mut value: u8 = 1;

        assert!(most_signifigant_bit_exists(value) == false);

        value = 120;

        assert!(most_signifigant_bit_exists(value) == false);

        value = 128;

        assert!(most_signifigant_bit_exists(value) == true);

        value = 129;

        assert!(most_signifigant_bit_exists(value) == true);
    }

}<|endoftext|>


<commit_before>#[macro_use] extern crate matches;
pub extern crate mime;

use std::io;

pub enum DataUrlError {
    NotADataUrl,
    NoComma,
}

pub struct DataUrl<'a> {
    mime_type: mime::Mime,
    base64: bool,
    encoded_body_plus_fragment: &'a str,
}

impl<'a> DataUrl<'a> {
    /// <https://fetch.spec.whatwg.org/#data-url-processor>
    /// but starting from a string rather than a Url, to avoid extra string copies.
    pub fn process(input: &'a str) -> Result<Self, DataUrlError> {
        use DataUrlError::*;

        let after_colon = pretend_parse_data_url(input).ok_or(NotADataUrl)?;
        let comma = after_colon.bytes().position(|byte| byte == b',').ok_or(NoComma)?;

        let (mime_type, base64) = parse_header(&after_colon[..comma]);
        let encoded_body_plus_fragment = &after_colon[comma + 1..];

        Ok(DataUrl { mime_type, base64, encoded_body_plus_fragment })
    }

    pub fn mime_type(&self) -> &mime::Mime {
        &self.mime_type
    }

    /// Streaming-decode the data URL’s body to `sink`.
    ///
    /// Errors while writing to the sink are propagated.
    /// Invalid base64 causes an error with `e.kind() == ErrorKind::InvalidData`.
    /// When decoding without error, the URL’s fragment identifier is returned if it has one.
    ///
    /// The fragment identifier is represented as in the origin input.
    /// It needs to be either percent-encoded to obtain the same string as in a parsed URL,
    /// or percent-decoded to interpret it as text.
    pub fn decode_body<W>(&self, sink: W) -> io::Result<Option<&'a str>>
        where W: io::Write
    {
        if self.base64 {
            decode_with_base64(self.encoded_body_plus_fragment, sink)
        } else {
            decode_without_base64(self.encoded_body_plus_fragment, sink)
        }
    }

    pub fn decode_body_to_vec(&self) -> Result<(Vec<u8>, Option<&str>), ()> {
        let mut sink = Vec::new();
        match self.decode_body(&mut sink) {
            Ok(url_fragment) => {
                Ok((sink, url_fragment))
            }
            Err(e) => {
                // Vec::write_all never returns an error
                debug_assert!(e.kind() == io::ErrorKind::InvalidData && self.base64);

                Err(())
            }
        }
    }
}

macro_rules! require {
    ($condition: expr) => {
        if !$condition {
            return None
        }
    }
}

/// Similar to <https://url.spec.whatwg.org/#concept-basic-url-parser>
/// followed by <https://url.spec.whatwg.org/#concept-url-serializer>
///
/// * `None`: not a data URL.
///
/// * `Some(s)`: sort of the result of serialization, except:
///
///   - `data:` prefix removed
///   - The fragment is included
///   - Other components are **not** UTF-8 percent-encoded
///   - ASCII tabs and newlines in the middle are **not** removed
fn pretend_parse_data_url(input: &str) -> Option<&str> {
    // Trim C0 control or space
    let left_trimmed = input.trim_left_matches(|ch| ch <= ' ');

    let mut bytes = left_trimmed.bytes();
    {
        // Ignore ASCII tabs or newlines
        let mut iter = bytes.by_ref().filter(|&byte| !matches!(byte, b'\t' | b'\n' | b'\r'));
        require!(iter.next()?.to_ascii_lowercase() == b'd');
        require!(iter.next()?.to_ascii_lowercase() == b'a');
        require!(iter.next()?.to_ascii_lowercase() == b't');
        require!(iter.next()?.to_ascii_lowercase() == b'a');
        require!(iter.next()? == b':');
    }
    let bytes_consumed = left_trimmed.len() - bytes.len();
    let after_colon = &left_trimmed[bytes_consumed..];

    // Trim C0 control or space
    Some(after_colon.trim_right_matches(|ch| ch <= ' '))
}

fn parse_header(from_colon_to_comma: &str) -> (mime::Mime, bool) {
    let input = from_colon_to_comma.chars()
        .filter(|&c| !matches!(c, '\t' | '\n' | '\r'))  // Removed by the URL parser
        .collect::<String>();

    let input = input.trim_matches(' ');

    let (input, base64) = match without_base64_suffix(input) {
        Some(s) => (s, true),
        None => (input, false),
    };

    // FIXME: does Mime::from_str match the MIME Sniffing Standard’s parsing algorithm?
    // <https://mimesniff.spec.whatwg.org/#parse-a-mime-type>
    let mime_type = input.parse()
        .unwrap_or_else(|_| "text/plain;charset=US-ASCII".parse().unwrap());

    (mime_type, base64)
}

/// None: no base64 suffix
fn without_base64_suffix(s: &str) -> Option<&str> {
    remove_suffix(
        remove_suffix(s, "base64", str::eq_ignore_ascii_case)?
            .trim_right_matches(' '),
        ";", str::eq
    )
}

fn remove_suffix<'a, Eq>(haystack: &'a str, needle: &str, eq: Eq) -> Option<&'a str>
    where Eq: Fn(&str, &str) -> bool
{
    let start_index = haystack.len().checked_sub(needle.len())?;
    let (before, after) = haystack.split_at(start_index);
    if eq(after, needle) {
        Some(before)
    } else {
        None
    }
}

/// This is <https://url.spec.whatwg.org/#string-percent-decode> while also:
///
/// * Ignoring ASCII tab or newlines
/// * Stopping at the first '#' (which indicates the start of the fragment)
///
/// Anything that would have been UTF-8 percent-encoded by the URL parser
/// would be percent-decoded here.
/// We skip that round-trip and pass it through unchanged.
fn decode_without_base64<W>(encoded_body_plus_fragment: &str, mut sink: W)
                            -> io::Result<Option<&str>>
    where W: io::Write
{
    let bytes = encoded_body_plus_fragment.as_bytes();
    let mut slice_start = 0;
    for (i, &byte) in bytes.iter().enumerate() {
        // We only need to look for 5 different "special" byte values.
        // For everything else we make slices as large as possible, borrowing the input,
        // in order to make fewer write_all() calls.
        if matches!(byte, b'%' | b'#' | b'\t' | b'\n' | b'\r') {
            // Write everything (if anything) "non-special" we’ve accumulated
            // before this special byte
            if i > slice_start {
                sink.write_all(&bytes[slice_start..i])?;
            }
            // Then deal with the special byte.
            match byte {
                b'%' => {
                    let l = bytes.get(i + 2).and_then(|&b| (b as char).to_digit(16));
                    let h = bytes.get(i + 1).and_then(|&b| (b as char).to_digit(16));
                    if let (Some(h), Some(l)) = (h, l) {
                        // '%' followed by two ASCII hex digits
                        let one_byte = h as u8 * 0x10 + l as u8;
                        sink.write_all(&[one_byte])?;
                        slice_start = i + 3;
                    } else {
                        // Do nothing. Leave slice_start unchanged.
                        // The % sign will be part of the next slice.
                    }
                }

                b'#' => {
                    let fragment_start = i + 1;
                    return Ok(Some(&encoded_body_plus_fragment[fragment_start..]))
                }

                // Ignore over '\t' | '\n' | '\r'
                _ => slice_start = i + 1
            }
        }
    }
    sink.write_all(&bytes[slice_start..])?;
    Ok(None)
}

/// `decode_without_base64()` composed with
/// <https://infra.spec.whatwg.org/#isomorphic-decode> composed with
/// <https://infra.spec.whatwg.org/#forgiving-base64-decode>.
fn decode_with_base64<W>(encoded_body_plus_fragment: &str, sink: W) -> io::Result<Option<&str>>
    where W: io::Write
{
    let mut decoder = Base64Decoder {
        sink,
        bit_buffer: 0,
        buffer_bit_length: 0,
        padding_symbols: 0,
    };
    let fragment = decode_without_base64(encoded_body_plus_fragment, &mut decoder)?;
    match (decoder.buffer_bit_length, decoder.padding_symbols) {
        (0, 0) => {
            // A multiple of four of alphabet symbols, and nothing else.
        }
        (12, 2) | (12, 0) => {
            // A multiple of four of alphabet symbols, followed by two more symbols,
            // optionally followed by two padding characters (which make a total multiple of four).
            let byte_buffer = [
                (decoder.bit_buffer >> 4) as u8,
            ];
            decoder.sink.write_all(&byte_buffer)?;
        }
        (18, 1) | (18, 0) => {
            // A multiple of four of alphabet symbols, followed by three more symbols,
            // optionally followed by one padding character (which make a total multiple of four).
            let byte_buffer = [
                (decoder.bit_buffer >> 10) as u8,
                (decoder.bit_buffer >> 2) as u8,
            ];
            decoder.sink.write_all(&byte_buffer)?;
        }
        _ => {
            // No other combination is acceptable
            Err(io::ErrorKind::InvalidData)?
        }
    }
    Ok(fragment)
}

struct Base64Decoder<W> {
    sink: W,
    bit_buffer: u32,
    buffer_bit_length: u8,
    padding_symbols: u8,
}

impl<W> io::Write for Base64Decoder<W> where W: io::Write {
    fn write(&mut self, _buf: &[u8]) -> io::Result<usize> { unimplemented!() }
    fn flush(&mut self) -> io::Result<()> { unimplemented!() }

    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        for &byte in buf.iter() {
            let value = BASE64_DECODE_TABLE[byte as usize];
            if value < 0 {
                // A character that’s not part of the alphabet

                // Remove ASCII whitespace
                // '\t' | '\n' | '\r' was already filtered by decode_without_base64()
                if byte == b' ' || byte == b'\x0C' {
                    continue
                }

                if byte == b'=' {
                    self.padding_symbols = self.padding_symbols.saturating_add(8);
                    continue
                }

                Err(io::ErrorKind::InvalidData)?
            }
            if self.padding_symbols > 0 {
                // Alphabet symbols after padding
                Err(io::ErrorKind::InvalidData)?
            }
            self.bit_buffer <<= 6;
            self.bit_buffer |= value as u32;
            if self.buffer_bit_length < 24 {
                self.buffer_bit_length += 6;
            } else {
                // We’ve accumulated four times 6 bits, which equals three times 8 bits.
                let byte_buffer = [
                    (self.bit_buffer >> 16) as u8,
                    (self.bit_buffer >> 8) as u8,
                    self.bit_buffer as u8,
                ];
                self.sink.write_all(&byte_buffer)?;
                self.buffer_bit_length = 0;
                // No need to reset self.bit_buffer,
                // since next time we’re only gonna read relevant bits.
            }
        }
        Ok(())
    }
}

/// Generated by `make_base64_decode_table.py` based on "Table 1: The Base 64 Alphabet"
/// at <https://tools.ietf.org/html/rfc4648#section-4>
///
/// Array indices are the byte value of symbols.
/// Array values are their positions in the base64 alphabet,
/// or -1 for symbols not in the alphabet.
/// The position contributes 6 bits to the decoded bytes.
const BASE64_DECODE_TABLE: [i8; 256] = [
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
    -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
];
<commit_msg>Implicit "text/plain" when MIME type starts with ";"<commit_after>#[macro_use] extern crate matches;
pub extern crate mime;

use std::io;

pub enum DataUrlError {
    NotADataUrl,
    NoComma,
}

pub struct DataUrl<'a> {
    mime_type: mime::Mime,
    base64: bool,
    encoded_body_plus_fragment: &'a str,
}

impl<'a> DataUrl<'a> {
    /// <https://fetch.spec.whatwg.org/#data-url-processor>
    /// but starting from a string rather than a Url, to avoid extra string copies.
    pub fn process(input: &'a str) -> Result<Self, DataUrlError> {
        use DataUrlError::*;

        let after_colon = pretend_parse_data_url(input).ok_or(NotADataUrl)?;
        let comma = after_colon.bytes().position(|byte| byte == b',').ok_or(NoComma)?;

        let (mime_type, base64) = parse_header(&after_colon[..comma]);
        let encoded_body_plus_fragment = &after_colon[comma + 1..];

        Ok(DataUrl { mime_type, base64, encoded_body_plus_fragment })
    }

    pub fn mime_type(&self) -> &mime::Mime {
        &self.mime_type
    }

    /// Streaming-decode the data URL’s body to `sink`.
    ///
    /// Errors while writing to the sink are propagated.
    /// Invalid base64 causes an error with `e.kind() == ErrorKind::InvalidData`.
    /// When decoding without error, the URL’s fragment identifier is returned if it has one.
    ///
    /// The fragment identifier is represented as in the origin input.
    /// It needs to be either percent-encoded to obtain the same string as in a parsed URL,
    /// or percent-decoded to interpret it as text.
    pub fn decode_body<W>(&self, sink: W) -> io::Result<Option<&'a str>>
        where W: io::Write
    {
        if self.base64 {
            decode_with_base64(self.encoded_body_plus_fragment, sink)
        } else {
            decode_without_base64(self.encoded_body_plus_fragment, sink)
        }
    }

    pub fn decode_body_to_vec(&self) -> Result<(Vec<u8>, Option<&str>), ()> {
        let mut sink = Vec::new();
        match self.decode_body(&mut sink) {
            Ok(url_fragment) => {
                Ok((sink, url_fragment))
            }
            Err(e) => {
                // Vec::write_all never returns an error
                debug_assert!(e.kind() == io::ErrorKind::InvalidData && self.base64);

                Err(())
            }
        }
    }
}

macro_rules! require {
    ($condition: expr) => {
        if !$condition {
            return None
        }
    }
}

/// Similar to <https://url.spec.whatwg.org/#concept-basic-url-parser>
/// followed by <https://url.spec.whatwg.org/#concept-url-serializer>
///
/// * `None`: not a data URL.
///
/// * `Some(s)`: sort of the result of serialization, except:
///
///   - `data:` prefix removed
///   - The fragment is included
///   - Other components are **not** UTF-8 percent-encoded
///   - ASCII tabs and newlines in the middle are **not** removed
fn pretend_parse_data_url(input: &str) -> Option<&str> {
    // Trim C0 control or space
    let left_trimmed = input.trim_left_matches(|ch| ch <= ' ');

    let mut bytes = left_trimmed.bytes();
    {
        // Ignore ASCII tabs or newlines
        let mut iter = bytes.by_ref().filter(|&byte| !matches!(byte, b'\t' | b'\n' | b'\r'));
        require!(iter.next()?.to_ascii_lowercase() == b'd');
        require!(iter.next()?.to_ascii_lowercase() == b'a');
        require!(iter.next()?.to_ascii_lowercase() == b't');
        require!(iter.next()?.to_ascii_lowercase() == b'a');
        require!(iter.next()? == b':');
    }
    let bytes_consumed = left_trimmed.len() - bytes.len();
    let after_colon = &left_trimmed[bytes_consumed..];

    // Trim C0 control or space
    Some(after_colon.trim_right_matches(|ch| ch <= ' '))
}

fn parse_header(from_colon_to_comma: &str) -> (mime::Mime, bool) {
    let input = from_colon_to_comma.chars()
        .filter(|&c| !matches!(c, '\t' | '\n' | '\r'))  // Removed by the URL parser
        .collect::<String>();
    let mut string;

    let input = input.trim_matches(' ');

    let (mut input, base64) = match without_base64_suffix(input) {
        Some(s) => (s, true),
        None => (input, false),
    };

    if input.starts_with(';') {
        string = String::from("text/plain");
        string.push_str(input);
        input = &*string;
    }

    // FIXME: does Mime::from_str match the MIME Sniffing Standard’s parsing algorithm?
    // <https://mimesniff.spec.whatwg.org/#parse-a-mime-type>
    let mime_type = input.parse()
        .unwrap_or_else(|_| "text/plain;charset=US-ASCII".parse().unwrap());

    (mime_type, base64)
}

/// None: no base64 suffix
fn without_base64_suffix(s: &str) -> Option<&str> {
    remove_suffix(
        remove_suffix(s, "base64", str::eq_ignore_ascii_case)?
            .trim_right_matches(' '),
        ";", str::eq
    )
}

fn remove_suffix<'a, Eq>(haystack: &'a str, needle: &str, eq: Eq) -> Option<&'a str>
    where Eq: Fn(&str, &str) -> bool
{
    let start_index = haystack.len().checked_sub(needle.len())?;
    let (before, after) = haystack.split_at(start_index);
    if eq(after, needle) {
        Some(before)
    } else {
        None
    }
}

/// This is <https://url.spec.whatwg.org/#string-percent-decode> while also:
///
/// * Ignoring ASCII tab or newlines
/// * Stopping at the first '#' (which indicates the start of the fragment)
///
/// Anything that would have been UTF-8 percent-encoded by the URL parser
/// would be percent-decoded here.
/// We skip that round-trip and pass it through unchanged.
fn decode_without_base64<W>(encoded_body_plus_fragment: &str, mut sink: W)
                            -> io::Result<Option<&str>>
    where W: io::Write
{
    let bytes = encoded_body_plus_fragment.as_bytes();
    let mut slice_start = 0;
    for (i, &byte) in bytes.iter().enumerate() {
        // We only need to look for 5 different "special" byte values.
        // For everything else we make slices as large as possible, borrowing the input,
        // in order to make fewer write_all() calls.
        if matches!(byte, b'%' | b'#' | b'\t' | b'\n' | b'\r') {
            // Write everything (if anything) "non-special" we’ve accumulated
            // before this special byte
            if i > slice_start {
                sink.write_all(&bytes[slice_start..i])?;
            }
            // Then deal with the special byte.
            match byte {
                b'%' => {
                    let l = bytes.get(i + 2).and_then(|&b| (b as char).to_digit(16));
                    let h = bytes.get(i + 1).and_then(|&b| (b as char).to_digit(16));
                    if let (Some(h), Some(l)) = (h, l) {
                        // '%' followed by two ASCII hex digits
                        let one_byte = h as u8 * 0x10 + l as u8;
                        sink.write_all(&[one_byte])?;
                        slice_start = i + 3;
                    } else {
                        // Do nothing. Leave slice_start unchanged.
                        // The % sign will be part of the next slice.
                    }
                }

                b'#' => {
                    let fragment_start = i + 1;
                    return Ok(Some(&encoded_body_plus_fragment[fragment_start..]))
                }

                // Ignore over '\t' | '\n' | '\r'
                _ => slice_start = i + 1
            }
        }
    }
    sink.write_all(&bytes[slice_start..])?;
    Ok(None)
}

/// `decode_without_base64()` composed with
/// <https://infra.spec.whatwg.org/#isomorphic-decode> composed with
/// <https://infra.spec.whatwg.org/#forgiving-base64-decode>.
fn decode_with_base64<W>(encoded_body_plus_fragment: &str, sink: W) -> io::Result<Option<&str>>
    where W: io::Write
{
    let mut decoder = Base64Decoder {
        sink,
        bit_buffer: 0,
        buffer_bit_length: 0,
        padding_symbols: 0,
    };
    let fragment = decode_without_base64(encoded_body_plus_fragment, &mut decoder)?;
    match (decoder.buffer_bit_length, decoder.padding_symbols) {
        (0, 0) => {
            // A multiple of four of alphabet symbols, and nothing else.
        }
        (12, 2) | (12, 0) => {
            // A multiple of four of alphabet symbols, followed by two more symbols,
            // optionally followed by two padding characters (which make a total multiple of four).
            let byte_buffer = [
                (decoder.bit_buffer >> 4) as u8,
            ];
            decoder.sink.write_all(&byte_buffer)?;
        }
        (18, 1) | (18, 0) => {
            // A multiple of four of alphabet symbols, followed by three more symbols,
            // optionally followed by one padding character (which make a total multiple of four).
            let byte_buffer = [
                (decoder.bit_buffer >> 10) as u8,
                (decoder.bit_buffer >> 2) as u8,
            ];
            decoder.sink.write_all(&byte_buffer)?;
        }
        _ => {
            // No other combination is acceptable
            Err(io::ErrorKind::InvalidData)?
        }
    }
    Ok(fragment)
}

struct Base64Decoder<W> {
    sink: W,
    bit_buffer: u32,
    buffer_bit_length: u8,
    padding_symbols: u8,
}

impl<W> io::Write for Base64Decoder<W> where W: io::Write {
    fn write(&mut self, _buf: &[u8]) -> io::Result<usize> { unimplemented!() }
    fn flush(&mut self) -> io::Result<()> { unimplemented!() }

    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        for &byte in buf.iter() {
            let value = BASE64_DECODE_TABLE[byte as usize];
            if value < 0 {
                // A character that’s not part of the alphabet

                // Remove ASCII whitespace
                // '\t' | '\n' | '\r' was already filtered by decode_without_base64()
                if byte == b' ' || byte == b'\x0C' {
                    continue
                }

                if byte == b'=' {
                    self.padding_symbols = self.padding_symbols.saturating_add(8);
                    continue
                }

                Err(io::ErrorKind::InvalidData)?
            }
            if self.padding_symbols > 0 {
                // Alphabet symbols after padding
                Err(io::ErrorKind::InvalidData)?
            }
            self.bit_buffer <<= 6;
            self.bit_buffer |= value as u32;
            if self.buffer_bit_length < 24 {
                self.buffer_bit_length += 6;
            } else {
                // We’ve accumulated four times 6 bits, which equals three times 8 bits.
                let byte_buffer = [
                    (self.bit_buffer >> 16) as u8,
                    (self.bit_buffer >> 8) as u8,
                    self.bit_buffer as u8,
                ];
                self.sink.write_all(&byte_buffer)?;
                self.buffer_bit_length = 0;
                // No need to reset self.bit_buffer,
                // since next time we’re only gonna read relevant bits.
            }
        }
        Ok(())
    }
}

/// Generated by `make_base64_decode_table.py` based on "Table 1: The Base 64 Alphabet"
/// at <https://tools.ietf.org/html/rfc4648#section-4>
///
/// Array indices are the byte value of symbols.
/// Array values are their positions in the base64 alphabet,
/// or -1 for symbols not in the alphabet.
/// The position contributes 6 bits to the decoded bytes.
const BASE64_DECODE_TABLE: [i8; 256] = [
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
    -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
];
<|endoftext|>


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

#![crate_name = "core_text"]
#![crate_type = "rlib"]

#![allow(non_snake_case_functions)]

extern crate libc;
extern crate std;

extern crate core_foundation;
extern crate core_graphics;

#[cfg(target_os="macos")]
pub mod font;
#[cfg(target_os="macos")]
pub mod font_collection;
#[cfg(target_os="macos")]
pub mod font_descriptor;
#[cfg(target_os="macos")]
pub mod font_manager;
<commit_msg>Rust upgrade<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![crate_name = "core_text"]
#![crate_type = "rlib"]

#![allow(non_snake_case_functions)]

extern crate libc;

extern crate core_foundation;
extern crate core_graphics;

#[cfg(target_os="macos")]
pub mod font;
#[cfg(target_os="macos")]
pub mod font_collection;
#[cfg(target_os="macos")]
pub mod font_descriptor;
#[cfg(target_os="macos")]
pub mod font_manager;
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate websocket;

use std::io::Write;
use std::io::Read;
use rustc_serialize::json::Json;
use rustc_serialize::json;
use websocket::Message;
use websocket::client::request::Url;
use websocket::dataframe::DataFrame;
use websocket::client::sender::Sender;
use websocket::client::receiver::Receiver;
use websocket::stream::WebSocketStream;
use websocket::result::WebSocketError;

pub use websocket::result::WebSocketResult;

mod requests;
mod responses;

use responses::*;
use requests::*;

type Client = websocket::Client<DataFrame, Sender<WebSocketStream>, Receiver<WebSocketStream>>;

fn handshake(url: &Url) -> WebSocketResult<Client> {
    // Handshake with the server
    let knock  = try!( Client::connect(url) );
    let answer = try!( knock.send() );
    try!( answer.validate() );

    // Get referennce to the client
    Ok(answer.begin())
}

fn negotiate(client: &mut Client, version: &str) -> WebSocketResult<NegotiateResp> {
    let request = requests::Connect::new(version);
    let request = Message::Text(request.to_json());

    try!( client.send_message(request) );

    for msg_result in client.incoming_messages::<Message>() {
        if let Ok(Message::Text(plaintext)) = msg_result {
            if let Ok(success) = json::decode::<VersionSuccess>(&plaintext) {
                if success.msg == "connected" {
                    return Ok(NegotiateResp::SessionId(success.session));
                }
            } else if let Ok(failure) = json::decode::<VersionFailed>(&plaintext) {
                if failure.msg == "failed" {
                    return Ok(NegotiateResp::Version(failure.version));
                }
            }
        }
    }
    Err(WebSocketError::ResponseError("No protocol version reply from the server.".to_string()))
}

pub enum NegotiateResp {
    SessionId(String),
    Version(String),
}

fn connect(url: &Url) -> WebSocketResult<(Client, String)> {
    let mut client = try!( handshake(url) );
    let mut curr_version = VER_NOW;

    loop {
        match negotiate(&mut client, curr_version) {
            Err(e) => return Err(e),
            Ok(NegotiateResp::SessionId(session)) => return Ok((client, session)),
            Ok(NegotiateResp::Version(version))   => {
                if let Some(v) = VERSIONS.iter().find(|&v| *v == version) {
                    curr_version = v;
                } else {
                    return Err(WebSocketError::ResponseError("No matching version.".to_string()));
                }
            },
        };
    }
}

#[test]
fn it_works() {

    let url = Url::parse("ws://127.0.0.1:3000/websocket").unwrap(); // Get the URL
    // assert_eq!("{:?}", format!("{:?}", request));

    connect(&url);

    let request = Client::connect(url).ok().expect("Could not connect"); // Connect to the server
    let response = request.send().ok().expect("Could not send response."); // Send the request

    response.validate().ok().expect("response is not valid!!"); // Ensure the response is valid

    let mut client = response.begin(); // Get a Client
    let body = "{
        \"msg\":     \"connect\",
        \"version\": \"1\",
        \"support\": [\"1\", \"pre2\", \"pre1\"]
    }".to_string();

    let message = Message::Text(body);
    client.send_message(message).ok().unwrap(); // Send message

    for message in client.incoming_messages::<Message>() {

        let json_text = match message.ok().unwrap() {
            Message::Text(plain) => plain,
            _ => unreachable!(),
        };

        let json = Json::from_str(&json_text);

        let object = match json.ok().unwrap() {
            Json::Object(o) => o,
            _ => unreachable!(),
        };

        let message = match object.get("msg") {
            Some(m) => match m.clone() {
                            Json::String(s) => s,
                            _ => unreachable!(),
                       },
            None    => "No Message".to_string(),
        };

        println!("The message was: {}", message);
    }
}
<commit_msg>Able to get session ids<commit_after>extern crate rustc_serialize;
extern crate websocket;

use std::io::Write;
use std::io::Read;
use rustc_serialize::json::Json;
use rustc_serialize::json;
use websocket::Message;
use websocket::client::request::Url;
use websocket::dataframe::DataFrame;
use websocket::client::sender::Sender;
use websocket::client::receiver::Receiver;
use websocket::stream::WebSocketStream;
use websocket::result::WebSocketError;

pub use websocket::result::WebSocketResult;

mod requests;
mod responses;

use responses::*;
use requests::*;

type Client = websocket::Client<DataFrame, Sender<WebSocketStream>, Receiver<WebSocketStream>>;

fn handshake(url: &Url) -> WebSocketResult<Client> {
    // Handshake with the server
    let knock  = try!( Client::connect(url) );
    let answer = try!( knock.send() );
    try!( answer.validate() );

    // Get referennce to the client
    Ok(answer.begin())
}

fn negotiate(client: &mut Client, version: &str) -> WebSocketResult<NegotiateResp> {
    let request = requests::Connect::new(version);
    let request = Message::Text(request.to_json());

    try!( client.send_message(request) );

    for msg_result in client.incoming_messages::<Message>() {
        if let Ok(Message::Text(plaintext)) = msg_result {
            if let Ok(success) = json::decode::<VersionSuccess>(&plaintext) {
                if success.msg == "connected" {
                    return Ok(NegotiateResp::SessionId(success.session));
                }
            } else if let Ok(failure) = json::decode::<VersionFailed>(&plaintext) {
                if failure.msg == "failed" {
                    return Ok(NegotiateResp::Version(failure.version));
                }
            }
        }
    }
    Err(WebSocketError::ResponseError("No protocol version reply from the server.".to_string()))
}

pub enum NegotiateResp {
    SessionId(String),
    Version(String),
}

fn connect(url: &Url) -> WebSocketResult<(Client, String)> {
    let mut client = try!( handshake(url) );
    let mut curr_version = VER_NOW;

    loop {
        match negotiate(&mut client, curr_version) {
            Err(e) => return Err(e),
            Ok(NegotiateResp::SessionId(session)) => return Ok((client, session)),
            Ok(NegotiateResp::Version(version))   => {
                if let Some(v) = VERSIONS.iter().find(|&v| *v == version) {
                    curr_version = v;
                } else {
                    return Err(WebSocketError::ResponseError("No matching version.".to_string()));
                }
            },
        };
    }
}

#[test]
fn it_works() {

    let url = Url::parse("ws://127.0.0.1:3000/websocket").unwrap(); // Get the URL
    // assert_eq!("{:?}", format!("{:?}", request));

    if let Ok((client, session_id)) = connect(&url) {
        println!("The session id is: {}", session_id);
    }

    // let request = Client::connect(url).ok().expect("Could not connect"); // Connect to the server
    // let response = request.send().ok().expect("Could not send response."); // Send the request
    //
    //
    // response.validate().ok().expect("response is not valid!!"); // Ensure the response is valid
    //
    // let mut client = response.begin(); // Get a Client
    // let body = "{
    //     \"msg\":     \"connect\",
    //     \"version\": \"1\",
    //     \"support\": [\"1\", \"pre2\", \"pre1\"]
    // }".to_string();
    //
    // let message = Message::Text(body);
    // client.send_message(message).ok().unwrap(); // Send message
    //
    // for message in client.incoming_messages::<Message>() {
    //
    //     let json_text = match message.ok().unwrap() {
    //         Message::Text(plain) => plain,
    //         _ => unreachable!(),
    //     };
    //
    //     let json = Json::from_str(&json_text);
    //
    //     let object = match json.ok().unwrap() {
    //         Json::Object(o) => o,
    //         _ => unreachable!(),
    //     };
    //
    //     let message = match object.get("msg") {
    //         Some(m) => match m.clone() {
    //                         Json::String(s) => s,
    //                         _ => unreachable!(),
    //                    },
    //         None    => "No Message".to_string(),
    //     };
    //
    //     println!("The message was: {}", message);
    // }
}
<|endoftext|>


<commit_before>//! The `ipnetwork` crate provides a set of APIs to work with IP CIDRs in
//! Rust. Implementation for IPv4 is more or less stable, IPv6 implementation
//! is still WIP.
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![cfg_attr(feature = "ipv6-iterator", feature(i128_type))]
#![cfg_attr(feature = "ipv6-methods", feature(i128_type))]
#![crate_type = "lib"]
#![doc(html_root_url = "https://docs.rs/ipnetwork/0.12.8")]

#[cfg(feature = "with-serde")]
extern crate serde;
#[cfg(feature = "with-serde")]
#[macro_use]
extern crate serde_derive;

#[cfg(feature = "with-serde")]
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};

use std::fmt;
use std::net::IpAddr;

mod common;
mod ipv4;
mod ipv6;

use std::str::FromStr;

pub use common::IpNetworkError;
pub use ipv4::{ipv4_mask_to_prefix, Ipv4Network};
pub use ipv6::{ipv6_mask_to_prefix, Ipv6Network};

/// Represents a generic network range. This type can have two variants:
/// the v4 and the v6 case.
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum IpNetwork {
    V4(Ipv4Network),
    V6(Ipv6Network),
}

#[cfg(feature = "with-serde")]
impl<'de> Deserialize<'de> for IpNetwork {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = <&str>::deserialize(deserializer)?;
        IpNetwork::from_str(s).map_err(de::Error::custom)
    }
}

#[cfg(feature = "with-serde")]
impl Serialize for IpNetwork {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&self.to_string())
    }
}

impl IpNetwork {
    /// Constructs a new `IpNetwork` from a given `IpAddr` and a prefix denoting the
    /// network size. If the prefix is larger than 32 (for IPv4) or 128 (for IPv6), this
    /// will raise an `IpNetworkError::InvalidPrefix` error. Support for IPv6 is not
    /// complete yet.
    pub fn new(ip: IpAddr, prefix: u8) -> Result<IpNetwork, IpNetworkError> {
        match ip {
            IpAddr::V4(a) => Ok(IpNetwork::V4(Ipv4Network::new(a, prefix)?)),
            IpAddr::V6(a) => Ok(IpNetwork::V6(Ipv6Network::new(a, prefix)?)),
        }
    }

    /// Returns the IP part of a given `IpNetwork`
    pub fn ip(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(a.ip()),
            IpNetwork::V6(ref a) => IpAddr::V6(a.ip()),
        }
    }

    /// Returns the prefix of the given `IpNetwork`
    ///
    /// # Example
    /// ```
    /// use ipnetwork::IpNetwork;
    ///
    /// assert_eq!(IpNetwork::V4("10.9.0.1".parse().unwrap()).prefix(), 32u8);
    /// assert_eq!(IpNetwork::V4("10.9.0.32/16".parse().unwrap()).prefix(), 16u8);
    ///
    /// assert_eq!(IpNetwork::V6("ff01::0".parse().unwrap()).prefix(), 128u8);
    /// assert_eq!(IpNetwork::V6("ff01::0/32".parse().unwrap()).prefix(), 32u8);
    /// ```
    pub fn prefix(&self) -> u8 {
        match *self {
            IpNetwork::V4(ref a) => a.prefix(),
            IpNetwork::V6(ref a) => a.prefix(),
        }
    }

    /// Returns the mask for this `IpNetwork`.
    /// That means the `prefix` most significant bits will be 1 and the rest 0
    ///
    /// # Example
    ///
    /// ```
    /// use ipnetwork::IpNetwork;
    /// use std::net::{Ipv4Addr, Ipv6Addr};
    ///
    /// let v4_net: IpNetwork = "10.9.0.1".parse().unwrap();
    /// assert_eq!(v4_net.mask(), Ipv4Addr::new(255, 255, 255, 255));
    /// let v4_net: IpNetwork = "10.9.0.32/16".parse().unwrap();
    /// assert_eq!(v4_net.mask(), Ipv4Addr::new(255, 255, 0, 0));
    ///
    /// let v6_net: IpNetwork = "ff01::0".parse().unwrap();
    /// assert_eq!(v6_net.mask(), Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff));
    /// let v6_net: IpNetwork = "ff01::0/32".parse().unwrap();
    /// assert_eq!(v6_net.mask(), Ipv6Addr::new(0xffff, 0xffff, 0, 0, 0, 0, 0, 0));
    /// ```
    pub fn mask(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(a.mask()),
            IpNetwork::V6(ref a) => IpAddr::V6(a.mask()),
        }
    }

    /// Returns true if the IP in this `IpNetwork` is a valid IPv4 address,
    /// false if it's a valid IPv6 address.
    ///
    /// # Example
    ///
    ///```
    /// use ipnetwork::IpNetwork;
    ///
    /// let v4: IpNetwork = IpNetwork::V4("10.9.0.32/16".parse().unwrap());
    /// assert_eq!(v4.is_ipv4(), true);
    /// assert_eq!(v4.is_ipv6(), false);
    ///```
    pub fn is_ipv4(&self) -> bool {
        match *self {
            IpNetwork::V4(_) => true,
            IpNetwork::V6(_) => false,
        }
    }

    /// Returns true if the IP in this `IpNetwork` is a valid IPv6 address,
    /// false if it's a valid IPv4 address.
    ///
    /// # Example
    ///
    ///```
    /// use ipnetwork::IpNetwork;
    ///
    /// let v6: IpNetwork = IpNetwork::V6("ff01::0/32".parse().unwrap());
    /// assert_eq!(v6.is_ipv6(), true);
    /// assert_eq!(v6.is_ipv4(), false);
    ///```
    pub fn is_ipv6(&self) -> bool {
        match *self {
            IpNetwork::V4(_) => false,
            IpNetwork::V6(_) => true,
        }
    }

    /// Checks if a given `IpAddr` is in this `IpNetwork`
    ///
    /// # Examples
    ///
    /// ```
    /// use std::net::IpAddr;
    /// use ipnetwork::IpNetwork;
    ///
    /// let net: IpNetwork = "127.0.0.0/24".parse().unwrap();
    /// let ip1: IpAddr = "127.0.0.1".parse().unwrap();
    /// let ip2: IpAddr = "172.0.0.1".parse().unwrap();
    /// let ip4: IpAddr = "::1".parse().unwrap();
    /// assert!(net.contains(ip1));
    /// assert!(!net.contains(ip2));
    /// assert!(!net.contains(ip4));
    /// ```
    pub fn contains(&self, ip: IpAddr) -> bool {
        match (*self, ip) {
            (IpNetwork::V4(net), IpAddr::V4(ip)) => net.contains(ip),
            (IpNetwork::V6(net), IpAddr::V6(ip)) => net.contains(ip),
            _ => false,
        }
    }
}

/// Tries to parse the given string into a `IpNetwork`. Will first try to parse
/// it as an `Ipv4Network` and if that fails as an `Ipv6Network`. If both
/// fails it will return an `InvalidAddr` error.
///
/// # Examples
///
/// ```
/// use std::net::Ipv4Addr;
/// use ipnetwork::{IpNetwork, Ipv4Network};
///
/// let expected = IpNetwork::V4(Ipv4Network::new(Ipv4Addr::new(10, 1, 9, 32), 16).unwrap());
/// let from_cidr: IpNetwork = "10.1.9.32/16".parse().unwrap();
/// assert_eq!(expected, from_cidr);
/// ```
impl FromStr for IpNetwork {
    type Err = IpNetworkError;
    fn from_str(s: &str) -> Result<IpNetwork, IpNetworkError> {
        if let Ok(net) = Ipv4Network::from_str(s) {
            Ok(IpNetwork::V4(net))
        } else if let Ok(net) = Ipv6Network::from_str(s) {
            Ok(IpNetwork::V6(net))
        } else {
            Err(IpNetworkError::InvalidAddr(s.to_string()))
        }
    }
}

impl From<Ipv4Network> for IpNetwork {
    fn from(v4: Ipv4Network) -> IpNetwork {
        IpNetwork::V4(v4)
    }
}

impl From<Ipv6Network> for IpNetwork {
    fn from(v6: Ipv6Network) -> IpNetwork {
        IpNetwork::V6(v6)
    }
}

impl From<IpAddr> for IpNetwork {
    fn from(addr: IpAddr) -> IpNetwork {
        match addr {
            IpAddr::V4(a) => IpNetwork::V4(Ipv4Network::from(a)),
            IpAddr::V6(a) => IpNetwork::V6(Ipv6Network::from(a)),
        }
    }
}

impl fmt::Display for IpNetwork {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            IpNetwork::V4(net) => net.fmt(f),
            IpNetwork::V6(net) => net.fmt(f),
        }
    }
}

/// Converts a `IpAddr` network mask into a prefix.
/// If the mask is invalid this will return an `IpNetworkError::InvalidPrefix`.
pub fn ip_mask_to_prefix(mask: IpAddr) -> Result<u8, IpNetworkError> {
    match mask {
        IpAddr::V4(mask) => ipv4_mask_to_prefix(mask),
        IpAddr::V6(mask) => ipv6_mask_to_prefix(mask),
    }
}
<commit_msg>No need to implement serialize/deserialize for enum, use serde(untagged)<commit_after>//! The `ipnetwork` crate provides a set of APIs to work with IP CIDRs in
//! Rust. Implementation for IPv4 is more or less stable, IPv6 implementation
//! is still WIP.
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![cfg_attr(feature = "ipv6-iterator", feature(i128_type))]
#![cfg_attr(feature = "ipv6-methods", feature(i128_type))]
#![crate_type = "lib"]
#![doc(html_root_url = "https://docs.rs/ipnetwork/0.12.8")]

#[cfg(feature = "with-serde")]
extern crate serde;
#[cfg(feature = "with-serde")]
#[macro_use]
extern crate serde_derive;

use std::fmt;
use std::net::IpAddr;

mod common;
mod ipv4;
mod ipv6;

use std::str::FromStr;

pub use common::IpNetworkError;
pub use ipv4::{ipv4_mask_to_prefix, Ipv4Network};
pub use ipv6::{ipv6_mask_to_prefix, Ipv6Network};

/// Represents a generic network range. This type can have two variants:
/// the v4 and the v6 case.
#[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "with-serde", serde(untagged))]
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum IpNetwork {
    V4(Ipv4Network),
    V6(Ipv6Network),
}

impl IpNetwork {
    /// Constructs a new `IpNetwork` from a given `IpAddr` and a prefix denoting the
    /// network size. If the prefix is larger than 32 (for IPv4) or 128 (for IPv6), this
    /// will raise an `IpNetworkError::InvalidPrefix` error. Support for IPv6 is not
    /// complete yet.
    pub fn new(ip: IpAddr, prefix: u8) -> Result<IpNetwork, IpNetworkError> {
        match ip {
            IpAddr::V4(a) => Ok(IpNetwork::V4(Ipv4Network::new(a, prefix)?)),
            IpAddr::V6(a) => Ok(IpNetwork::V6(Ipv6Network::new(a, prefix)?)),
        }
    }

    /// Returns the IP part of a given `IpNetwork`
    pub fn ip(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(a.ip()),
            IpNetwork::V6(ref a) => IpAddr::V6(a.ip()),
        }
    }

    /// Returns the prefix of the given `IpNetwork`
    ///
    /// # Example
    /// ```
    /// use ipnetwork::IpNetwork;
    ///
    /// assert_eq!(IpNetwork::V4("10.9.0.1".parse().unwrap()).prefix(), 32u8);
    /// assert_eq!(IpNetwork::V4("10.9.0.32/16".parse().unwrap()).prefix(), 16u8);
    ///
    /// assert_eq!(IpNetwork::V6("ff01::0".parse().unwrap()).prefix(), 128u8);
    /// assert_eq!(IpNetwork::V6("ff01::0/32".parse().unwrap()).prefix(), 32u8);
    /// ```
    pub fn prefix(&self) -> u8 {
        match *self {
            IpNetwork::V4(ref a) => a.prefix(),
            IpNetwork::V6(ref a) => a.prefix(),
        }
    }

    /// Returns the mask for this `IpNetwork`.
    /// That means the `prefix` most significant bits will be 1 and the rest 0
    ///
    /// # Example
    ///
    /// ```
    /// use ipnetwork::IpNetwork;
    /// use std::net::{Ipv4Addr, Ipv6Addr};
    ///
    /// let v4_net: IpNetwork = "10.9.0.1".parse().unwrap();
    /// assert_eq!(v4_net.mask(), Ipv4Addr::new(255, 255, 255, 255));
    /// let v4_net: IpNetwork = "10.9.0.32/16".parse().unwrap();
    /// assert_eq!(v4_net.mask(), Ipv4Addr::new(255, 255, 0, 0));
    ///
    /// let v6_net: IpNetwork = "ff01::0".parse().unwrap();
    /// assert_eq!(v6_net.mask(), Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff));
    /// let v6_net: IpNetwork = "ff01::0/32".parse().unwrap();
    /// assert_eq!(v6_net.mask(), Ipv6Addr::new(0xffff, 0xffff, 0, 0, 0, 0, 0, 0));
    /// ```
    pub fn mask(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(a.mask()),
            IpNetwork::V6(ref a) => IpAddr::V6(a.mask()),
        }
    }

    /// Returns true if the IP in this `IpNetwork` is a valid IPv4 address,
    /// false if it's a valid IPv6 address.
    ///
    /// # Example
    ///
    ///```
    /// use ipnetwork::IpNetwork;
    ///
    /// let v4: IpNetwork = IpNetwork::V4("10.9.0.32/16".parse().unwrap());
    /// assert_eq!(v4.is_ipv4(), true);
    /// assert_eq!(v4.is_ipv6(), false);
    ///```
    pub fn is_ipv4(&self) -> bool {
        match *self {
            IpNetwork::V4(_) => true,
            IpNetwork::V6(_) => false,
        }
    }

    /// Returns true if the IP in this `IpNetwork` is a valid IPv6 address,
    /// false if it's a valid IPv4 address.
    ///
    /// # Example
    ///
    ///```
    /// use ipnetwork::IpNetwork;
    ///
    /// let v6: IpNetwork = IpNetwork::V6("ff01::0/32".parse().unwrap());
    /// assert_eq!(v6.is_ipv6(), true);
    /// assert_eq!(v6.is_ipv4(), false);
    ///```
    pub fn is_ipv6(&self) -> bool {
        match *self {
            IpNetwork::V4(_) => false,
            IpNetwork::V6(_) => true,
        }
    }

    /// Checks if a given `IpAddr` is in this `IpNetwork`
    ///
    /// # Examples
    ///
    /// ```
    /// use std::net::IpAddr;
    /// use ipnetwork::IpNetwork;
    ///
    /// let net: IpNetwork = "127.0.0.0/24".parse().unwrap();
    /// let ip1: IpAddr = "127.0.0.1".parse().unwrap();
    /// let ip2: IpAddr = "172.0.0.1".parse().unwrap();
    /// let ip4: IpAddr = "::1".parse().unwrap();
    /// assert!(net.contains(ip1));
    /// assert!(!net.contains(ip2));
    /// assert!(!net.contains(ip4));
    /// ```
    pub fn contains(&self, ip: IpAddr) -> bool {
        match (*self, ip) {
            (IpNetwork::V4(net), IpAddr::V4(ip)) => net.contains(ip),
            (IpNetwork::V6(net), IpAddr::V6(ip)) => net.contains(ip),
            _ => false,
        }
    }
}

/// Tries to parse the given string into a `IpNetwork`. Will first try to parse
/// it as an `Ipv4Network` and if that fails as an `Ipv6Network`. If both
/// fails it will return an `InvalidAddr` error.
///
/// # Examples
///
/// ```
/// use std::net::Ipv4Addr;
/// use ipnetwork::{IpNetwork, Ipv4Network};
///
/// let expected = IpNetwork::V4(Ipv4Network::new(Ipv4Addr::new(10, 1, 9, 32), 16).unwrap());
/// let from_cidr: IpNetwork = "10.1.9.32/16".parse().unwrap();
/// assert_eq!(expected, from_cidr);
/// ```
impl FromStr for IpNetwork {
    type Err = IpNetworkError;
    fn from_str(s: &str) -> Result<IpNetwork, IpNetworkError> {
        if let Ok(net) = Ipv4Network::from_str(s) {
            Ok(IpNetwork::V4(net))
        } else if let Ok(net) = Ipv6Network::from_str(s) {
            Ok(IpNetwork::V6(net))
        } else {
            Err(IpNetworkError::InvalidAddr(s.to_string()))
        }
    }
}

impl From<Ipv4Network> for IpNetwork {
    fn from(v4: Ipv4Network) -> IpNetwork {
        IpNetwork::V4(v4)
    }
}

impl From<Ipv6Network> for IpNetwork {
    fn from(v6: Ipv6Network) -> IpNetwork {
        IpNetwork::V6(v6)
    }
}

impl From<IpAddr> for IpNetwork {
    fn from(addr: IpAddr) -> IpNetwork {
        match addr {
            IpAddr::V4(a) => IpNetwork::V4(Ipv4Network::from(a)),
            IpAddr::V6(a) => IpNetwork::V6(Ipv6Network::from(a)),
        }
    }
}

impl fmt::Display for IpNetwork {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            IpNetwork::V4(net) => net.fmt(f),
            IpNetwork::V6(net) => net.fmt(f),
        }
    }
}

/// Converts a `IpAddr` network mask into a prefix.
/// If the mask is invalid this will return an `IpNetworkError::InvalidPrefix`.
pub fn ip_mask_to_prefix(mask: IpAddr) -> Result<u8, IpNetworkError> {
    match mask {
        IpAddr::V4(mask) => ipv4_mask_to_prefix(mask),
        IpAddr::V6(mask) => ipv6_mask_to_prefix(mask),
    }
}
<|endoftext|>


<commit_before>use dirs;
use std::fs;
use std::io::ErrorKind;
use std::process::Command;

pub fn run() {
    // Environment (Unix)

    println!("Removing package manager artifacts.");

    match Command::new("brew").arg("cleanup").output() {
        Ok(_) => (),
        Err(error) => match error.kind() {
            ErrorKind::NotFound => panic!("The `brew` command is missing."),
            other_error => panic!("There was a problem: {:?}", other_error),
        },
    }

    // Version control (Git)

    println!("Checking the status of each repo.");

    let home_dir = match dirs::home_dir() {
        Some(directory) => directory,
        None => panic!("Cannot find the home directory."),
    };

    let repos_path = &home_dir.join("repos");

    match fs::read_dir(&repos_path) {
        Ok(paths) => {
            for path in paths {
                let path = match &path {
                    Ok(path) => path.path(),
                    Err(error) => panic!("There was a problem: {:?}", error),
                };

                let dirty_check = match Command::new("git")
                    .current_dir(&path)
                    .arg("status")
                    .arg("--porcelain")
                    .output()
                {
                    Ok(output) => output.stdout,
                    Err(error) => panic!("There was a problem: {:?}", error),
                };

                if !dirty_check.is_empty() {
                    panic!("The {} repo is dirty.", &path.display());
                }

                let unpushed_check = match Command::new("git")
                    .current_dir(&path)
                    .arg("log")
                    .arg("@{u}..")
                    .output()
                {
                    Ok(output) => output.stdout,
                    Err(error) => panic!("There was a problem: {:?}", error),
                };

                if !unpushed_check.is_empty() {
                    panic!("The {} repo has unpushed commits.", &path.display());
                }
            }
        }
        Err(error) => panic!("There was a problem: {:?}", error),
    };

    // Editor (Vim)

    println!("Quitting editor processes.");

    match Command::new("killall").arg("vim").output() {
        Ok(_) => (),
        Err(error) => match error.kind() {
            ErrorKind::NotFound => panic!("The `killall` command is missing."),
            other_error => panic!("There was a problem: {:?}", other_error),
        },
    }

    // Application programming (JavaScript)

    println!("Quitting application programming processes.");

    match Command::new("killall").arg("node").output() {
        Ok(_) => (),
        Err(error) => match error.kind() {
            ErrorKind::NotFound => panic!("The `killall` command is missing."),
            other_error => panic!("There was a problem: {:?}", other_error),
        },
    }

    // Systems programming (Rust)

    println!("Quitting systems programming processes.");

    match Command::new("killall").arg("rls").output() {
        Ok(_) => (),
        Err(error) => match error.kind() {
            ErrorKind::NotFound => panic!("The `killall` command is missing."),
            other_error => panic!("There was a problem: {:?}", other_error),
        },
    }
}
<commit_msg>Output all dirty repos at once with end script<commit_after>use dirs;
use std::fs;
use std::io::ErrorKind;
use std::process::Command;

pub fn run() {
    // Environment (Unix)

    println!("Removing package manager artifacts.");

    match Command::new("brew").arg("cleanup").output() {
        Ok(_) => (),
        Err(error) => match error.kind() {
            ErrorKind::NotFound => panic!("The `brew` command is missing."),
            other_error => panic!("There was a problem: {:?}", other_error),
        },
    }

    // Version control (Git)

    println!("Making sure all repos are clean.");

    let home_dir = match dirs::home_dir() {
        Some(directory) => directory,
        None => panic!("Cannot find the home directory."),
    };

    let repos_path = &home_dir.join("repos");

    match fs::read_dir(&repos_path) {
        Ok(paths) => {
            let mut all_repos_clean = true;

            for path in paths {
                let path = match &path {
                    Ok(path) => path.path(),
                    Err(error) => panic!("There was a problem: {:?}", error),
                };

                let status_check = match Command::new("git")
                    .current_dir(&path)
                    .arg("status")
                    .arg("--porcelain")
                    .output()
                {
                    Ok(output) => output.stdout,
                    Err(error) => panic!("There was a problem: {:?}", error),
                };

                let unpushed_check = match Command::new("git")
                    .current_dir(&path)
                    .arg("log")
                    .arg("@{u}..")
                    .output()
                {
                    Ok(output) => output.stdout,
                    Err(error) => panic!("There was a problem: {:?}", error),
                };

                if !status_check.is_empty() || !unpushed_check.is_empty() {
                    all_repos_clean = false;
                    eprintln!("A dirty repo was found: {}", &path.display());
                }
            }

            if !all_repos_clean {
                panic!("Repos are dirty.");
            }
        }
        Err(error) => panic!("There was a problem: {:?}", error),
    };

    // Editor (Vim)

    println!("Quitting editor processes.");

    match Command::new("killall").arg("vim").output() {
        Ok(_) => (),
        Err(error) => match error.kind() {
            ErrorKind::NotFound => panic!("The `killall` command is missing."),
            other_error => panic!("There was a problem: {:?}", other_error),
        },
    }

    // Application programming (JavaScript)

    println!("Quitting application programming processes.");

    match Command::new("killall").arg("node").output() {
        Ok(_) => (),
        Err(error) => match error.kind() {
            ErrorKind::NotFound => panic!("The `killall` command is missing."),
            other_error => panic!("There was a problem: {:?}", other_error),
        },
    }

    // Systems programming (Rust)

    println!("Quitting systems programming processes.");

    match Command::new("killall").arg("rls").output() {
        Ok(_) => (),
        Err(error) => match error.kind() {
            ErrorKind::NotFound => panic!("The `killall` command is missing."),
            other_error => panic!("There was a problem: {:?}", other_error),
        },
    }
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]

//! `Router` provides fast and flexible routing for Iron.

extern crate iron;
extern crate route_recognizer as recognizer;

pub use router::Router;
pub use recognizer::Params;

mod router;
mod macros;
<commit_msg>(feat) Publicize error types in lib.rs.<commit_after>#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]

//! `Router` provides fast and flexible routing for Iron.

extern crate iron;
extern crate route_recognizer as recognizer;

pub use router::{Router, NoRoute, TrailingSlash};
pub use recognizer::Params;

mod router;
mod macros;
<|endoftext|>


<commit_before>#![feature(unstable)]
#![crate_type = "rlib"]
#![crate_name = "cripes"]

#![feature(alloc)]

/// Utility wrapper for `std::ptr::copy` that retains C's `memcpy`
/// argument-order semantics.
#[inline(always)]
fn memcpy(dest: &mut [u8], src: &[u8]) {
    unsafe { std::ptr::copy(src.as_ptr(), dest.as_mut_ptr(), std::cmp::min(src.len(), dest.len())) }
}

#[macro_use]
pub mod util;

#[macro_use]
pub mod symbol;
pub mod pattern;
<commit_msg>lib.rs: update crate feature requirements for current Rust nightly<commit_after>#![crate_type = "rlib"]
#![crate_name = "cripes"]

#![feature(alloc)]

#![feature(core_intrinsics)]
#![feature(heap_api)]
#![feature(unsize)]
#![feature(coerce_unsized)]
#![feature(drop_in_place)]

/// Utility wrapper for `std::ptr::copy` that retains C's `memcpy`
/// argument-order semantics.
#[inline(always)]
fn memcpy(dest: &mut [u8], src: &[u8]) {
    unsafe { std::ptr::copy(src.as_ptr(), dest.as_mut_ptr(), std::cmp::min(src.len(), dest.len())) }
}

#[macro_use]
pub mod util;

#[macro_use]
pub mod symbol;
pub mod pattern;
<|endoftext|>