<commit_before>use super::errors::{Error, Result};
use super::system::System;
use super::window::Window;
use crate::internal_derive::DependenciesFrom;
pub use glium::glutin::MouseButton;
pub use glium::glutin::VirtualKeyCode as Scancode;
use glium::glutin::{DeviceEvent, ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent};
use math::Vec2f;
use num_traits::Zero;
use std::vec::Vec;

pub type Sensitivity = f32;

pub enum Gesture {
    NoGesture,
    KeyHold(VirtualKeyCode),
    KeyTrigger(VirtualKeyCode),
    ButtonHold(MouseButton),
    ButtonTrigger(MouseButton),
    AnyOf(Vec<Gesture>),
    AllOf(Vec<Gesture>),
    QuitTrigger,
}

pub enum Analog2d {
    NoAnalog2d,

    Mouse {
        sensitivity: Sensitivity,
    },

    Gestures {
        x_positive: Gesture,
        x_negative: Gesture,
        y_positive: Gesture,
        y_negative: Gesture,
        step: Sensitivity,
    },

    Sum {
        analogs: Vec<Analog2d>,
    },
}

impl Input {
    pub fn set_cursor_grabbed(&mut self, grabbed: bool) {
        self.new_mouse_grabbed = grabbed
    }

    pub fn set_mouse_enabled(&mut self, enable: bool) {
        self.mouse_enabled = enable;
    }

    pub fn poll_gesture(&self, gesture: &Gesture) -> bool {
        match *gesture {
            Gesture::QuitTrigger => self.quit_requested_index == self.current_update_index,
            Gesture::KeyHold(code) => match self.keyboard_state[code as usize] {
                ButtonState::Down(_) => true,
                ButtonState::Up(_) => false,
            },
            Gesture::KeyTrigger(code) => match self.keyboard_state[code as usize] {
                ButtonState::Down(index) => self.current_update_index == index,
                ButtonState::Up(_) => false,
            },
            Gesture::ButtonHold(button) => {
                match self.mouse_button_state[mouse_button_to_index(button)] {
                    ButtonState::Down(_) => true,
                    ButtonState::Up(_) => false,
                }
            }
            Gesture::ButtonTrigger(button) => {
                match self.mouse_button_state[mouse_button_to_index(button)] {
                    ButtonState::Down(index) => self.current_update_index == index,
                    ButtonState::Up(_) => false,
                }
            }
            Gesture::AnyOf(ref subgestures) => subgestures
                .iter()
                .any(|subgesture| self.poll_gesture(subgesture)),
            Gesture::AllOf(ref subgestures) => subgestures
                .iter()
                .all(|subgesture| self.poll_gesture(subgesture)),
            Gesture::NoGesture => false,
        }
    }

    pub fn poll_analog2d(&self, motion: &Analog2d) -> Vec2f {
        match *motion {
            Analog2d::Sum { ref analogs } => analogs
                .iter()
                .map(|analog| self.poll_analog2d(analog))
                .fold(Vec2f::zero(), |x, y| x + y),
            Analog2d::Mouse { sensitivity } => self.mouse_rel * sensitivity,
            Analog2d::Gestures {
                ref x_positive,
                ref x_negative,
                ref y_positive,
                ref y_negative,
                step,
            } => Vec2f::new(
                if self.poll_gesture(x_positive) {
                    step
                } else if self.poll_gesture(x_negative) {
                    -step
                } else {
                    0.0
                },
                if self.poll_gesture(y_positive) {
                    step
                } else if self.poll_gesture(y_negative) {
                    -step
                } else {
                    0.0
                },
            ),
            Analog2d::NoAnalog2d => Vec2f::zero(),
        }
    }
}

#[derive(DependenciesFrom)]
pub struct Dependencies<'context> {
    window: &'context mut Window,
}

pub struct Input {
    current_update_index: UpdateIndex,

    keyboard_state: [ButtonState; NUM_SCAN_CODES],
    mouse_button_state: [ButtonState; NUM_MOUSE_BUTTONS],
    quit_requested_index: UpdateIndex,

    mouse_enabled: bool,
    mouse_grabbed: bool,
    new_mouse_grabbed: bool,
    mouse_rel: Vec2f,
}

impl<'context> System<'context> for Input {
    type Dependencies = Dependencies<'context>;
    type Error = Error;

    fn create(_deps: Dependencies) -> Result<Self> {
        Ok(Input {
            current_update_index: 1,
            keyboard_state: [ButtonState::Up(0); NUM_SCAN_CODES],
            mouse_button_state: [ButtonState::Up(0); NUM_MOUSE_BUTTONS],
            quit_requested_index: 0,
            mouse_enabled: true,
            new_mouse_grabbed: true,
            mouse_grabbed: false,
            mouse_rel: Vec2f::zero(),
        })
    }

    fn debug_name() -> &'static str {
        "input"
    }

    fn update(&mut self, deps: Dependencies) -> Result<()> {
        if self.new_mouse_grabbed != self.mouse_grabbed {
            self.mouse_grabbed = self.new_mouse_grabbed;
            deps.window
                .facade()
                .gl_window()
                .window()
                .grab_cursor(self.mouse_grabbed)
                .ok();
            deps.window
                .facade()
                .gl_window()
                .window()
                .hide_cursor(self.mouse_grabbed);
        }
        let (center_x, center_y) = (deps.window.width() / 2, deps.window.height() / 2);
        if self.mouse_grabbed {
            let _ = deps
                .window
                .facade()
                .gl_window()
                .window()
                .set_cursor_position((center_x as i32, center_y as i32).into());
        }
        self.current_update_index += 1;
        self.mouse_rel = Vec2f::zero();
        deps.window.events().poll_events(|event| match event {
            Event::WindowEvent {
                event: WindowEvent::CloseRequested,
                ..
            } => {
                self.quit_requested_index = self.current_update_index;
            }
            Event::DeviceEvent {
                event:
                    DeviceEvent::Key(KeyboardInput {
                        state,
                        virtual_keycode: Some(virtual_keycode),
                        ..
                    }),
                ..
            } => {
                self.keyboard_state[virtual_keycode as usize] = match state {
                    ElementState::Pressed => ButtonState::Down(self.current_update_index),
                    ElementState::Released => ButtonState::Up(self.current_update_index),
                }
            }
            Event::DeviceEvent {
                event: DeviceEvent::Motion { axis, value },
                ..
            } => {
                if self.mouse_enabled && axis < 2 {
                    self.mouse_rel[axis as usize] += value as f32;
                }
            }
            Event::DeviceEvent {
                event: DeviceEvent::Button { button, state },
                ..
            } => {
                let button = button as usize;
                if self.mouse_enabled && button < NUM_MOUSE_BUTTONS {
                    self.mouse_button_state[button] = match state {
                        ElementState::Pressed => ButtonState::Down(self.current_update_index),
                        ElementState::Released => ButtonState::Up(self.current_update_index),
                    }
                }
            }
            _ => {}
        });
        Ok(())
    }
}

const NUM_SCAN_CODES: usize = 512;
const NUM_MOUSE_BUTTONS: usize = 256;

type UpdateIndex = u32;

#[derive(Copy, Clone)]
enum ButtonState {
    Up(UpdateIndex),
    Down(UpdateIndex),
}

fn mouse_button_to_index(button: MouseButton) -> usize {
    match button {
        MouseButton::Left => 1,
        MouseButton::Middle => 2,
        MouseButton::Right => 3,
        MouseButton::Other(index) => ((index + 4) as usize).min(NUM_MOUSE_BUTTONS - 1),
    }
}
<commit_msg>input: fix events on mac<commit_after>use super::errors::{Error, Result};
use super::system::System;
use super::window::Window;
use crate::internal_derive::DependenciesFrom;
pub use glium::glutin::MouseButton;
pub use glium::glutin::VirtualKeyCode as Scancode;
use glium::glutin::{DeviceEvent, ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent};
use math::Vec2f;
use num_traits::Zero;
use std::vec::Vec;

pub type Sensitivity = f32;

pub enum Gesture {
    NoGesture,
    KeyHold(VirtualKeyCode),
    KeyTrigger(VirtualKeyCode),
    ButtonHold(MouseButton),
    ButtonTrigger(MouseButton),
    AnyOf(Vec<Gesture>),
    AllOf(Vec<Gesture>),
    QuitTrigger,
}

pub enum Analog2d {
    NoAnalog2d,

    Mouse {
        sensitivity: Sensitivity,
    },

    Gestures {
        x_positive: Gesture,
        x_negative: Gesture,
        y_positive: Gesture,
        y_negative: Gesture,
        step: Sensitivity,
    },

    Sum {
        analogs: Vec<Analog2d>,
    },
}

impl Input {
    pub fn set_cursor_grabbed(&mut self, grabbed: bool) {
        self.new_mouse_grabbed = grabbed
    }

    pub fn set_mouse_enabled(&mut self, enable: bool) {
        self.mouse_enabled = enable;
    }

    pub fn poll_gesture(&self, gesture: &Gesture) -> bool {
        match *gesture {
            Gesture::QuitTrigger => self.quit_requested_index == self.current_update_index,
            Gesture::KeyHold(code) => match self.keyboard_state[code as usize] {
                ButtonState::Down(_) => true,
                ButtonState::Up(_) => false,
            },
            Gesture::KeyTrigger(code) => match self.keyboard_state[code as usize] {
                ButtonState::Down(index) => self.current_update_index == index,
                ButtonState::Up(_) => false,
            },
            Gesture::ButtonHold(button) => {
                match self.mouse_button_state[mouse_button_to_index(button)] {
                    ButtonState::Down(_) => true,
                    ButtonState::Up(_) => false,
                }
            }
            Gesture::ButtonTrigger(button) => {
                match self.mouse_button_state[mouse_button_to_index(button)] {
                    ButtonState::Down(index) => self.current_update_index == index,
                    ButtonState::Up(_) => false,
                }
            }
            Gesture::AnyOf(ref subgestures) => subgestures
                .iter()
                .any(|subgesture| self.poll_gesture(subgesture)),
            Gesture::AllOf(ref subgestures) => subgestures
                .iter()
                .all(|subgesture| self.poll_gesture(subgesture)),
            Gesture::NoGesture => false,
        }
    }

    pub fn poll_analog2d(&self, motion: &Analog2d) -> Vec2f {
        match *motion {
            Analog2d::Sum { ref analogs } => analogs
                .iter()
                .map(|analog| self.poll_analog2d(analog))
                .fold(Vec2f::zero(), |x, y| x + y),
            Analog2d::Mouse { sensitivity } => self.mouse_rel * sensitivity,
            Analog2d::Gestures {
                ref x_positive,
                ref x_negative,
                ref y_positive,
                ref y_negative,
                step,
            } => Vec2f::new(
                if self.poll_gesture(x_positive) {
                    step
                } else if self.poll_gesture(x_negative) {
                    -step
                } else {
                    0.0
                },
                if self.poll_gesture(y_positive) {
                    step
                } else if self.poll_gesture(y_negative) {
                    -step
                } else {
                    0.0
                },
            ),
            Analog2d::NoAnalog2d => Vec2f::zero(),
        }
    }
}

