<commit_before>#[macro_use]
extern crate wlroots;

use wlroots::{CompositorBuilder, CompositorHandle, Cursor, CursorHandle, CursorHandler,
              InputManagerHandler, KeyboardHandle, KeyboardHandler, OutputBuilder,
              OutputBuilderResult, OutputHandle, OutputHandler, OutputLayout, OutputLayoutHandle,
              OutputLayoutHandler, OutputManagerHandler, PointerHandle, PointerHandler,
              XCursorTheme, XCursorManager};
use wlroots::key_events::KeyEvent;
use wlroots::pointer_events::{AxisEvent, ButtonEvent, MotionEvent, AbsoluteMotionEvent};
use wlroots::utils::{init_logging, L_DEBUG};
use wlroots::wlroots_sys::gl;
use wlroots::wlroots_sys::wlr_button_state::WLR_BUTTON_RELEASED;
use wlroots::xkbcommon::xkb::keysyms::KEY_Escape;

struct State {
    color: [f32; 4],
    default_color: [f32; 4],
    xcursor_manager: XCursorManager,
    cursor: CursorHandle,
    layout: OutputLayoutHandle
}

impl State {
    fn new(xcursor_manager: XCursorManager, layout: OutputLayoutHandle, cursor: CursorHandle) -> Self {
        State { color: [0.25, 0.25, 0.25, 1.0],
                default_color: [0.25, 0.25, 0.25, 1.0],
                xcursor_manager,
                cursor,
                layout }
    }
}

compositor_data!(State);

struct ExCursor;

struct OutputManager;

struct ExOutput;

struct InputManager;

struct ExPointer;

struct ExKeyboardHandler;

struct OutputLayoutEx;

impl CursorHandler for ExCursor {}

impl OutputLayoutHandler for OutputLayoutEx {}

impl OutputManagerHandler for OutputManager {
    fn output_added<'output>(&mut self,
                             compositor: CompositorHandle,
                             builder: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        let mut result = builder.build_best_mode(ExOutput);
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            let layout = &mut state.layout;
            let cursor = &mut state.cursor;
            let xcursor_manager = &mut state.xcursor_manager;
            // TODO use output config if present instead of auto
            with_handles!([(layout: {layout}),
                          (cursor: {cursor}),
                          (output: {&mut result.output})] => {
                layout.add_auto(output);
                cursor.attach_output_layout(layout);
                xcursor_manager.set_cursor_image("left_ptr".to_string(), cursor);
                let (x, y) = cursor.coords();
                // https://en.wikipedia.org/wiki/Mouse_warping
                cursor.warp(None, x, y);
            }).unwrap();
            Some(result)
        }).unwrap()
    }
}

impl KeyboardHandler for ExKeyboardHandler {
    fn on_key(&mut self, compositor: CompositorHandle, _: KeyboardHandle, key_event: &KeyEvent) {
        with_handles!([(compositor: {compositor})] => {
            for key in key_event.pressed_keys() {
                if key == KEY_Escape {
                    compositor.terminate()
                }
            }
        }).unwrap();
    }
}

impl PointerHandler for ExPointer {
    fn on_motion_absolute(&mut self, compositor: CompositorHandle, _: PointerHandle, event: &AbsoluteMotionEvent) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            let (x, y) = event.pos();
            state.cursor
                .run(|cursor| cursor.warp_absolute(event.device(), x, y))
                .unwrap();
        }).unwrap();
    }

    fn on_motion(&mut self, compositor: CompositorHandle, _: PointerHandle, event: &MotionEvent) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            let (delta_x, delta_y) = event.delta();
            state.cursor
                .run(|cursor| cursor.move_to(None, delta_x, delta_y))
                .unwrap();
        }).unwrap();
    }

    fn on_button(&mut self, compositor: CompositorHandle, _: PointerHandle, event: &ButtonEvent) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            if event.state() == WLR_BUTTON_RELEASED {
                state.color = state.default_color;
            } else {
                state.color = [0.25, 0.25, 0.25, 1.0];
                state.color[event.button() as usize % 3] = 1.0;
            }
        }).unwrap();
    }

    fn on_axis(&mut self, compositor: CompositorHandle, _: PointerHandle, event: &AxisEvent) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            for color_byte in &mut state.default_color[..3] {
                *color_byte += if event.delta() > 0.0 { -0.05 } else { 0.05 };
                if *color_byte > 1.0 {
                    *color_byte = 1.0
                }
                if *color_byte < 0.0 {
                    *color_byte = 0.0
                }
            }
            state.color = state.default_color.clone()
        }).unwrap();
    }
}

impl OutputHandler for ExOutput {
    fn on_frame(&mut self, compositor: CompositorHandle, output: OutputHandle) {
        with_handles!([(compositor: {compositor}), (output: {output})] => {
            let state: &mut State = compositor.into();
            // NOTE gl functions will probably always be unsafe.
            unsafe {
                output.make_current();
                gl::ClearColor(state.color[0], state.color[1], state.color[2], 1.0);
                gl::Clear(gl::COLOR_BUFFER_BIT);
                output.swap_buffers(None, None);
            }
        }).unwrap();
    }
}

impl InputManagerHandler for InputManager {
    fn pointer_added(&mut self,
                     compositor: CompositorHandle,
                     pointer: PointerHandle)
                     -> Option<Box<PointerHandler>> {
        with_handles!([(compositor: {compositor}), (pointer: {pointer})] => {
            let state: &mut State = compositor.into();
            state.cursor
                .run(|cursor| cursor.attach_input_device(pointer.input_device()))
                .unwrap();
        }).unwrap();
        Some(Box::new(ExPointer))
    }

    fn keyboard_added(&mut self,
                      _: CompositorHandle,
                      _: KeyboardHandle)
                      -> Option<Box<KeyboardHandler>> {
        Some(Box::new(ExKeyboardHandler))
    }
}

fn main() {
    init_logging(L_DEBUG, None);
    let cursor = Cursor::create(Box::new(ExCursor));
    let xcursor_manager = XCursorManager::create(Some("default".to_string()), 24).expect("Could not create xcursor manager");
    let layout = OutputLayout::create(Box::new(OutputLayoutEx));

    let compositor = CompositorBuilder::new().input_manager(Box::new(InputManager))
                                             .output_manager(Box::new(OutputManager))
                                             .build_auto(State::new(xcursor_manager, layout, cursor));
    compositor.run();
}
<commit_msg>mess up example to build<commit_after>#[macro_use]
extern crate wlroots;

use wlroots::{CompositorBuilder, CompositorHandle, Cursor, CursorHandle, CursorHandler,
              InputManagerHandler, KeyboardHandle, KeyboardHandler, OutputBuilder,
              OutputBuilderResult, OutputHandle, OutputHandler, OutputLayout, OutputLayoutHandle,
              OutputLayoutHandler, OutputManagerHandler, PointerHandle, PointerHandler,
              XCursorTheme, XCursorManager};
use wlroots::key_events::KeyEvent;
use wlroots::pointer_events::{AxisEvent, ButtonEvent, MotionEvent, AbsoluteMotionEvent};
use wlroots::utils::{init_logging, L_DEBUG};
use wlroots::wlroots_sys::gl;
use wlroots::wlroots_sys::wlr_button_state::WLR_BUTTON_RELEASED;
use wlroots::xkbcommon::xkb::keysyms::KEY_Escape;

struct State<'s> {
    color: [f32; 4],
    default_color: [f32; 4],
    xcursor_manager: XCursorManager<'s>,
    cursor: CursorHandle,
    layout: OutputLayoutHandle
}

impl<'s> State<'s> {
    fn new(xcursor_manager: XCursorManager<'s>, layout: OutputLayoutHandle, cursor: CursorHandle) -> Self {
        State { color: [0.25, 0.25, 0.25, 1.0],
                default_color: [0.25, 0.25, 0.25, 1.0],
                xcursor_manager,
                cursor,
                layout }
    }
}

compositor_data!(State<'static>);

struct ExCursor;

struct OutputManager;

struct ExOutput;

struct InputManager;

struct ExPointer;

struct ExKeyboardHandler;

struct OutputLayoutEx;

impl CursorHandler for ExCursor {}

impl OutputLayoutHandler for OutputLayoutEx {}

impl OutputManagerHandler for OutputManager {
    fn output_added<'output>(&mut self,
                             compositor: CompositorHandle,
                             builder: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        let mut result = builder.build_best_mode(ExOutput);
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            let layout = &mut state.layout;
            let cursor = &mut state.cursor;
            let xcursor_manager = &mut state.xcursor_manager;
            // TODO use output config if present instead of auto
            with_handles!([(layout: {layout}),
                          (cursor: {cursor}),
                          (output: {&mut result.output})] => {
                layout.add_auto(output);
                cursor.attach_output_layout(layout);
                xcursor_manager.set_cursor_image("left_ptr".to_string(), cursor);
                let (x, y) = cursor.coords();
                // https://en.wikipedia.org/wiki/Mouse_warping
                cursor.warp(None, x, y);
            }).unwrap();
            Some(result)
        }).unwrap()
    }
}

impl KeyboardHandler for ExKeyboardHandler {
    fn on_key(&mut self, compositor: CompositorHandle, _: KeyboardHandle, key_event: &KeyEvent) {
        with_handles!([(compositor: {compositor})] => {
            for key in key_event.pressed_keys() {
                if key == KEY_Escape {
                    compositor.terminate()
                }
            }
        }).unwrap();
    }
}

impl PointerHandler for ExPointer {
    fn on_motion_absolute(&mut self, compositor: CompositorHandle, _: PointerHandle, event: &AbsoluteMotionEvent) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            let (x, y) = event.pos();
            state.cursor
                .run(|cursor| cursor.warp_absolute(event.device(), x, y))
                .unwrap();
        }).unwrap();
    }

    fn on_motion(&mut self, compositor: CompositorHandle, _: PointerHandle, event: &MotionEvent) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            let (delta_x, delta_y) = event.delta();
            state.cursor
                .run(|cursor| cursor.move_to(None, delta_x, delta_y))
                .unwrap();
        }).unwrap();
    }

    fn on_button(&mut self, compositor: CompositorHandle, _: PointerHandle, event: &ButtonEvent) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            if event.state() == WLR_BUTTON_RELEASED {
                state.color = state.default_color;
            } else {
                state.color = [0.25, 0.25, 0.25, 1.0];
                state.color[event.button() as usize % 3] = 1.0;
            }
        }).unwrap();
    }

    fn on_axis(&mut self, compositor: CompositorHandle, _: PointerHandle, event: &AxisEvent) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            for color_byte in &mut state.default_color[..3] {
                *color_byte += if event.delta() > 0.0 { -0.05 } else { 0.05 };
                if *color_byte > 1.0 {
                    *color_byte = 1.0
                }
                if *color_byte < 0.0 {
                    *color_byte = 0.0
                }
            }
            state.color = state.default_color.clone()
        }).unwrap();
    }
}

