<commit_before>use crate::error::Error;
use crate::hasher::{Digest, Hasher};
use core::convert::TryFrom;
use generic_array::ArrayLength;

/// Stack allocated multihash storage backend for codes up to 127.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct MultihashArray
where
    Code: MultihashCode,
    Size: ArrayLength<u8>,
{
    code: Code,
    digest: Digest<Size>,
}

impl MultihashArray
where
    Code: MultihashCode,
    Size: ArrayLength<u8>,
{
    /// Create a multihash from a code and a digest.
    pub fn new(code: Code, digest: Digest<Size>) -> Self {
        Self { code, digest }
    }
}

/// Trait for a multihash digest.
pub trait MultihashDigest {
    /// Returns the code of the multihash.
    fn code(&self) -> Code;

    /// Returns the size of the digest.
    fn size(&self) -> u8;

    /// Returns the digest.
    fn digest(&self) -> &[u8];

    /// Reads a multihash from a byte stream.
    #[cfg(feature = "std")]
    fn read<R: std::io::Read>(r: R) -> Result<Self, Error>
    where
        Self: Sized;

    /// Parses a multihash from a bytes.
    #[cfg(feature = "std")]
    fn from_bytes(mut bytes: &[u8]) -> Result<Self, Error>
    where
        Self: Sized,
    {
        Self::read(&mut bytes)
    }

    /// Writes a multihash to a byte stream.
    #[cfg(feature = "std")]
    fn write<W: std::io::Write>(&self, w: W) -> Result<(), Error>;

    /// Returns the bytes of a multihash.
    #[cfg(feature = "std")]
    fn to_bytes(&self) -> Vec<u8> {
        let mut bytes = vec![];
        self.write(&mut bytes)
            .expect("writing to a vec should never fail");
        bytes
    }
}

impl MultihashDigest for MultihashArray
where
    Code: MultihashCode,
    Size: ArrayLength<u8>,
{
    fn code(&self) -> Code {
        self.code
    }

    fn size(&self) -> u8 {
        Size::to_u8()
    }

    fn digest(&self) -> &[u8] {
        self.digest.as_ref()
    }

    #[cfg(feature = "std")]
    fn read<R: std::io::Read>(mut r: R) -> Result<Self, Error>
    where
        Self: Sized,
    {
        let code = read_code(&mut r)?;
        read_mh(r, code)
    }

    #[cfg(feature = "std")]
    fn write<W: std::io::Write>(&self, w: W) -> Result<(), Error> {
        write_mh(w, self)
    }
}

/// Trait to compute the digest of a multihash code.
pub trait MultihashCode: Into<u64> + TryFrom<u64, Error = Error> + Copy {
    /// Multihash type.
    type Multihash: MultihashDigest<Self>;

    /// Returns the size of the digest.
    fn size(&self) -> u8;

    /// Returns the hash of the input.
    fn digest(&self, input: &[u8]) -> Self::Multihash;
}

/// Trait to extend a `Hasher` with support for a code.
pub trait MultihasherCode: Hasher {
    /// The code of the hash function.
    const CODE: Code;

    /// Get the code at runtime.
    fn code(&self) -> Code {
        Self::CODE
    }
}

/// Trait that extends a `Hasher` with support for multihashes.
pub trait Multihasher: MultihasherCode
where
    Code: MultihashCode,
    <Self as Hasher>::Size: ArrayLength<u8>,
{
    /// Returns the multihash of the input.
    fn multi_digest(input: &[u8]) -> MultihashArray<Code, <Self as Hasher>::Size>;

    /// Returns the multihash of the internal state.
    fn multi_sum(self) -> MultihashArray<Code, <Self as Hasher>::Size>;
}

impl<Code, H: MultihasherCode> Multihasher for H
where
    Code: MultihashCode,
    H::Size: ArrayLength<u8>,
{
    fn multi_digest(input: &[u8]) -> MultihashArray<Code, <Self as Hasher>::Size> {
        let digest = <H as Hasher>::digest(input);
        let code = <H as MultihasherCode>::CODE;
        MultihashArray::new(code, digest)
    }

    fn multi_sum(self) -> MultihashArray<Code, <Self as Hasher>::Size> {
        let sum = Hasher::sum(self);
        let code = <H as MultihasherCode>::CODE;
        MultihashArray::new(code, sum)
    }
}

/// Writes the multihash to a byte stream.
#[cfg(feature = "std")]
pub fn write_mh<W, C, D>(mut w: W, mh: &D) -> Result<(), Error>
where
    W: std::io::Write,
    C: MultihashCode,
    D: MultihashDigest<C>,
{
    use unsigned_varint::encode as varint_encode;

    let mut code_buf = varint_encode::u64_buffer();
    let code = varint_encode::u64(mh.code().into(), &mut code_buf);

    let mut size_buf = varint_encode::u8_buffer();
    let size = varint_encode::u8(mh.size(), &mut size_buf);

    w.write_all(code)?;
    w.write_all(size)?;
    w.write_all(mh.digest())?;
    Ok(())
}

/// Reads a code from a byte stream.
#[cfg(feature = "std")]
pub fn read_code<R, C>(mut r: R) -> Result<C, Error>
where
    R: std::io::Read,
    C: MultihashCode,
{
    use unsigned_varint::io::read_u64;
    C::try_from(read_u64(&mut r)?)
}

/// Reads a multihash from a byte stream.
#[cfg(feature = "std")]
pub fn read_mh<R, C, S>(mut r: R, code: C) -> Result<MultihashArray<C, S>, Error>
where
    R: std::io::Read,
    C: MultihashCode,
    S: ArrayLength<u8>,
{
    use generic_array::GenericArray;
    use unsigned_varint::io::read_u64;

    let size = read_u64(&mut r)?;
    if size != S::to_u64() {
        return Err(Error::InvalidSize(size));
    }
    let mut buf = GenericArray::default();
    r.read_exact(&mut buf)?;
    let digest = Digest::new(buf);
    Ok(MultihashArray::new(code, digest))
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::code::Code;
    use crate::hasher_impl::strobe::Strobe256;

    #[test]
    fn roundtrip() {
        let digest = Strobe256::digest(b"hello world");
        let hash = MultihashArray::new(Code::Strobe256, digest);
        let mut buf = [0u8; 35];
        hash.write(&mut buf[..]).unwrap();
        let hash2 = MultihashArray::read(&buf[..]).unwrap();
        assert_eq!(hash, hash2);
    }
}
<commit_msg>Make digest clone.<commit_after>use crate::error::Error;
use crate::hasher::{Digest, Hasher};
use core::convert::TryFrom;
use generic_array::ArrayLength;

/// Stack allocated multihash storage backend for codes up to 127.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct MultihashArray
where
    Code: MultihashCode,
    Size: ArrayLength<u8>,
{
    code: Code,
    digest: Digest<Size>,
}

impl MultihashArray
where
    Code: MultihashCode,
    Size: ArrayLength<u8>,
{
    /// Create a multihash from a code and a digest.
    pub fn new(code: Code, digest: Digest<Size>) -> Self {
        Self { code, digest }
    }
}

/// Trait for a multihash digest.
pub trait MultihashDigest: Clone {
    /// Returns the code of the multihash.
    fn code(&self) -> Code;

    /// Returns the size of the digest.
    fn size(&self) -> u8;

    /// Returns the digest.
    fn digest(&self) -> &[u8];

    /// Reads a multihash from a byte stream.
    #[cfg(feature = "std")]
    fn read<R: std::io::Read>(r: R) -> Result<Self, Error>
    where
        Self: Sized;

    /// Parses a multihash from a bytes.
    #[cfg(feature = "std")]
    fn from_bytes(mut bytes: &[u8]) -> Result<Self, Error>
    where
        Self: Sized,
    {
        Self::read(&mut bytes)
    }

    /// Writes a multihash to a byte stream.
    #[cfg(feature = "std")]
    fn write<W: std::io::Write>(&self, w: W) -> Result<(), Error>;

    /// Returns the bytes of a multihash.
    #[cfg(feature = "std")]
    fn to_bytes(&self) -> Vec<u8> {
        let mut bytes = vec![];
        self.write(&mut bytes)
            .expect("writing to a vec should never fail");
        bytes
    }
}

impl MultihashDigest for MultihashArray
where
    Code: MultihashCode,
    Size: ArrayLength<u8>,
{
    fn code(&self) -> Code {
        self.code
    }

    fn size(&self) -> u8 {
        Size::to_u8()
    }

    fn digest(&self) -> &[u8] {
        self.digest.as_ref()
    }

    #[cfg(feature = "std")]
    fn read<R: std::io::Read>(mut r: R) -> Result<Self, Error>
    where
        Self: Sized,
    {
        let code = read_code(&mut r)?;
        read_mh(r, code)
    }

    #[cfg(feature = "std")]
    fn write<W: std::io::Write>(&self, w: W) -> Result<(), Error> {
        write_mh(w, self)
    }
}

/// Trait to compute the digest of a multihash code.
pub trait MultihashCode: Into<u64> + TryFrom<u64, Error = Error> + Copy {
    /// Multihash type.
    type Multihash: MultihashDigest<Self>;

    /// Returns the size of the digest.
    fn size(&self) -> u8;

    /// Returns the hash of the input.
    fn digest(&self, input: &[u8]) -> Self::Multihash;
}

/// Trait to extend a `Hasher` with support for a code.
pub trait MultihasherCode: Hasher {
    /// The code of the hash function.
    const CODE: Code;

    /// Get the code at runtime.
    fn code(&self) -> Code {
        Self::CODE
    }
}

/// Trait that extends a `Hasher` with support for multihashes.
pub trait Multihasher: MultihasherCode
where
    Code: MultihashCode,
    <Self as Hasher>::Size: ArrayLength<u8>,
{
    /// Returns the multihash of the input.
    fn multi_digest(input: &[u8]) -> MultihashArray<Code, <Self as Hasher>::Size>;

    /// Returns the multihash of the internal state.
    fn multi_sum(self) -> MultihashArray<Code, <Self as Hasher>::Size>;
}

impl<Code, H: MultihasherCode> Multihasher for H
where
    Code: MultihashCode,
    H::Size: ArrayLength<u8>,
{
    fn multi_digest(input: &[u8]) -> MultihashArray<Code, <Self as Hasher>::Size> {
        let digest = <H as Hasher>::digest(input);
        let code = <H as MultihasherCode>::CODE;
        MultihashArray::new(code, digest)
    }

    fn multi_sum(self) -> MultihashArray<Code, <Self as Hasher>::Size> {
        let sum = Hasher::sum(self);
        let code = <H as MultihasherCode>::CODE;
        MultihashArray::new(code, sum)
    }
}

/// Writes the multihash to a byte stream.
#[cfg(feature = "std")]
pub fn write_mh<W, C, D>(mut w: W, mh: &D) -> Result<(), Error>
where
    W: std::io::Write,
    C: MultihashCode,
    D: MultihashDigest<C>,
{
    use unsigned_varint::encode as varint_encode;

    let mut code_buf = varint_encode::u64_buffer();
    let code = varint_encode::u64(mh.code().into(), &mut code_buf);

    let mut size_buf = varint_encode::u8_buffer();
    let size = varint_encode::u8(mh.size(), &mut size_buf);

    w.write_all(code)?;
    w.write_all(size)?;
    w.write_all(mh.digest())?;
    Ok(())
}