#[derive(DependenciesFrom)]
pub struct Dependencies<'context> {
    window: &'context mut Window,
}

pub struct Input {
    current_update_index: UpdateIndex,

    keyboard_state: [ButtonState; NUM_SCAN_CODES],
    mouse_button_state: [ButtonState; NUM_MOUSE_BUTTONS],
    quit_requested_index: UpdateIndex,

    mouse_enabled: bool,
    mouse_grabbed: bool,
    new_mouse_grabbed: bool,
    mouse_rel: Vec2f,
}

impl<'context> System<'context> for Input {
    type Dependencies = Dependencies<'context>;
    type Error = Error;

    fn create(_deps: Dependencies) -> Result<Self> {
        Ok(Input {
            current_update_index: 1,
            keyboard_state: [ButtonState::Up(0); NUM_SCAN_CODES],
            mouse_button_state: [ButtonState::Up(0); NUM_MOUSE_BUTTONS],
            quit_requested_index: 0,
            mouse_enabled: true,
            new_mouse_grabbed: true,
            mouse_grabbed: false,
            mouse_rel: Vec2f::zero(),
        })
    }

    fn debug_name() -> &'static str {
        "input"
    }

    fn update(&mut self, deps: Dependencies) -> Result<()> {
        if self.new_mouse_grabbed != self.mouse_grabbed {
            self.mouse_grabbed = self.new_mouse_grabbed;
            deps.window
                .facade()
                .gl_window()
                .window()
                .grab_cursor(self.mouse_grabbed)
                .ok();
            deps.window
                .facade()
                .gl_window()
                .window()
                .hide_cursor(self.mouse_grabbed);
        }
        if self.mouse_grabbed {
            let _ = deps.window.facade().gl_window().window();
        }
        self.current_update_index += 1;
        self.mouse_rel = Vec2f::zero();
        deps.window.events().poll_events(|event| match event {
            Event::WindowEvent {
                event: WindowEvent::CloseRequested,
                ..
            } => {
                self.quit_requested_index = self.current_update_index;
            }
            Event::WindowEvent {
                event:
                    WindowEvent::KeyboardInput {
                        input:
                            KeyboardInput {
                                state,
                                virtual_keycode: Some(virtual_keycode),
                                ..
                            },
                        ..
                    },
                ..
            } => {
                self.keyboard_state[virtual_keycode as usize] = match state {
                    ElementState::Pressed => ButtonState::Down(self.current_update_index),
                    ElementState::Released => ButtonState::Up(self.current_update_index),
                }
            }
            Event::DeviceEvent {
                event: DeviceEvent::Motion { axis, value },
                ..
            } => {
                if self.mouse_enabled && axis < 2 {
                    self.mouse_rel[axis as usize] += value as f32;
                }
            }
            Event::DeviceEvent {
                event: DeviceEvent::Button { button, state },
                ..
            } => {
                let button = button as usize;
                if self.mouse_enabled && button < NUM_MOUSE_BUTTONS {
                    self.mouse_button_state[button] = match state {
                        ElementState::Pressed => ButtonState::Down(self.current_update_index),
                        ElementState::Released => ButtonState::Up(self.current_update_index),
                    }
                }
            }
            _ => {}
        });
        Ok(())
    }
}

const NUM_SCAN_CODES: usize = 512;
const NUM_MOUSE_BUTTONS: usize = 256;

type UpdateIndex = u32;

#[derive(Copy, Clone)]
enum ButtonState {
    Up(UpdateIndex),
    Down(UpdateIndex),
}

fn mouse_button_to_index(button: MouseButton) -> usize {
    match button {
        MouseButton::Left => 1,
        MouseButton::Middle => 2,
        MouseButton::Right => 3,
        MouseButton::Other(index) => ((index + 4) as usize).min(NUM_MOUSE_BUTTONS - 1),
    }
}
<|endoftext|>


<commit_before>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

#![feature(collections, std_misc)]

extern crate gcc;
extern crate "pkg-config" as pkg_config;

use std::process::Command;
use gcc::Config;
use std::env;
use std::path::AsPath;

fn main() {
    env::set_var("PKG_CONFIG_ALLOW_CROSS", "1");

    // try to find gtk+-3.0 library
    pkg_config::find_library("gtk+-3.0").unwrap();

    // call native pkg-config, there is no way to do this with pkg-config for now
    let cmd = Command::new("pkg-config").arg("--cflags").arg("gtk+-3.0")
                .output().unwrap();
    if !cmd.status.success() {
        panic!("{}", String::from_utf8_lossy(&cmd.stderr));
    }

    // make the vector of path to set to gcc::Config
    let output = String::from_utf8(cmd.stdout).unwrap();

    // build include path
    let mut gcc_conf = Config::new();
    for s in output.split(' ') {
        if s.starts_with("-I") {
            gcc_conf.include(s[2..].as_path());
        }
    }
    gcc_conf.file("src/gtk_glue.c");

    // pass the GTK feature flags
    for (key, _) in env::vars() {
        if key.starts_with("CARGO_FEATURE_") {
            let feature = key.trim_left_matches("CARGO_FEATURE_");
            if feature.starts_with("GTK_") {
                let mut flag = String::from_str("-D");
                flag.push_str(feature);
                gcc_conf.flag(&flag);
            }
        }
    }

    // build library
    gcc_conf.compile("librgtk_glue.a");
}
<commit_msg>Revert "Replace match...Err block with equivalent unwrap()"<commit_after>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

#![feature(collections, std_misc)]

extern crate gcc;
extern crate "pkg-config" as pkg_config;

use std::process::Command;
use gcc::Config;
use std::env;
use std::path::AsPath;

fn main() {
    env::set_var("PKG_CONFIG_ALLOW_CROSS", "1");

    // try to find gtk+-3.0 library
    match pkg_config::find_library("gtk+-3.0") {
        Ok(_) => {},
        Err(e) => panic!("{}", e)
    };

    // call native pkg-config, there is no way to do this with pkg-config for now
    let cmd = Command::new("pkg-config").arg("--cflags").arg("gtk+-3.0")
                .output().unwrap();
    if !cmd.status.success() {
        panic!("{}", String::from_utf8_lossy(&cmd.stderr));
    }

    // make the vector of path to set to gcc::Config
    let output = String::from_utf8(cmd.stdout).unwrap();

    // build include path
    let mut gcc_conf = Config::new();
    for s in output.split(' ') {
        if s.starts_with("-I") {
            gcc_conf.include(s[2..].as_path());
        }
    }
    gcc_conf.file("src/gtk_glue.c");

    // pass the GTK feature flags
    for (key, _) in env::vars() {
        if key.starts_with("CARGO_FEATURE_") {
            let feature = key.trim_left_matches("CARGO_FEATURE_");
            if feature.starts_with("GTK_") {
                let mut flag = String::from_str("-D");
                flag.push_str(feature);
                gcc_conf.flag(&flag);
            }
        }
    }

    // build library
    gcc_conf.compile("librgtk_glue.a");
}
<|endoftext|>


<commit_before>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

#![feature(collections)]

extern crate gcc;
extern crate "pkg-config" as pkg_config;

use std::process::Command;
use gcc::Config;
use std::env;
use std::path::PathBuf;

fn main() {
    env::set_var("PKG_CONFIG_ALLOW_CROSS", "1");

    // try to find gtk+-3.0 library
    pkg_config::find_library("gtk+-3.0").unwrap();

    // call native pkg-config, there is no way to do this with pkg-config for now
    let cmd = Command::new("pkg-config").arg("--cflags").arg("gtk+-3.0")
                .output().unwrap();
    if !cmd.status.success() {
        panic!("{}", String::from_utf8_lossy(&cmd.stderr));
    }

    // make the vector of path to set to gcc::Config
    let output = String::from_utf8(cmd.stdout).unwrap();
    let res: Vec<&str> = output.split(' ').collect();
    let paths: Vec<PathBuf> = res.iter().filter_map(|s| {
        if s.len() > 1 && s.chars().nth(1).unwrap() == 'I' { Some(PathBuf::new(&s[2..])) }
        else { None }
    }).collect();

    // build include path
    let mut gcc_conf = Config::new();
    for path in paths {
        gcc_conf.include(&path);
    }
    gcc_conf.file("src/gtk_glue.c");

    // pass the GTK feature flags
    for (key, _) in env::vars() {
        if key.starts_with("CARGO_FEATURE_") {
            let feature = key.trim_left_matches("CARGO_FEATURE_");
            if feature.starts_with("GTK_") {
                let mut flag = String::from_str("-D");
                flag.push_str(feature);
                gcc_conf.flag(&flag);
            }
        }
    }

    // build library
    gcc_conf.compile("librgtk_glue.a");
}
<commit_msg>Improve build.rs for gtk3-sys<commit_after>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

#![feature(collections, std_misc)]

extern crate gcc;
extern crate "pkg-config" as pkg_config;

use std::process::Command;
use gcc::Config;
use std::env;
use std::path::AsPath;

fn main() {
    env::set_var("PKG_CONFIG_ALLOW_CROSS", "1");

    // try to find gtk+-3.0 library
    pkg_config::find_library("gtk+-3.0").unwrap();

    // call native pkg-config, there is no way to do this with pkg-config for now
    let cmd = Command::new("pkg-config").arg("--cflags").arg("gtk+-3.0")
                .output().unwrap();
    if !cmd.status.success() {
        panic!("{}", String::from_utf8_lossy(&cmd.stderr));
    }

    // make the vector of path to set to gcc::Config
    let output = String::from_utf8(cmd.stdout).unwrap();

    // build include path
    let mut gcc_conf = Config::new();
    for s in output.split(' ') {
        if s.starts_with("-I") {
            gcc_conf.include(s[2..].as_path());
        }
    }
    gcc_conf.file("src/gtk_glue.c");

    // pass the GTK feature flags
    for (key, _) in env::vars() {
        if key.starts_with("CARGO_FEATURE_") {
            let feature = key.trim_left_matches("CARGO_FEATURE_");
            if feature.starts_with("GTK_") {
                let mut flag = String::from_str("-D");
                flag.push_str(feature);
                gcc_conf.flag(&flag);
            }
        }
    }

    // build library
    gcc_conf.compile("librgtk_glue.a");
}
<|endoftext|>


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

use arrow::{
    array::{Array, ArrayRef, Float32Array, Float64Array, Float64Builder},
    datatypes::DataType,
    record_batch::RecordBatch,
    util::pretty,
};

use datafusion::error::Result;
use datafusion::{physical_plan::functions::ScalarFunctionImplementation, prelude::*};
use std::sync::Arc;

// create local execution context with an in-memory table
fn create_context() -> Result<ExecutionContext> {
    use arrow::datatypes::{Field, Schema};
    use datafusion::datasource::MemTable;
    // define a schema.
    let schema = Arc::new(Schema::new(vec![
        Field::new("a", DataType::Float32, false),
        Field::new("b", DataType::Float64, false),
    ]));

    // define data.
    let batch = RecordBatch::try_new(
        schema.clone(),
        vec![
            Arc::new(Float32Array::from(vec![2.1, 3.1, 4.1, 5.1])),
            Arc::new(Float64Array::from(vec![1.0, 2.0, 3.0, 4.0])),
        ],
    )?;

    // declare a new context. In spark API, this corresponds to a new spark SQLsession
    let mut ctx = ExecutionContext::new();

    // declare a table in memory. In spark API, this corresponds to createDataFrame(...).
    let provider = MemTable::try_new(schema, vec![vec![batch]])?;
    ctx.register_table("t", Box::new(provider));
    Ok(ctx)
}