impl OutputHandler for ExOutput {
    fn on_frame(&mut self, compositor: CompositorHandle, output: OutputHandle) {
        with_handles!([(compositor: {compositor}), (output: {output})] => {
            let state: &mut State = compositor.into();
            // NOTE gl functions will probably always be unsafe.
            unsafe {
                output.make_current();
                gl::ClearColor(state.color[0], state.color[1], state.color[2], 1.0);
                gl::Clear(gl::COLOR_BUFFER_BIT);
                output.swap_buffers(None, None);
            }
        }).unwrap();
    }
}

impl InputManagerHandler for InputManager {
    fn pointer_added(&mut self,
                     compositor: CompositorHandle,
                     pointer: PointerHandle)
                     -> Option<Box<PointerHandler>> {
        with_handles!([(compositor: {compositor}), (pointer: {pointer})] => {
            let state: &mut State = compositor.into();
            state.cursor
                .run(|cursor| cursor.attach_input_device(pointer.input_device()))
                .unwrap();
        }).unwrap();
        Some(Box::new(ExPointer))
    }

    fn keyboard_added(&mut self,
                      _: CompositorHandle,
                      _: KeyboardHandle)
                      -> Option<Box<KeyboardHandler>> {
        Some(Box::new(ExKeyboardHandler))
    }
}

fn main() {
    init_logging(L_DEBUG, None);
    let cursor = Cursor::create(Box::new(ExCursor));
    let xcursor_manager = XCursorManager::create(Some("default".to_string()), 24).expect("Could not create xcursor manager");
    let layout = OutputLayout::create(Box::new(OutputLayoutEx));

    let compositor = CompositorBuilder::new().input_manager(Box::new(InputManager))
                                             .output_manager(Box::new(OutputManager))
                                             .build_auto(State::new(xcursor_manager, layout, cursor));
    compositor.run();
}
<|endoftext|>


<commit_before>extern crate natural;

use natural::distance::jaro_winkler_distance;
use natural::distance::levenshtein_distance;

#[test]
fn test_jaro_winkler() {
  f64_eq(jaro_winkler_distance("one", "one"), 1f32);
  f64_eq(jaro_winkler_distance("one", ""), 0f32);
  f64_eq(jaro_winkler_distance("", ""), 0f32);
  f64_eq(jaro_winkler_distance("", "one"), 0f32);
  f64_eq(jaro_winkler_distance("DWAYNE", "DUANE"), 0.822);
  f64_eq(jaro_winkler_distance("Martha", "Marhta"), 0.944);
  f64_eq(jaro_winkler_distance("dixon", "dicksonx"), 0.767);
}

#[test]
fn test_jaro_strings() {
  f64_eq(jaro_winkler_distance("one".to_string(), "one".to_string()), 1f32);
  f64_eq(jaro_winkler_distance("one", "one".to_string()), 1f32);
  f64_eq(jaro_winkler_distance("one".to_string(), "one"), 1f32);
  f64_eq(jaro_winkler_distance("one", "one"), 1f32);
}

fn f64_eq(a: f32, b: f32) {
  assert!((a - b).abs() < 0.01);
}

#[test]
fn test_lev_distance() {
  assert_eq!(levenshtein_distance("one", "one"), 0);
  assert_eq!(levenshtein_distance("one", ""), 3);
  assert_eq!(levenshtein_distance("", ""), 0);
  assert_eq!(levenshtein_distance("kitten", "sitting"), 3);
}<commit_msg>Add float to distance tests<commit_after>extern crate natural;

use natural::distance::jaro_winkler_distance;
use natural::distance::levenshtein_distance;
use std::num::Float;

#[test]
fn test_jaro_winkler() {
  f64_eq(jaro_winkler_distance("one", "one"), 1f32);
  f64_eq(jaro_winkler_distance("one", ""), 0f32);
  f64_eq(jaro_winkler_distance("", ""), 0f32);
  f64_eq(jaro_winkler_distance("", "one"), 0f32);
  f64_eq(jaro_winkler_distance("DWAYNE", "DUANE"), 0.822);
  f64_eq(jaro_winkler_distance("Martha", "Marhta"), 0.944);
  f64_eq(jaro_winkler_distance("dixon", "dicksonx"), 0.767);
}

#[test]
fn test_jaro_strings() {
  f64_eq(jaro_winkler_distance("one".to_string(), "one".to_string()), 1f32);
  f64_eq(jaro_winkler_distance("one", "one".to_string()), 1f32);
  f64_eq(jaro_winkler_distance("one".to_string(), "one"), 1f32);
  f64_eq(jaro_winkler_distance("one", "one"), 1f32);
}

fn f64_eq(a: f32, b: f32) {
  assert!((a - b).abs() < 0.01);
}

#[test]
fn test_lev_distance() {
  assert_eq!(levenshtein_distance("one", "one"), 0);
  assert_eq!(levenshtein_distance("one", ""), 3);
  assert_eq!(levenshtein_distance("", ""), 0);
  assert_eq!(levenshtein_distance("kitten", "sitting"), 3);
}<|endoftext|>


<commit_before>//! Format the output of this TeX parser into a string which
//! is TeX compatible.

use tex::parser::TeXToken;

pub fn format(parser_output: &Vec<TeXToken>) -> String {
    let mut out = String::new();
    for elem in parser_output {
        match elem {
            &TeXToken::Text(ref v) => {
                out.push_str(&v);
            }
            _ => continue,
        }
    }
    out.push_str("\\bye");
    out
}
<commit_msg>handle escaped char<commit_after>//! Format the output of this TeX parser into a string which
//! is TeX compatible.

use tex::parser::TeXToken;

pub fn format(parser_output: &Vec<TeXToken>) -> String {
    let mut out = String::new();
    for elem in parser_output {
        match elem {
            &TeXToken::Text(ref v) => {
                out.push_str(&escape_str(v));
            }
            _ => continue,
        }
    }
    out.push_str("\\bye");
    out
}

fn escape_str(seq: &str) -> String {
    let escaped_ch = [
        ('&', "\\&"),
        ('%', "\\%"),
        ('$', "\\$"),
        ('#', "\\#"),
        ('_', "\\_"),
        ('{', "$\\{$"),
        ('}', "$\\}$"),
        ('~', "\\~"),
        // TODO
        ('^', ""),
        ('\\', "\\backslash"),
    ];
    let mut output = String::new();

    for ch in seq.chars() {
        let mut escaped = false;
        for esc_ch in escaped_ch.iter() {
            if esc_ch.0 == ch {
                escaped = true;
                output.push_str(esc_ch.1);
            }
        }
        if !escaped {
            output.push(ch);
        }
    }
    output
}
<|endoftext|>


<commit_before>use std::error::Error;
use diesel::prelude::*;
use schema::{images, tags, images_tags, images_collections, collections};
use schema::images::dsl::*;
use super::super::models::{ImagesTag, NewImagesTag, Tag, Image, NewImage, Collection,
                           ImagesCollection};
use super::super::db_manager;
use super::super::diesel;
use super::file_storage;

pub fn create(new_image: &NewImage, data: &[u8], sidecar: &[u8]) -> Result<Image, Box<Error>> {
    let ref conn = *try!(db_manager::POOL.get());
    let result = try!(conn.transaction::<Image, Box<Error>, _>(|| {
        let result: Image = try!(diesel::insert(new_image)
                                     .into(images::table)
                                     .get_result(conn));
        try!(file_storage::store_image(result.id, data));
        try!(file_storage::store_sidecar_file(result.id, sidecar));
        Ok(result)
    }));
    Ok(result)
}

pub fn find(image_id: i32) -> Result<(Image, Vec<u8>), Box<Error>> {
    use schema::images::dsl::*;
    let ref conn = *try!(db_manager::POOL.get());
    let img: Image = try!(images.find(image_id).first(conn));
    let data = try!(file_storage::load_image(img.id));
    Ok((img, data))
}

pub fn find_sidecar(image_id: i32) -> Result<(Image, Vec<u8>), Box<Error>> {
    use schema::images::dsl::*;
    let ref conn = *try!(db_manager::POOL.get());
    let img: Image = try!(images.find(image_id).first(conn));
    let data = try!(file_storage::load_sidecar_file(img.id));
    Ok((img, data))
}

pub fn find_range(size: i64, offset: i64) -> Result<Vec<Image>, Box<Error>> {
    let ref conn = *try!(db_manager::POOL.get());
    let result = try!(images.limit(size).offset(offset).load(conn));
    Ok(result)
}

pub fn update(image: &Image) -> Result<Image, Box<Error>> {
    let ref conn = *try!(db_manager::POOL.get());
    let result = try!(diesel::update(images.find(image.id))
                          .set((title.eq(image.title.clone()),
                                description.eq(image.description.clone()),
                                license.eq(image.license.clone()),
                                side_car_file.eq(image.side_car_file.clone()),
                                raw_image_id.eq(image.raw_image_id.clone())))
                          .get_result(conn));
    Ok(result)
}

pub fn add_tag_to_image(image: &Image, tag: &Tag) -> Result<ImagesTag, Box<Error>> {
    let ref conn = *try!(db_manager::POOL.get());
    let new_image_tag = NewImagesTag {
        image_id: image.id,
        tag_id: tag.id,
    };
    let result = try!(diesel::insert(&new_image_tag)
                          .into(images_tags::table)
                          .get_result(conn));
    Ok(result)
}

pub fn get_tags_of_image(image: &Image) -> Result<Vec<Tag>, Box<Error>> {
    use diesel::pg::expression::dsl::any;
    let ref conn = *try!(db_manager::POOL.get());
    let image_tag_ids = ImagesTag::belonging_to(image).select(images_tags::tag_id);
    Ok(try!(tags::table
                .filter(tags::id.eq(any(image_tag_ids)))
                .load::<Tag>(conn)))
}