/// Reads a code from a byte stream.
#[cfg(feature = "std")]
pub fn read_code<R, C>(mut r: R) -> Result<C, Error>
where
    R: std::io::Read,
    C: MultihashCode,
{
    use unsigned_varint::io::read_u64;
    C::try_from(read_u64(&mut r)?)
}

/// Reads a multihash from a byte stream.
#[cfg(feature = "std")]
pub fn read_mh<R, C, S>(mut r: R, code: C) -> Result<MultihashArray<C, S>, Error>
where
    R: std::io::Read,
    C: MultihashCode,
    S: ArrayLength<u8>,
{
    use generic_array::GenericArray;
    use unsigned_varint::io::read_u64;

    let size = read_u64(&mut r)?;
    if size != S::to_u64() {
        return Err(Error::InvalidSize(size));
    }
    let mut buf = GenericArray::default();
    r.read_exact(&mut buf)?;
    let digest = Digest::new(buf);
    Ok(MultihashArray::new(code, digest))
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::code::Code;
    use crate::hasher_impl::strobe::Strobe256;

    #[test]
    fn roundtrip() {
        let digest = Strobe256::digest(b"hello world");
        let hash = MultihashArray::new(Code::Strobe256, digest);
        let mut buf = [0u8; 35];
        hash.write(&mut buf[..]).unwrap();
        let hash2 = MultihashArray::read(&buf[..]).unwrap();
        assert_eq!(hash, hash2);
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015-2017 The imgui-rs Developers
 * Copyright (C) 2017-2019 Ryan Huang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

use std::time::{Duration, Instant};

use glium::glutin::{self, Api, GlRequest};
use glium::{Display, Surface};
use imgui::{FontGlyphRange, FrameSize, ImFontConfig, ImGui, Ui};
use imgui_glium_renderer::Renderer;

use crate::model::Model;
use crate::update;

const FRAME_DURATION: Duration = Duration::from_millis(16);

#[derive(Copy, Clone, PartialEq, Debug, Default)]
struct MouseState {
    pos: (i32, i32),
    pressed: (bool, bool, bool),
    wheel: f32,
}

pub fn run<F: FnMut(&mut Model, &Ui, (f32, f32)) -> bool>(
    title: String,
    dimensions: (u32, u32),
    clear_color: [f32; 4],
    mut events_loop: glutin::EventsLoop,
    mut model: Model,
    mut run_ui: F,
) {
    let window = glutin::WindowBuilder::new()
        .with_title(title)
        .with_dimensions(dimensions.into());
    let mut context = glutin::ContextBuilder::new().with_vsync(true);
    if cfg!(target_os = "android") {
        // https://github.com/tomaka/android-rs-glue/issues/153#issuecomment-318348732
        // On Android we must specify an OpenGL ES version or glutin will assume we are using an
        // unsupported version and panic
        context = context.with_gl(GlRequest::Specific(Api::OpenGlEs, (2, 0)));
    }

    let display = Display::new(window, context, &events_loop).unwrap();
    let gl_window = display.gl_window();

    let mut imgui = ImGui::init();
    unsafe {
        imgui::sys::igStyleColorsClassic(imgui.style_mut());
    }
    imgui.set_ini_filename(None);

    let config = ImFontConfig::new()
        .oversample_h(4)
        .oversample_v(4)
        .size_pixels(21.0)
        .rasterizer_multiply(1.05);

    config.add_font(
        &mut imgui.fonts(),
        include_bytes!("../../assets/FiraSans-Regular.ttf"),
        &FontGlyphRange::default(),
    );

    let mut renderer = Renderer::init(&mut imgui, &display).expect("Failed to initialize renderer");

    let mut last_frame = Instant::now();
    let mut mouse_state = MouseState::default();

    let mut render = |model: &mut Model, imgui: &mut ImGui, last_frame: &mut Instant| {
        let now = Instant::now();
        let delta = now - *last_frame;
        let delta_s = delta.as_secs() as f32 + delta.subsec_nanos() as f32 / 1_000_000_000.0;
        *last_frame = now;

        let frame_size = FrameSize {
            logical_size: gl_window.get_inner_size().unwrap().into(),
            hidpi_factor: gl_window.get_hidpi_factor(),
        };
        let size_points = (
            (frame_size.logical_size.0 / frame_size.hidpi_factor) as f32,
            (frame_size.logical_size.1 / frame_size.hidpi_factor) as f32,
        );

        let ui = imgui.frame(frame_size, delta_s);
        if !run_ui(model, &ui, size_points) {
            return false;
        }

        let mut target = display.draw();
        target.clear_color(
            clear_color[0],
            clear_color[1],
            clear_color[2],
            clear_color[3],
        );
        renderer.render(&mut target, ui).expect("Rendering failed");
        target.finish().unwrap();
        true
    };

    // Render one frame before the event loop so the screen isn't empty
    render(&mut model, &mut imgui, &mut last_frame);

    events_loop.run_forever(|event| {
        use glium::glutin::ElementState::Pressed;
        use glium::glutin::WindowEvent::*;
        use glium::glutin::{
            ControlFlow, Event, MouseButton, MouseScrollDelta, TouchPhase, VirtualKeyCode,
        };

        if let Event::Awakened = event {
            if Instant::now() - last_frame < FRAME_DURATION {
                // Receive the AI move, and queue the next one (if it's a computer-only game)
                update::update(&mut model, None);
                update::update(&mut model, None);

                // If the AI is moving very quickly, then the last move of the game will be
                // throttled and not receive a render. This appears to "freeze" the game. So, we
                // render if the game is finished.
                if model.is_game_over() && !render(&mut model, &mut imgui, &mut last_frame) {
                    return ControlFlow::Break;
                }
            } else {
                // Receive the AI move, then render
                update::update(&mut model, None);
                if !render(&mut model, &mut imgui, &mut last_frame) {
                    return ControlFlow::Break;
                }
            }
        } else if let Event::Suspended(true) = event {
            // This is so that the AI doesn't run in the background on Android. Technically, we
            // should also call update or render on Suspended(false) to restart the AI, but there's
            // no point since the app crashes when it's resumed or even right after it's suspended.
            model.ai.stop();
        } else if let Event::WindowEvent { event, .. } = event {
            match event {
                CloseRequested => return ControlFlow::Break,
                KeyboardInput { input, .. } => {
                    if let Some(VirtualKeyCode::Q) = input.virtual_keycode {
                        if cfg!(target_os = "macos") && input.modifiers.logo {
                            return ControlFlow::Break;
                        }
                    }
                }
                Refresh | Resized(_) | HiDpiFactorChanged(_) => {
                    if !render(&mut model, &mut imgui, &mut last_frame) {
                        return ControlFlow::Break;
                    }
                }
                CursorMoved { position, .. } => {
                    mouse_state.pos = position.into();
                    update_mouse(&mut imgui, &mut mouse_state);

                    if Instant::now() - last_frame < FRAME_DURATION {
                        return ControlFlow::Continue;
                    } else if !render(&mut model, &mut imgui, &mut last_frame) {
                        return ControlFlow::Break;
                    }
                }
                MouseWheel {
                    delta,
                    phase: TouchPhase::Moved,
                    ..
                } => {
                    mouse_state.wheel = match delta {
                        MouseScrollDelta::LineDelta(_, y) => y,
                        MouseScrollDelta::PixelDelta(position) => position.y as f32,
                    };
                    update_mouse(&mut imgui, &mut mouse_state);

                    if !render(&mut model, &mut imgui, &mut last_frame) {
                        return ControlFlow::Break;
                    }
                }
                MouseInput { state, button, .. } => {
                    if MouseButton::Left == button {
                        mouse_state.pressed.0 = state == Pressed;
                        update_mouse(&mut imgui, &mut mouse_state);

                        // Render twice to immediately show the results of the click
                        if !render(&mut model, &mut imgui, &mut last_frame) {
                            return ControlFlow::Break;
                        }
                        if !render(&mut model, &mut imgui, &mut last_frame) {
                            return ControlFlow::Break;
                        }
                    }
                }
                Touch(glutin::Touch {
                    phase, location, ..
                }) => {
                    mouse_state.pos = location.into();
                    mouse_state.pressed.0 =
                        phase == TouchPhase::Started || phase == TouchPhase::Moved;
                    update_mouse(&mut imgui, &mut mouse_state);

                    match phase {
                        TouchPhase::Moved => {
                            if Instant::now() - last_frame < FRAME_DURATION {
                                return ControlFlow::Continue;
                            } else if !render(&mut model, &mut imgui, &mut last_frame) {
                                return ControlFlow::Break;
                            }
                        }
                        _ => {
                            // Render twice to immediately show the results of the touch
                            if !render(&mut model, &mut imgui, &mut last_frame) {
                                return ControlFlow::Break;
                            }
                            if !render(&mut model, &mut imgui, &mut last_frame) {
                                return ControlFlow::Break;
                            }
                        }
                    }
                }
                _ => (),
            }
        }
        ControlFlow::Continue
    });
}

fn update_mouse(imgui: &mut ImGui, mouse_state: &mut MouseState) {
    let scale = imgui.display_framebuffer_scale();
    imgui.set_mouse_pos(
        mouse_state.pos.0 as f32 / scale.0,
        mouse_state.pos.1 as f32 / scale.1,
    );
    imgui.set_mouse_down([
        mouse_state.pressed.0,
        mouse_state.pressed.1,
        mouse_state.pressed.2,
        false,
        false,
    ]);
    imgui.set_mouse_wheel(mouse_state.wheel / scale.1);
    mouse_state.wheel = 0.0;
}
<commit_msg>Use logical pixels<commit_after>/*
 * Copyright (C) 2015-2017 The imgui-rs Developers
 * Copyright (C) 2017-2019 Ryan Huang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

use std::time::{Duration, Instant};

use glium::glutin::{self, Api, GlRequest};
use glium::{Display, Surface};
use imgui::{FontGlyphRange, FrameSize, ImFontConfig, ImGui, Ui};
use imgui_glium_renderer::Renderer;

use crate::model::Model;
use crate::update;

const FRAME_DURATION: Duration = Duration::from_millis(16);

#[derive(Copy, Clone, PartialEq, Debug, Default)]
struct MouseState {
    pos: (f64, f64),
    pressed: (bool, bool, bool),
    wheel: f32,
}

pub fn run<F: FnMut(&mut Model, &Ui, (f32, f32)) -> bool>(
    title: String,
    dimensions: (u32, u32),
    clear_color: [f32; 4],
    mut events_loop: glutin::EventsLoop,
    mut model: Model,
    mut run_ui: F,
) {
    let window = glutin::WindowBuilder::new()
        .with_title(title)
        .with_dimensions(dimensions.into());
    let mut context = glutin::ContextBuilder::new().with_vsync(true);
    if cfg!(target_os = "android") {
        // https://github.com/tomaka/android-rs-glue/issues/153#issuecomment-318348732
        // On Android we must specify an OpenGL ES version or glutin will assume we are using an
        // unsupported version and panic
        context = context.with_gl(GlRequest::Specific(Api::OpenGlEs, (2, 0)));
    }

    let display = Display::new(window, context, &events_loop).unwrap();
    let gl_window = display.gl_window();

    let mut imgui = ImGui::init();
    unsafe {
        imgui::sys::igStyleColorsClassic(imgui.style_mut());
    }
    imgui.set_ini_filename(None);

    let config = ImFontConfig::new()
        .oversample_h(4)
        .oversample_v(4)
        .size_pixels(21.0)
        .rasterizer_multiply(1.05);

    config.add_font(
        &mut imgui.fonts(),
        include_bytes!("../../assets/FiraSans-Regular.ttf"),
        &FontGlyphRange::default(),
    );

    let mut renderer = Renderer::init(&mut imgui, &display).expect("Failed to initialize renderer");

    let mut last_frame = Instant::now();
    let mut mouse_state = MouseState::default();

    let mut render = |model: &mut Model, imgui: &mut ImGui, last_frame: &mut Instant| {
        let now = Instant::now();
        let delta = now - *last_frame;
        let delta_s = delta.as_secs() as f32 + delta.subsec_nanos() as f32 / 1_000_000_000.0;
        *last_frame = now;

        let frame_size = FrameSize {
            logical_size: gl_window.get_inner_size().unwrap().into(),
            hidpi_factor: gl_window.get_hidpi_factor(),
        };

        let ui = imgui.frame(frame_size, delta_s);
        if !run_ui(
            model,
            &ui,
            (
                frame_size.logical_size.0 as f32,
                frame_size.logical_size.1 as f32,
            ),
        ) {
            return false;
        }

        let mut target = display.draw();
        target.clear_color(
            clear_color[0],
            clear_color[1],
            clear_color[2],
            clear_color[3],
        );
        renderer.render(&mut target, ui).expect("Rendering failed");
        target.finish().unwrap();
        true
    };

    // Render one frame before the event loop so the screen isn't empty
    render(&mut model, &mut imgui, &mut last_frame);

    events_loop.run_forever(|event| {
        use glium::glutin::ElementState::Pressed;
        use glium::glutin::WindowEvent::*;
        use glium::glutin::{
            ControlFlow, Event, MouseButton, MouseScrollDelta, TouchPhase, VirtualKeyCode,
        };

        if let Event::Awakened = event {
            if Instant::now() - last_frame < FRAME_DURATION {
                // Receive the AI move, and queue the next one (if it's a computer-only game)
                update::update(&mut model, None);
                update::update(&mut model, None);

                // If the AI is moving very quickly, then the last move of the game will be
                // throttled and not receive a render. This appears to "freeze" the game. So, we
                // render if the game is finished.
                if model.is_game_over() && !render(&mut model, &mut imgui, &mut last_frame) {
                    return ControlFlow::Break;
                }
            } else {
                // Receive the AI move, then render
                update::update(&mut model, None);
                if !render(&mut model, &mut imgui, &mut last_frame) {
                    return ControlFlow::Break;
                }
            }
        } else if let Event::Suspended(true) = event {
            // This is so that the AI doesn't run in the background on Android. Technically, we
            // should also call update or render on Suspended(false) to restart the AI, but there's
            // no point since the app crashes when it's resumed or even right after it's suspended.
            model.ai.stop();
        } else if let Event::WindowEvent { event, .. } = event {
            match event {
                CloseRequested => return ControlFlow::Break,
                KeyboardInput { input, .. } => {
                    if let Some(VirtualKeyCode::Q) = input.virtual_keycode {
                        if cfg!(target_os = "macos") && input.modifiers.logo {
                            return ControlFlow::Break;
                        }
                    }
                }
                Refresh | Resized(_) | HiDpiFactorChanged(_) => {
                    if !render(&mut model, &mut imgui, &mut last_frame) {
                        return ControlFlow::Break;
                    }
                }
                CursorMoved { position, .. } => {
                    mouse_state.pos = position.into();
                    update_mouse(&mut imgui, &mut mouse_state);

                    if Instant::now() - last_frame < FRAME_DURATION {
                        return ControlFlow::Continue;
                    } else if !render(&mut model, &mut imgui, &mut last_frame) {
                        return ControlFlow::Break;
                    }
                }
                MouseWheel {
                    delta,
                    phase: TouchPhase::Moved,
                    ..
                } => {
                    mouse_state.wheel = match delta {
                        MouseScrollDelta::LineDelta(_, y) => y,
                        MouseScrollDelta::PixelDelta(position) => position.y as f32,
                    };
                    update_mouse(&mut imgui, &mut mouse_state);

                    if !render(&mut model, &mut imgui, &mut last_frame) {
                        return ControlFlow::Break;
                    }
                }
                MouseInput { state, button, .. } => {
                    if MouseButton::Left == button {
                        mouse_state.pressed.0 = state == Pressed;
                        update_mouse(&mut imgui, &mut mouse_state);

                        // Render twice to immediately show the results of the click
                        if !render(&mut model, &mut imgui, &mut last_frame) {
                            return ControlFlow::Break;
                        }
                        if !render(&mut model, &mut imgui, &mut last_frame) {
                            return ControlFlow::Break;
                        }
                    }
                }
                Touch(glutin::Touch {
                    phase, location, ..
                }) => {
                    mouse_state.pos = location.into();
                    mouse_state.pressed.0 =
                        phase == TouchPhase::Started || phase == TouchPhase::Moved;
                    update_mouse(&mut imgui, &mut mouse_state);

                    match phase {
                        TouchPhase::Moved => {
                            if Instant::now() - last_frame < FRAME_DURATION {
                                return ControlFlow::Continue;
                            } else if !render(&mut model, &mut imgui, &mut last_frame) {
                                return ControlFlow::Break;
                            }
                        }
                        _ => {
                            // Render twice to immediately show the results of the touch
                            if !render(&mut model, &mut imgui, &mut last_frame) {
                                return ControlFlow::Break;
                            }
                            if !render(&mut model, &mut imgui, &mut last_frame) {
                                return ControlFlow::Break;
                            }
                        }
                    }
                }
                _ => (),
            }
        }
        ControlFlow::Continue
    });
}

fn update_mouse(imgui: &mut ImGui, mouse_state: &mut MouseState) {
    imgui.set_mouse_pos(mouse_state.pos.0 as f32, mouse_state.pos.1 as f32);
    imgui.set_mouse_down([
        mouse_state.pressed.0,
        mouse_state.pressed.1,
        mouse_state.pressed.2,
        false,
        false,
    ]);
    imgui.set_mouse_wheel(mouse_state.wheel);
    mouse_state.wheel = 0.0;
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::path::PathBuf;
use std::path::Path;

use error::*;

#[derive(Debug, Clone)]
pub struct VfsConfig {
	pub mount_points: HashMap<String, PathBuf>,
}

impl VfsConfig {
    pub fn new() -> VfsConfig {
        VfsConfig {
            mount_points: HashMap::new(),
        }
    }
}

pub struct Vfs {
    mount_points: HashMap<String, PathBuf>,
}

impl Vfs {
    pub fn new(config: VfsConfig) -> Vfs {
        Vfs { mount_points: config.mount_points }
    }

    pub fn real_to_virtual(&self, real_path: &Path) -> Result<PathBuf, PError> {
        for (name, target) in &self.mount_points {
            match real_path.strip_prefix(target) {
                Ok(p) => {
                    let mount_path = Path::new(&name);
                    return Ok(mount_path.join(p));
                }
                Err(_) => (),
            }
        }
        Err(PError::PathNotInVfs)
    }

    pub fn virtual_to_real(&self, virtual_path: &Path) -> Result<PathBuf, PError> {
        for (name, target) in &self.mount_points {
            let mount_path = Path::new(&name);
            match virtual_path.strip_prefix(mount_path) {
                Ok(p) => return Ok(target.join(p)),
                Err(_) => (),
            }
        }
        Err(PError::PathNotInVfs)
    }

    pub fn get_mount_points(&self) -> &HashMap<String, PathBuf> {
        return &self.mount_points;
    }
}

#[test]
fn test_virtual_to_real() {
    let mut config = VFSConfig::new();
    config.mount_points.insert("root".to_owned(), Path::new("test_dir").to_path_buf());
    let vfs = Vfs::new(config);

    let correct_path = Path::new("test_dir/somewhere/something.png");
    let found_path = vfs.virtual_to_real(Path::new("root/somewhere/something.png")).unwrap();
    assert!(found_path == correct_path);
}

#[test]
fn test_real_to_virtual() {
    let mut config = VFSConfig::new();
    config.mount_points.insert("root".to_owned(), Path::new("test_dir").to_path_buf());
    let vfs = Vfs::new(config);

    let correct_path = Path::new("root/somewhere/something.png");
    let found_path = vfs.real_to_virtual(Path::new("test_dir/somewhere/something.png")).unwrap();
    assert!(found_path == correct_path);
}
<commit_msg>Fixed test suite<commit_after>use std::collections::HashMap;
use std::path::PathBuf;
use std::path::Path;

use error::*;

#[derive(Debug, Clone)]
pub struct VfsConfig {
	pub mount_points: HashMap<String, PathBuf>,
}

impl VfsConfig {
    pub fn new() -> VfsConfig {
        VfsConfig {
            mount_points: HashMap::new(),
        }
    }
}

pub struct Vfs {
    mount_points: HashMap<String, PathBuf>,
}

impl Vfs {
    pub fn new(config: VfsConfig) -> Vfs {
        Vfs { mount_points: config.mount_points }
    }

    pub fn real_to_virtual(&self, real_path: &Path) -> Result<PathBuf, PError> {
        for (name, target) in &self.mount_points {
            match real_path.strip_prefix(target) {
                Ok(p) => {
                    let mount_path = Path::new(&name);
                    return Ok(mount_path.join(p));
                }
                Err(_) => (),
            }
        }
        Err(PError::PathNotInVfs)
    }

    pub fn virtual_to_real(&self, virtual_path: &Path) -> Result<PathBuf, PError> {
        for (name, target) in &self.mount_points {
            let mount_path = Path::new(&name);
            match virtual_path.strip_prefix(mount_path) {
                Ok(p) => return Ok(target.join(p)),
                Err(_) => (),
            }
        }
        Err(PError::PathNotInVfs)
    }

    pub fn get_mount_points(&self) -> &HashMap<String, PathBuf> {
        return &self.mount_points;
    }
}

#[test]
fn test_virtual_to_real() {
    let mut config = VfsConfig::new();
    config.mount_points.insert("root".to_owned(), Path::new("test_dir").to_path_buf());
    let vfs = Vfs::new(config);

    let correct_path = Path::new("test_dir/somewhere/something.png");
    let found_path = vfs.virtual_to_real(Path::new("root/somewhere/something.png")).unwrap();
    assert!(found_path == correct_path);
}

#[test]
fn test_real_to_virtual() {
    let mut config = VfsConfig::new();
    config.mount_points.insert("root".to_owned(), Path::new("test_dir").to_path_buf());
    let vfs = Vfs::new(config);

    let correct_path = Path::new("root/somewhere/something.png");
    let found_path = vfs.real_to_virtual(Path::new("test_dir/somewhere/something.png")).unwrap();
    assert!(found_path == correct_path);
}
<|endoftext|>


<commit_before>
use iron::{Iron, IronResult, Listening, status};
use iron::error::HttpResult;
use iron::response::Response;
#[cfg(feature = "gzip")]
use iron::response::WriteBody;
use iron::request::Request;
use iron::middleware::Handler;
use iron::mime::Mime;

use sysinfo::{System, SystemExt};

#[cfg(feature = "gzip")]
use flate2::Compression;
#[cfg(feature = "gzip")]
use flate2::write::GzEncoder;

use std::sync::{Arc, Mutex, RwLock};
use std::thread;
use std::time::{Duration, SystemTime};
#[cfg(feature = "gzip")]
use std::io::{self, Write};

use SysinfoExt;
use serde_json;

const INDEX_HTML: &'static [u8] = include_bytes!("index.html");
const FAVICON: &'static [u8] = include_bytes!("../resources/favicon.ico");
const REFRESH_DELAY: u64 = 60 * 10; // 10 minutes

/// Simple wrapper to get gzip compressed output on string types.
#[cfg(feature = "gzip")]
struct GzipContent(Box<WriteBody>);

#[cfg(feature = "gzip")]
impl WriteBody for GzipContent {
    fn write_body(&mut self, w: &mut Write) -> io::Result<()> {
        let mut w = GzEncoder::new(w, Compression::default());
        self.0.write_body(&mut w)?;
        w.finish().map(|_| ())
    }
}

struct SysinfoIronHandler(Arc<DataHandler>);

struct DataHandler {
    system: RwLock<System>,
    last_connection: Mutex<SystemTime>,
    json_output: RwLock<String>,
}

impl DataHandler {
    fn can_update_system_info(&self) -> bool {
        SystemTime::now().duration_since(*self.last_connection.lock().unwrap())
                         .unwrap()
                         .as_secs() < REFRESH_DELAY
    }

    fn update_last_connection(&self) {
        *self.last_connection.lock().unwrap() = SystemTime::now();
    }
}

#[cfg(feature = "gzip")]
macro_rules! return_gzip_or_not {
    ($req:expr, $content:expr, $typ:expr) => {{
        let mut use_gzip = false;

        if let Some(raw_accept_encoding) = $req.headers.get_raw("accept-encoding") {
            for accept_encoding in raw_accept_encoding {
                match ::std::str::from_utf8(accept_encoding).map(|s| s.to_lowercase()) {
                    Ok(ref s) if s.contains("gzip") => {
                        use_gzip = true;
                        break;
                    }
                    _ => continue,
                }
            }
        }
        if !use_gzip {
            Ok(Response::with((status::Ok, $typ.parse::<Mime>().unwrap(), $content)))
        } else {
            use iron::headers::{ContentType, ContentEncoding, Encoding};
            let mut res = Response::new();
            res.status = Some(status::Ok);
            res.body = Some(Box::new(GzipContent(Box::new($content))));
            res.headers.set(ContentType($typ.parse::<Mime>().unwrap()));
            res.headers.set(ContentEncoding(vec![Encoding::Gzip]));
            Ok(res)
        }
    }}
}

#[cfg(not(feature = "gzip"))]
macro_rules! return_gzip_or_not {
    ($req:expr, $content:expr, $typ:expr) => {{
        Ok(Response::with((status::Ok, $typ.parse::<Mime>().unwrap(), $content)))
    }}
}

impl Handler for SysinfoIronHandler {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        match match req.url.path().last() {
            Some(path) => {
                if *path == "" {
                    1
                } else if *path == "favicon.ico" {
                    2
                } else {
                    3
                }
            }
            None => 0,
        } {
            1 => return_gzip_or_not!(req, INDEX_HTML, "text/html"),
            2 => return_gzip_or_not!(req, FAVICON, "image/x-icon"),
            3 => {
                self.0.update_last_connection();
                return_gzip_or_not!(req,
                                    self.0.json_output.read().unwrap().clone(),
                                    "application/json")
            }
            _ => Ok(Response::with((status::NotFound, "Not found"))),
        }
    }
}

pub fn start_web_server(sock_addr: Option<String>) -> HttpResult<Listening> {
    let data_handler = Arc::new(DataHandler {
        system: RwLock::new(System::new()),
        last_connection: Mutex::new(SystemTime::now()),
        json_output: RwLock::new(String::from("[]")),
    });
    let data_handler_clone = data_handler.clone();
    thread::spawn(move || {
        let mut sleeping = false;
        loop {
            if data_handler_clone.can_update_system_info() {
                {
                    let mut system = data_handler_clone.system.write().unwrap();
                    system.refresh_all();
                    // refresh it twice to provide accurate information after wake up
                    if sleeping {
                        system.refresh_all();
                        sleeping = false;
                    }
                    let sysinfo = SysinfoExt::new(&system);
                    let mut json_output = data_handler_clone.json_output.write().unwrap();
                    json_output.clear();
                    use std::fmt::Write;
                    json_output.write_str(&serde_json::to_string(&sysinfo)
                                          .unwrap_or(String::from("[]"))).unwrap();
                }
                thread::sleep(Duration::new(5, 0));
            } else {
                // If we don't need to refresh the system information, we can sleep a lot less.
                thread::sleep(Duration::from_millis(500));
                sleeping = true;
            }
        }
    });
    let mut iron = Iron::new(SysinfoIronHandler(data_handler));
    iron.threads = 4;
    iron.http(sock_addr.unwrap_or("localhost:3000".to_owned()))
}
<commit_msg>add message when server started<commit_after>
use iron::{Iron, IronResult, Listening, status};
use iron::error::HttpResult;
use iron::response::Response;
#[cfg(feature = "gzip")]
use iron::response::WriteBody;
use iron::request::Request;
use iron::middleware::Handler;
use iron::mime::Mime;

use sysinfo::{System, SystemExt};

#[cfg(feature = "gzip")]
use flate2::Compression;
#[cfg(feature = "gzip")]
use flate2::write::GzEncoder;

use std::sync::{Arc, Mutex, RwLock};
use std::thread;
use std::time::{Duration, SystemTime};
#[cfg(feature = "gzip")]
use std::io::{self, Write};

use SysinfoExt;
use serde_json;

const INDEX_HTML: &'static [u8] = include_bytes!("index.html");
const FAVICON: &'static [u8] = include_bytes!("../resources/favicon.ico");
const REFRESH_DELAY: u64 = 60 * 10; // 10 minutes

/// Simple wrapper to get gzip compressed output on string types.
#[cfg(feature = "gzip")]
struct GzipContent(Box<WriteBody>);

#[cfg(feature = "gzip")]
impl WriteBody for GzipContent {
    fn write_body(&mut self, w: &mut Write) -> io::Result<()> {
        let mut w = GzEncoder::new(w, Compression::default());
        self.0.write_body(&mut w)?;
        w.finish().map(|_| ())
    }
}

struct SysinfoIronHandler(Arc<DataHandler>);

struct DataHandler {
    system: RwLock<System>,
    last_connection: Mutex<SystemTime>,
    json_output: RwLock<String>,
}

impl DataHandler {
    fn can_update_system_info(&self) -> bool {
        SystemTime::now().duration_since(*self.last_connection.lock().unwrap())
                         .unwrap()
                         .as_secs() < REFRESH_DELAY
    }

    fn update_last_connection(&self) {
        *self.last_connection.lock().unwrap() = SystemTime::now();
    }
}

#[cfg(feature = "gzip")]
macro_rules! return_gzip_or_not {
    ($req:expr, $content:expr, $typ:expr) => {{
        let mut use_gzip = false;

        if let Some(raw_accept_encoding) = $req.headers.get_raw("accept-encoding") {
            for accept_encoding in raw_accept_encoding {
                match ::std::str::from_utf8(accept_encoding).map(|s| s.to_lowercase()) {
                    Ok(ref s) if s.contains("gzip") => {
                        use_gzip = true;
                        break;
                    }
                    _ => continue,
                }
            }
        }
        if !use_gzip {
            Ok(Response::with((status::Ok, $typ.parse::<Mime>().unwrap(), $content)))
        } else {
            use iron::headers::{ContentType, ContentEncoding, Encoding};
            let mut res = Response::new();
            res.status = Some(status::Ok);
            res.body = Some(Box::new(GzipContent(Box::new($content))));
            res.headers.set(ContentType($typ.parse::<Mime>().unwrap()));
            res.headers.set(ContentEncoding(vec![Encoding::Gzip]));
            Ok(res)
        }
    }}
}

#[cfg(not(feature = "gzip"))]
macro_rules! return_gzip_or_not {
    ($req:expr, $content:expr, $typ:expr) => {{
        Ok(Response::with((status::Ok, $typ.parse::<Mime>().unwrap(), $content)))
    }}
}

impl Handler for SysinfoIronHandler {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        match match req.url.path().last() {
            Some(path) => {
                if *path == "" {
                    1
                } else if *path == "favicon.ico" {
                    2
                } else {
                    3
                }
            }
            None => 0,
        } {
            1 => return_gzip_or_not!(req, INDEX_HTML, "text/html"),
            2 => return_gzip_or_not!(req, FAVICON, "image/x-icon"),
            3 => {
                self.0.update_last_connection();
                return_gzip_or_not!(req,
                                    self.0.json_output.read().unwrap().clone(),
                                    "application/json")
            }
            _ => Ok(Response::with((status::NotFound, "Not found"))),
        }
    }
}

pub fn start_web_server(sock_addr: Option<String>) -> HttpResult<Listening> {
    let data_handler = Arc::new(DataHandler {
        system: RwLock::new(System::new()),
        last_connection: Mutex::new(SystemTime::now()),
        json_output: RwLock::new(String::from("[]")),
    });
    let data_handler_clone = data_handler.clone();
    thread::spawn(move || {
        let mut sleeping = false;
        loop {
            if data_handler_clone.can_update_system_info() {
                {
                    let mut system = data_handler_clone.system.write().unwrap();
                    system.refresh_all();
                    // refresh it twice to provide accurate information after wake up
                    if sleeping {
                        system.refresh_all();
                        sleeping = false;
                    }
                    let sysinfo = SysinfoExt::new(&system);
                    let mut json_output = data_handler_clone.json_output.write().unwrap();
                    json_output.clear();
                    use std::fmt::Write;
                    json_output.write_str(&serde_json::to_string(&sysinfo)
                                          .unwrap_or(String::from("[]"))).unwrap();
                }
                thread::sleep(Duration::new(5, 0));
            } else {
                // If we don't need to refresh the system information, we can sleep a lot less.
                thread::sleep(Duration::from_millis(500));
                sleeping = true;
            }
        }
    });
    let mut iron = Iron::new(SysinfoIronHandler(data_handler));
    iron.threads = 4;
    let ret = iron.http(sock_addr.unwrap_or("localhost:3000".to_owned()));
    if ret.is_ok() {
        println!("Started server on port 3000");
    }
    ret
}
<|endoftext|>


<commit_before>use std::io;
use std::fmt;
use std::error;
use std::vec::Vec;
use byteorder;
use byteorder::{BigEndian,ReadBytesExt,WriteBytesExt};

#[derive(Debug)]
pub enum Error {
	Io(byteorder::Error),
	InvalidValue,
	InvalidType
}

impl From<byteorder::Error> for Error {
	fn from(err: byteorder::Error) -> Error { Error::Io(err) }
}

impl From<Error> for byteorder::Error {
	fn from(err: Error) -> byteorder::Error {
		match err {
			Error::Io(err) => err,
			Error::InvalidValue => byteorder::Error::Io(io::Error::new(io::ErrorKind::Other, "Invalid value")),
			Error::InvalidType => byteorder::Error::Io(io::Error::new(io::ErrorKind::Other, "Invalid type")),
		}
	}
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
	        match *self {
				Error::InvalidValue => write!(f, "Invalid value."),
				Error::InvalidType => write!(f, "Invalid type."),
				Error::Io(ref err) => err.fmt(f),
			}
	}
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::InvalidValue => "Invalid value.",
            Error::InvalidType => "Invalid type.",
            Error::Io(ref err) => error::Error::description(err),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::InvalidValue => None,
            Error::InvalidType => None,
            Error::Io(ref err) => err.cause(),
        }
    }
}

pub struct XdrReader {
	reader : io::Cursor<Vec<u8>>
}

pub struct XdrWriter {
	writer : io::Cursor<Vec<u8>>
}

impl XdrWriter {
	pub fn new() -> XdrWriter {
		let v : Vec<u8>= Vec::new();
		XdrWriter{ writer: io::Cursor::new(v)}
	}

	pub fn get_buffer(self) -> Vec<u8> {
		self.writer.into_inner()
	}

	pub fn pack<T:XdrPrimitive>(&mut self, x:T) {
		XdrPrimitive::write_to_xdr(self, x)
	}

}
pub trait XdrPrimitive {
	fn read_from_xdr(x: &mut XdrReader) -> Result<Self, Error>;
	fn write_to_xdr(x: &mut XdrWriter, v: Self);
}

impl XdrPrimitive for u32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u32, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<byteorder::BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for u16 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u16, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as u16),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<byteorder::BigEndian>(v as u32).unwrap();
	}
}
impl XdrPrimitive for u8 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u8, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as u8),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<byteorder::BigEndian>(v as u32).unwrap();
	}
}
impl XdrPrimitive for i8 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i8, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as i8),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<byteorder::BigEndian>(v as i32).unwrap();
	}
}
impl XdrPrimitive for i16 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i16, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as i16),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<byteorder::BigEndian>(v as i32).unwrap();
	}
}
impl XdrPrimitive for i32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i32, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<byteorder::BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for i64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i64, Error>{
		match x.reader.read_i64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i64::<byteorder::BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for u64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u64, Error>{
		match x.reader.read_u64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u64::<byteorder::BigEndian>(v).unwrap();
	}

}

impl XdrPrimitive for f32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<f32, Error>{
		match x.reader.read_f32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_f32::<byteorder::BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for f64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<f64, Error>{
		match x.reader.read_f64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_f64::<byteorder::BigEndian>(v).unwrap();
	}
}

impl XdrPrimitive for bool {
	fn read_from_xdr(x: &mut XdrReader) -> Result<bool, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(0) => Ok(false),
			Ok(1) => Ok(true),
			Ok(_) => Err(Error::InvalidValue),
			Err(v) => Err(Error::Io(v))
		}
	}

	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		match v {
			true => x.writer.write_u32::<byteorder::BigEndian>(1).unwrap(),
			false => x.writer.write_u32::<byteorder::BigEndian>(0).unwrap(),
		}
	}
}
<commit_msg>Implement XdrReader new and unpack functions for XdrPrimitive<commit_after>use std::io;
use std::fmt;
use std::error;
use std::vec::Vec;
use byteorder;
use byteorder::{BigEndian,ReadBytesExt,WriteBytesExt};

#[derive(Debug)]
pub enum Error {
	Io(byteorder::Error),
	InvalidValue,
	InvalidType
}

impl From<byteorder::Error> for Error {
	fn from(err: byteorder::Error) -> Error { Error::Io(err) }
}

impl From<Error> for byteorder::Error {
	fn from(err: Error) -> byteorder::Error {
		match err {
			Error::Io(err) => err,
			Error::InvalidValue => byteorder::Error::Io(io::Error::new(io::ErrorKind::Other, "Invalid value")),
			Error::InvalidType => byteorder::Error::Io(io::Error::new(io::ErrorKind::Other, "Invalid type")),
		}
	}
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
	        match *self {
				Error::InvalidValue => write!(f, "Invalid value."),
				Error::InvalidType => write!(f, "Invalid type."),
				Error::Io(ref err) => err.fmt(f),
			}
	}
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::InvalidValue => "Invalid value.",
            Error::InvalidType => "Invalid type.",
            Error::Io(ref err) => error::Error::description(err),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::InvalidValue => None,
            Error::InvalidType => None,
            Error::Io(ref err) => err.cause(),
        }
    }
}

pub struct XdrReader {
	reader : io::Cursor<Vec<u8>>
}

pub struct XdrWriter {
	writer : io::Cursor<Vec<u8>>
}

impl XdrWriter {
	pub fn new() -> XdrWriter {
		let v : Vec<u8>= Vec::new();
		XdrWriter{ writer: io::Cursor::new(v)}
	}

	pub fn get_buffer(self) -> Vec<u8> {
		self.writer.into_inner()
	}

	pub fn pack<T:XdrPrimitive>(&mut self, x:T) {
		XdrPrimitive::write_to_xdr(self, x)
	}

}

impl XdrReader {
	pub fn new(x: Vec<u8>) -> XdrReader {
		XdrReader{ reader : io::Cursor::new(x) }
	}

	pub fn unpack<T: XdrPrimitive>(&mut self) -> Result<T,Error> {
		T::read_from_xdr(self)
	}
}

pub trait XdrPrimitive {
	fn read_from_xdr(x: &mut XdrReader) -> Result<Self, Error>;
	fn write_to_xdr(x: &mut XdrWriter, v: Self);
}

impl XdrPrimitive for u32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u32, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<byteorder::BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for u16 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u16, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as u16),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<byteorder::BigEndian>(v as u32).unwrap();
	}
}
impl XdrPrimitive for u8 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u8, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as u8),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<byteorder::BigEndian>(v as u32).unwrap();
	}
}
impl XdrPrimitive for i8 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i8, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as i8),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<byteorder::BigEndian>(v as i32).unwrap();
	}
}
impl XdrPrimitive for i16 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i16, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as i16),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<byteorder::BigEndian>(v as i32).unwrap();
	}
}
impl XdrPrimitive for i32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i32, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<byteorder::BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for i64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i64, Error>{
		match x.reader.read_i64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i64::<byteorder::BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for u64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u64, Error>{
		match x.reader.read_u64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u64::<byteorder::BigEndian>(v).unwrap();
	}

}

impl XdrPrimitive for f32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<f32, Error>{
		match x.reader.read_f32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_f32::<byteorder::BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for f64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<f64, Error>{
		match x.reader.read_f64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_f64::<byteorder::BigEndian>(v).unwrap();
	}
}

impl XdrPrimitive for bool {
	fn read_from_xdr(x: &mut XdrReader) -> Result<bool, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(0) => Ok(false),
			Ok(1) => Ok(true),
			Ok(_) => Err(Error::InvalidValue),
			Err(v) => Err(Error::Io(v))
		}
	}

	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		match v {
			true => x.writer.write_u32::<byteorder::BigEndian>(1).unwrap(),
			false => x.writer.write_u32::<byteorder::BigEndian>(0).unwrap(),
		}
	}
}
<|endoftext|>


<commit_before>extern crate toml;
use config::Config;
use std::env;
use std::fs::File;
use std::io::Read;

pub struct Workflow {
    config: Config,
}

pub fn new() -> Workflow {
    let config = load_config().unwrap();
    Workflow {
        config: config,
    }
}

fn load_config() -> Result<Config, String> {
    let mut config_file = env::home_dir().unwrap();
    config_file.push(".jiraconfig");
    let mut file = File::open(&config_file).expect("open config file");

    let mut toml_string = String::new();
    file.read_to_string(&mut toml_string).unwrap();

    match toml::from_str(&toml_string) {
        Ok(c) => c,
        Err(_) => Err("Failed load config file".to_string())
    }
}<commit_msg>:art: Make Improve error handling<commit_after>extern crate toml;
use config::Config;
use std::env;
use std::fs::File;
use std::io::Read;
use std::process;

pub struct Workflow {
    config: Config,
}

impl Workflow {
    pub fn config(&self) -> &Config {
        &self.config
    }
}

pub fn new() -> Workflow {
    let config = match load_config() {
        Ok(c) => c,
        Err(e) => {
            println!("cause: {}", e);
            process::exit(1);
        }
    };
    Workflow {
        config: config,
    }
}

fn load_config() -> Result<Config, String> {
    let mut config_file = env::home_dir().unwrap();
    config_file.push(".jiraconfig");
    let mut file = File::open(&config_file).expect("open config file");

    let mut toml_string = String::new();
    file.read_to_string(&mut toml_string).unwrap();

    toml::from_str::<Config>(&toml_string)
        .map_err(|e| e.to_string())
}<|endoftext|>


<commit_before>

fn main() {
    // println!("{:?}", pn(7));
}

// fn testing3(n: i64, exp: i64) -> () {
//     assert_eq!(an_over_average(n), exp)
// }

#[test]
fn returns_expected() {
    assert_eq!(count_ones(1), 1);
    assert_eq!(count_ones(10), 8);
    assert_eq!(count_ones(100), 90);

    // assert_eq!(max_pn(1), 5);
    // assert_eq!(max_pn(5), 47);
    // assert_eq!(max_pn(7), 101);

    // testing3(5, 3);

}

fn count_ones(n: i64) -> i64 {
    if n == 0 { return 0 }
    let g_s = gn(n);
    let mut count: i64 = 0;
    for elem in g_s { if elem == 1 { count += 1; } }

    count
}

// fn pn(n: i64) -> Vec<i64> {
// }

// fn max_pn(n: i64) -> i64 {
//     *pn(n).last().unwrap()
// }

// fn an_over_average(n: i64) -> i64 {
//     n
// }

// fn an(n: i64) -> Vec<i64> {
//     vec![n]
// }

fn an(n: i64) -> i64 {
    match n {
        0 => return 0,
        1 => return 7,
        _ => { let an_val = an(n-1); return an_val + gcd(n, an_val) }
    }
}

fn an_seq(n: i64) -> Vec<i64> {
    let mut v: Vec<i64> = vec![];
    match n {
        0 => return v,
        _ => for i in 1..(n+1) { v.push(an(i)); }
    }

    v
}

fn gn(n: i64) -> Vec<i64> {
    let a_s = an_seq(n);
    let mut g_s: Vec<i64> = vec![];
    let mut last = 6; // hack, 7-6 == 1 at head of list...
    for elem in a_s {
        g_s.push((elem - last).abs());
        last = elem
    }

    g_s
}

fn gcd(v1: i64, v2: i64) -> i64 {
    let mut x = v1;
    let mut y = v2;
    while y != 0 {
        let t = y;
        y = x % y;
        x = t;
    }
    x
}
<commit_msg>works but waaay to slow to pass tests<commit_after>

#![feature(test)]
extern crate test;

fn main() {
    println!("{:?}", an_seq(10000, vec![]));
    // println!("{:?}", an_over_average(5));
    // println!("{:?}", pn(1));
    // println!("{:?}", max_pn(1));
//     println!("{:?}", gn(10, vec![]));
//     println!("{:?}", count_ones(10));
}

// println!("max_pn(n) : {}", n);

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

    // #[test]
    // fn returns_expected() {
    //     assert_eq!(count_ones(1), 1);
    //     assert_eq!(count_ones(10), 8);
    //     assert_eq!(count_ones(100), 90);

    //     assert_eq!(max_pn(1), 5);
    //     assert_eq!(max_pn(5), 47);
    //     assert_eq!(max_pn(7), 101);

    //     assert_eq!(an_over_average(5), 3);
    // }

    #[bench]
    fn bench_count_ones(b: &mut Bencher) {
        b.iter(|| {
            assert_eq!(count_ones(100), 90);
        });
    }

    #[bench]
    fn bench_max_pn(b: &mut Bencher) {
        b.iter(|| {
            assert_eq!(max_pn(7), 101);
        });
    }

    #[bench]
    fn bench_an_over_average(b: &mut Bencher) {
        b.iter(|| {
            assert_eq!(an_over_average(5), 3);
        });
    }
}

fn count_ones(n: i64) -> i64 {
    if n == 0 { return 0 }
    gn(n, vec![]).iter().filter(|&n| *n == 1).count() as i64
}

fn pn(n: i64) -> Vec<i64> {

    let mut count: i64 = n;
    let mut gn_vec: Vec<i64> = vec![];
    loop {
        gn_vec = gn(count, gn_vec);
        gn_vec.sort();
        gn_vec.dedup();
        gn_vec.remove(0);
        if gn_vec.len() == n as usize { return gn_vec }
        count += 1;
    }
}

fn max_pn(n: i64) -> i64 {
    *pn(n).last().unwrap()
}

fn an_over_average(n: i64) -> i64 {
    let mut avg: i64 = 0;
    let ao_s = an_over(n);
    let denom = ao_s.len() as i64;
    for elem in ao_s {
        avg += elem;
    }

    avg / (denom + 1)
}

fn an_over(n: i64) -> Vec<i64> {
    let pn_vec = pn(n);
    let mut ret: Vec<i64> = vec![];

    for (i, elem) in pn_vec.iter().enumerate() {
        if *elem != 1 {
            ret.push(elem/(i as i64 + 1));
        }
    }

    ret
}

fn an(n: i64) -> i64 {
    match n {
        0 => return 0,
        1 => return 7,
        _ => {
            let an_val = an(n-1); return an_val + gcd(n, an_val)
        }
    }
}

fn an_seq(n: i64, mut state: Vec<i64>) -> Vec<i64> {
    match n {
        0 => { return state }
        _ => for i in (state.len() + 1)..(n as usize + 1) { state.push(an(i as i64)); }
    }

    state
}

fn gn(n: i64, state: Vec<i64>) -> Vec<i64> {
    let mut last;
    let len = state.len();

    if  len > 0 {
        last = *state.last().unwrap() - 1; // starting from a previous state
    } else {
        last = 6; // starting from beginning, 7-6 == 1 at head of list...
    }

    let ret_vec = an_seq(n, state);
    let mut gn_vec: Vec<i64> = vec![];

    for elem in ret_vec[len..(n as usize)].iter() {
        let val = (elem - last).abs();
        gn_vec.push(val);
        last = *elem
    }

    gn_vec
}

fn gcd(v1: i64, v2: i64) -> i64 {
    let mut x = v1;
    let mut y = v2;
    while y != 0 {
        let t = y;
        y = x % y;
        x = t;
    }
    x
}
<|endoftext|>


<commit_before>use x86::__m128i;

#[cfg(test)]
use stdsimd_test::assert_instr;

/// Load 128-bits of integer data from unaligned memory.
/// This intrinsic may perform better than `_mm_loadu_si128`
/// when the data crosses a cache line boundary.
#[inline(always)]
#[target_feature = "+sse3"]
#[cfg_attr(test, assert_instr(lddqu))]
pub unsafe fn _mm_lddqu_si128(mem_addr: *const __m128i) -> __m128i {
    lddqu(mem_addr as *const _)
}

#[allow(improper_ctypes)]
extern {
    #[link_name = "llvm.x86.sse3.ldu.dq"]
    fn lddqu(mem_addr: *const i8) -> __m128i;
}

#[cfg(test)]
mod tests {
    use stdsimd_test::simd_test;

    use v128::*;
    use x86::sse3 as sse3;

    #[simd_test = "sse3"]
    unsafe fn _mm_lddqu_si128() {
        let a = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
        let r = sse3::_mm_lddqu_si128(&a);
        assert_eq!(a, r);
    }
}<commit_msg>sse3: _mm_addsub_ps<commit_after>use x86::__m128i;
use v128::f32x4;

#[cfg(test)]
use stdsimd_test::assert_instr;

/// Alternatively add and subtract packed single-precision (32-bit)
/// floating-point elements in `a` to/from packed elements in `b`.
#[inline(always)]
#[target_feature = "+sse3"]
#[cfg_attr(test, assert_instr(addsub))]
pub unsafe fn _mm_addsub_ps(a: f32x4, b: f32x4) -> f32x4 {
    addsubps(a, b)
}

/// Load 128-bits of integer data from unaligned memory.
/// This intrinsic may perform better than `_mm_loadu_si128`
/// when the data crosses a cache line boundary.
#[inline(always)]
#[target_feature = "+sse3"]
#[cfg_attr(test, assert_instr(lddqu))]
pub unsafe fn _mm_lddqu_si128(mem_addr: *const __m128i) -> __m128i {
    lddqu(mem_addr as *const _)
}

#[allow(improper_ctypes)]
extern {
    #[link_name = "llvm.x86.sse3.addsub.ps"]
    fn addsubps(a: f32x4, b: f32x4) -> f32x4;
    #[link_name = "llvm.x86.sse3.ldu.dq"]
    fn lddqu(mem_addr: *const i8) -> __m128i;
}

#[cfg(test)]
mod tests {
    use stdsimd_test::simd_test;

    use v128::*;
    use x86::sse3 as sse3;

    #[simd_test = "sse3"]
    unsafe fn _mm_addsub_ps() {
        let a = f32x4::new(-1.0, 5.0, 0.0, -10.0);
        let b = f32x4::new(-100.0, 20.0, 0.0, -5.0);
        let r = sse3::_mm_addsub_ps(a, b);
        assert_eq!(r, f32x4::new(99.0, 25.0, 0.0, -15.0));
    }

    #[simd_test = "sse3"]
    unsafe fn _mm_lddqu_si128() {
        let a = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
        let r = sse3::_mm_lddqu_si128(&a);
        assert_eq!(a, r);
    }
}<|endoftext|>


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

/// Macro to create a local `base_ptr` raw pointer of the given type, avoiding UB as
/// much as is possible currently.
#[cfg(maybe_uninit)]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__let_base_ptr {
    ($name:ident, $type:ty) => {
        // No UB here, and the pointer does not dangle, either.
        // But we have to make sure that `uninit` lives long enough,
        // so it has to be in the same scope as `$name`. That's why
        // `let_base_ptr` declares a variable (several, actually)
        // instead of returning one.
        let uninit = $crate::mem::MaybeUninit::<$type>::uninit();
        let $name: *const $type = uninit.as_ptr();
    };
}
#[cfg(not(maybe_uninit))]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__let_base_ptr {
    ($name:ident, $type:ty) => {
        // No UB right here, but we will later dereference this pointer to
        // offset into a field, and that is UB because the pointer is dangling.
        let $name = $crate::mem::align_of::<$type>() as *const $type;
    };
}

/// Macro to compute the distance between two pointers.
#[cfg(feature = "unstable_const")]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset_offset_from {
    ($field:expr, $base:expr) => {{
        let field = $field; // evaluate $field outside the `unsafe` block
        let base = $base; // evaluate $base outside the `unsafe` block
        // Compute offset, with unstable `offset_from` for const-compatibility.
        // (Requires the pointers to not dangle, but we already need that for `raw_field!` anyway.)
        unsafe { (field as *const u8).offset_from(base as *const u8) as usize }
    }};
}
#[cfg(not(feature = "unstable_const"))]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset_offset_from {
    ($field:expr, $base:expr) => {
        // Compute offset.
        ($field as usize) - ($base as usize)
    };
}

/// Calculates the offset of the specified field from the start of the named struct.
///
/// ## Examples
/// ```
/// #[macro_use]
/// extern crate memoffset;
///
/// #[repr(C, packed)]
/// struct Foo {
///     a: u32,
///     b: u64,
///     c: [u8; 5]
/// }
///
/// fn main() {
///     assert_eq!(offset_of!(Foo, a), 0);
///     assert_eq!(offset_of!(Foo, b), 4);
/// }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! offset_of {
    ($parent:path, $field:tt) => {{
        // Get a base pointer (non-dangling if rustc supports `MaybeUninit`).
        _memoffset__let_base_ptr!(base_ptr, $parent);
        // Get field pointer.
        let field_ptr = raw_field!(base_ptr, $parent, $field);
        // Compute offset.
        _memoffset_offset_from!(field_ptr, base_ptr)
    }};
}

/// Calculates the offset of the specified field from the start of the tuple.
///
/// ## Examples
/// ```
/// #[macro_use]
/// extern crate memoffset;
///
/// fn main() {
///     assert!(offset_of_tuple!((u8, u32), 1) >= 0, "Tuples do not have a defined layout");
/// }
/// ```
#[cfg(tuple_ty)]
#[macro_export(local_inner_macros)]
macro_rules! offset_of_tuple {
    ($parent:ty, $field:tt) => {{
        // Get a base pointer (non-dangling if rustc supports `MaybeUninit`).
        _memoffset__let_base_ptr!(base_ptr, $parent);
        // Get field pointer.
        let field_ptr = raw_field_tuple!(base_ptr, $parent, $field);
        // Compute offset.
        _memoffset_offset_from!(field_ptr, base_ptr)
    }};
}

#[cfg(test)]
mod tests {
    #[test]
    fn offset_simple() {
        #[repr(C)]
        struct Foo {
            a: u32,
            b: [u8; 2],
            c: i64,
        }

        assert_eq!(offset_of!(Foo, a), 0);
        assert_eq!(offset_of!(Foo, b), 4);
        assert_eq!(offset_of!(Foo, c), 8);
    }

    #[test]
    #[cfg_attr(miri, ignore)] // this creates unaligned references
    fn offset_simple_packed() {
        #[repr(C, packed)]
        struct Foo {
            a: u32,
            b: [u8; 2],
            c: i64,
        }

        assert_eq!(offset_of!(Foo, a), 0);
        assert_eq!(offset_of!(Foo, b), 4);
        assert_eq!(offset_of!(Foo, c), 6);
    }

    #[test]
    fn tuple_struct() {
        #[repr(C)]
        struct Tup(i32, i32);

        assert_eq!(offset_of!(Tup, 0), 0);
        assert_eq!(offset_of!(Tup, 1), 4);
    }

    #[test]
    fn path() {
        mod sub {
            #[repr(C)]
            pub struct Foo {
                pub x: u32,
            }
        }

        assert_eq!(offset_of!(sub::Foo, x), 0);
    }

    #[test]
    fn inside_generic_method() {
        struct Pair<T, U>(T, U);

        fn foo<T, U>(_: Pair<T, U>) -> usize {
            offset_of!(Pair<T, U>, 1)
        }

        assert_eq!(foo(Pair(0, 0)), 4);
    }

    #[cfg(tuple_ty)]
    #[test]
    fn test_tuple_offset() {
        let f = (0i32, 0.0f32, 0u8);
        let f_ptr = &f as *const _;
        let f1_ptr = &f.1 as *const _;

        assert_eq!(
            f1_ptr as usize - f_ptr as usize,
            offset_of_tuple!((i32, f32, u8), 1)
        );
    }

    #[test]
    fn test_raw_field() {
        #[repr(C)]
        struct Foo {
            a: u32,
            b: [u8; 2],
            c: i64,
        }

        let f: Foo = Foo {
            a: 0,
            b: [0, 0],
            c: 0,
        };
        let f_ptr = &f as *const _;
        assert_eq!(f_ptr as usize + 0, raw_field!(f_ptr, Foo, a) as usize);
        assert_eq!(f_ptr as usize + 4, raw_field!(f_ptr, Foo, b) as usize);
        assert_eq!(f_ptr as usize + 8, raw_field!(f_ptr, Foo, c) as usize);
    }

    #[cfg(tuple_ty)]
    #[test]
    fn test_raw_field_tuple() {
        let t = (0u32, 0u8, false);
        let t_ptr = &t as *const _;
        let t_addr = t_ptr as usize;

        assert_eq!(
            &t.0 as *const _ as usize - t_addr,
            raw_field_tuple!(t_ptr, (u32, u8, bool), 0) as usize - t_addr
        );
        assert_eq!(
            &t.1 as *const _ as usize - t_addr,
            raw_field_tuple!(t_ptr, (u32, u8, bool), 1) as usize - t_addr
        );
        assert_eq!(
            &t.2 as *const _ as usize - t_addr,
            raw_field_tuple!(t_ptr, (u32, u8, bool), 2) as usize - t_addr
        );
    }

    #[cfg(feature = "unstable_const")]
    #[test]
    fn const_offset() {
        #[repr(C)]
        struct Foo {
            a: u32,
            b: [u8; 2],
            c: i64,
        }

        assert_eq!([0; offset_of!(Foo, b)].len(), 4);
    }

    #[cfg(feature = "unstable_const")]
    #[test]
    fn const_fn_offset() {
        const fn test_fn() -> usize {
            #[repr(C)]
            struct Foo {
                a: u32,
                b: [u8; 2],
                c: i64,
            }

            offset_of!(Foo, b)
        }

        assert_eq!([0; test_fn()].len(), 4);
    }
}
<commit_msg>rename _memoffset_offset_from macro to reflect that it is unsafe to call<commit_after>// Copyright (c) 2017 Gilad Naaman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

/// Macro to create a local `base_ptr` raw pointer of the given type, avoiding UB as
/// much as is possible currently.
#[cfg(maybe_uninit)]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__let_base_ptr {
    ($name:ident, $type:ty) => {
        // No UB here, and the pointer does not dangle, either.
        // But we have to make sure that `uninit` lives long enough,
        // so it has to be in the same scope as `$name`. That's why
        // `let_base_ptr` declares a variable (several, actually)
        // instead of returning one.
        let uninit = $crate::mem::MaybeUninit::<$type>::uninit();
        let $name: *const $type = uninit.as_ptr();
    };
}
#[cfg(not(maybe_uninit))]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__let_base_ptr {
    ($name:ident, $type:ty) => {
        // No UB right here, but we will later dereference this pointer to
        // offset into a field, and that is UB because the pointer is dangling.
        let $name = $crate::mem::align_of::<$type>() as *const $type;
    };
}

/// Macro to compute the distance between two pointers.
#[cfg(feature = "unstable_const")]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset_offset_from_unsafe {
    ($field:expr, $base:expr) => {{
        let field = $field; // evaluate $field outside the `unsafe` block
        let base = $base; // evaluate $base outside the `unsafe` block
        // Compute offset, with unstable `offset_from` for const-compatibility.
        // (Requires the pointers to not dangle, but we already need that for `raw_field!` anyway.)
        unsafe { (field as *const u8).offset_from(base as *const u8) as usize }
    }};
}
#[cfg(not(feature = "unstable_const"))]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset_offset_from_unsafe {
    ($field:expr, $base:expr) => {
        // Compute offset.
        ($field as usize) - ($base as usize)
    };
}

/// Calculates the offset of the specified field from the start of the named struct.
///
/// ## Examples
/// ```
/// #[macro_use]
/// extern crate memoffset;
///
/// #[repr(C, packed)]
/// struct Foo {
///     a: u32,
///     b: u64,
///     c: [u8; 5]
/// }
///
/// fn main() {
///     assert_eq!(offset_of!(Foo, a), 0);
///     assert_eq!(offset_of!(Foo, b), 4);
/// }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! offset_of {
    ($parent:path, $field:tt) => {{
        // Get a base pointer (non-dangling if rustc supports `MaybeUninit`).
        _memoffset__let_base_ptr!(base_ptr, $parent);
        // Get field pointer.
        let field_ptr = raw_field!(base_ptr, $parent, $field);
        // Compute offset.
        _memoffset_offset_from_unsafe!(field_ptr, base_ptr)
    }};
}

/// Calculates the offset of the specified field from the start of the tuple.
///
/// ## Examples
/// ```
/// #[macro_use]
/// extern crate memoffset;
///
/// fn main() {
///     assert!(offset_of_tuple!((u8, u32), 1) >= 0, "Tuples do not have a defined layout");
/// }
/// ```
#[cfg(tuple_ty)]
#[macro_export(local_inner_macros)]
macro_rules! offset_of_tuple {
    ($parent:ty, $field:tt) => {{
        // Get a base pointer (non-dangling if rustc supports `MaybeUninit`).
        _memoffset__let_base_ptr!(base_ptr, $parent);
        // Get field pointer.
        let field_ptr = raw_field_tuple!(base_ptr, $parent, $field);
        // Compute offset.
        _memoffset_offset_from_unsafe!(field_ptr, base_ptr)
    }};
}

#[cfg(test)]
mod tests {
    #[test]
    fn offset_simple() {
        #[repr(C)]
        struct Foo {
            a: u32,
            b: [u8; 2],
            c: i64,
        }

        assert_eq!(offset_of!(Foo, a), 0);
        assert_eq!(offset_of!(Foo, b), 4);
        assert_eq!(offset_of!(Foo, c), 8);
    }

    #[test]
    #[cfg_attr(miri, ignore)] // this creates unaligned references
    fn offset_simple_packed() {
        #[repr(C, packed)]
        struct Foo {
            a: u32,
            b: [u8; 2],
            c: i64,
        }

        assert_eq!(offset_of!(Foo, a), 0);
        assert_eq!(offset_of!(Foo, b), 4);
        assert_eq!(offset_of!(Foo, c), 6);
    }

    #[test]
    fn tuple_struct() {
        #[repr(C)]
        struct Tup(i32, i32);

        assert_eq!(offset_of!(Tup, 0), 0);
        assert_eq!(offset_of!(Tup, 1), 4);
    }

    #[test]
    fn path() {
        mod sub {
            #[repr(C)]
            pub struct Foo {
                pub x: u32,
            }
        }

        assert_eq!(offset_of!(sub::Foo, x), 0);
    }

    #[test]
    fn inside_generic_method() {
        struct Pair<T, U>(T, U);

        fn foo<T, U>(_: Pair<T, U>) -> usize {
            offset_of!(Pair<T, U>, 1)
        }

        assert_eq!(foo(Pair(0, 0)), 4);
    }

    #[cfg(tuple_ty)]
    #[test]
    fn test_tuple_offset() {
        let f = (0i32, 0.0f32, 0u8);
        let f_ptr = &f as *const _;
        let f1_ptr = &f.1 as *const _;

        assert_eq!(
            f1_ptr as usize - f_ptr as usize,
            offset_of_tuple!((i32, f32, u8), 1)
        );
    }

    #[test]
    fn test_raw_field() {
        #[repr(C)]
        struct Foo {
            a: u32,
            b: [u8; 2],
            c: i64,
        }

        let f: Foo = Foo {
            a: 0,
            b: [0, 0],
            c: 0,
        };
        let f_ptr = &f as *const _;
        assert_eq!(f_ptr as usize + 0, raw_field!(f_ptr, Foo, a) as usize);
        assert_eq!(f_ptr as usize + 4, raw_field!(f_ptr, Foo, b) as usize);
        assert_eq!(f_ptr as usize + 8, raw_field!(f_ptr, Foo, c) as usize);
    }

    #[cfg(tuple_ty)]
    #[test]
    fn test_raw_field_tuple() {
        let t = (0u32, 0u8, false);
        let t_ptr = &t as *const _;
        let t_addr = t_ptr as usize;

        assert_eq!(
            &t.0 as *const _ as usize - t_addr,
            raw_field_tuple!(t_ptr, (u32, u8, bool), 0) as usize - t_addr
        );
        assert_eq!(
            &t.1 as *const _ as usize - t_addr,
            raw_field_tuple!(t_ptr, (u32, u8, bool), 1) as usize - t_addr
        );
        assert_eq!(
            &t.2 as *const _ as usize - t_addr,
            raw_field_tuple!(t_ptr, (u32, u8, bool), 2) as usize - t_addr
        );
    }

    #[cfg(feature = "unstable_const")]
    #[test]
    fn const_offset() {
        #[repr(C)]
        struct Foo {
            a: u32,
            b: [u8; 2],
            c: i64,
        }

        assert_eq!([0; offset_of!(Foo, b)].len(), 4);
    }

    #[cfg(feature = "unstable_const")]
    #[test]
    fn const_fn_offset() {
        const fn test_fn() -> usize {
            #[repr(C)]
            struct Foo {
                a: u32,
                b: [u8; 2],
                c: i64,
            }

            offset_of!(Foo, b)
        }

        assert_eq!([0; test_fn()].len(), 4);
    }
}
<|endoftext|>


<commit_before>use crate::core::prelude::*;
use crate::core::util::{filter, geo::MapBbox};

#[cfg_attr(rustfmt, rustfmt_skip)]
#[derive(Debug, Clone)]
pub struct SearchRequest<'a, 'b> {
    pub bbox          : MapBbox,
    pub categories    : Vec<&'a str>,
    pub ids           : Vec<&'b str>,
    pub tags          : Vec<String>,
    pub text          : Option<String>,
}

pub fn search(
    index: &EntryIndex,
    req: SearchRequest,
    limit: usize,
) -> Result<(Vec<IndexedEntry>, Vec<IndexedEntry>)> {
    let visible_bbox: MapBbox = req.bbox;
    let index_bbox =
        if req.text.as_ref().map(String::is_empty).unwrap_or(true) && req.tags.is_empty() {
            Some(filter::extend_bbox(&visible_bbox))
        } else {
            None
        };

    let index_query = EntryIndexQuery {
        bbox: index_bbox.map(Into::into),
        categories: req.categories,
        ids: req.ids,
        tags: req.tags,
        text: req.text,
    };

    let entries = index
        .query_entries(&index_query, limit)
        .map_err(|err| RepoError::Other(Box::new(err.compat())))?;

    let (visible_entries, invisible_entries): (Vec<_>, Vec<_>) = entries
        .into_iter()
        .partition(|e| visible_bbox.contains_point(&e.pos));

    Ok((visible_entries, invisible_entries))
}

/// The global search usecase is like the one
/// of usual internet search engines that exists
/// of only one single search input.
/// So here we don't care about tags, categories etc.
/// We also ignore the rating of an entry for now.
pub fn global_search(index: &EntryIndex, txt: &str, limit: usize) -> Result<Vec<IndexedEntry>> {
    let index_query = EntryIndexQuery {
        text: Some(txt.into()),
        ..Default::default()
    };

    let entries = index
        .query_entries(&index_query, limit)
        .map_err(|err| RepoError::Other(Box::new(err.compat())))?;

    Ok(entries)
}

#[cfg(test)]
mod tests {

    use super::super::tests::MockDb;
    use super::*;
    use crate::core::util::sort;
    use crate::test::Bencher;

    #[bench]
    fn bench_search_in_1_000_rated_entries(b: &mut Bencher) {
        let mut db = MockDb::default();
        let (entries, ratings) = sort::tests::create_entries_with_ratings(1_000);
        db.entries = entries.into();
        db.ratings = ratings.into();
        let req = SearchRequest {
            bbox: MapBbox::new(
                MapPoint::from_lat_lng_deg(-10.0, -10.0),
                MapPoint::from_lat_lng_deg(10.0, 10.0),
            ),
            categories: vec![],
            ids: vec![],
            tags: vec![],
            text: None,
        };

        b.iter(|| super::search(&db, req.clone(), 100).unwrap());
    }

    #[ignore]
    #[bench]
    fn bench_search_in_10_000_rated_entries(b: &mut Bencher) {
        let mut db = MockDb::default();
        let (entries, ratings) = sort::tests::create_entries_with_ratings(10_000);
        db.entries = entries.into();
        db.ratings = ratings.into();
        let req = SearchRequest {
            bbox: MapBbox::new(
                MapPoint::from_lat_lng_deg(-10.0, -10.0),
                MapPoint::from_lat_lng_deg(10.0, 10.0),
            ),
            categories: vec![],
            ids: vec![],
            tags: vec![],
            text: None,
        };

        b.iter(|| super::search(&db, req.clone(), 100).unwrap());
    }

}
<commit_msg>Fix bug when searching with text/tags and bbox (#168)<commit_after>use crate::core::prelude::*;
use crate::core::util::{filter, geo::MapBbox};

#[cfg_attr(rustfmt, rustfmt_skip)]
#[derive(Debug, Clone)]
pub struct SearchRequest<'a, 'b> {
    pub bbox          : MapBbox,
    pub categories    : Vec<&'a str>,
    pub ids           : Vec<&'b str>,
    pub tags          : Vec<String>,
    pub text          : Option<String>,
}

pub fn search(
    index: &EntryIndex,
    req: SearchRequest,
    limit: usize,
) -> Result<(Vec<IndexedEntry>, Vec<IndexedEntry>)> {
    let visible_bbox: MapBbox = req.bbox;

    let index_query = EntryIndexQuery {
        bbox: Some(filter::extend_bbox(&visible_bbox)),
        categories: req.categories,
        ids: req.ids,
        tags: req.tags,
        text: req.text,
    };

    let entries = index
        .query_entries(&index_query, limit)
        .map_err(|err| RepoError::Other(Box::new(err.compat())))?;

    let (visible_entries, invisible_entries): (Vec<_>, Vec<_>) = entries
        .into_iter()
        .partition(|e| visible_bbox.contains_point(&e.pos));

    Ok((visible_entries, invisible_entries))
}

/// The global search usecase is like the one
/// of usual internet search engines that exists
/// of only one single search input.
/// So here we don't care about tags, categories etc.
/// We also ignore the rating of an entry for now.
pub fn global_search(index: &EntryIndex, txt: &str, limit: usize) -> Result<Vec<IndexedEntry>> {
    let index_query = EntryIndexQuery {
        text: Some(txt.into()),
        ..Default::default()
    };

    let entries = index
        .query_entries(&index_query, limit)
        .map_err(|err| RepoError::Other(Box::new(err.compat())))?;

    Ok(entries)
}

#[cfg(test)]
mod tests {

    use super::super::tests::MockDb;
    use super::*;
    use crate::core::util::sort;
    use crate::test::Bencher;

    #[bench]
    fn bench_search_in_1_000_rated_entries(b: &mut Bencher) {
        let mut db = MockDb::default();
        let (entries, ratings) = sort::tests::create_entries_with_ratings(1_000);
        db.entries = entries.into();
        db.ratings = ratings.into();
        let req = SearchRequest {
            bbox: MapBbox::new(
                MapPoint::from_lat_lng_deg(-10.0, -10.0),
                MapPoint::from_lat_lng_deg(10.0, 10.0),
            ),
            categories: vec![],
            ids: vec![],
            tags: vec![],
            text: None,
        };

        b.iter(|| super::search(&db, req.clone(), 100).unwrap());
    }

    #[ignore]
    #[bench]
    fn bench_search_in_10_000_rated_entries(b: &mut Bencher) {
        let mut db = MockDb::default();
        let (entries, ratings) = sort::tests::create_entries_with_ratings(10_000);
        db.entries = entries.into();
        db.ratings = ratings.into();
        let req = SearchRequest {
            bbox: MapBbox::new(
                MapPoint::from_lat_lng_deg(-10.0, -10.0),
                MapPoint::from_lat_lng_deg(10.0, 10.0),
            ),
            categories: vec![],
            ids: vec![],
            tags: vec![],
            text: None,
        };

        b.iter(|| super::search(&db, req.clone(), 100).unwrap());
    }

}
<|endoftext|>


<commit_before>use std::convert::From;

use binding::symbol::{id_to_name, id_to_sym, sym_to_id};
use binding::util::internal_id;
use types::Value;

use super::traits::Object;

/// `Symbol`
#[derive(Debug, PartialEq)]
pub struct Symbol {
    value: Value
}

impl Symbol {
    /// Creates a new instance of Ruby `Symbol`.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ruru::{Symbol, VM};
    /// # VM::init();
    ///
    /// let symbol = Symbol::new("hello");
    ///
    /// assert_eq!(symbol.to_string(), "hello");
    pub fn new(string: &str) -> Self {
        Symbol {
            value: id_to_sym(internal_id(string))
        }
    }

    /// Retrieves the Rust `String` corresponding to `Symbol` object (Ruby `Symbol#to_s`).
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ruru::{Symbol, VM};
    /// # VM::init();
    ///
    /// let symbol = Symbol::new("hello");
    ///
    /// assert_eq!(symbol.to_string(), "hello");
    pub fn to_string(&self) -> String {
        id_to_name(sym_to_id(self.value()))
    }
}

impl From<Value> for Symbol {
    fn from(value: Value) -> Self {
        Symbol {
            value: value
        }
    }
}

impl Object for Symbol {
    fn value(&self) -> Value {
        self.value
    }
}
<commit_msg>Add Ruby examples for Symbol<commit_after>use std::convert::From;

use binding::symbol::{id_to_name, id_to_sym, sym_to_id};
use binding::util::internal_id;
use types::Value;

use super::traits::Object;

/// `Symbol`
#[derive(Debug, PartialEq)]
pub struct Symbol {
    value: Value
}

impl Symbol {
    /// Creates a new instance of Ruby `Symbol`.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ruru::{Symbol, VM};
    /// # VM::init();
    ///
    /// let symbol = Symbol::new("hello");
    ///
    /// assert_eq!(symbol.to_string(), "hello");
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// sym = :hello
    ///
    /// sym.to_s == 'hello'
    /// ```
    pub fn new(string: &str) -> Self {
        Symbol {
            value: id_to_sym(internal_id(string))
        }
    }

    /// Retrieves the Rust `String` corresponding to `Symbol` object (Ruby `Symbol#to_s`).
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ruru::{Symbol, VM};
    /// # VM::init();
    ///
    /// let symbol = Symbol::new("hello");
    ///
    /// assert_eq!(symbol.to_string(), "hello");
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// sym = :hello
    ///
    /// sym.to_s == 'hello'
    /// ```
    pub fn to_string(&self) -> String {
        id_to_name(sym_to_id(self.value()))
    }
}

impl From<Value> for Symbol {
    fn from(value: Value) -> Self {
        Symbol {
            value: value
        }
    }
}

impl Object for Symbol {
    fn value(&self) -> Value {
        self.value
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{client_proxy::ClientProxy, commands::*};

/// Command to transfer coins between two accounts.
pub struct TransferCommand {}

impl Command for TransferCommand {
    fn get_aliases(&self) -> Vec<&'static str> {
        vec!["transfer", "transferb", "t", "tb"]
    }
    fn get_params_help(&self) -> &'static str {
        "\n\t<sender_account_address>|<sender_account_ref_id> \
         <receiver_account_address>|<receiver_account_ref_id> <number_of_coins> \
         [gas_unit_price (default=0)] [max_gas_amount (default 10000)] \
         Suffix 'b' is for blocking. "
    }
    fn get_description(&self) -> &'static str {
        "Transfer coins from account to another."
    }
    fn execute(&self, client: &mut ClientProxy, params: &[&str]) {
        if params.len() < 4 || params.len() > 6 {
            println!("Invalid number of arguments for transfer");
            println!(
                "{} {}",
                self.get_aliases().join(" | "),
                self.get_params_help()
            );
            return;
        }

        println!(">> Transferring");
        let is_blocking = blocking_cmd(&params[0]);
        match client.transfer_coins(&params, is_blocking) {
            Ok(index_and_seq) => {
                if is_blocking {
                    println!("Finished transaction!");
                } else {
                    println!("Transaction submitted to validator");
                }
                println!(
                    "To query for transaction status, run: query txn_acc_seq {} {} \
                     <fetch_events=true|false>",
                    index_and_seq.account_index, index_and_seq.sequence_number
                );
            }
            Err(e) => report_error("Failed to perform transaction", e),
        }
    }
}
<commit_msg>[cli] Make gas args of transfer command specify units<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{client_proxy::ClientProxy, commands::*};

/// Command to transfer coins between two accounts.
pub struct TransferCommand {}

impl Command for TransferCommand {
    fn get_aliases(&self) -> Vec<&'static str> {
        vec!["transfer", "transferb", "t", "tb"]
    }
    fn get_params_help(&self) -> &'static str {
        "\n\t<sender_account_address>|<sender_account_ref_id> \
         <receiver_account_address>|<receiver_account_ref_id> <number_of_coins> \
         [gas_unit_price_in_micro_libras (default=0)] [max_gas_amount_in_micro_libras (default 10000)] \
         Suffix 'b' is for blocking. "
    }
    fn get_description(&self) -> &'static str {
        "Transfer coins (in libra) from account to another."
    }
    fn execute(&self, client: &mut ClientProxy, params: &[&str]) {
        if params.len() < 4 || params.len() > 6 {
            println!("Invalid number of arguments for transfer");
            println!(
                "{} {}",
                self.get_aliases().join(" | "),
                self.get_params_help()
            );
            return;
        }

        println!(">> Transferring");
        let is_blocking = blocking_cmd(&params[0]);
        match client.transfer_coins(&params, is_blocking) {
            Ok(index_and_seq) => {
                if is_blocking {
                    println!("Finished transaction!");
                } else {
                    println!("Transaction submitted to validator");
                }
                println!(
                    "To query for transaction status, run: query txn_acc_seq {} {} \
                     <fetch_events=true|false>",
                    index_and_seq.account_index, index_and_seq.sequence_number
                );
            }
            Err(e) => report_error("Failed to perform transaction", e),
        }
    }
}
<|endoftext|>