/// In this example we will declare a single-type, single return type UDF that exponentiates f64, a^b
#[tokio::main]
async fn main() -> Result<()> {
    let mut ctx = create_context()?;

    // First, declare the actual implementation of the calculation
    let pow: ScalarFunctionImplementation = Arc::new(|args: &[ArrayRef]| {
        // in DataFusion, all `args` and output are dynamically-typed arrays, which means that we need to:
        // 1. cast the values to the type we want
        // 2. perform the computation for every element in the array (using a loop or SIMD)
        // 3. construct the resulting array

        // this is guaranteed by DataFusion based on the function's signature.
        assert_eq!(args.len(), 2);

        // 1. cast both arguments to f64. These casts MUST be aligned with the signature or this function panics!
        let base = &args[0]
            .as_any()
            .downcast_ref::<Float64Array>()
            .expect("cast failed");
        let exponent = &args[1]
            .as_any()
            .downcast_ref::<Float64Array>()
            .expect("cast failed");

        // this is guaranteed by DataFusion. We place it just to make it obvious.
        assert_eq!(exponent.len(), base.len());

        // 2. Arrow's builder is used to construct an Arrow array.
        let mut builder = Float64Builder::new(base.len());
        for index in 0..base.len() {
            // in arrow, any value can be null.
            // Here we decide to make our UDF to return null when either base or exponent is null.
            if base.is_null(index) || exponent.is_null(index) {
                builder.append_null()?;
            } else {
                // 3. computation. Since we do not have any SIMD `pow` operation at our hands,
                // we loop over each entry. Array's values are obtained via `.value(index)`.
                let value = base.value(index).powf(exponent.value(index));
                builder.append_value(value)?;
            }
        }
        Ok(Arc::new(builder.finish()))
    });

    // Next:
    // * give it a name so that it shows nicely when the plan is printed
    // * declare what input it expects
    // * declare its return type
    let pow = create_udf(
        "pow",
        // expects two f64
        vec![DataType::Float64, DataType::Float64],
        // returns f64
        Arc::new(DataType::Float64),
        pow,
    );

    // at this point, we can use it or register it, depending on the use-case:
    // * if the UDF is expected to be used throughout the program in different contexts,
    //   we can register it, and call it later:
    ctx.register_udf(pow.clone()); // clone is only required in this example because we show both usages

    // * if the UDF is expected to be used directly in the scope, `.call` it directly:
    let expr = pow.call(vec![col("a"), col("b")]);

    // get a DataFrame from the context
    let df = ctx.table("t")?;

    // if we do not have `pow` in the scope and we registered it, we can get it from the registry
    let pow = df.registry().udf("pow")?;
    // equivalent to expr
    let expr1 = pow.call(vec![col("a"), col("b")]);

    // equivalent to `'SELECT pow(a, b), pow(a, b) AS pow1 FROM t'`
    let df = df.select(vec![
        expr,
        // alias so that they have different column names
        expr1.alias("pow1"),
    ])?;

    // note that "b" is f32, not f64. DataFusion coerces the types to match the UDF's signature.

    // execute the query
    let results = df.collect().await?;

    // print the results
    pretty::print_batches(&results)?;

    Ok(())
}
<commit_msg>ARROW-11343: [Rust][DataFusion] Simplified example with UDF.<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

use arrow::{
    array::{ArrayRef, Float32Array, Float64Array},
    datatypes::DataType,
    record_batch::RecordBatch,
    util::pretty,
};

use datafusion::error::Result;
use datafusion::{physical_plan::functions::ScalarFunctionImplementation, prelude::*};
use std::sync::Arc;

// create local execution context with an in-memory table
fn create_context() -> Result<ExecutionContext> {
    use arrow::datatypes::{Field, Schema};
    use datafusion::datasource::MemTable;
    // define a schema.
    let schema = Arc::new(Schema::new(vec![
        Field::new("a", DataType::Float32, false),
        Field::new("b", DataType::Float64, false),
    ]));

    // define data.
    let batch = RecordBatch::try_new(
        schema.clone(),
        vec![
            Arc::new(Float32Array::from(vec![2.1, 3.1, 4.1, 5.1])),
            Arc::new(Float64Array::from(vec![1.0, 2.0, 3.0, 4.0])),
        ],
    )?;

    // declare a new context. In spark API, this corresponds to a new spark SQLsession
    let mut ctx = ExecutionContext::new();

    // declare a table in memory. In spark API, this corresponds to createDataFrame(...).
    let provider = MemTable::try_new(schema, vec![vec![batch]])?;
    ctx.register_table("t", Box::new(provider));
    Ok(ctx)
}