pub fn get_collections_of_image(image: &Image) -> Result<Vec<Collection>, Box<Error>> {
    use diesel::pg::expression::dsl::any;
    let ref conn = *try!(db_manager::POOL.get());
    let image_collection_ids = ImagesCollection::belonging_to(image)
        .select(images_collections::collection_id);
    Ok(try!(collections::table
                .filter(collections::id.eq(any(image_collection_ids)))
                .load::<Collection>(conn)))
}

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

    #[test]
    fn test_create() {
        let image = b"Hello, wurst image!";
        let sidecar = b"I am a sidecar file!";
        let test_img = NewImage {
            title: "test image",
            description: "desc of test image",
            license: "MIT",
            side_car_file: "carly",
            raw_image_id: 1,
        };
        let img = match create(&test_img, image, sidecar) {
            Ok(i) => i,
            Err(x) => {
                println!("err: {}", x);
                panic!();
            }
        };
        match find(img.id) {
            Ok(i) => {
                let (_, data) = i;
                assert_eq!(image, data.as_slice())
            }
            Err(x) => {
                println!("err: {}", x);
                panic!();
            }
        };
        match find_sidecar(img.id) {
            Ok(i) => {
                let (_, data) = i;
                assert_eq!(sidecar, data.as_slice())
            }
            Err(x) => {
                println!("err: {}", x);
                panic!();
            }
        }

    }
}
<commit_msg>Fix image service create test<commit_after>use std::error::Error;
use diesel::prelude::*;
use schema::{images, tags, images_tags, images_collections, collections};
use schema::images::dsl::*;
use super::super::models::{ImagesTag, NewImagesTag, Tag, Image, NewImage, Collection,
                           ImagesCollection};
use super::super::db_manager;
use super::super::diesel;
use super::file_storage;

pub fn create(new_image: &NewImage, data: &[u8], sidecar: &[u8]) -> Result<Image, Box<Error>> {
    let ref conn = *try!(db_manager::POOL.get());
    let result = try!(conn.transaction::<Image, Box<Error>, _>(|| {
        let result: Image = try!(diesel::insert(new_image)
                                     .into(images::table)
                                     .get_result(conn));
        try!(file_storage::store_image(result.id, data));
        try!(file_storage::store_sidecar_file(result.id, sidecar));
        Ok(result)
    }));
    Ok(result)
}

pub fn find(image_id: i32) -> Result<(Image, Vec<u8>), Box<Error>> {
    use schema::images::dsl::*;
    let ref conn = *try!(db_manager::POOL.get());
    let img: Image = try!(images.find(image_id).first(conn));
    let data = try!(file_storage::load_image(img.id));
    Ok((img, data))
}

pub fn find_sidecar(image_id: i32) -> Result<(Image, Vec<u8>), Box<Error>> {
    use schema::images::dsl::*;
    let ref conn = *try!(db_manager::POOL.get());
    let img: Image = try!(images.find(image_id).first(conn));
    let data = try!(file_storage::load_sidecar_file(img.id));
    Ok((img, data))
}

pub fn find_range(size: i64, offset: i64) -> Result<Vec<Image>, Box<Error>> {
    let ref conn = *try!(db_manager::POOL.get());
    let result = try!(images.limit(size).offset(offset).load(conn));
    Ok(result)
}

pub fn update(image: &Image) -> Result<Image, Box<Error>> {
    let ref conn = *try!(db_manager::POOL.get());
    let result = try!(diesel::update(images.find(image.id))
                          .set((title.eq(image.title.clone()),
                                description.eq(image.description.clone()),
                                license.eq(image.license.clone()),
                                side_car_file.eq(image.side_car_file.clone()),
                                raw_image_id.eq(image.raw_image_id.clone())))
                          .get_result(conn));
    Ok(result)
}

pub fn add_tag_to_image(image: &Image, tag: &Tag) -> Result<ImagesTag, Box<Error>> {
    let ref conn = *try!(db_manager::POOL.get());
    let new_image_tag = NewImagesTag {
        image_id: image.id,
        tag_id: tag.id,
    };
    let result = try!(diesel::insert(&new_image_tag)
                          .into(images_tags::table)
                          .get_result(conn));
    Ok(result)
}

pub fn get_tags_of_image(image: &Image) -> Result<Vec<Tag>, Box<Error>> {
    use diesel::pg::expression::dsl::any;
    let ref conn = *try!(db_manager::POOL.get());
    let image_tag_ids = ImagesTag::belonging_to(image).select(images_tags::tag_id);
    Ok(try!(tags::table
                .filter(tags::id.eq(any(image_tag_ids)))
                .load::<Tag>(conn)))
}

pub fn get_collections_of_image(image: &Image) -> Result<Vec<Collection>, Box<Error>> {
    use diesel::pg::expression::dsl::any;
    let ref conn = *try!(db_manager::POOL.get());
    let image_collection_ids = ImagesCollection::belonging_to(image)
        .select(images_collections::collection_id);
    Ok(try!(collections::table
                .filter(collections::id.eq(any(image_collection_ids)))
                .load::<Collection>(conn)))
}

#[cfg(test)]
mod tests {
    use super::*;
    use models::NewRawImage;
    use super::super::raw_image_service;
    use diesel::pg::data_types::PgDate;

    #[test]
    fn test_create() {
        // create raw image
        let image = b"Hello, wurst!";
        let raw_img = NewRawImage {
            user_id: 999,
            camera: "megapixelzoom",
            latitude: 0.22,
            longitude: 0.32,
            creation: PgDate(0),
        };
        let raw = match raw_image_service::create(&raw_img, image) {
            Ok(i) => i,
            Err(x) => {
                println!("err: {}", x);
                panic!();
            }
        };
        // do the test
        let image = b"Hello, wurst image!";
        let sidecar = b"I am a sidecar file!";
        let test_img = NewImage {
            title: "test image",
            description: "desc of test image",
            license: "MIT",
            side_car_file: "carly",
            raw_image_id: raw.id,
        };
        let img = match create(&test_img, image, sidecar) {
            Ok(i) => i,
            Err(x) => {
                println!("err: {}", x);
                panic!();
            }
        };
        match find(img.id) {
            Ok(i) => {
                let (_, data) = i;
                assert_eq!(image, data.as_slice())
            }
            Err(x) => {
                println!("err: {}", x);
                panic!();
            }
        };
        match find_sidecar(img.id) {
            Ok(i) => {
                let (_, data) = i;
                assert_eq!(sidecar, data.as_slice())
            }
            Err(x) => {
                println!("err: {}", x);
                panic!();
            }
        }

    }
}
<|endoftext|>


<commit_before>// functions5.rs
// Make me compile! Scroll down for hints :)

fn main() {
    let answer = square(3);
    println!("The answer is {}", answer);
}

fn square(num: i32) -> i32 {
    num * num;
}

// This is a really common error that can be fixed by removing one character.
// It happens because Rust distinguishes between expressions and statements: expressions return
// a value based on its operand and statements simply retun a `()` type which just like `void` in C/C++ language.
// We want to return a value of `i32` type from the `square` function, but it is returning a `()` type...
// They are not the same. There are two solusions:
// 1. Add a `return` ahead of `num * num;`
// 2. remove `;`, make it to be `num * num`
<commit_msg>Update functions5.rs<commit_after>// functions5.rs
// Make me compile! Scroll down for hints :)

fn main() {
    let answer = square(3);
    println!("The answer is {}", answer);
}

fn square(num: i32) -> i32 {
    num * num;
}

// This is a really common error that can be fixed by removing one character.
// It happens because Rust distinguishes between expressions and statements: expressions return
// a value based on its operand, and statements simply retun a () type which behaves just like `void` in C/C++ language.
// We want to return a value of `i32` type from the `square` function, but it is returning a `()` type...
// They are not the same. There are two solusions:
// 1. Add a `return` ahead of `num * num;`
// 2. remove `;`, make it to be `num * num`
<|endoftext|>


<commit_before>//! Checks that all error codes have at least one test to prevent having error
//! codes that are silently not thrown by the compiler anymore.

use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs::read_to_string;
use std::io::Read;
use std::path::Path;

// A few of those error codes can't be tested but all the others can and *should* be tested!
const WHITELIST: &[&str] = &[
    "E0183",
    "E0227",
    "E0279",
    "E0280",
    "E0311",
    "E0313",
    "E0314",
    "E0315",
    "E0377",
    "E0456",
    "E0461",
    "E0462",
    "E0464",
    "E0465",
    "E0472",
    "E0473",
    "E0474",
    "E0475",
    "E0476",
    "E0479",
    "E0480",
    "E0481",
    "E0482",
    "E0483",
    "E0484",
    "E0485",
    "E0486",
    "E0487",
    "E0488",
    "E0489",
    "E0514",
    "E0519",
    "E0523",
    "E0554",
    "E0570",
    "E0629",
    "E0630",
    "E0640",
    "E0717",
    "E0727",
    "E0729",
];

fn check_error_code_explanation(
    f: &str,
    error_codes: &mut HashMap<String, bool>,
    err_code: String,
) {
    for line in f.lines() {
        let s = line.trim();
        if s.starts_with("```") && s.contains("compile_fail") && s.contains('E') {
            error_codes.insert(err_code, true);
            return;
        } else if s.starts_with("#### Note: this error code is no longer emitted by the compiler") {
            error_codes.get_mut(&err_code).map(|x| *x = true);
            return;
        }
    }
}

macro_rules! some_or_continue {
    ($e:expr) => (
        match $e {
            Some(e) => e,
            None => continue,
        }
    );
}

fn extract_error_codes(f: &str, error_codes: &mut HashMap<String, bool>, path: &Path) {
    let mut reached_no_explanation = false;

    for line in f.lines() {
        let s = line.trim();
        if !reached_no_explanation && s.starts_with('E') && s.contains("include_str!(\"") {
            if let Some(err_code) = s.splitn(2, ':').next() {
                let err_code = err_code.to_owned();
                if !error_codes.contains_key(&err_code) {
                    error_codes.insert(err_code.clone(), false);
                }
                // Now we extract the tests from the markdown file!
                let md = some_or_continue!(s.splitn(2, "include_str!(\"").skip(1).next());
                let md_file_name = some_or_continue!(md.splitn(2, "\")").next());
                let path = some_or_continue!(path.parent()).join(md_file_name);
                match read_to_string(&path) {
                    Ok(content) => {
                        check_error_code_explanation(
                            &content,
                            error_codes,
                            err_code,
                        );
                    }
                    Err(e) => {
                        eprintln!("Couldn't read `{}`: {}", path.display(), e);
                    }
                }
            }
        } else if reached_no_explanation && s.starts_with('E') {
            if let Some(err_code) = s.splitn(2, ',').next() {
                let err_code = err_code.to_owned();
                if !error_codes.contains_key(&err_code) { // this check should *never* fail!
                    error_codes.insert(err_code, false);
                }
            }
        } else if s == ";" {
            reached_no_explanation = true;
        }
    }
}

fn extract_error_codes_from_tests(f: &str, error_codes: &mut HashMap<String, bool>) {
    for line in f.lines() {
        let s = line.trim();
        if s.starts_with("error[E") || s.starts_with("warning[E") {
            if let Some(err_code) = s.splitn(2, ']').next() {
                if let Some(err_code) = err_code.splitn(2, '[').skip(1).next() {
                    let nb = error_codes.entry(err_code.to_owned()).or_insert(false);
                    *nb = true;
                }
            }
        }
    }
}

pub fn check(path: &Path, bad: &mut bool) {
    println!("Checking which error codes lack tests...");
    let mut error_codes: HashMap<String, bool> = HashMap::new();
    super::walk(path,
                &mut |path| super::filter_dirs(path),
                &mut |entry, contents| {
        let file_name = entry.file_name();
        if file_name == "error_codes.rs" {
            extract_error_codes(contents, &mut error_codes, entry.path());
        } else if entry.path().extension() == Some(OsStr::new("stderr")) {
            extract_error_codes_from_tests(contents, &mut error_codes);
        }
    });
    println!("Found {} error codes", error_codes.len());

    let mut errors = Vec::new();
    for (err_code, nb) in &error_codes {
        if !*nb && !WHITELIST.contains(&err_code.as_str()) {
            errors.push(format!("Error code {} needs to have at least one UI test!", err_code));
        }
    }
    errors.sort();
    for err in &errors {
        eprintln!("{}", err);
    }
    println!("Found {} error codes with no tests", errors.len());
    if !errors.is_empty() {
        *bad = true;
    }
    println!("Done!");
}
<commit_msg>tidy: Remove unused import<commit_after>//! Checks that all error codes have at least one test to prevent having error
//! codes that are silently not thrown by the compiler anymore.

use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs::read_to_string;
use std::path::Path;

// A few of those error codes can't be tested but all the others can and *should* be tested!
const WHITELIST: &[&str] = &[
    "E0183",
    "E0227",
    "E0279",
    "E0280",
    "E0311",
    "E0313",
    "E0314",
    "E0315",
    "E0377",
    "E0456",
    "E0461",
    "E0462",
    "E0464",
    "E0465",
    "E0472",
    "E0473",
    "E0474",
    "E0475",
    "E0476",
    "E0479",
    "E0480",
    "E0481",
    "E0482",
    "E0483",
    "E0484",
    "E0485",
    "E0486",
    "E0487",
    "E0488",
    "E0489",
    "E0514",
    "E0519",
    "E0523",
    "E0554",
    "E0570",
    "E0629",
    "E0630",
    "E0640",
    "E0717",
    "E0727",
    "E0729",
];

fn check_error_code_explanation(
    f: &str,
    error_codes: &mut HashMap<String, bool>,
    err_code: String,
) {
    for line in f.lines() {
        let s = line.trim();
        if s.starts_with("```") && s.contains("compile_fail") && s.contains('E') {
            error_codes.insert(err_code, true);
            return;
        } else if s.starts_with("#### Note: this error code is no longer emitted by the compiler") {
            error_codes.get_mut(&err_code).map(|x| *x = true);
            return;
        }
    }
}

macro_rules! some_or_continue {
    ($e:expr) => (
        match $e {
            Some(e) => e,
            None => continue,
        }
    );
}

fn extract_error_codes(f: &str, error_codes: &mut HashMap<String, bool>, path: &Path) {
    let mut reached_no_explanation = false;

    for line in f.lines() {
        let s = line.trim();
        if !reached_no_explanation && s.starts_with('E') && s.contains("include_str!(\"") {
            if let Some(err_code) = s.splitn(2, ':').next() {
                let err_code = err_code.to_owned();
                if !error_codes.contains_key(&err_code) {
                    error_codes.insert(err_code.clone(), false);
                }
                // Now we extract the tests from the markdown file!
                let md = some_or_continue!(s.splitn(2, "include_str!(\"").skip(1).next());
                let md_file_name = some_or_continue!(md.splitn(2, "\")").next());
                let path = some_or_continue!(path.parent()).join(md_file_name);
                match read_to_string(&path) {
                    Ok(content) => {
                        check_error_code_explanation(
                            &content,
                            error_codes,
                            err_code,
                        );
                    }
                    Err(e) => {
                        eprintln!("Couldn't read `{}`: {}", path.display(), e);
                    }
                }
            }
        } else if reached_no_explanation && s.starts_with('E') {
            if let Some(err_code) = s.splitn(2, ',').next() {
                let err_code = err_code.to_owned();
                if !error_codes.contains_key(&err_code) { // this check should *never* fail!
                    error_codes.insert(err_code, false);
                }
            }
        } else if s == ";" {
            reached_no_explanation = true;
        }
    }
}

fn extract_error_codes_from_tests(f: &str, error_codes: &mut HashMap<String, bool>) {
    for line in f.lines() {
        let s = line.trim();
        if s.starts_with("error[E") || s.starts_with("warning[E") {
            if let Some(err_code) = s.splitn(2, ']').next() {
                if let Some(err_code) = err_code.splitn(2, '[').skip(1).next() {
                    let nb = error_codes.entry(err_code.to_owned()).or_insert(false);
                    *nb = true;
                }
            }
        }
    }
}

pub fn check(path: &Path, bad: &mut bool) {
    println!("Checking which error codes lack tests...");
    let mut error_codes: HashMap<String, bool> = HashMap::new();
    super::walk(path,
                &mut |path| super::filter_dirs(path),
                &mut |entry, contents| {
        let file_name = entry.file_name();
        if file_name == "error_codes.rs" {
            extract_error_codes(contents, &mut error_codes, entry.path());
        } else if entry.path().extension() == Some(OsStr::new("stderr")) {
            extract_error_codes_from_tests(contents, &mut error_codes);
        }
    });
    println!("Found {} error codes", error_codes.len());

    let mut errors = Vec::new();
    for (err_code, nb) in &error_codes {
        if !*nb && !WHITELIST.contains(&err_code.as_str()) {
            errors.push(format!("Error code {} needs to have at least one UI test!", err_code));
        }
    }
    errors.sort();
    for err in &errors {
        eprintln!("{}", err);
    }
    println!("Found {} error codes with no tests", errors.len());
    if !errors.is_empty() {
        *bad = true;
    }
    println!("Done!");
}
<|endoftext|>


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

use std::{
    borrow::Cow,
    fmt::Debug,
    io::{Cursor, Write},
};