/// In this example we will declare a single-type, single return type UDF that exponentiates f64, a^b
#[tokio::main]
async fn main() -> Result<()> {
    let mut ctx = create_context()?;

    // First, declare the actual implementation of the calculation
    let pow: ScalarFunctionImplementation = Arc::new(|args: &[ArrayRef]| {
        // in DataFusion, all `args` and output are dynamically-typed arrays, which means that we need to:
        // 1. cast the values to the type we want
        // 2. perform the computation for every element in the array (using a loop or SIMD) and construct the result

        // this is guaranteed by DataFusion based on the function's signature.
        assert_eq!(args.len(), 2);

        // 1. cast both arguments to f64. These casts MUST be aligned with the signature or this function panics!
        let base = &args[0]
            .as_any()
            .downcast_ref::<Float64Array>()
            .expect("cast failed");
        let exponent = &args[1]
            .as_any()
            .downcast_ref::<Float64Array>()
            .expect("cast failed");

        // this is guaranteed by DataFusion. We place it just to make it obvious.
        assert_eq!(exponent.len(), base.len());

        // 2. perform the computation
        let array = base
            .iter()
            .zip(exponent.iter())
            .map(|(base, exponent)| {
                match (base, exponent) {
                    // in arrow, any value can be null.
                    // Here we decide to make our UDF to return null when either base or exponent is null.
                    (Some(base), Some(exponent)) => Some(base.powf(exponent)),
                    _ => None,
                }
            })
            .collect::<Float64Array>();

        // `Ok` because no error occurred during the calculation (we should add one if exponent was [0, 1[ and the base < 0 because that panics!)
        // `Arc` because arrays are immutable, thread-safe, trait objects.
        Ok(Arc::new(array))
    });

    // Next:
    // * give it a name so that it shows nicely when the plan is printed
    // * declare what input it expects
    // * declare its return type
    let pow = create_udf(
        "pow",
        // expects two f64
        vec![DataType::Float64, DataType::Float64],
        // returns f64
        Arc::new(DataType::Float64),
        pow,
    );

    // at this point, we can use it or register it, depending on the use-case:
    // * if the UDF is expected to be used throughout the program in different contexts,
    //   we can register it, and call it later:
    ctx.register_udf(pow.clone()); // clone is only required in this example because we show both usages

    // * if the UDF is expected to be used directly in the scope, `.call` it directly:
    let expr = pow.call(vec![col("a"), col("b")]);

    // get a DataFrame from the context
    let df = ctx.table("t")?;

    // if we do not have `pow` in the scope and we registered it, we can get it from the registry
    let pow = df.registry().udf("pow")?;
    // equivalent to expr
    let expr1 = pow.call(vec![col("a"), col("b")]);

    // equivalent to `'SELECT pow(a, b), pow(a, b) AS pow1 FROM t'`
    let df = df.select(vec![
        expr,
        // alias so that they have different column names
        expr1.alias("pow1"),
    ])?;

    // note that "b" is f32, not f64. DataFusion coerces the types to match the UDF's signature.

    // execute the query
    let results = df.collect().await?;

    // print the results
    pretty::print_batches(&results)?;

    Ok(())
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017-2018 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/>.
 */

mod board;
mod board_parts;
mod sys;
mod vec2;

use imgui::{ImGuiCond, ImStr, ImVec2, StyleVar, Ui};

use self::board::board;
pub use self::sys::run;
use self::vec2::Vec2;
use model::{Color, ColorMap, Model, Player};
use update::Event;

pub fn draw(ui: &Ui, size: (f32, f32), model: &Model) -> Option<Event> {
    let mut event = None;

    ui.main_menu_bar(|| {
        ui.menu(im_str!("Game")).build(|| {
            ui.menu_item(im_str!("New game")).enabled(false).build();

            use self::Player::*;
            if ui.menu_item(im_str!("Human vs. Human")).build() {
                insert_if_empty(&mut event, Event::NewGame(ColorMap::new(Human, Human)));
            }
            if ui.menu_item(im_str!("Human vs. Computer")).build() {
                insert_if_empty(&mut event, Event::NewGame(ColorMap::new(Human, Computer)));
            }
            if ui.menu_item(im_str!("Computer vs. Human")).build() {
                insert_if_empty(&mut event, Event::NewGame(ColorMap::new(Computer, Human)));
            }
            if ui.menu_item(im_str!("Computer vs. Computer")).build() {
                insert_if_empty(
                    &mut event,
                    Event::NewGame(ColorMap::new(Computer, Computer)),
                );
            }
            ui.separator();
            if ui.menu_item(im_str!("Quit")).build() {
                insert_if_empty(&mut event, Event::Quit);
            }
        });

        let mut depth = i32::from(model.ai_search_depth);
        ui.menu(im_str!("Computer")).build(|| {
            ui.slider_int(im_str!("Search depth"), &mut depth, 1, 7)
                .build();
            if ui.is_item_hovered() {
                ui.tooltip_text("How many moves ahead the computer will search.\nFewer moves is faster and easier, while more moves is slower and more difficult.");
            }
        });
        if depth as u8 != model.ai_search_depth {
            insert_if_empty(&mut event, Event::SetAIDepth(depth as u8));
        }
    });

    ui.with_style_var(StyleVar::WindowRounding(0.0), || {
        draw_window(ui, size, model, &mut event);
    });

    event
}

fn draw_window(ui: &Ui, size: (f32, f32), model: &Model, event: &mut Option<Event>) {
    ui.window(im_str!("Coerceo"))
        .size(size, ImGuiCond::Always)
        .position((0.0, 27.0), ImGuiCond::Always)
        .title_bar(false)
        .resizable(false)
        .movable(false)
        .build(|| {
            ui.text("Welcome to Coerceo!");
            ui.text(format!(
                "{:?} vs. {:?}",
                model.players.white, model.players.black
            ));

            if let Some(click) = board(ui, model, Vec2::new(size.0 - 16.0, size.1 - 230.0)) {
                insert_if_empty(event, click);
            }

            let format_piece_count = |count| match count {
                1 => String::from("1 piece"),
                _ => format!("{} pieces", count),
            };

            let format_hex_count = |count| match count {
                1 => String::from("1 captured hex"),
                _ => format!("{} captured hexes", count),
            };

            let display_vitals = || {
                ui.text(format!(
                    "{:?} has {} and {}.",
                    Color::White,
                    format_piece_count(model.board.pieces(Color::White)),
                    format_hex_count(model.board.hexes(Color::White)),
                ));
                ui.text(format!(
                    "{:?} has {} and {}.",
                    Color::Black,
                    format_piece_count(model.board.pieces(Color::Black)),
                    format_hex_count(model.board.hexes(Color::Black)),
                ));
            };

            let button_size = Vec2::new(120.0, 28.0);
            use model::Outcome::*;
            match model.outcome {
                Win(color) => {
                    ui.text(format!("{:?} wins!", color));
                    display_vitals();
                    if model.can_undo() && ui.button(im_str!("Undo"), button_size) {
                        insert_if_empty(event, Event::Undo);
                    }
                }
                InProgress => {
                    if model.players.white == model.players.black {
                        ui.text(format!("It's {:?}'s turn.", model.board.turn,));
                    } else {
                        ui.text(match model.current_player() {
                            Player::Computer => "Waiting for the computer...",
                            Player::Human => "It's your turn.",
                        });
                    }

                    display_vitals();

                    horz_button_layout(
                        ui,
                        vec![
                            (model.can_undo(), im_str!("Undo"), Event::Undo),
                            (model.can_redo(), im_str!("Redo"), Event::Redo),
                        ],
                        &button_size,
                        event,
                    );
                    let is_human_player = model.current_player() == Player::Human;
                    horz_button_layout(
                        ui,
                        vec![
                            (is_human_player, im_str!("Resign"), Event::Resign),
                            (
                                model.board.can_exchange() && is_human_player,
                                if model.exchanging {
                                    im_str!("Stop Exchanging")
                                } else {
                                    im_str!("Exchange")
                                },
                                Event::Exchange,
                            ),
                        ],
                        &button_size,
                        event,
                    );
                }
                // Draw cases
                _ => {
                    let message = match model.outcome {
                        DrawStalemate => "It's a draw by stalemate!",
                        DrawThreefoldRepetition => "It's a draw by threefold repetition!",
                        DrawInsufficientMaterial => "It's a draw by insufficient material!",
                        _ => unreachable!(),
                    };
                    ui.text(message);
                    display_vitals();
                    if model.can_undo() && ui.button(im_str!("Undo"), button_size) {
                        insert_if_empty(event, Event::Undo);
                    }
                }
            }
        });
}

fn horz_button_layout(
    ui: &Ui,
    buttons: Vec<(bool, &ImStr, Event)>,
    size: &Vec2,
    event: &mut Option<Event>,
) {
    if !buttons.iter().any(|&(show, _, _)| show) {
        return;
    }

    let size: ImVec2 = (*size).into();

    for (show, label, action) in buttons {
        if show {
            if ui.button(label, size) {
                insert_if_empty(event, action);
            }
        } else {
            ui.dummy(size);
        }
        ui.same_line(0.0);
    }
    ui.new_line();
}

fn insert_if_empty<T>(a: &mut Option<T>, b: T) {
    if a.is_none() {
        *a = Some(b);
    }
}
<commit_msg>Increase button size to fit "Stop exchanging"<commit_after>/*
 * Copyright (C) 2017-2018 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/>.
 */

mod board;
mod board_parts;
mod sys;
mod vec2;

use imgui::{ImGuiCond, ImStr, ImVec2, StyleVar, Ui};

use self::board::board;
pub use self::sys::run;
use self::vec2::Vec2;
use model::{Color, ColorMap, Model, Player};
use update::Event;

pub fn draw(ui: &Ui, size: (f32, f32), model: &Model) -> Option<Event> {
    let mut event = None;

    ui.main_menu_bar(|| {
        ui.menu(im_str!("Game")).build(|| {
            ui.menu_item(im_str!("New game")).enabled(false).build();

            use self::Player::*;
            if ui.menu_item(im_str!("Human vs. Human")).build() {
                insert_if_empty(&mut event, Event::NewGame(ColorMap::new(Human, Human)));
            }
            if ui.menu_item(im_str!("Human vs. Computer")).build() {
                insert_if_empty(&mut event, Event::NewGame(ColorMap::new(Human, Computer)));
            }
            if ui.menu_item(im_str!("Computer vs. Human")).build() {
                insert_if_empty(&mut event, Event::NewGame(ColorMap::new(Computer, Human)));
            }
            if ui.menu_item(im_str!("Computer vs. Computer")).build() {
                insert_if_empty(
                    &mut event,
                    Event::NewGame(ColorMap::new(Computer, Computer)),
                );
            }
            ui.separator();
            if ui.menu_item(im_str!("Quit")).build() {
                insert_if_empty(&mut event, Event::Quit);
            }
        });

        let mut depth = i32::from(model.ai_search_depth);
        ui.menu(im_str!("Computer")).build(|| {
            ui.slider_int(im_str!("Search depth"), &mut depth, 1, 7)
                .build();
            if ui.is_item_hovered() {
                ui.tooltip_text("How many moves ahead the computer will search.\nFewer moves is faster and easier, while more moves is slower and more difficult.");
            }
        });
        if depth as u8 != model.ai_search_depth {
            insert_if_empty(&mut event, Event::SetAIDepth(depth as u8));
        }
    });

    ui.with_style_var(StyleVar::WindowRounding(0.0), || {
        draw_window(ui, size, model, &mut event);
    });

    event
}

fn draw_window(ui: &Ui, size: (f32, f32), model: &Model, event: &mut Option<Event>) {
    ui.window(im_str!("Coerceo"))
        .size(size, ImGuiCond::Always)
        .position((0.0, 27.0), ImGuiCond::Always)
        .title_bar(false)
        .resizable(false)
        .movable(false)
        .build(|| {
            ui.text("Welcome to Coerceo!");
            ui.text(format!(
                "{:?} vs. {:?}",
                model.players.white, model.players.black
            ));

            if let Some(click) = board(ui, model, Vec2::new(size.0 - 16.0, size.1 - 232.0)) {
                insert_if_empty(event, click);
            }

            let format_piece_count = |count| match count {
                1 => String::from("1 piece"),
                _ => format!("{} pieces", count),
            };

            let format_hex_count = |count| match count {
                1 => String::from("1 captured hex"),
                _ => format!("{} captured hexes", count),
            };

            let display_vitals = || {
                ui.text(format!(
                    "{:?} has {} and {}.",
                    Color::White,
                    format_piece_count(model.board.pieces(Color::White)),
                    format_hex_count(model.board.hexes(Color::White)),
                ));
                ui.text(format!(
                    "{:?} has {} and {}.",
                    Color::Black,
                    format_piece_count(model.board.pieces(Color::Black)),
                    format_hex_count(model.board.hexes(Color::Black)),
                ));
            };

            let button_size = Vec2::new(155.0, 29.0);
            use model::Outcome::*;
            match model.outcome {
                Win(color) => {
                    ui.text(format!("{:?} wins!", color));
                    display_vitals();
                    if model.can_undo() && ui.button(im_str!("Undo"), button_size) {
                        insert_if_empty(event, Event::Undo);
                    }
                }
                InProgress => {
                    if model.players.white == model.players.black {
                        ui.text(format!("It's {:?}'s turn.", model.board.turn,));
                    } else {
                        ui.text(match model.current_player() {
                            Player::Computer => "Waiting for the computer...",
                            Player::Human => "It's your turn.",
                        });
                    }

                    display_vitals();

                    horz_button_layout(
                        ui,
                        vec![
                            (model.can_undo(), im_str!("Undo"), Event::Undo),
                            (model.can_redo(), im_str!("Redo"), Event::Redo),
                        ],
                        &button_size,
                        event,
                    );
                    let is_human_player = model.current_player() == Player::Human;
                    horz_button_layout(
                        ui,
                        vec![
                            (is_human_player, im_str!("Resign"), Event::Resign),
                            (
                                model.board.can_exchange() && is_human_player,
                                if model.exchanging {
                                    im_str!("Stop Exchanging")
                                } else {
                                    im_str!("Exchange")
                                },
                                Event::Exchange,
                            ),
                        ],
                        &button_size,
                        event,
                    );
                }
                // Draw cases
                _ => {
                    let message = match model.outcome {
                        DrawStalemate => "It's a draw by stalemate!",
                        DrawThreefoldRepetition => "It's a draw by threefold repetition!",
                        DrawInsufficientMaterial => "It's a draw by insufficient material!",
                        _ => unreachable!(),
                    };
                    ui.text(message);
                    display_vitals();
                    if model.can_undo() && ui.button(im_str!("Undo"), button_size) {
                        insert_if_empty(event, Event::Undo);
                    }
                }
            }
        });
}

fn horz_button_layout(
    ui: &Ui,
    buttons: Vec<(bool, &ImStr, Event)>,
    size: &Vec2,
    event: &mut Option<Event>,
) {
    if !buttons.iter().any(|&(show, _, _)| show) {
        return;
    }

    let size: ImVec2 = (*size).into();

    for (show, label, action) in buttons {
        if show {
            if ui.button(label, size) {
                insert_if_empty(event, action);
            }
        } else {
            ui.dummy(size);
        }
        ui.same_line(0.0);
    }
    ui.new_line();
}

fn insert_if_empty<T>(a: &mut Option<T>, b: T) {
    if a.is_none() {
        *a = Some(b);
    }
}
<|endoftext|>


<commit_before>extern crate serenity;
#[macro_use] extern crate matches;

use serenity::framework::standard::{Args, ArgError};

#[test]
fn single_i32_with_2_bytes_long_delimiter() {
    let mut args = Args::new("1, 2", &[", ".to_string()]);

    assert_eq!(args.single::<i32>().unwrap(), 1);
    assert_eq!(args.single::<i32>().unwrap(), 2);
}

#[test]
fn single_i32_with_1_byte_long_delimiter_i32() {
    let mut args = Args::new("1,2", &[",".to_string()]);

    assert_eq!(args.single::<i32>().unwrap(), 1);
    assert_eq!(args.single::<i32>().unwrap(), 2);
}

#[test]
fn single_i32_with_wrong_char_after_first_arg() {
    let mut args = Args::new("1, 2", &[",".to_string()]);

    assert_eq!(args.single::<i32>().unwrap(), 1);
    assert!(args.single::<i32>().is_err());
}

#[test]
fn single_i32_with_one_character_being_3_bytes_long() {
    let mut args = Args::new("1★2", &["★".to_string()]);

    assert_eq!(args.single::<i32>().unwrap(), 1);
    assert_eq!(args.single::<i32>().unwrap(), 2);
}

#[test]
fn single_i32_with_untrimmed_whitespaces() {
    let mut args = Args::new(" 1, 2 ", &[",".to_string()]);

    assert!(args.single::<i32>().is_err());
}

#[test]
fn single_i32_n() {
    let args = Args::new("1,2", &[",".to_string()]);

    assert_eq!(args.single_n::<i32>().unwrap(), 1);
    assert_eq!(args.single_n::<i32>().unwrap(), 1);
}

#[test]
fn single_quoted_chaining() {
    let mut args = Args::new(r#""1, 2" "2" """#, &[" ".to_string()]);

    assert_eq!(args.single_quoted::<String>().unwrap(), "1, 2");
    assert_eq!(args.single_quoted::<String>().unwrap(), "2");
    assert_eq!(args.single_quoted::<String>().unwrap(), "");
}

#[test]
fn single_quoted_and_single_chaining() {
    let mut args = Args::new(r#""1, 2" "2" "3" 4"#, &[" ".to_string()]);

    assert_eq!(args.single_quoted::<String>().unwrap(), "1, 2");
    assert!(args.single_n::<i32>().is_err());
    assert_eq!(args.single::<String>().unwrap(), "\"2\"");
    assert_eq!(args.single_quoted::<i32>().unwrap(), 3);
    assert_eq!(args.single::<i32>().unwrap(), 4);
}

#[test]
fn full_on_args() {
    let test_text = "Some text to ensure `full()` works.";
    let args = Args::new(test_text, &[" ".to_string()]);

    assert_eq!(args.full(), test_text);
}

#[test]
fn multiple_quoted_strings_one_delimiter() {
    let args = Args::new(r#""1, 2" "a" "3" 4 "5"#, &[" ".to_string()]);

    assert_eq!(args.multiple_quoted::<String>().unwrap(), ["1, 2", "a", "3", "4", "\"5"]);
}

#[test]
fn multiple_quoted_strings_with_multiple_delimiter() {
    let args = Args::new(r#""1, 2" "a","3"4 "5"#, &[" ".to_string(), ",".to_string()]);

    assert_eq!(args.multiple_quoted::<String>().unwrap(), ["1, 2", "a", "3", "4", "\"5"]);
}

#[test]
fn multiple_quoted_strings_with_multiple_delimiters() {
    let args = Args::new(r#""1, 2" "a","3" """#, &[" ".to_string(), ",".to_string()]);

    assert_eq!(args.multiple_quoted::<String>().unwrap(), ["1, 2", "a", "3", ""]);
}

#[test]
fn multiple_quoted_i32() {
    let args = Args::new(r#""1" "2" 3"#, &[" ".to_string()]);

    assert_eq!(args.multiple_quoted::<i32>().unwrap(), [1, 2, 3]);
}

#[test]
fn multiple_quoted_quote_appears_without_delimiter_in_front() {
    let args = Args::new(r#"hello, my name is cake" 2"#, &[",".to_string(), " ".to_string()]);

    assert_eq!(args.multiple_quoted::<String>().unwrap(), ["hello", "", "my", "name", "is", "cake\"", "2"]);
}

#[test]
fn multiple_quoted_single_quote() {
    let args = Args::new(r#"hello "2 b"#, &[",".to_string(), " ".to_string()]);

    assert_eq!(args.multiple_quoted::<String>().unwrap(), ["hello", "\"2", "b"]);
}

#[test]
fn multiple_quoted_one_quote_pair() {
    let args = Args::new(r#"hello "2 b""#, &[",".to_string(), " ".to_string()]);

    assert_eq!(args.multiple_quoted::<String>().unwrap(), ["hello", "2 b"]);
}

#[test]
fn delimiter_before_multiple_quoted() {
    let args = Args::new(r#","hello, my name is cake" "2""#, &[",".to_string(), " ".to_string()]);

    assert_eq!(args.multiple_quoted::<String>().unwrap(), ["", "hello, my name is cake", "2"]);
}

#[test]
fn no_quote() {
    let args = Args::new("hello, my name is cake", &[",".to_string(), " ".to_string()]);

    assert_eq!(args.single_quoted_n::<String>().unwrap(), "hello");
}

#[test]
fn single_quoted_n() {
    let args = Args::new(r#""hello, my name is cake","test"#, &[",".to_string()]);

    assert_eq!(args.single_quoted_n::<String>().unwrap(), "hello, my name is cake");
    assert_eq!(args.single_quoted_n::<String>().unwrap(), "hello, my name is cake");
}

#[test]
fn multiple_quoted_starting_with_wrong_delimiter_in_first_quote() {
    let args = Args::new(r#""hello, my name is cake" "2""#, &[",".to_string(), " ".to_string()]);

    assert_eq!(args.multiple_quoted::<String>().unwrap(), ["hello, my name is cake", "2"]);
}

#[test]
fn multiple_quoted_with_one_correct_and_one_invalid_quote() {
    let args = Args::new(r#""hello, my name is cake" "2""#, &[",".to_string(), " ".to_string()]);

    assert_eq!(args.multiple_quoted::<String>().unwrap(), ["hello, my name is cake", "2"]);
}

#[test]
fn find_i32_one_one_byte_delimiter() {
    let mut args = Args::new("hello,my name is cake 2", &[" ".to_string()]);

    assert_eq!(args.find::<i32>().unwrap(), 2);
}

#[test]
fn find_i32_one_three_byte_delimiter() {
    let mut args = Args::new("hello,my name is cakeé2", &["é".to_string()]);

    assert_eq!(args.find::<i32>().unwrap(), 2);
}

#[test]
fn find_i32_multiple_delimiter_but_i32_not_last() {
    let mut args = Args::new("hello,my name is 2 cake", &[" ".to_string(), ",".to_string()]);

    assert_eq!(args.find::<i32>().unwrap(), 2);
}

#[test]
fn find_i32_multiple_delimiter() {
    let mut args = Args::new("hello,my name is cake 2", &[" ".to_string(), ",".to_string()]);

    assert_eq!(args.find::<i32>().unwrap(), 2);
}

#[test]
fn find_n_i32() {
    let mut args = Args::new("a 2", &[" ".to_string()]);

    assert_eq!(args.find_n::<i32>().unwrap(), 2);
    assert_eq!(args.find_n::<i32>().unwrap(), 2);
}

#[test]
fn skip() {
    let mut args = Args::new("1 2", &[" ".to_string()]);

    assert_eq!(args.skip().unwrap(), "1");
    assert_eq!(args.full(), "2");
}

#[test]
fn skip_for() {
    let mut args = Args::new("1 2 neko 100", &[" ".to_string()]);

    assert_eq!(args.skip_for(2).unwrap(), ["1", "2"]);
    assert_eq!(args.full(), "neko 100");
}

#[test]
fn len_with_one_delimiter() {
    let mut args = Args::new("1 2 neko 100", &[" ".to_string()]);

    assert_eq!(args.len(), 4);
    assert_eq!(args.len(), 4);
}

#[test]
fn len_multiple_quoted() {
    let mut args = Args::new(r#""hello, my name is cake" "2""#, &[" ".to_string()]);

    assert_eq!(args.len_quoted(), 2);
}

#[test]
fn len_before_and_after_single() {
    let mut args = Args::new("1 2", &[" ".to_string()]);

    assert_eq!(args.len(), 2);
    assert_eq!(args.single::<i32>().unwrap(), 1);
    assert_eq!(args.len(), 1);
    assert_eq!(args.single::<i32>().unwrap(), 2);
    assert_eq!(args.len(), 0);
}

#[test]
fn len_before_and_after_single_quoted() {
    let mut args = Args::new(r#""1" "2" "3""#, &[" ".to_string()]);

    assert_eq!(args.len_quoted(), 3);
    assert_eq!(args.single_quoted::<i32>().unwrap(), 1);
    assert_eq!(args.len_quoted(), 2);
    assert_eq!(args.single_quoted::<i32>().unwrap(), 2);
    assert_eq!(args.len_quoted(), 1);
    assert_eq!(args.single_quoted::<i32>().unwrap(), 3);
    assert_eq!(args.len_quoted(), 0);
}

#[test]
fn len_before_and_after_skip() {
    let mut args = Args::new("1 2", &[" ".to_string()]);

    assert_eq!(args.len(), 2);
    assert_eq!(args.skip().unwrap(), "1");
    assert_eq!(args.len(), 1);
    assert_eq!(args.skip().unwrap(), "2");
    assert_eq!(args.len(), 0);
}

#[test]
fn len_before_and_after_skip_empty_string() {
    let mut args = Args::new("", &[" ".to_string()]);

    assert_eq!(args.len(), 0);
    assert_eq!(args.skip().unwrap(), "");
    assert_eq!(args.len(), 0);
}

#[test]
fn len_before_and_after_skip_for() {
    let mut args = Args::new("1 2", &[" ".to_string()]);

    assert_eq!(args.len(), 2);
    assert_eq!(args.skip_for(4), Some(vec!["1".to_string(), "2".to_string(), "".to_string(), "".to_string()]));
    assert_eq!(args.len(), 0);
}

#[test]
fn len_before_and_after_find() {
    let mut args = Args::new("a 2 6", &[" ".to_string()]);

    assert_eq!(args.len(), 3);
    assert_eq!(args.find::<i32>().unwrap(), 2);
    assert_eq!(args.len(), 2);
    assert_eq!(args.find::<i32>().unwrap(), 6);
    assert_eq!(args.len(), 1);
    assert_eq!(args.find::<String>().unwrap(), "a");
    assert_eq!(args.len(), 0);
    assert_matches!(args.find::<String>().unwrap_err(), ArgError::Eos);
    assert_eq!(args.len(), 0);
}

#[test]
fn len_before_and_after_find_n() {
    let mut args = Args::new("a 2 6", &[" ".to_string()]);

    assert_eq!(args.len(), 3);
    assert_eq!(args.find_n::<i32>().unwrap(), 2);
    assert_eq!(args.len(), 3);
}

#[test]
fn multiple_strings_with_one_delimiter() {
    let args = Args::new("hello, my name is cake 2", &[" ".to_string()]);

    assert_eq!(args.multiple::<String>().unwrap(), ["hello,", "my", "name", "is", "cake", "2"]);
}

#[test]
fn multiple_i32_with_one_delimiter() {
    let args = Args::new("1 2 3", &[" ".to_string()]);

    assert_eq!(args.multiple::<i32>().unwrap(), [1, 2, 3]);
}

#[test]
fn multiple_i32_with_one_delimiter_and_parse_error() {
    let args = Args::new("1 2 3 abc", &[" ".to_string()]);

    assert_matches!(args.multiple::<i32>().unwrap_err(), ArgError::Parse(_));
}

#[test]
fn multiple_i32_with_three_delimiters() {
    let args = Args::new("1 2 3", &[" ".to_string(), ",".to_string()]);

    assert_eq!(args.multiple::<i32>().unwrap(), [1, 2, 3]);
}

#[test]
fn single_after_failed_single() {
    let mut args = Args::new("b 2", &[" ".to_string()]);

    assert_matches!(args.single::<i32>().unwrap_err(), ArgError::Parse(_));
    assert_eq!(args.full(), "2");
}

#[test]
fn len_quoted_after_failed_single_quoted() {
    let mut args = Args::new("b a", &[" ".to_string()]);

    assert_eq!(args.len_quoted(), 2);
    assert_matches!(args.single_quoted::<i32>().unwrap_err(), ArgError::Parse(_));
    assert_eq!(args.len_quoted(), 1);
}
<commit_msg>Fix tests<commit_after>extern crate serenity;
#[macro_use] extern crate matches;

use serenity::framework::standard::{Args, ArgError};

#[test]
fn single_i32_with_2_bytes_long_delimiter() {
    let mut args = Args::new("1, 2", &[", ".to_string()]);

    assert_eq!(args.single::<i32>().unwrap(), 1);
    assert_eq!(args.single::<i32>().unwrap(), 2);
}

#[test]
fn single_i32_with_1_byte_long_delimiter_i32() {
    let mut args = Args::new("1,2", &[",".to_string()]);

    assert_eq!(args.single::<i32>().unwrap(), 1);
    assert_eq!(args.single::<i32>().unwrap(), 2);
}

#[test]
fn single_i32_with_wrong_char_after_first_arg() {
    let mut args = Args::new("1, 2", &[",".to_string()]);

    assert_eq!(args.single::<i32>().unwrap(), 1);
    assert!(args.single::<i32>().is_err());
}

#[test]
fn single_i32_with_one_character_being_3_bytes_long() {
    let mut args = Args::new("1★2", &["★".to_string()]);

    assert_eq!(args.single::<i32>().unwrap(), 1);
    assert_eq!(args.single::<i32>().unwrap(), 2);
}

#[test]
fn single_i32_with_untrimmed_whitespaces() {
    let mut args = Args::new(" 1, 2 ", &[",".to_string()]);

    assert!(args.single::<i32>().is_err());
}

#[test]
fn single_i32_n() {
    let args = Args::new("1,2", &[",".to_string()]);

    assert_eq!(args.single_n::<i32>().unwrap(), 1);
    assert_eq!(args.single_n::<i32>().unwrap(), 1);
}

#[test]
fn single_quoted_chaining() {
    let mut args = Args::new(r#""1, 2" "2" """#, &[" ".to_string()]);

    assert_eq!(args.single_quoted::<String>().unwrap(), "1, 2");
    assert_eq!(args.single_quoted::<String>().unwrap(), "2");
    assert_eq!(args.single_quoted::<String>().unwrap(), "");
}

#[test]
fn single_quoted_and_single_chaining() {
    let mut args = Args::new(r#""1, 2" "2" "3" 4"#, &[" ".to_string()]);

    assert_eq!(args.single_quoted::<String>().unwrap(), "1, 2");
    assert!(args.single_n::<i32>().is_err());
    assert_eq!(args.single::<String>().unwrap(), "\"2\"");
    assert_eq!(args.single_quoted::<i32>().unwrap(), 3);
    assert_eq!(args.single::<i32>().unwrap(), 4);
}

#[test]
fn full_on_args() {
    let test_text = "Some text to ensure `full()` works.";
    let args = Args::new(test_text, &[" ".to_string()]);

    assert_eq!(args.full(), test_text);
}

#[test]
fn multiple_quoted_strings_one_delimiter() {
    let args = Args::new(r#""1, 2" "a" "3" 4 "5"#, &[" ".to_string()]);

    assert_eq!(args.multiple_quoted::<String>().unwrap(), ["1, 2", "a", "3", "4", "\"5"]);
}

#[test]
fn multiple_quoted_strings_with_multiple_delimiter() {
    let args = Args::new(r#""1, 2" "a","3"4 "5"#, &[" ".to_string(), ",".to_string()]);

    assert_eq!(args.multiple_quoted::<String>().unwrap(), ["1, 2", "a", "3", "4", "\"5"]);
}

#[test]
fn multiple_quoted_strings_with_multiple_delimiters() {
    let args = Args::new(r#""1, 2" "a","3" """#, &[" ".to_string(), ",".to_string()]);

    assert_eq!(args.multiple_quoted::<String>().unwrap(), ["1, 2", "a", "3", ""]);
}

#[test]
fn multiple_quoted_i32() {
    let args = Args::new(r#""1" "2" 3"#, &[" ".to_string()]);

    assert_eq!(args.multiple_quoted::<i32>().unwrap(), [1, 2, 3]);
}

#[test]
fn multiple_quoted_quote_appears_without_delimiter_in_front() {
    let args = Args::new(r#"hello, my name is cake" 2"#, &[",".to_string(), " ".to_string()]);

    assert_eq!(args.multiple_quoted::<String>().unwrap(), ["hello", "", "my", "name", "is", "cake\"", "2"]);
}

#[test]
fn multiple_quoted_single_quote() {
    let args = Args::new(r#"hello "2 b"#, &[",".to_string(), " ".to_string()]);

    assert_eq!(args.multiple_quoted::<String>().unwrap(), ["hello", "\"2", "b"]);
}

#[test]
fn multiple_quoted_one_quote_pair() {
    let args = Args::new(r#"hello "2 b""#, &[",".to_string(), " ".to_string()]);

    assert_eq!(args.multiple_quoted::<String>().unwrap(), ["hello", "2 b"]);
}

#[test]
fn delimiter_before_multiple_quoted() {
    let args = Args::new(r#","hello, my name is cake" "2""#, &[",".to_string(), " ".to_string()]);

    assert_eq!(args.multiple_quoted::<String>().unwrap(), ["", "hello, my name is cake", "2"]);
}

#[test]
fn no_quote() {
    let args = Args::new("hello, my name is cake", &[",".to_string(), " ".to_string()]);

    assert_eq!(args.single_quoted_n::<String>().unwrap(), "hello");
}

#[test]
fn single_quoted_n() {
    let args = Args::new(r#""hello, my name is cake","test"#, &[",".to_string()]);

    assert_eq!(args.single_quoted_n::<String>().unwrap(), "hello, my name is cake");
    assert_eq!(args.single_quoted_n::<String>().unwrap(), "hello, my name is cake");
}

#[test]
fn multiple_quoted_starting_with_wrong_delimiter_in_first_quote() {
    let args = Args::new(r#""hello, my name is cake" "2""#, &[",".to_string(), " ".to_string()]);

    assert_eq!(args.multiple_quoted::<String>().unwrap(), ["hello, my name is cake", "2"]);
}

#[test]
fn multiple_quoted_with_one_correct_and_one_invalid_quote() {
    let args = Args::new(r#""hello, my name is cake" "2""#, &[",".to_string(), " ".to_string()]);

    assert_eq!(args.multiple_quoted::<String>().unwrap(), ["hello, my name is cake", "2"]);
}

#[test]
fn find_i32_one_one_byte_delimiter() {
    let mut args = Args::new("hello,my name is cake 2", &[" ".to_string()]);

    assert_eq!(args.find::<i32>().unwrap(), 2);
}

#[test]
fn find_i32_one_three_byte_delimiter() {
    let mut args = Args::new("hello,my name is cakeé2", &["é".to_string()]);

    assert_eq!(args.find::<i32>().unwrap(), 2);
}

#[test]
fn find_i32_multiple_delimiter_but_i32_not_last() {
    let mut args = Args::new("hello,my name is 2 cake", &[" ".to_string(), ",".to_string()]);

    assert_eq!(args.find::<i32>().unwrap(), 2);
}

#[test]
fn find_i32_multiple_delimiter() {
    let mut args = Args::new("hello,my name is cake 2", &[" ".to_string(), ",".to_string()]);

    assert_eq!(args.find::<i32>().unwrap(), 2);
}

#[test]
fn find_n_i32() {
    let mut args = Args::new("a 2", &[" ".to_string()]);

    assert_eq!(args.find_n::<i32>().unwrap(), 2);
    assert_eq!(args.find_n::<i32>().unwrap(), 2);
}

#[test]
fn skip() {
    let mut args = Args::new("1 2", &[" ".to_string()]);

    assert_eq!(args.skip().unwrap(), "1");
    assert_eq!(args.full(), "2");
}

#[test]
fn skip_for() {
    let mut args = Args::new("1 2 neko 100", &[" ".to_string()]);

    assert_eq!(args.skip_for(2).unwrap(), ["1", "2"]);
    assert_eq!(args.full(), "neko 100");
}

#[test]
fn len_with_one_delimiter() {
    let mut args = Args::new("1 2 neko 100", &[" ".to_string()]);

    assert_eq!(args.len(), 4);
    assert_eq!(args.len(), 4);
}

#[test]
fn len_multiple_quoted() {
    let mut args = Args::new(r#""hello, my name is cake" "2""#, &[" ".to_string()]);

    assert_eq!(args.len_quoted(), 2);
}

#[test]
fn len_before_and_after_single() {
    let mut args = Args::new("1 2", &[" ".to_string()]);

    assert_eq!(args.len(), 2);
    assert_eq!(args.single::<i32>().unwrap(), 1);
    assert_eq!(args.len(), 1);
    assert_eq!(args.single::<i32>().unwrap(), 2);
    assert_eq!(args.len(), 0);
}

#[test]
fn len_before_and_after_single_quoted() {
    let mut args = Args::new(r#""1" "2" "3""#, &[" ".to_string()]);

    assert_eq!(args.len_quoted(), 3);
    assert_eq!(args.single_quoted::<i32>().unwrap(), 1);
    assert_eq!(args.len_quoted(), 2);
    assert_eq!(args.single_quoted::<i32>().unwrap(), 2);
    assert_eq!(args.len_quoted(), 1);
    assert_eq!(args.single_quoted::<i32>().unwrap(), 3);
    assert_eq!(args.len_quoted(), 0);
}

#[test]
fn len_before_and_after_skip() {
    let mut args = Args::new("1 2", &[" ".to_string()]);

    assert_eq!(args.len(), 2);
    assert_eq!(args.skip().unwrap(), "1");
    assert_eq!(args.len(), 1);
    assert_eq!(args.skip().unwrap(), "2");
    assert_eq!(args.len(), 0);
}

#[test]
fn len_before_and_after_skip_empty_string() {
    let mut args = Args::new("", &[" ".to_string()]);

    assert_eq!(args.len(), 0);
    assert_eq!(args.skip(), None);
    assert_eq!(args.len(), 0);
}

#[test]
fn len_before_and_after_skip_for() {
    let mut args = Args::new("1 2", &[" ".to_string()]);

    assert_eq!(args.len(), 2);
    assert_eq!(args.skip_for(2), Some(vec!["1".to_string(), "2".to_string()]));
    assert_eq!(args.skip_for(2), None);
    assert_eq!(args.len(), 0);
}

#[test]
fn len_before_and_after_find() {
    let mut args = Args::new("a 2 6", &[" ".to_string()]);

    assert_eq!(args.len(), 3);
    assert_eq!(args.find::<i32>().unwrap(), 2);
    assert_eq!(args.len(), 2);
    assert_eq!(args.find::<i32>().unwrap(), 6);
    assert_eq!(args.len(), 1);
    assert_eq!(args.find::<String>().unwrap(), "a");
    assert_eq!(args.len(), 0);
    assert_matches!(args.find::<String>().unwrap_err(), ArgError::Eos);
    assert_eq!(args.len(), 0);
}

#[test]
fn len_before_and_after_find_n() {
    let mut args = Args::new("a 2 6", &[" ".to_string()]);

    assert_eq!(args.len(), 3);
    assert_eq!(args.find_n::<i32>().unwrap(), 2);
    assert_eq!(args.len(), 3);
}

#[test]
fn multiple_strings_with_one_delimiter() {
    let args = Args::new("hello, my name is cake 2", &[" ".to_string()]);

    assert_eq!(args.multiple::<String>().unwrap(), ["hello,", "my", "name", "is", "cake", "2"]);
}

#[test]
fn multiple_i32_with_one_delimiter() {
    let args = Args::new("1 2 3", &[" ".to_string()]);

    assert_eq!(args.multiple::<i32>().unwrap(), [1, 2, 3]);
}

#[test]
fn multiple_i32_with_one_delimiter_and_parse_error() {
    let args = Args::new("1 2 3 abc", &[" ".to_string()]);

    assert_matches!(args.multiple::<i32>().unwrap_err(), ArgError::Parse(_));
}

#[test]
fn multiple_i32_with_three_delimiters() {
    let args = Args::new("1 2 3", &[" ".to_string(), ",".to_string()]);

    assert_eq!(args.multiple::<i32>().unwrap(), [1, 2, 3]);
}

#[test]
fn single_after_failed_single() {
    let mut args = Args::new("b 2", &[" ".to_string()]);

    assert_matches!(args.single::<i32>().unwrap_err(), ArgError::Parse(_));
    assert_eq!(args.full(), "2");
}

#[test]
fn len_quoted_after_failed_single_quoted() {
    let mut args = Args::new("b a", &[" ".to_string()]);

    assert_eq!(args.len_quoted(), 2);
    assert_matches!(args.single_quoted::<i32>().unwrap_err(), ArgError::Parse(_));
    assert_eq!(args.len_quoted(), 1);
}
<|endoftext|>


<commit_before>use libc::{c_int, c_ushort, c_uchar, size_t};

use symbols::{ZOPFLI_WINDOW_MASK, ZOPFLI_MIN_MATCH};

const HASH_SHIFT: c_int = 5;
const HASH_MASK: c_int = 32767;

#[repr(C)]
pub struct ZopfliHash {
    head: Vec<c_int>,  /* Hash value to index of its most recent occurrence. */
    prev: Vec<c_ushort>,  /* Index to index of prev. occurrence of same hash. */
    hashval: Vec<c_int>,  /* Index to hash value at this index. */
    val: c_int,  /* Current hash value. */

    /* Fields with similar purpose as the above hash, but for the second hash with
    a value that is calculated differently.  */
    head2: Vec<c_int>,  /* Hash value to index of its most recent occurrence. */
    prev2: Vec<c_ushort>,  /* Index to index of prev. occurrence of same hash. */
    hashval2: Vec<c_int>,  /* Index to hash value at this index. */
    val2: c_int,  /* Current hash value. */

    same: Vec<c_ushort>,  /* Amount of repetitions of same byte after this .*/
}

impl ZopfliHash {
    pub fn new(window_size: size_t) -> ZopfliHash {
        ZopfliHash {
           head: vec![-1; 65536],
           prev: (0..window_size as c_ushort).collect::<Vec<_>>(),
           hashval: vec![-1; window_size],
           val: 0,

           /* Fields with similar purpose as the above hash, but for the second hash with
           a value that is calculated differently.  */
           head2: vec![-1; 65536],
           prev2: (0..window_size as c_ushort).collect::<Vec<_>>(),
           hashval2: vec![-1; window_size],
           val2: 0,

           same: vec![0; window_size],
       }
    }

    /// Update the sliding hash value with the given byte. All calls to this function
    /// must be made on consecutive input characters. Since the hash value exists out
    /// of multiple input bytes, a few warmups with this function are needed initially.
    pub fn update_val(&mut self, c: c_uchar) {
        self.val = ((self.val << HASH_SHIFT) ^ c as c_int) & HASH_MASK;
    }
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn UpdateHashValue(h_ptr: *mut ZopfliHash, c: c_uchar) {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.update_val(c);
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliWarmupHash(array: *const c_uchar, pos: size_t, end: size_t, h_ptr: *mut ZopfliHash) {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    let c = unsafe { *array.offset((pos + 0) as isize) };
    h.update_val(c);

    if pos + 1 < end {
        let c = unsafe { *array.offset((pos + 1) as isize) };
        h.update_val(c);
    }
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliUpdateHash(array: *const c_uchar, pos: size_t, end: size_t, h_ptr: *mut ZopfliHash) {
    let hpos = (pos & ZOPFLI_WINDOW_MASK) as usize;
    let mut amount: c_int = 0;

    let hash_value = if pos + ZOPFLI_MIN_MATCH as size_t <= end {
        unsafe { *array.offset((pos + ZOPFLI_MIN_MATCH as size_t - 1) as isize) }
    } else {
        0
    };
    UpdateHashValue(h_ptr, hash_value);

    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.hashval[hpos] = h.val;

    if h.head[h.val as usize] != -1 && h.hashval[h.head[h.val as usize] as usize] == h.val {
        h.prev[hpos] = h.head[h.val as usize] as c_ushort;
    } else {
        h.prev[hpos] = hpos as c_ushort;
    }

    h.head[h.val as usize] = hpos as c_int;

    /* Update "same". */
    if h.same[((pos - 1) & ZOPFLI_WINDOW_MASK) as usize] > 1 {
        amount = h.same[((pos - 1) & ZOPFLI_WINDOW_MASK) as usize] as c_int - 1;
    }

    unsafe {
        while pos + amount as size_t + 1 < end && *array.offset(pos as isize) == *array.offset((pos + amount as size_t + 1) as isize) && amount < -1 {
            amount += 1;
        }
    }
    h.same[hpos] = amount as c_ushort;

    h.val2 = (((h.same[hpos] - ZOPFLI_MIN_MATCH) & 255) ^ h.val as c_ushort) as c_int;
    h.hashval2[hpos] = h.val2;
    if h.head2[h.val2 as usize] != -1 as i32 && h.hashval2[h.head2[h.val2 as usize] as usize] == h.val2 {
        h.prev2[hpos] = h.head2[h.val2 as usize] as c_ushort;
    } else {
        h.prev2[hpos] = hpos as c_ushort;
    }
    h.head2[h.val2 as usize] = hpos as c_int;
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliHashHead(h_ptr: *mut ZopfliHash) -> *mut c_int {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.head.as_mut_ptr()
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliHashPrev(h_ptr: *mut ZopfliHash) -> *mut c_ushort {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.prev.as_mut_ptr()
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliHashHashval(h_ptr: *mut ZopfliHash) -> *mut c_int {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.hashval.as_mut_ptr()
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliHashVal(h_ptr: *mut ZopfliHash) -> c_int {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.val
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliHashHead2(h_ptr: *mut ZopfliHash) -> *mut c_int {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.head2.as_mut_ptr()
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliHashPrev2(h_ptr: *mut ZopfliHash) -> *mut c_ushort {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.prev2.as_mut_ptr()
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliHashHashval2(h_ptr: *mut ZopfliHash) -> *mut c_int {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.hashval2.as_mut_ptr()
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliHashVal2(h_ptr: *mut ZopfliHash) -> c_int {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.val2
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliHashSame(h_ptr: *mut ZopfliHash) -> *mut c_ushort {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.same.as_mut_ptr()
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliCleanHash(ptr: *mut ZopfliHash) {
    if ptr.is_null() { return }
    unsafe { Box::from_raw(ptr); }
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliInitHash(window_size: size_t) -> *mut ZopfliHash {
    Box::into_raw(Box::new(ZopfliHash::new(window_size)))
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliResetHash(window_size: size_t, h_ptr: *mut ZopfliHash) {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };

    h.val = 0;
    h.head = vec![-1; 65536];
    h.prev = (0..window_size as c_ushort).collect::<Vec<_>>();
    h.hashval = vec![-1; window_size];

    h.same = vec![0; window_size];

    h.val2 = 0;
    h.head2 = vec![-1; 65536];
    h.prev2 = (0..window_size as c_ushort).collect::<Vec<_>>();
    h.hashval2 = vec![-1; window_size];
}
<commit_msg>Move the work of ZopfliUpdateHash to an update method<commit_after>use libc::{c_int, c_ushort, c_uchar, size_t};

use symbols::{ZOPFLI_WINDOW_MASK, ZOPFLI_MIN_MATCH};

const HASH_SHIFT: c_int = 5;
const HASH_MASK: c_int = 32767;

#[repr(C)]
pub struct ZopfliHash {
    head: Vec<c_int>,  /* Hash value to index of its most recent occurrence. */
    prev: Vec<c_ushort>,  /* Index to index of prev. occurrence of same hash. */
    hashval: Vec<c_int>,  /* Index to hash value at this index. */
    val: c_int,  /* Current hash value. */

    /* Fields with similar purpose as the above hash, but for the second hash with
    a value that is calculated differently.  */
    head2: Vec<c_int>,  /* Hash value to index of its most recent occurrence. */
    prev2: Vec<c_ushort>,  /* Index to index of prev. occurrence of same hash. */
    hashval2: Vec<c_int>,  /* Index to hash value at this index. */
    val2: c_int,  /* Current hash value. */

    same: Vec<c_ushort>,  /* Amount of repetitions of same byte after this .*/
}

impl ZopfliHash {
    pub fn new(window_size: size_t) -> ZopfliHash {
        ZopfliHash {
           head: vec![-1; 65536],
           prev: (0..window_size as c_ushort).collect::<Vec<_>>(),
           hashval: vec![-1; window_size],
           val: 0,

           /* Fields with similar purpose as the above hash, but for the second hash with
           a value that is calculated differently.  */
           head2: vec![-1; 65536],
           prev2: (0..window_size as c_ushort).collect::<Vec<_>>(),
           hashval2: vec![-1; window_size],
           val2: 0,

           same: vec![0; window_size],
       }
    }

    /// Update the sliding hash value with the given byte. All calls to this function
    /// must be made on consecutive input characters. Since the hash value exists out
    /// of multiple input bytes, a few warmups with this function are needed initially.
    pub fn update_val(&mut self, c: c_uchar) {
        self.val = ((self.val << HASH_SHIFT) ^ c as c_int) & HASH_MASK;
    }

    pub fn update(&mut self, array: *const c_uchar, pos: size_t, end: size_t) {
        let hpos = (pos & ZOPFLI_WINDOW_MASK) as usize;
        let mut amount: c_int = 0;

        let hash_value = if pos + ZOPFLI_MIN_MATCH as size_t <= end {
            unsafe { *array.offset((pos + ZOPFLI_MIN_MATCH as size_t - 1) as isize) }
        } else {
            0
        };
        self.update_val(hash_value);

        self.hashval[hpos] = self.val;

        let index = self.val as usize;

        if self.head[index] != -1 && self.hashval[self.head[index] as usize] == self.val {
            self.prev[hpos] = self.head[index] as c_ushort;
        } else {
            self.prev[hpos] = hpos as c_ushort;
        }

        self.head[index] = hpos as c_int;

        // Update "same".
        if self.same[((pos - 1) & ZOPFLI_WINDOW_MASK) as usize] > 1 {
            amount = self.same[((pos - 1) & ZOPFLI_WINDOW_MASK) as usize] as c_int - 1;
        }

        unsafe {
            while pos + amount as size_t + 1 < end && *array.offset(pos as isize) == *array.offset((pos + amount as size_t + 1) as isize) && amount < -1 {
                amount += 1;
            }
        }
        self.same[hpos] = amount as c_ushort;

        self.val2 = (((self.same[hpos] - ZOPFLI_MIN_MATCH) & 255) ^ self.val as c_ushort) as c_int;
        self.hashval2[hpos] = self.val2;

        let index2 = self.val2 as usize;
        if self.head2[index2] != -1 as i32 && self.hashval2[self.head2[index2] as usize] == self.val2 {
            self.prev2[hpos] = self.head2[index2] as c_ushort;
        } else {
            self.prev2[hpos] = hpos as c_ushort;
        }
        self.head2[index2] = hpos as c_int;
    }
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn UpdateHashValue(h_ptr: *mut ZopfliHash, c: c_uchar) {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.update_val(c);
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliWarmupHash(array: *const c_uchar, pos: size_t, end: size_t, h_ptr: *mut ZopfliHash) {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    let c = unsafe { *array.offset((pos + 0) as isize) };
    h.update_val(c);

    if pos + 1 < end {
        let c = unsafe { *array.offset((pos + 1) as isize) };
        h.update_val(c);
    }
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliUpdateHash(array: *const c_uchar, pos: size_t, end: size_t, h_ptr: *mut ZopfliHash) {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.update(array, pos, end);
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliHashHead(h_ptr: *mut ZopfliHash) -> *mut c_int {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.head.as_mut_ptr()
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliHashPrev(h_ptr: *mut ZopfliHash) -> *mut c_ushort {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.prev.as_mut_ptr()
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliHashHashval(h_ptr: *mut ZopfliHash) -> *mut c_int {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.hashval.as_mut_ptr()
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliHashVal(h_ptr: *mut ZopfliHash) -> c_int {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.val
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliHashHead2(h_ptr: *mut ZopfliHash) -> *mut c_int {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.head2.as_mut_ptr()
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliHashPrev2(h_ptr: *mut ZopfliHash) -> *mut c_ushort {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.prev2.as_mut_ptr()
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliHashHashval2(h_ptr: *mut ZopfliHash) -> *mut c_int {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.hashval2.as_mut_ptr()
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliHashVal2(h_ptr: *mut ZopfliHash) -> c_int {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.val2
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliHashSame(h_ptr: *mut ZopfliHash) -> *mut c_ushort {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };
    h.same.as_mut_ptr()
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliCleanHash(ptr: *mut ZopfliHash) {
    if ptr.is_null() { return }
    unsafe { Box::from_raw(ptr); }
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliInitHash(window_size: size_t) -> *mut ZopfliHash {
    Box::into_raw(Box::new(ZopfliHash::new(window_size)))
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliResetHash(window_size: size_t, h_ptr: *mut ZopfliHash) {
    let h = unsafe {
        assert!(!h_ptr.is_null());
        &mut *h_ptr
    };

    h.val = 0;
    h.head = vec![-1; 65536];
    h.prev = (0..window_size as c_ushort).collect::<Vec<_>>();
    h.hashval = vec![-1; window_size];

    h.same = vec![0; window_size];

    h.val2 = 0;
    h.head2 = vec![-1; 65536];
    h.prev2 = (0..window_size as c_ushort).collect::<Vec<_>>();
    h.hashval2 = vec![-1; window_size];
}
<|endoftext|>


<commit_before>#![cfg(target_pointer_width = "64")]

use std::mem;
use syn::{Expr, Item, Lit, Pat, Type};

#[test]
fn test_expr_size() {
    assert_eq!(mem::size_of::<Expr>(), 264);
}

#[test]
fn test_item_size() {
    assert_eq!(mem::size_of::<Item>(), 320);
}

#[test]
fn test_type_size() {
    assert_eq!(mem::size_of::<Type>(), 280);
}

#[test]
fn test_pat_size() {
    assert_eq!(mem::size_of::<Pat>(), 144);
}

#[test]
fn test_lit_size() {
    assert_eq!(mem::size_of::<Lit>(), 32);
}
<commit_msg>Update test suite to nightly-2022-11-24<commit_after>#![cfg(target_pointer_width = "64")]

use std::mem;
use syn::{Expr, Item, Lit, Pat, Type};

#[test]
fn test_expr_size() {
    assert_eq!(mem::size_of::<Expr>(), 272);
}

#[test]
fn test_item_size() {
    assert_eq!(mem::size_of::<Item>(), 320);
}

#[test]
fn test_type_size() {
    assert_eq!(mem::size_of::<Type>(), 288);
}

#[test]
fn test_pat_size() {
    assert_eq!(mem::size_of::<Pat>(), 144);
}

#[test]
fn test_lit_size() {
    assert_eq!(mem::size_of::<Lit>(), 32);
}
<|endoftext|>


<commit_before>use common::util::*;

static UTIL_NAME: &'static str = "sort";

fn new_ucmd() -> UCommand {
    TestScenario::new(UTIL_NAME).ucmd()
}

#[test]
fn test_numeric_floats_and_ints() {
    test_helper("numeric_floats_and_ints", "-n");
}

#[test]
fn test_numeric_floats() {
    test_helper("numeric_floats", "-n");
}

#[test]
fn test_numeric_unfixed_floats() {
    test_helper("numeric_unfixed_floats", "-n");
}

#[test]
fn test_numeric_fixed_floats() {
    test_helper("numeric_fixed_floats", "-n");
}

#[test]
fn test_numeric_unsorted_ints() {
    test_helper("numeric_unsorted_ints", "-n");
}

#[test]
fn test_human_block_sizes() {
    test_helper("human_block_sizes", "-h");
}

#[test]
fn test_month_default() {
    test_helper("month_default", "-M");
}

#[test]
fn test_month_stable() {
    test_helper("month_stable", "-Ms");
}

#[test]
fn test_default_unsorted_ints() {
    test_helper("default_unsorted_ints", "");
}

#[test]
fn test_numeric_unique_ints() {
    test_helper("numeric_unsorted_ints_unique", "-nu");
}

#[test]
fn test_version() {
    test_helper("version", "-V");
}

#[test]
fn test_multiple_files() {
    new_ucmd()
        .arg("-n")
        .arg("multiple_files1.txt")
        .arg("multiple_files2.txt")
        .succeeds().stdout_is_fixture("multiple_files.expected");
}

#[test]
fn test_merge_interleaved() {
    new_ucmd()
        .arg("-m")
        .arg("merge_ints_interleaved_1.txt")
        .arg("merge_ints_interleaved_2.txt")
        .arg("merge_ints_interleaved_3.txt")
        .succeeds().stdout_is_fixture("merge_ints_interleaved.expected");
}

#[test]
fn test_merge_unique() {
    new_ucmd()
        .arg("-m")
        .arg("--unique")
        .arg("merge_ints_interleaved_1.txt")
        .arg("merge_ints_interleaved_2.txt")
        .arg("merge_ints_interleaved_3.txt")
        .arg("merge_ints_interleaved_3.txt")
        .arg("merge_ints_interleaved_2.txt")
        .arg("merge_ints_interleaved_1.txt")
        .succeeds().stdout_is_fixture("merge_ints_interleaved.expected");
}

#[test]
fn test_merge_reversed() {
    new_ucmd()
        .arg("-m")
        .arg("--reverse")
        .arg("merge_ints_reversed_1.txt")
        .arg("merge_ints_reversed_2.txt")
        .arg("merge_ints_reversed_3.txt")
        .succeeds().stdout_is_fixture("merge_ints_reversed.expected");
}

#[test]
fn test_check() {
    new_ucmd()
        .arg("-c")
        .arg("check_fail.txt")
        .fails().stdout_is("sort: disorder in line 4\n");

    new_ucmd()
        .arg("-c")
        .arg("multiple_files.expected")
        .succeeds().stdout_is("");
}

fn test_helper(file_name: &str, args: &str) {
    new_ucmd().arg(args).arg(format!("{}{}", file_name, ".txt"))
        .succeeds().stdout_is_fixture(format!("{}{}", file_name, ".expected"));
}
<commit_msg>sort: use stdout_only_fixture in tests<commit_after>use common::util::*;

static UTIL_NAME: &'static str = "sort";

fn new_ucmd() -> UCommand {
    TestScenario::new(UTIL_NAME).ucmd()
}

#[test]
fn test_numeric_floats_and_ints() {
    test_helper("numeric_floats_and_ints", "-n");
}

#[test]
fn test_numeric_floats() {
    test_helper("numeric_floats", "-n");
}

#[test]
fn test_numeric_unfixed_floats() {
    test_helper("numeric_unfixed_floats", "-n");
}

#[test]
fn test_numeric_fixed_floats() {
    test_helper("numeric_fixed_floats", "-n");
}

#[test]
fn test_numeric_unsorted_ints() {
    test_helper("numeric_unsorted_ints", "-n");
}

#[test]
fn test_human_block_sizes() {
    test_helper("human_block_sizes", "-h");
}

#[test]
fn test_month_default() {
    test_helper("month_default", "-M");
}

#[test]
fn test_month_stable() {
    test_helper("month_stable", "-Ms");
}

#[test]
fn test_default_unsorted_ints() {
    test_helper("default_unsorted_ints", "");
}

#[test]
fn test_numeric_unique_ints() {
    test_helper("numeric_unsorted_ints_unique", "-nu");
}

#[test]
fn test_version() {
    test_helper("version", "-V");
}

#[test]
fn test_multiple_files() {
    new_ucmd()
        .arg("-n")
        .arg("multiple_files1.txt")
        .arg("multiple_files2.txt")
        .succeeds().stdout_only_fixture("multiple_files.expected");
}

#[test]
fn test_merge_interleaved() {
    new_ucmd()
        .arg("-m")
        .arg("merge_ints_interleaved_1.txt")
        .arg("merge_ints_interleaved_2.txt")
        .arg("merge_ints_interleaved_3.txt")
        .succeeds().stdout_only_fixture("merge_ints_interleaved.expected");
}

#[test]
fn test_merge_unique() {
    new_ucmd()
        .arg("-m")
        .arg("--unique")
        .arg("merge_ints_interleaved_1.txt")
        .arg("merge_ints_interleaved_2.txt")
        .arg("merge_ints_interleaved_3.txt")
        .arg("merge_ints_interleaved_3.txt")
        .arg("merge_ints_interleaved_2.txt")
        .arg("merge_ints_interleaved_1.txt")
        .succeeds().stdout_only_fixture("merge_ints_interleaved.expected");
}

#[test]
fn test_merge_reversed() {
    new_ucmd()
        .arg("-m")
        .arg("--reverse")
        .arg("merge_ints_reversed_1.txt")
        .arg("merge_ints_reversed_2.txt")
        .arg("merge_ints_reversed_3.txt")
        .succeeds().stdout_only_fixture("merge_ints_reversed.expected");
}

#[test]
fn test_check() {
    new_ucmd()
        .arg("-c")
        .arg("check_fail.txt")
        .fails().stdout_is("sort: disorder in line 4\n");

    new_ucmd()
        .arg("-c")
        .arg("multiple_files.expected")
        .succeeds().stdout_is("");
}

fn test_helper(file_name: &str, args: &str) {
    new_ucmd().arg(args).arg(format!("{}{}", file_name, ".txt"))
        .succeeds().stdout_is_fixture(format!("{}{}", file_name, ".expected"));
}
<|endoftext|>


<commit_before><commit_msg>Fix eg01<commit_after><|endoftext|>


<commit_before><commit_msg>Parse await expression<commit_after><|endoftext|>