use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt};
use criterion::{Bencher, Criterion, black_box};
use rand::{RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;

use exonum_crypto::{self, CryptoHash, Hash};
use exonum_merkledb::{proof_map_index::BranchNode, StorageValue};

const CHUNK_SIZE: usize = 64;
const SEED: [u8; 16] = [100; 16];

#[derive(Debug, Clone, Copy, PartialEq)]
struct SampleData {
    id: u16,
    class: i16,
    value: i32,
    hash: Hash,
}

impl StorageValue for SampleData {
    fn into_bytes(self) -> Vec<u8> {
        let mut buffer = vec![0; 40];
        LittleEndian::write_u16(&mut buffer[0..2], self.id);
        LittleEndian::write_i16(&mut buffer[2..4], self.class);
        LittleEndian::write_i32(&mut buffer[4..8], self.value);
        buffer[8..].copy_from_slice(self.hash.as_ref());
        buffer
    }

    fn from_bytes(bytes: Cow<[u8]>) -> Self {
        let id = LittleEndian::read_u16(&bytes[0..2]);
        let class = LittleEndian::read_i16(&bytes[2..4]);
        let value = LittleEndian::read_i32(&bytes[4..8]);
        let hash = Hash::from_slice(&bytes[8..40]).unwrap();
        Self {
            id,
            class,
            value,
            hash,
        }
    }
}

impl CryptoHash for SampleData {
    fn hash(&self) -> Hash {
        exonum_crypto::hash(&self.into_bytes())
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
struct CursorData {
    id: u16,
    class: i16,
    value: i32,
    hash: Hash,
}

impl StorageValue for CursorData {
    fn into_bytes(self) -> Vec<u8> {
        let mut cursor = Cursor::new(vec![0; 40]);
        cursor.write_u16::<LittleEndian>(self.id).unwrap();
        cursor.write_i16::<LittleEndian>(self.class).unwrap();
        cursor.write_i32::<LittleEndian>(self.value).unwrap();
        cursor.write_all(self.hash.as_ref()).unwrap();
        cursor.into_inner()
    }

    fn from_bytes(bytes: Cow<[u8]>) -> Self {
        let mut bytes = bytes.as_ref();
        let id = bytes.read_u16::<LittleEndian>().unwrap();
        let class = bytes.read_i16::<LittleEndian>().unwrap();
        let value = bytes.read_i32::<LittleEndian>().unwrap();
        let hash = Hash::from_slice(bytes).unwrap();
        Self {
            id,
            class,
            value,
            hash,
        }
    }
}

impl CryptoHash for CursorData {
    fn hash(&self) -> Hash {
        exonum_crypto::hash(&self.into_bytes())
    }
}

fn gen_bytes_data() -> Vec<u8> {
    let mut rng = XorShiftRng::from_seed(SEED);
    let mut v = vec![0; CHUNK_SIZE];
    rng.fill_bytes(&mut v);
    v
}

fn gen_sample_data() -> SampleData {
    SampleData {
        id: 1,
        class: -5,
        value: 127,
        hash: exonum_crypto::hash(&[1, 2, 3]),
    }
}

fn gen_cursor_data() -> CursorData {
    CursorData {
        id: 1,
        class: -5,
        value: 127,
        hash: exonum_crypto::hash(&[1, 2, 3]),
    }
}

fn gen_branch_node_data() -> BranchNode {
    BranchNode::empty()
}

fn bench_binary_value<F, V>(c: &mut Criterion, name: &str, f: F)
where
    F: Fn() -> V + 'static + Clone + Copy,
    V: StorageValue + Clone + PartialEq + Debug,
{
    // Checks that binary value is correct.
    let val = f();
    let bytes = val.clone().into_bytes();
    let val2 = V::from_bytes(bytes.into());
    assert_eq!(val, val2);
    // Runs benchmarks.
    c.bench_function(
        &format!("encoding/{}/into_bytes", name),
        move |b: &mut Bencher| {
            b.iter_with_setup(f, |data| black_box(data.into_bytes()));
        },
    );
    c.bench_function(
        &format!("encoding/{}/from_bytes", name),
        move |b: &mut Bencher| {
            b.iter_with_setup(
                || {
                    let val = f();
                    val.into_bytes()
                },
                |bytes| black_box(V::from_bytes(bytes.into())),
            );
        },
    );
    c.bench_function(
        &format!("encoding/{}/hash", name),
        move |b: &mut Bencher| {
            b.iter_with_setup(f, |data| black_box(data.hash()));
        },
    );
}

pub fn bench_encoding(c: &mut Criterion) {
    exonum_crypto::init();

    bench_binary_value(c, "bytes", gen_bytes_data);
    bench_binary_value(c, "sample", gen_sample_data);
    bench_binary_value(c, "cursor", gen_cursor_data);
    bench_binary_value(c, "branch_node", gen_branch_node_data);
}
<commit_msg>Add test for storage keys concatenation<commit_after>// Copyright 2018 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{
    borrow::Cow,
    fmt::Debug,
    io::{Cursor, Write},
};

use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt};
use criterion::{black_box, Bencher, Criterion};
use rand::{RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;

use exonum_crypto::{self, CryptoHash, Hash};
use exonum_merkledb::{
    proof_map_index::{BranchNode, ProofPath},
    StorageKey, StorageValue,
};

const CHUNK_SIZE: usize = 64;
const SEED: [u8; 16] = [100; 16];

#[derive(Debug, Clone, Copy, PartialEq)]
struct SimpleData {
    id: u16,
    class: i16,
    value: i32,
    hash: Hash,
}

impl StorageValue for SimpleData {
    fn into_bytes(self) -> Vec<u8> {
        let mut buffer = vec![0; 40];
        LittleEndian::write_u16(&mut buffer[0..2], self.id);
        LittleEndian::write_i16(&mut buffer[2..4], self.class);
        LittleEndian::write_i32(&mut buffer[4..8], self.value);
        buffer[8..].copy_from_slice(self.hash.as_ref());
        buffer
    }

    fn from_bytes(bytes: Cow<[u8]>) -> Self {
        let id = LittleEndian::read_u16(&bytes[0..2]);
        let class = LittleEndian::read_i16(&bytes[2..4]);
        let value = LittleEndian::read_i32(&bytes[4..8]);
        let hash = Hash::from_slice(&bytes[8..40]).unwrap();
        Self {
            id,
            class,
            value,
            hash,
        }
    }
}

impl CryptoHash for SimpleData {
    fn hash(&self) -> Hash {
        exonum_crypto::hash(&self.into_bytes())
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
struct CursorData {
    id: u16,
    class: i16,
    value: i32,
    hash: Hash,
}

impl StorageValue for CursorData {
    fn into_bytes(self) -> Vec<u8> {
        let mut cursor = Cursor::new(vec![0; 40]);
        cursor.write_u16::<LittleEndian>(self.id).unwrap();
        cursor.write_i16::<LittleEndian>(self.class).unwrap();
        cursor.write_i32::<LittleEndian>(self.value).unwrap();
        cursor.write_all(self.hash.as_ref()).unwrap();
        cursor.into_inner()
    }

    fn from_bytes(bytes: Cow<[u8]>) -> Self {
        let mut bytes = bytes.as_ref();
        let id = bytes.read_u16::<LittleEndian>().unwrap();
        let class = bytes.read_i16::<LittleEndian>().unwrap();
        let value = bytes.read_i32::<LittleEndian>().unwrap();
        let hash = Hash::from_slice(bytes).unwrap();
        Self {
            id,
            class,
            value,
            hash,
        }
    }
}

impl CryptoHash for CursorData {
    fn hash(&self) -> Hash {
        exonum_crypto::hash(&self.into_bytes())
    }
}

fn gen_bytes_data() -> Vec<u8> {
    let mut rng = XorShiftRng::from_seed(SEED);
    let mut v = vec![0; CHUNK_SIZE];
    rng.fill_bytes(&mut v);
    v
}

fn gen_sample_data() -> SimpleData {
    SimpleData {
        id: 1,
        class: -5,
        value: 127,
        hash: exonum_crypto::hash(&[1, 2, 3]),
    }
}

fn gen_cursor_data() -> CursorData {
    CursorData {
        id: 1,
        class: -5,
        value: 127,
        hash: exonum_crypto::hash(&[1, 2, 3]),
    }
}

fn gen_branch_node_data() -> BranchNode {
    BranchNode::empty()
}

fn bench_binary_value<F, V>(c: &mut Criterion, name: &str, f: F)
where
    F: Fn() -> V + 'static + Clone + Copy,
    V: StorageValue + Clone + PartialEq + Debug,
{
    // Checks that binary value is correct.
    let val = f();
    let bytes = val.clone().into_bytes();
    let val2 = V::from_bytes(bytes.into());
    assert_eq!(val, val2);
    // Runs benchmarks.
    c.bench_function(
        &format!("encoding/{}/into_bytes", name),
        move |b: &mut Bencher| {
            b.iter_with_setup(f, |data| black_box(data.into_bytes()));
        },
    );
    c.bench_function(
        &format!("encoding/{}/from_bytes", name),
        move |b: &mut Bencher| {
            b.iter_with_setup(
                || {
                    let val = f();
                    val.into_bytes()
                },
                |bytes| black_box(V::from_bytes(bytes.into())),
            );
        },
    );
    c.bench_function(
        &format!("encoding/{}/hash", name),
        move |b: &mut Bencher| {
            b.iter_with_setup(f, |data| black_box(data.hash()));
        },
    );
}

fn bench_storage_key_concat(b: &mut Bencher) {
    b.iter_with_setup(
        || ("prefixed.key", Hash::zero(), ProofPath::new(&Hash::zero())),
        |(prefix, key, path)| {
            let mut v = vec![0; prefix.size() + key.size() + path.size()];
            let mut pos = 0;
            prefix.write(&mut v[pos..pos + prefix.size()]);
            pos += prefix.size();
            key.write(&mut v[pos..pos + key.size()]);
            pos += key.size();
            path.write(&mut v[pos..pos + path.size()]);
            black_box(v);
        },
    );
}

pub fn bench_encoding(c: &mut Criterion) {
    exonum_crypto::init();
    bench_binary_value(c, "bytes", gen_bytes_data);
    bench_binary_value(c, "simple", gen_sample_data);
    bench_binary_value(c, "cursor", gen_cursor_data);
    bench_binary_value(c, "branch_node", gen_branch_node_data);
    c.bench_function("encoding/storage_key/concat", bench_storage_key_concat);
}
<|endoftext|>


<commit_before>// Reference: http://www.redblobgames.com/pathfinding/a-star/introduction.html

use std::collections::BinaryHeap;
use std::collections::HashMap;
use std::cmp::Ordering;
use std::cmp;

#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct Position {
    pub x: usize,
    pub y: usize
}

// Used to maintain a priority queue of positions to explore.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
struct PositionPriority {
    minimum_cost: usize,
    position: Position,
}

// The priority queue depends on `Ord`.
impl Ord for PositionPriority {
    // Reverse the comparison so the position with the lowest cost is
    // explored first.
    fn cmp(&self, other: &PositionPriority) -> Ordering {
        other.minimum_cost.cmp(&self.minimum_cost)
    }
}

impl PartialOrd for PositionPriority {
    fn partial_cmp(&self, other: &PositionPriority) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

#[inline]
fn min_distance_heuristic(p1: Position, p2: Position) -> usize {
    let x_diff = match p1.x > p2.x {
        true => p1.x - p2.x,
        false => p2.x - p1.x,
    };
    let y_diff = match p1.y > p2.y {
        true => p1.y - p2.y,
        false => p2.y - p1.y,
    };

    x_diff + y_diff
}

#[inline]
fn neighbours(grid: &Vec<Vec<char>>, pos: Position) -> Vec<Position> {
    let mut v = Vec::new();

    if pos.x > 0 && grid[pos.y][pos.x-1] == ' ' {
        v.push(Position{x: pos.x-1, y: pos.y});
    }
    if pos.x + 1 < grid[pos.y].len() && grid[pos.y][pos.x+1] == ' ' {
        v.push(Position{x: pos.x+1, y: pos.y});
    }

    if pos.y > 0 && pos.x < grid[pos.y-1].len() && grid[pos.y-1][pos.x] == ' ' {
        v.push(Position{x: pos.x, y: pos.y-1});
    }
    if pos.y + 1 < grid.len() &&
       pos.x < grid[pos.y+1].len() &&
       grid[pos.y+1][pos.x] == ' ' {
        v.push(Position{x: pos.x, y: pos.y+1});
    }
    v
}

/// Generate the optimal path from start to goal given a mapping from positions
/// to the position that lead to that position.
#[inline]
fn reconstruct(came_from: &HashMap<Position, Position>,
               start: Position,
               goal: Position) -> Vec<Position> {
    let mut current = goal;
    let mut path = vec![current];
    while current != start {
        current = came_from[&current];
        path.push(current);
    }
    path.reverse();
    path
}

/// Find the optimal path from a starting position to a goal position. Return
/// None if no path is possible. The input grid is a 2-dimensional grid of
/// characters. Any character other than a space is considered an impassable
/// obstacle.
///
/// # Examples
///
/// ```
/// use bestpath::{find_path, Position};
///
/// let grid = vec![vec![' ', '*', '*', ' '],
///                 vec![' ', ' ', ' ', '*'],
///                 vec!['*', '*', ' ', ' '],
///                 vec![' ', '*', ' ', ' ']];
/// assert_eq!(Some(vec![Position{x: 0, y: 0},
///                      Position{x: 0, y: 1},
///                      Position{x: 1, y: 1},
///                      Position{x: 2, y: 1},
///                      Position{x: 2, y: 2}]),
///            find_path(&grid, Position{x: 0, y: 0}, Position{x: 2, y: 2}));
/// assert_eq!(None,
///            find_path(&grid, Position{x: 0, y: 0}, Position{x: 3, y: 0}));
/// ```
#[inline]
pub fn find_path(grid: &Vec<Vec<char>>, start: Position, goal: Position)
        -> Option<Vec<Position>>  {
    let mut frontier = BinaryHeap::new();
    frontier.push(PositionPriority { minimum_cost: 0, position: start });

    let mut came_from = HashMap::new();
    let mut cost_so_far = HashMap::new();
    cost_so_far.insert(start, 0);

    while let Some(PositionPriority { minimum_cost, position }) =
            frontier.pop() {
        if position == goal {
            return Some(reconstruct(&came_from, start, goal));
        }
        let cost = cost_so_far[&position];

        for next_position in neighbours(grid, position) {
            let new_cost = cost + 1;
            if let Some(existing_cost) = cost_so_far.get(&next_position) {
                if new_cost >= *existing_cost {
                    continue;
                }
            }
            cost_so_far.insert(next_position, new_cost);
            frontier.push(PositionPriority {
                minimum_cost: new_cost +
                    min_distance_heuristic(goal, next_position),
                position: next_position });
            came_from.insert(next_position, position);
        }
    }
    None
}

/// Generate a copy of the given grid with the path filled in. The starting
/// position is shown with a '@' , the goal postiion with a 'X' and all other
/// points on the path with a 'o'.
///
/// # Examples
///
/// ```
/// use bestpath::{find_path, format_path_map, Position};
///
/// let grid = vec![vec![' ', ' ', ' ', ' '],
///                 vec![' ', '*', ' ', '*'],
///                 vec!['*', '*', ' ', ' '],
///                 vec![' ', '*', ' ', ' ']];
/// let path = find_path(&grid,
///                      Position{x: 0, y: 1},
///                      Position{x: 3, y: 2}).unwrap();
/// assert_eq!(vec![vec!['o', 'o', 'o', ' '],
///                 vec!['@', '*', 'o', '*'],
///                 vec!['*', '*', 'o', 'X'],
///                 vec![' ', '*', ' ', ' ']],
///            format_path_map(&grid, &path));
/// ```
#[inline]
pub fn format_path_map(grid: &Vec<Vec<char>>, path: &Vec<Position>)
        -> Vec<Vec<char>> {
    let mut m = grid.clone();
    let last_path = path.len() - 1;
    for (i, p) in path.iter().enumerate() {
        m[p.y][p.x] = match i {
            0 => '@',
            _ if i == last_path => 'X',
            _ => 'o',
        }
    }
    m
}

#[allow(dead_code)]
fn print_grid(grid: &Vec<Vec<char>>) {
    println!("");
    for row in grid {
        for ch in row {
            print!(" {} ", ch);
        }
        println!("");
    }
}

#[test]
fn no_path() {
    let map =
        vec![vec![' ', ' ', '█', ' ', ' ', ' ', ' '],
             vec!['█', '█', ' ', ' ', '█', '█', ' '],
             vec![' ', '█', ' ', '█', '█', ' ', '█'],
             vec![' ', ' ', ' ', '█', ' ', '█', ' '],
             vec!['█', ' ', ' ', ' ', ' ', '█', ' '],
             vec![' ', '█', '█', '█', '█', ' ', ' '],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' ']];

    let path = find_path(&map, Position { x: 0, y: 0}, Position { x: 6, y: 6});
    assert_eq!(None, path);
}

#[test]
fn multiple_complex_paths_to_goal() {
    let map =
        vec![vec![' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec![' ', '█', '█', '█', '█', ' ', ' '],
             vec![' ', ' ', ' ', '█', '█', ' ', '█'],
             vec![' ', '█', ' ', '█', ' ', ' ', ' '],
             vec![' ', '█', ' ', '█', ' ', ' ', '█'],
             vec![' ', ' ', ' ', '█', ' ', ' ', ' '],
             vec![' ', '█', ' ', ' ', ' ', '█', ' '],
             vec![' ', ' ', ' ', ' ', ' ', '█', ' '],
             vec![' ', ' ', ' ', ' ', '█', ' ', ' ']];

    let path = find_path(&map,
                         Position { x: 0, y: 0},
                         Position { x: 6, y: 8}).unwrap();
    let path_map = format_path_map(&map, &path);
    print_grid(&path_map);
    assert_eq!(
        vec![vec!['@', 'o', 'o', 'o', 'o', 'o', ' '],
             vec![' ', '█', '█', '█', '█', 'o', ' '],
             vec![' ', ' ', ' ', '█', '█', 'o', '█'],
             vec![' ', '█', ' ', '█', ' ', 'o', ' '],
             vec![' ', '█', ' ', '█', ' ', 'o', '█'],
             vec![' ', ' ', ' ', '█', ' ', 'o', 'o'],
             vec![' ', '█', ' ', ' ', ' ', '█', 'o'],
             vec![' ', ' ', ' ', ' ', ' ', '█', 'o'],
             vec![' ', ' ', ' ', ' ', '█', ' ', 'X']],
        path_map);
}

#[test]
fn verticle_map() {
    let map =
        vec![vec![' '],
             vec![' '],
             vec![' '],
             vec![' ']];

    let path = find_path(&map,
                         Position { x: 0, y: 0},
                         Position { x: 0, y: 3}).unwrap();
    let path_map = format_path_map(&map, &path);
    print_grid(&path_map);
    assert_eq!(
        vec![vec!['@'],
             vec!['o'],
             vec!['o'],
             vec!['X']],
        path_map);
}

#[test]
fn horizontal_map() {
    let map =
        vec![vec![' ', ' ', ' ', ' ']];

    let path = find_path(&map,
                         Position { x: 0, y: 0},
                         Position { x: 3, y: 0}).unwrap();
    let path_map = format_path_map(&map, &path);
    print_grid(&path_map);
    assert_eq!(
        vec![vec!['@', 'o', 'o', 'X']],
        path_map);
}

#[test]
fn start_at_goal() {
    let map =
        vec![vec![' ', ' ', ' ', ' ']];

    let path = find_path(&map,
                         Position { x: 0, y: 0},
                         Position { x: 0, y: 0}).unwrap();
    assert_eq!(vec![Position{x: 0, y: 0 }], path);
}

#[test]
fn straight_diagonal_to_goal() {
    let map =
        vec![vec![' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' ']];

    let path = find_path(&map,
                         Position { x: 0, y: 0},
                         Position { x: 6, y: 6}).unwrap();
    let path_map = format_path_map(&map, &path);
    print_grid(&path_map);
    assert_eq!(13, path.len())  // There are many equivalent paths.
}

#[test]
fn single_walled_path_to_goal() {
    let map =
        vec![vec![' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec!['█', '█', '█', '█', '█', '█', ' '],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec![' ', '█', '█', '█', '█', '█', '█'],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec!['█', '█', '█', '█', '█', '█', ' '],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' ']];

    let path = find_path(&map,
                         Position { x: 0, y: 0},
                         Position { x: 0, y: 6}).unwrap();
    let path_map = format_path_map(&map, &path);
    print_grid(&path_map);
    assert_eq!(
        vec![vec!['@', 'o', 'o', 'o', 'o', 'o', 'o'],
             vec!['█', '█', '█', '█', '█', '█', 'o'],
             vec!['o', 'o', 'o', 'o', 'o', 'o', 'o'],
             vec!['o', '█', '█', '█', '█', '█', '█'],
             vec!['o', 'o', 'o', 'o', 'o', 'o', 'o'],
             vec!['█', '█', '█', '█', '█', '█', 'o'],
             vec!['X', 'o', 'o', 'o', 'o', 'o', 'o']],
        path_map);
}

#[test]
fn spiral_wall_path_to_goal() {
    let map =
        vec![vec![' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec![' ', '█', '█', '█', '█', '█', '█', '█'],
             vec![' ', '█', ' ', ' ', ' ', ' ', ' ', ' '],
             vec![' ', '█', ' ', '█', '█', '█', '█', ' '],
             vec![' ', '█', ' ', '█', ' ', ' ', '█', ' '],
             vec![' ', '█', ' ', '█', '█', ' ', '█', ' '],
             vec![' ', '█', ' ', ' ', ' ', ' ', '█', ' '],
             vec![' ', '█', '█', '█', '█', '█', '█', ' '],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']];

    let path = find_path(&map,
                         Position { x: 0, y: 0},
                         Position { x: 4, y: 4}).unwrap();
    let path_map = format_path_map(&map, &path);
    print_grid(&path_map);
    assert_eq!(
        vec![vec!['@', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec!['o', '█', '█', '█', '█', '█', '█', '█'],
             vec!['o', '█', 'o', 'o', 'o', 'o', 'o', 'o'],
             vec!['o', '█', 'o', '█', '█', '█', '█', 'o'],
             vec!['o', '█', 'o', '█', 'X', 'o', '█', 'o'],
             vec!['o', '█', 'o', '█', '█', 'o', '█', 'o'],
             vec!['o', '█', 'o', 'o', 'o', 'o', '█', 'o'],
             vec!['o', '█', '█', '█', '█', '█', '█', 'o'],
             vec!['o', 'o', 'o', 'o', 'o', 'o', 'o', 'o']],
        path_map);
}
<commit_msg>Add some documentation<commit_after>// Reference: http://www.redblobgames.com/pathfinding/a-star/introduction.html

use std::collections::BinaryHeap;
use std::collections::HashMap;
use std::cmp::Ordering;
use std::cmp;

#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct Position {
    pub x: usize,
    pub y: usize
}

// Used to maintain a priority queue of positions to explore.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
struct PositionPriority {
    minimum_cost: usize,
    position: Position,
}

// The priority queue depends on `Ord`.
impl Ord for PositionPriority {
    // Reverse the comparison so the position with the lowest cost is
    // explored first.
    fn cmp(&self, other: &PositionPriority) -> Ordering {
        other.minimum_cost.cmp(&self.minimum_cost)
    }
}

impl PartialOrd for PositionPriority {
    fn partial_cmp(&self, other: &PositionPriority) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

#[inline]
fn min_distance_heuristic(p1: Position, p2: Position) -> usize {
    let x_diff = match p1.x > p2.x {
        true => p1.x - p2.x,
        false => p2.x - p1.x,
    };
    let y_diff = match p1.y > p2.y {
        true => p1.y - p2.y,
        false => p2.y - p1.y,
    };

    x_diff + y_diff  // Since diagonal moves aren't allowed.
}

/// Return the navigable neighbouring cells to the given one.
#[inline]
fn neighbours(grid: &Vec<Vec<char>>, pos: Position) -> Vec<Position> {
    let mut v = Vec::new();

    if pos.x > 0 && grid[pos.y][pos.x-1] == ' ' {
        v.push(Position{x: pos.x-1, y: pos.y});
    }
    if pos.x + 1 < grid[pos.y].len() && grid[pos.y][pos.x+1] == ' ' {
        v.push(Position{x: pos.x+1, y: pos.y});
    }

    if pos.y > 0 && pos.x < grid[pos.y-1].len() && grid[pos.y-1][pos.x] == ' ' {
        v.push(Position{x: pos.x, y: pos.y-1});
    }
    if pos.y + 1 < grid.len() &&
       pos.x < grid[pos.y+1].len() &&
       grid[pos.y+1][pos.x] == ' ' {
        v.push(Position{x: pos.x, y: pos.y+1});
    }
    v
}

/// Generate the optimal path from start to goal given a mapping from positions
/// to the position that lead to that position.
#[inline]
fn reconstruct(came_from: &HashMap<Position, Position>,
               start: Position,
               goal: Position) -> Vec<Position> {
    let mut current = goal;
    let mut path = vec![current];
    while current != start {
        current = came_from[&current];
        path.push(current);
    }
    path.reverse();
    path
}

/// Find the optimal path from a starting position to a goal position. Return
/// None if no path is possible. The input grid is a 2-dimensional grid of
/// characters. Any character other than a space is considered an impassable
/// obstacle.
///
/// # Examples
///
/// ```
/// use bestpath::{find_path, Position};
///
/// let grid = vec![vec![' ', '*', '*', ' '],
///                 vec![' ', ' ', ' ', '*'],
///                 vec!['*', '*', ' ', ' '],
///                 vec![' ', '*', ' ', ' ']];
/// assert_eq!(Some(vec![Position{x: 0, y: 0},
///                      Position{x: 0, y: 1},
///                      Position{x: 1, y: 1},
///                      Position{x: 2, y: 1},
///                      Position{x: 2, y: 2}]),
///            find_path(&grid, Position{x: 0, y: 0}, Position{x: 2, y: 2}));
/// assert_eq!(None,
///            find_path(&grid, Position{x: 0, y: 0}, Position{x: 3, y: 0}));
/// ```
#[inline]
pub fn find_path(grid: &Vec<Vec<char>>, start: Position, goal: Position)
        -> Option<Vec<Position>>  {
    let mut frontier = BinaryHeap::new();
    frontier.push(PositionPriority { minimum_cost: 0, position: start });

    let mut came_from = HashMap::new();
    let mut cost_so_far = HashMap::new();
    cost_so_far.insert(start, 0);

    while let Some(PositionPriority { minimum_cost, position }) =
            frontier.pop() {
        if position == goal {
            return Some(reconstruct(&came_from, start, goal));
        }
        let cost = cost_so_far[&position];

        for next_position in neighbours(grid, position) {
            let new_cost = cost + 1;
            if let Some(existing_cost) = cost_so_far.get(&next_position) {
                if new_cost >= *existing_cost {
                    continue;
                }
            }
            cost_so_far.insert(next_position, new_cost);
            frontier.push(PositionPriority {
                minimum_cost: new_cost +
                    min_distance_heuristic(goal, next_position),
                position: next_position });
            came_from.insert(next_position, position);
        }
    }
    None
}

/// Generate a copy of the given grid with the path filled in. The starting
/// position is shown with a '@' , the goal postiion with a 'X' and all other
/// points on the path with a 'o'.
///
/// # Examples
///
/// ```
/// use bestpath::{find_path, format_path_map, Position};
///
/// let grid = vec![vec![' ', ' ', ' ', ' '],
///                 vec![' ', '*', ' ', '*'],
///                 vec!['*', '*', ' ', ' '],
///                 vec![' ', '*', ' ', ' ']];
/// let path = find_path(&grid,
///                      Position{x: 0, y: 1},
///                      Position{x: 3, y: 2}).unwrap();
/// assert_eq!(vec![vec!['o', 'o', 'o', ' '],
///                 vec!['@', '*', 'o', '*'],
///                 vec!['*', '*', 'o', 'X'],
///                 vec![' ', '*', ' ', ' ']],
///            format_path_map(&grid, &path));
/// ```
#[inline]
pub fn format_path_map(grid: &Vec<Vec<char>>, path: &Vec<Position>)
        -> Vec<Vec<char>> {
    let mut m = grid.clone();
    let last_path = path.len() - 1;
    for (i, p) in path.iter().enumerate() {
        m[p.y][p.x] = match i {
            0 => '@',
            _ if i == last_path => 'X',
            _ => 'o',
        }
    }
    m
}

#[allow(dead_code)]
fn print_grid(grid: &Vec<Vec<char>>) {
    println!("");
    for row in grid {
        for ch in row {
            print!(" {} ", ch);
        }
        println!("");
    }
}

#[test]
fn no_path() {
    let map =
        vec![vec![' ', ' ', '█', ' ', ' ', ' ', ' '],
             vec!['█', '█', ' ', ' ', '█', '█', ' '],
             vec![' ', '█', ' ', '█', '█', ' ', '█'],
             vec![' ', ' ', ' ', '█', ' ', '█', ' '],
             vec!['█', ' ', ' ', ' ', ' ', '█', ' '],
             vec![' ', '█', '█', '█', '█', ' ', ' '],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' ']];

    let path = find_path(&map, Position { x: 0, y: 0}, Position { x: 6, y: 6});
    assert_eq!(None, path);
}

#[test]
fn multiple_complex_paths_to_goal() {
    let map =
        vec![vec![' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec![' ', '█', '█', '█', '█', ' ', ' '],
             vec![' ', ' ', ' ', '█', '█', ' ', '█'],
             vec![' ', '█', ' ', '█', ' ', ' ', ' '],
             vec![' ', '█', ' ', '█', ' ', ' ', '█'],
             vec![' ', ' ', ' ', '█', ' ', ' ', ' '],
             vec![' ', '█', ' ', ' ', ' ', '█', ' '],
             vec![' ', ' ', ' ', ' ', ' ', '█', ' '],
             vec![' ', ' ', ' ', ' ', '█', ' ', ' ']];

    let path = find_path(&map,
                         Position { x: 0, y: 0},
                         Position { x: 6, y: 8}).unwrap();
    let path_map = format_path_map(&map, &path);
    print_grid(&path_map);
    assert_eq!(
        vec![vec!['@', 'o', 'o', 'o', 'o', 'o', ' '],
             vec![' ', '█', '█', '█', '█', 'o', ' '],
             vec![' ', ' ', ' ', '█', '█', 'o', '█'],
             vec![' ', '█', ' ', '█', ' ', 'o', ' '],
             vec![' ', '█', ' ', '█', ' ', 'o', '█'],
             vec![' ', ' ', ' ', '█', ' ', 'o', 'o'],
             vec![' ', '█', ' ', ' ', ' ', '█', 'o'],
             vec![' ', ' ', ' ', ' ', ' ', '█', 'o'],
             vec![' ', ' ', ' ', ' ', '█', ' ', 'X']],
        path_map);
}

#[test]
fn verticle_map() {
    let map =
        vec![vec![' '],
             vec![' '],
             vec![' '],
             vec![' ']];

    let path = find_path(&map,
                         Position { x: 0, y: 0},
                         Position { x: 0, y: 3}).unwrap();
    let path_map = format_path_map(&map, &path);
    print_grid(&path_map);
    assert_eq!(
        vec![vec!['@'],
             vec!['o'],
             vec!['o'],
             vec!['X']],
        path_map);
}

#[test]
fn horizontal_map() {
    let map =
        vec![vec![' ', ' ', ' ', ' ']];

    let path = find_path(&map,
                         Position { x: 0, y: 0},
                         Position { x: 3, y: 0}).unwrap();
    let path_map = format_path_map(&map, &path);
    print_grid(&path_map);
    assert_eq!(
        vec![vec!['@', 'o', 'o', 'X']],
        path_map);
}

#[test]
fn start_at_goal() {
    let map =
        vec![vec![' ', ' ', ' ', ' ']];

    let path = find_path(&map,
                         Position { x: 0, y: 0},
                         Position { x: 0, y: 0}).unwrap();
    assert_eq!(vec![Position{x: 0, y: 0 }], path);
}

#[test]
fn straight_diagonal_to_goal() {
    let map =
        vec![vec![' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' ']];

    let path = find_path(&map,
                         Position { x: 0, y: 0},
                         Position { x: 6, y: 6}).unwrap();
    let path_map = format_path_map(&map, &path);
    print_grid(&path_map);
    assert_eq!(13, path.len())  // There are many equivalent paths.
}

#[test]
fn single_walled_path_to_goal() {
    let map =
        vec![vec![' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec!['█', '█', '█', '█', '█', '█', ' '],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec![' ', '█', '█', '█', '█', '█', '█'],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec!['█', '█', '█', '█', '█', '█', ' '],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' ']];

    let path = find_path(&map,
                         Position { x: 0, y: 0},
                         Position { x: 0, y: 6}).unwrap();
    let path_map = format_path_map(&map, &path);
    print_grid(&path_map);
    assert_eq!(
        vec![vec!['@', 'o', 'o', 'o', 'o', 'o', 'o'],
             vec!['█', '█', '█', '█', '█', '█', 'o'],
             vec!['o', 'o', 'o', 'o', 'o', 'o', 'o'],
             vec!['o', '█', '█', '█', '█', '█', '█'],
             vec!['o', 'o', 'o', 'o', 'o', 'o', 'o'],
             vec!['█', '█', '█', '█', '█', '█', 'o'],
             vec!['X', 'o', 'o', 'o', 'o', 'o', 'o']],
        path_map);
}

#[test]
fn spiral_wall_path_to_goal() {
    let map =
        vec![vec![' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec![' ', '█', '█', '█', '█', '█', '█', '█'],
             vec![' ', '█', ' ', ' ', ' ', ' ', ' ', ' '],
             vec![' ', '█', ' ', '█', '█', '█', '█', ' '],
             vec![' ', '█', ' ', '█', ' ', ' ', '█', ' '],
             vec![' ', '█', ' ', '█', '█', ' ', '█', ' '],
             vec![' ', '█', ' ', ' ', ' ', ' ', '█', ' '],
             vec![' ', '█', '█', '█', '█', '█', '█', ' '],
             vec![' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']];

    let path = find_path(&map,
                         Position { x: 0, y: 0},
                         Position { x: 4, y: 4}).unwrap();
    let path_map = format_path_map(&map, &path);
    print_grid(&path_map);
    assert_eq!(
        vec![vec!['@', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
             vec!['o', '█', '█', '█', '█', '█', '█', '█'],
             vec!['o', '█', 'o', 'o', 'o', 'o', 'o', 'o'],
             vec!['o', '█', 'o', '█', '█', '█', '█', 'o'],
             vec!['o', '█', 'o', '█', 'X', 'o', '█', 'o'],
             vec!['o', '█', 'o', '█', '█', 'o', '█', 'o'],
             vec!['o', '█', 'o', 'o', 'o', 'o', '█', 'o'],
             vec!['o', '█', '█', '█', '█', '█', '█', 'o'],
             vec!['o', 'o', 'o', 'o', 'o', 'o', 'o', 'o']],
        path_map);
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate serde;

fn run_data_url(input: String, expected_mime: Option<String>, expected_body: Option<Vec<u8>>) {
    let url = data_url::DataUrl::process(&input);
    if let Some(expected_mime) = expected_mime {
        let url = url.unwrap();
        let (body, _) = url.decode_to_vec().unwrap();
        if expected_mime == "" {
            assert_eq!(url.mime_type().to_string(), "text/plain;charset=US-ASCII")
        } else {
            assert_eq!(url.mime_type().to_string(), expected_mime)
        }
        if let Some(expected_body) = expected_body {
            assert_eq!(body, expected_body)
        }
    } else if let Ok(url) = url {
        assert!(url.decode_to_vec().is_err(), "{:?}", url.mime_type())
    }
}

fn collect_data_url<F>(add_test: &mut F)
where
    F: FnMut(String, bool, rustc_test::TestFn),
{
    let known_failures = ["data://test:test/,X"];

    #[derive(Deserialize)]
    #[serde(untagged)]
    enum TestCase {
        Two(String, Option<String>),
        Three(String, Option<String>, Vec<u8>),
    };

    let v: Vec<TestCase> = serde_json::from_str(include_str!("data-urls.json")).unwrap();
    for test in v {
        let (input, expected_mime, expected_body) = match test {
            TestCase::Two(i, m) => (i, m, None),
            TestCase::Three(i, m, b) => (i, m, Some(b)),
        };
        let should_panic = known_failures.contains(&&*input);
        add_test(
            format!("data: URL {:?}", input),
            should_panic,
            rustc_test::TestFn::dyn_test_fn(move || {
                run_data_url(input, expected_mime, expected_body)
            }),
        );
    }
}

fn run_base64(input: String, expected: Option<Vec<u8>>) {
    let result = data_url::forgiving_base64::decode_to_vec(input.as_bytes());
    match (result, expected) {
        (Ok(bytes), Some(expected)) => assert_eq!(bytes, expected),
        (Ok(bytes), None) => panic!("Expected error, got {:?}", bytes),
        (Err(e), Some(expected)) => panic!("Expected {:?}, got error {:?}", expected, e),
        (Err(_), None) => {}
    }
}

fn collect_base64<F>(add_test: &mut F)
where
    F: FnMut(String, bool, rustc_test::TestFn),
{
    let known_failures = [];

    let v: Vec<(String, Option<Vec<u8>>)> =
        serde_json::from_str(include_str!("base64.json")).unwrap();
    for (input, expected) in v {
        let should_panic = known_failures.contains(&&*input);
        add_test(
            format!("base64 {:?}", input),
            should_panic,
            rustc_test::TestFn::dyn_test_fn(move || run_base64(input, expected)),
        );
    }
}

fn run_mime(input: String, expected: Option<String>) {
    let result = input.parse::<data_url::mime::Mime>();
    match (result, expected) {
        (Ok(mime), Some(expected)) => assert_eq!(mime.to_string(), expected),
        (Ok(mime), None) => panic!("Expected error, got {:?}", mime),
        (Err(e), Some(expected)) => panic!("Expected {:?}, got error {:?}", expected, e),
        (Err(_), None) => {}
    }
}

fn collect_mime<F>(add_test: &mut F)
where
    F: FnMut(String, bool, rustc_test::TestFn),
{
    let known_failures = [];

    #[derive(Deserialize)]
    #[serde(untagged)]
    enum Entry {
        Comment(String),
        TestCase {
            input: String,
            output: Option<String>,
        },
    }

    let v: Vec<Entry> = serde_json::from_str(include_str!("mime-types.json")).unwrap();
    let v2: Vec<Entry> = serde_json::from_str(include_str!("generated-mime-types.json")).unwrap();
    let entries = v.into_iter().chain(v2);

    let mut last_comment = None;
    for entry in entries {
        let (input, expected) = match entry {
            Entry::TestCase { input, output } => (input, output),
            Entry::Comment(s) => {
                last_comment = Some(s);
                continue;
            }
        };

        let should_panic = known_failures.contains(&&*input);
        add_test(
            if let Some(ref s) = last_comment {
                format!("MIME type {:?} {:?}", s, input)
            } else {
                format!("MIME type {:?}", input)
            },
            should_panic,
            rustc_test::TestFn::dyn_test_fn(move || run_mime(input, expected)),
        );
    }
}

fn main() {
    let mut tests = Vec::new();
    {
        let mut add_one = |name: String, should_panic: bool, run: rustc_test::TestFn| {
            let mut desc = rustc_test::TestDesc::new(rustc_test::DynTestName(name));
            if should_panic {
                desc.should_panic = rustc_test::ShouldPanic::Yes
            }
            tests.push(rustc_test::TestDescAndFn { desc, testfn: run })
        };
        collect_data_url(&mut add_one);
        collect_base64(&mut add_one);
        collect_mime(&mut add_one);
    }
    rustc_test::test_main(&std::env::args().collect::<Vec<_>>(), tests)
}
<commit_msg>Silence only panics that expect panic<commit_after>#[macro_use]
extern crate serde;

fn run_data_url(
    input: String,
    expected_mime: Option<String>,
    expected_body: Option<Vec<u8>>,
    expected_panic: bool,
) {
    let priorhook = std::panic::take_hook();
    std::panic::set_hook(Box::new(move |p| {
        if !expected_panic {
            priorhook(p);
        }
    }));
    let url = data_url::DataUrl::process(&input);
    if let Some(expected_mime) = expected_mime {
        let url = url.unwrap();
        let (body, _) = url.decode_to_vec().unwrap();
        if expected_mime == "" {
            assert_eq!(url.mime_type().to_string(), "text/plain;charset=US-ASCII")
        } else {
            assert_eq!(url.mime_type().to_string(), expected_mime)
        }
        if let Some(expected_body) = expected_body {
            assert_eq!(body, expected_body)
        }
    } else if let Ok(url) = url {
        assert!(url.decode_to_vec().is_err(), "{:?}", url.mime_type())
    }
}

fn collect_data_url<F>(add_test: &mut F)
where
    F: FnMut(String, bool, rustc_test::TestFn),
{
    let known_failures = ["data://test:test/,X"];

    #[derive(Deserialize)]
    #[serde(untagged)]
    enum TestCase {
        Two(String, Option<String>),
        Three(String, Option<String>, Vec<u8>),
    };

    let v: Vec<TestCase> = serde_json::from_str(include_str!("data-urls.json")).unwrap();
    for test in v {
        let (input, expected_mime, expected_body) = match test {
            TestCase::Two(i, m) => (i, m, None),
            TestCase::Three(i, m, b) => (i, m, Some(b)),
        };
        let should_panic = known_failures.contains(&&*input);
        add_test(
            format!("data: URL {:?}", input),
            should_panic,
            rustc_test::TestFn::dyn_test_fn(move || {
                run_data_url(input, expected_mime, expected_body, should_panic)
            }),
        );
    }
}

fn run_base64(input: String, expected: Option<Vec<u8>>) {
    let result = data_url::forgiving_base64::decode_to_vec(input.as_bytes());
    match (result, expected) {
        (Ok(bytes), Some(expected)) => assert_eq!(bytes, expected),
        (Ok(bytes), None) => panic!("Expected error, got {:?}", bytes),
        (Err(e), Some(expected)) => panic!("Expected {:?}, got error {:?}", expected, e),
        (Err(_), None) => {}
    }
}

fn collect_base64<F>(add_test: &mut F)
where
    F: FnMut(String, bool, rustc_test::TestFn),
{
    let known_failures = [];

    let v: Vec<(String, Option<Vec<u8>>)> =
        serde_json::from_str(include_str!("base64.json")).unwrap();
    for (input, expected) in v {
        let should_panic = known_failures.contains(&&*input);
        add_test(
            format!("base64 {:?}", input),
            should_panic,
            rustc_test::TestFn::dyn_test_fn(move || run_base64(input, expected)),
        );
    }
}

fn run_mime(input: String, expected: Option<String>) {
    let result = input.parse::<data_url::mime::Mime>();
    match (result, expected) {
        (Ok(mime), Some(expected)) => assert_eq!(mime.to_string(), expected),
        (Ok(mime), None) => panic!("Expected error, got {:?}", mime),
        (Err(e), Some(expected)) => panic!("Expected {:?}, got error {:?}", expected, e),
        (Err(_), None) => {}
    }
}

fn collect_mime<F>(add_test: &mut F)
where
    F: FnMut(String, bool, rustc_test::TestFn),
{
    let known_failures = [];

    #[derive(Deserialize)]
    #[serde(untagged)]
    enum Entry {
        Comment(String),
        TestCase {
            input: String,
            output: Option<String>,
        },
    }

    let v: Vec<Entry> = serde_json::from_str(include_str!("mime-types.json")).unwrap();
    let v2: Vec<Entry> = serde_json::from_str(include_str!("generated-mime-types.json")).unwrap();
    let entries = v.into_iter().chain(v2);

    let mut last_comment = None;
    for entry in entries {
        let (input, expected) = match entry {
            Entry::TestCase { input, output } => (input, output),
            Entry::Comment(s) => {
                last_comment = Some(s);
                continue;
            }
        };

        let should_panic = known_failures.contains(&&*input);
        add_test(
            if let Some(ref s) = last_comment {
                format!("MIME type {:?} {:?}", s, input)
            } else {
                format!("MIME type {:?}", input)
            },
            should_panic,
            rustc_test::TestFn::dyn_test_fn(move || run_mime(input, expected)),
        );
    }
}

fn main() {
    let mut tests = Vec::new();
    {
        let mut add_one = |name: String, should_panic: bool, run: rustc_test::TestFn| {
            let mut desc = rustc_test::TestDesc::new(rustc_test::DynTestName(name));
            if should_panic {
                desc.should_panic = rustc_test::ShouldPanic::Yes
            }
            tests.push(rustc_test::TestDescAndFn { desc, testfn: run })
        };
        collect_data_url(&mut add_one);
        collect_base64(&mut add_one);
        collect_mime(&mut add_one);
    }
    rustc_test::test_main(&std::env::args().collect::<Vec<_>>(), tests)
}
<|endoftext|>