<commit_before>// The Computer Language Benchmarks Game
// http://benchmarksgame.alioth.debian.org/
//
// contributed by the Rust Project Developers

// Copyright (c) 2011-2014 The Rust Project Developers
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// - Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in
//   the documentation and/or other materials provided with the
//   distribution.
//
// - Neither the name of "The Computer Language Benchmarks Game" nor
//   the name of "The Computer Language Shootout Benchmarks" nor the
//   names of its contributors may be used to endorse or promote
//   products derived from this software without specific prior
//   written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

use std::mem;

const PI: f64 = 3.141592653589793;
const SOLAR_MASS: f64 = 4.0 * PI * PI;
const YEAR: f64 = 365.24;
const N_BODIES: usize = 5;

static BODIES: [Planet;N_BODIES] = [
    // Sun
    Planet {
        x: 0.0, y: 0.0, z: 0.0,
        vx: 0.0, vy: 0.0, vz: 0.0,
        mass: SOLAR_MASS,
    },
    // Jupiter
    Planet {
        x: 4.84143144246472090e+00,
        y: -1.16032004402742839e+00,
        z: -1.03622044471123109e-01,
        vx: 1.66007664274403694e-03 * YEAR,
        vy: 7.69901118419740425e-03 * YEAR,
        vz: -6.90460016972063023e-05 * YEAR,
        mass: 9.54791938424326609e-04 * SOLAR_MASS,
    },
    // Saturn
    Planet {
        x: 8.34336671824457987e+00,
        y: 4.12479856412430479e+00,
        z: -4.03523417114321381e-01,
        vx: -2.76742510726862411e-03 * YEAR,
        vy: 4.99852801234917238e-03 * YEAR,
        vz: 2.30417297573763929e-05 * YEAR,
        mass: 2.85885980666130812e-04 * SOLAR_MASS,
    },
    // Uranus
    Planet {
        x: 1.28943695621391310e+01,
        y: -1.51111514016986312e+01,
        z: -2.23307578892655734e-01,
        vx: 2.96460137564761618e-03 * YEAR,
        vy: 2.37847173959480950e-03 * YEAR,
        vz: -2.96589568540237556e-05 * YEAR,
        mass: 4.36624404335156298e-05 * SOLAR_MASS,
    },
    // Neptune
    Planet {
        x: 1.53796971148509165e+01,
        y: -2.59193146099879641e+01,
        z: 1.79258772950371181e-01,
        vx: 2.68067772490389322e-03 * YEAR,
        vy: 1.62824170038242295e-03 * YEAR,
        vz: -9.51592254519715870e-05 * YEAR,
        mass: 5.15138902046611451e-05 * SOLAR_MASS,
    },
];

#[derive(Copy, Clone)]
struct Planet {
    x: f64, y: f64, z: f64,
    vx: f64, vy: f64, vz: f64,
    mass: f64,
}

fn advance(bodies: &mut [Planet;N_BODIES], dt: f64, steps: isize) {
    for _ in 0..steps {
        let mut b_slice: &mut [_] = bodies;
        loop {
            let bi = match shift_mut_ref(&mut b_slice) {
                Some(bi) => bi,
                None => break
            };
            for bj in &mut *b_slice {
                let dx = bi.x - bj.x;
                let dy = bi.y - bj.y;
                let dz = bi.z - bj.z;

                let d2 = dx * dx + dy * dy + dz * dz;
                let mag = dt / (d2 * d2.sqrt());

                let massj_mag = bj.mass * mag;
                bi.vx -= dx * massj_mag;
                bi.vy -= dy * massj_mag;
                bi.vz -= dz * massj_mag;

                let massi_mag = bi.mass * mag;
                bj.vx += dx * massi_mag;
                bj.vy += dy * massi_mag;
                bj.vz += dz * massi_mag;
            }
            bi.x += dt * bi.vx;
            bi.y += dt * bi.vy;
            bi.z += dt * bi.vz;
        }
    }
}

fn energy(bodies: &[Planet;N_BODIES]) -> f64 {
    let mut e = 0.0;
    let mut bodies = bodies.iter();
    loop {
        let bi = match bodies.next() {
            Some(bi) => bi,
            None => break
        };
        e += (bi.vx * bi.vx + bi.vy * bi.vy + bi.vz * bi.vz) * bi.mass / 2.0;
        for bj in bodies.clone() {
            let dx = bi.x - bj.x;
            let dy = bi.y - bj.y;
            let dz = bi.z - bj.z;
            let dist = (dx * dx + dy * dy + dz * dz).sqrt();
            e -= bi.mass * bj.mass / dist;
        }
    }
    e
}

fn offset_momentum(bodies: &mut [Planet;N_BODIES]) {
    let mut px = 0.0;
    let mut py = 0.0;
    let mut pz = 0.0;
    for bi in bodies.iter() {
        px += bi.vx * bi.mass;
        py += bi.vy * bi.mass;
        pz += bi.vz * bi.mass;
    }
    let sun = &mut bodies[0];
    sun.vx = - px / SOLAR_MASS;
    sun.vy = - py / SOLAR_MASS;
    sun.vz = - pz / SOLAR_MASS;
}

fn main() {
    let n = if std::env::var_os("RUST_BENCH").is_some() {
        5000000
    } else {
        std::env::args().nth(1)
            .and_then(|arg| arg.parse().ok())
            .unwrap_or(1000)
    };
    let mut bodies = BODIES;

    offset_momentum(&mut bodies);
    println!("{:.9}", energy(&bodies));

    advance(&mut bodies, 0.01, n);

    println!("{:.9}", energy(&bodies));
}

/// Pop a mutable reference off the head of a slice, mutating the slice to no
/// longer contain the mutable reference. This is a safe operation because the
/// two mutable borrows are entirely disjoint.
fn shift_mut_ref<'a, T>(r: &mut &'a mut [T]) -> Option<&'a mut T> {
    let res = mem::replace(r, &mut []);
    if res.is_empty() { return None }
    let (a, b) = res.split_at_mut(1);
    *r = b;
    Some(&mut a[0])
}
<commit_msg>bench: rewrite nbody for better vectorization<commit_after>// The Computer Language Benchmarks Game
// http://benchmarksgame.alioth.debian.org/
//
// contributed by the Rust Project Developers

// Copyright (c) 2011-2014 The Rust Project Developers
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// - Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in
//   the documentation and/or other materials provided with the
//   distribution.
//
// - Neither the name of "The Computer Language Benchmarks Game" nor
//   the name of "The Computer Language Shootout Benchmarks" nor the
//   names of its contributors may be used to endorse or promote
//   products derived from this software without specific prior
//   written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

use std::mem;
use std::ops::{Add, Sub, Mul};

const PI: f64 = 3.141592653589793;
const SOLAR_MASS: f64 = 4.0 * PI * PI;
const YEAR: f64 = 365.24;
const N_BODIES: usize = 5;
const N_PAIRS: usize = N_BODIES * (N_BODIES - 1) / 2;

const BODIES: [Planet; N_BODIES] = [
    // Sun
    Planet {
        pos: Vec3(0.0, 0.0, 0.0),
        vel: Vec3(0.0, 0.0, 0.0),
        mass: SOLAR_MASS,
    },
    // Jupiter
    Planet {
        pos: Vec3(4.84143144246472090e+00,
                  -1.16032004402742839e+00,
                  -1.03622044471123109e-01),
        vel: Vec3(1.66007664274403694e-03 * YEAR,
                  7.69901118419740425e-03 * YEAR,
                  -6.90460016972063023e-05 * YEAR),
        mass: 9.54791938424326609e-04 * SOLAR_MASS,
    },
    // Saturn
    Planet {
        pos: Vec3(8.34336671824457987e+00,
                  4.12479856412430479e+00,
                  -4.03523417114321381e-01),
        vel: Vec3(-2.76742510726862411e-03 * YEAR,
                  4.99852801234917238e-03 * YEAR,
                  2.30417297573763929e-05 * YEAR),
        mass: 2.85885980666130812e-04 * SOLAR_MASS,
    },
    // Uranus
    Planet {
        pos: Vec3(1.28943695621391310e+01,
                  -1.51111514016986312e+01,
                  -2.23307578892655734e-01),
        vel: Vec3(2.96460137564761618e-03 * YEAR,
                  2.37847173959480950e-03 * YEAR,
                  -2.96589568540237556e-05 * YEAR),
        mass: 4.36624404335156298e-05 * SOLAR_MASS,
    },
    // Neptune
    Planet {
        pos: Vec3(1.53796971148509165e+01,
                  -2.59193146099879641e+01,
                  1.79258772950371181e-01),
        vel: Vec3(2.68067772490389322e-03 * YEAR,
                  1.62824170038242295e-03 * YEAR,
                  -9.51592254519715870e-05 * YEAR),
        mass: 5.15138902046611451e-05 * SOLAR_MASS,
    },
];

/// A 3d Vector type with oveloaded operators to improve readability.
#[derive(Clone, Copy)]
struct Vec3(pub f64, pub f64, pub f64);

impl Vec3 {
    fn zero() -> Self { Vec3(0.0, 0.0, 0.0) }

    fn norm(&self) -> f64 { self.squared_norm().sqrt() }

    fn squared_norm(&self) -> f64 {
        self.0 * self.0 + self.1 * self.1 + self.2 * self.2
    }
}

impl Add for Vec3 {
    type Output = Self;
    fn add(self, rhs: Self) -> Self {
        Vec3(self.0 + rhs.0, self.1 + rhs.1, self.2 + rhs.2)
    }
}

impl Sub for Vec3 {
    type Output = Self;
    fn sub(self, rhs: Self) -> Self {
        Vec3(self.0 - rhs.0, self.1 - rhs.1, self.2 - rhs.2)
    }
}

impl Mul<f64> for Vec3 {
    type Output = Self;
    fn mul(self, rhs: f64) -> Self {
        Vec3(self.0 * rhs, self.1 * rhs, self.2 * rhs)
    }
}

#[derive(Clone, Copy)]
struct Planet {
    pos: Vec3,
    vel: Vec3,
    mass: f64,
}

/// Computes all pairwise position differences between the planets.
fn pairwise_diffs(bodies: &[Planet; N_BODIES], diff: &mut [Vec3; N_PAIRS]) {
    let mut bodies = bodies.iter();
    let mut diff = diff.iter_mut();
    while let Some(bi) = bodies.next() {
        for bj in bodies.clone() {
            *diff.next().unwrap() = bi.pos - bj.pos;
        }
    }
}

/// Computes the magnitude of the force between each pair of planets.
fn magnitudes(diff: &[Vec3; N_PAIRS], dt: f64, mag: &mut [f64; N_PAIRS]) {
    for (mag, diff) in mag.iter_mut().zip(diff.iter()) {
        let d2 = diff.squared_norm();
        *mag = dt / (d2 * d2.sqrt());
    }
}

/// Updates the velocities of the planets by computing their gravitational
/// accelerations and performing one step of Euler integration.
fn update_velocities(bodies: &mut [Planet; N_BODIES], dt: f64,
                     diff: &mut [Vec3; N_PAIRS], mag: &mut [f64; N_PAIRS]) {
    pairwise_diffs(bodies, diff);
    magnitudes(&diff, dt, mag);

    let mut bodies = &mut bodies[..];
    let mut mag = mag.iter();
    let mut diff = diff.iter();
    while let Some(bi) = shift_mut_ref(&mut bodies) {
        for bj in bodies.iter_mut() {
            let diff = *diff.next().unwrap();
            let mag = *mag.next().unwrap();
            bi.vel = bi.vel - diff * (bj.mass * mag);
            bj.vel = bj.vel + diff * (bi.mass * mag);
        }
    }
}

/// Advances the solar system by one timestep by first updating the
/// velocities and then integrating the positions using the updated velocities.
///
/// Note: the `diff` & `mag` arrays are effectively scratch space. They're
/// provided as arguments to avoid re-zeroing them every time `advance` is
/// called.
fn advance(mut bodies: &mut [Planet; N_BODIES], dt: f64,
           diff: &mut [Vec3; N_PAIRS], mag: &mut [f64; N_PAIRS]) {
    update_velocities(bodies, dt, diff, mag);
    for body in bodies.iter_mut() {
        body.pos = body.pos + body.vel * dt;
    }
}

/// Computes the total energy of the solar system.
fn energy(bodies: &[Planet; N_BODIES]) -> f64 {
    let mut e = 0.0;
    let mut bodies = bodies.iter();
    while let Some(bi) = bodies.next() {
        e += bi.vel.squared_norm() * bi.mass / 2.0
           - bi.mass * bodies.clone()
                             .map(|bj| bj.mass / (bi.pos - bj.pos).norm())
                             .fold(0.0, |a, b| a + b);
    }
    e
}

/// Offsets the sun's velocity to make the overall momentum of the system zero.
fn offset_momentum(bodies: &mut [Planet; N_BODIES]) {
    let p = bodies.iter().fold(Vec3::zero(), |v, b| v + b.vel * b.mass);
    bodies[0].vel = p * (-1.0 / bodies[0].mass);
}

fn main() {
    let n = if std::env::var_os("RUST_BENCH").is_some() {
        5000000
    } else {
        std::env::args().nth(1)
            .and_then(|arg| arg.parse().ok())
            .unwrap_or(1000)
    };
    let mut bodies = BODIES;
    let mut diff = [Vec3::zero(); N_PAIRS];
    let mut mag = [0.0f64; N_PAIRS];

    offset_momentum(&mut bodies);
    println!("{:.9}", energy(&bodies));

    for _ in (0..n) {
        advance(&mut bodies, 0.01, &mut diff, &mut mag);
    }

    println!("{:.9}", energy(&bodies));
}

/// Pop a mutable reference off the head of a slice, mutating the slice to no
/// longer contain the mutable reference. This is a safe operation because the
/// two mutable borrows are entirely disjoint.
fn shift_mut_ref<'a, T>(r: &mut &'a mut [T]) -> Option<&'a mut T> {
    let res = mem::replace(r, &mut []);
    if res.is_empty() { return None }
    let (a, b) = res.split_at_mut(1);
    *r = b;
    Some(&mut a[0])
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::mem::transmute;

use dbus_serialize::types::{Value,BasicValue,Path,Signature,Struct,Variant,Array,Dictionary};

#[derive(Debug)]
pub enum DemarshalError {
    MessageTooShort,
    CorruptedMessage,
    BadUTF8,
    BadSignature,
    ElementTooBig,
    MismatchedParens,
}

pub fn get_alignment(sig: char) -> usize {
    match sig {
        'y' => 1,
        'b' => 1,
        'n' => 2,
        'q' => 2,
        'i' => 4,
        'u' => 4,
        'x' => 8,
        't' => 8,
        's' => 4,
        'o' => 4,
        'g' => 1,

        'a' => 4,
        '(' => 8,
        '{' => 8,
        'v' => 1,
        _ => panic!("Bogus type")
    }
}

fn demarshal_byte(buf: &mut Vec<u8>, offset: &mut usize) -> Result<Value,DemarshalError> {
    if buf.len() < 1 {
        return Err(DemarshalError::MessageTooShort);
    }
    let byte = buf.remove(0);
    *offset += 1;
    Ok(Value::BasicValue(BasicValue::Byte(byte)))
}

fn align_to(buf: &mut Vec<u8>, offset: &mut usize, align: usize) -> Result<(),DemarshalError> {
    if *offset % align == 0 {
        return Ok(());
    }
    let delta = align - (*offset % align);
    if buf.len() < delta {
        return Err(DemarshalError::MessageTooShort);
    }
    for _ in 0..delta {
        buf.remove(0);
        *offset += 1;
    }
    Ok(())
}

fn demarshal_bool(buf: &mut Vec<u8>, offset: &mut usize) -> Result<Value,DemarshalError> {
    try!(align_to(buf, offset, 4));
    if buf.len() < 4 {
        return Err(DemarshalError::MessageTooShort);
    }
    let byte = buf.remove(0);
    *offset += 1;
    // XXX: assumes LE
    for _ in 0..3 {
        *offset += 1;
        // Only the first byte should have a non-zero value
        if buf.remove(0) != 0 {
            return Err(DemarshalError::CorruptedMessage);
        }
    }
    match byte {
        0 => Ok(Value::BasicValue(BasicValue::Boolean(false))),
        1 => Ok(Value::BasicValue(BasicValue::Boolean(true))),
        _ => Err(DemarshalError::CorruptedMessage)
    }
}

fn demarshal_int(buf: &mut Vec<u8>, offset: &mut usize, len: usize, is_signed: bool) -> Result<Value,DemarshalError> {
    try!(align_to(buf, offset, len));
    if buf.len() < len {
        return Err(DemarshalError::MessageTooShort);
    }
    let mut intbuf = [0; 8];
    for i in 0..len {
        intbuf[i] = buf.remove(0);
        *offset += 1;
    }
    // Check for sign-extension
    if is_signed && (intbuf[len-1] & 128 == 128) {
        for i in len..8 {
            intbuf[i] = 0xff;
        }
    }
    let val : u64 = unsafe { transmute(intbuf) };
    if is_signed {
        match len {
            2 => Ok(Value::BasicValue(BasicValue::Int16(val as i16))),
            4 => Ok(Value::BasicValue(BasicValue::Int32(val as i32))),
            8 => Ok(Value::BasicValue(BasicValue::Int64(val as i64))),
            _ => panic!("Bogus length {}", len)
        }
    } else {
        match len {
            1 => Ok(Value::BasicValue(BasicValue::Byte(val as u8))),
            2 => Ok(Value::BasicValue(BasicValue::Uint16(val as u16))),
            4 => Ok(Value::BasicValue(BasicValue::Uint32(val as u32))),
            8 => Ok(Value::BasicValue(BasicValue::Uint64(val))),
            _ => panic!("Bogus length {}", len)
        }
    }
}

fn demarshal_string(buf: &mut Vec<u8>, offset: &mut usize, count_size: usize, is_path: bool) -> Result<Value,DemarshalError> {
    // demarshal_int ensure we're correctly aligned with input
    let len = match demarshal_int(buf, offset, count_size, false) {
        Ok(Value::BasicValue(BasicValue::Uint32(x))) => x,
        Ok(Value::BasicValue(BasicValue::Byte(x))) => x as u32,
        _ => return Err(DemarshalError::CorruptedMessage),
    };
    let mut strbuf = Vec::new();
    for _ in 0..len {
        strbuf.push(buf.remove(0));
        *offset += 1
    }
    // Check the NUL byte
    if buf.remove(0) != 0 {
        return Err(DemarshalError::CorruptedMessage);
    }
    *offset += 1;
    let val = try!(String::from_utf8(strbuf).or(Err(DemarshalError::BadUTF8)));
    if is_path {
        Ok(Value::BasicValue(BasicValue::ObjectPath(Path(val))))
    } else {
        if count_size == 4 {
            Ok(Value::BasicValue(BasicValue::String(val)))
        } else {
            Ok(Value::BasicValue(BasicValue::Signature(Signature(val))))
        }
    }
}

fn demarshal_array(buf: &mut Vec<u8>, offset: &mut usize, sig: &mut String) -> Result<Value,DemarshalError> {
    if sig.len() < 1 {
        return Err(DemarshalError::BadSignature);
    }
    let typ = sig.chars().next().unwrap();
    let is_dict = if typ == '{' {
        true
    } else {
        false
    };
    // demarshal_int ensure we're correctly aligned with input
    let array_len = match demarshal_int(buf, offset, 4, false) {
        Ok(Value::BasicValue(BasicValue::Uint32(x))) => x,
        _ => return Err(DemarshalError::CorruptedMessage),
    };
    if array_len > 1 << 26 {
        return Err(DemarshalError::ElementTooBig);
    }
    try!(align_to(buf, offset, get_alignment(typ)));
    if buf.len() < (array_len as usize) {
        return Err(DemarshalError::MessageTooShort);
    }

    let mut vec = Vec::new();
    let start_offset = *offset;
    let mut sig_copy = "".to_owned();
    while *offset < start_offset+(array_len as usize) {
        // We want to pass the same signature to each call of demarshal
        sig_copy = sig.to_owned();
        vec.push(try!(demarshal(buf, offset, &mut sig_copy)));
    }
    // Now that we're done with our elements we can forget the elements consumed by demarshal
    let mut mysig = sig.clone();
    mysig.truncate(sig.len() - sig_copy.len());
    mysig.insert(0, 'a');
    *sig = sig_copy;

    if is_dict {
        let mut map : HashMap<BasicValue,Value> = HashMap::new();
        for x in vec {
            let mut s = match x {
                Value::Struct(x) => x,
                _ => panic!("Dictionaries should contain structs")
            };
            let val = s.objects.remove(1);
            let key = match s.objects[0] {
                Value::BasicValue(ref x) => x,
                _ => panic!("Dictionaries require BasicValue keys")
            };
            map.insert(key.clone(), val);
        }
        return Ok(Value::Dictionary(Dictionary::new_with_sig(map, mysig)));
    }

    Ok(Value::Array(Array::new_with_sig(vec, mysig)))
}

fn demarshal_struct(buf: &mut Vec<u8>, offset: &mut usize, sig: &mut String) -> Result<Value,DemarshalError> {
    if sig.len() < 1 {
        return Err(DemarshalError::BadSignature);
    }
    try!(align_to(buf, offset, 8));

    let mut vec = Vec::new();
    let mut mysig = sig.to_owned();
    loop {
        let typ = match sig.chars().next() {
            Some(x) => x,
            None => return Err(DemarshalError::MismatchedParens)
        };
        if typ == ')' {
            sig.remove(0);
            break;
        }
        vec.push(try!(demarshal(buf, offset, sig)));
    }
    // Only keep the characters that were consumed by demarshal
    let oldlen = mysig.len();
    mysig.truncate(oldlen - sig.len());
    mysig.insert(0, '(');

    Ok(Value::Struct(Struct{
        objects: vec,
        signature: Signature(mysig)
    }))
}

fn demarshal_variant(buf: &mut Vec<u8>, offset: &mut usize) -> Result<Value,DemarshalError> {
    let mut variant_sig = "g".to_owned();
    let sigval = try!(demarshal(buf, offset, &mut variant_sig));
    let sig = match sigval {
        Value::BasicValue(BasicValue::Signature(x)) => x,
        _ => return Err(DemarshalError::CorruptedMessage)
    };
    let mut s = sig.0.to_owned();
    let var = try!(demarshal(buf, offset, &mut s));
    Ok(Value::Variant(Variant{
        object: Box::new(var),
        signature: sig
    }))
}

pub fn demarshal(buf: &mut Vec<u8>, offset: &mut usize, sig: &mut String) -> Result<Value,DemarshalError> {
    let typ = sig.remove(0);
    match typ {
        'y' => demarshal_byte(buf, offset),
        'b' => demarshal_bool(buf, offset),
        'n' => demarshal_int(buf, offset, 2, true),
        'q' => demarshal_int(buf, offset, 2, false),
        'i' => demarshal_int(buf, offset, 4, true),
        'u' => demarshal_int(buf, offset, 4, false),
        'x' => demarshal_int(buf, offset, 8, true),
        't' => demarshal_int(buf, offset, 8, false),
        's' => demarshal_string(buf, offset, 4, false),
        'o' => demarshal_string(buf, offset, 4, true),
        'g' => demarshal_string(buf, offset, 1, false),

        'a' => demarshal_array(buf, offset, sig),
        '(' => demarshal_struct(buf, offset, sig),
        '{' => demarshal_struct(buf, offset, sig),
        'v' => demarshal_variant(buf, offset),
        _ => Err(DemarshalError::BadSignature)
    }
}

#[cfg(test)]
mod test {
    use marshal::Marshal;
    use demarshal::demarshal;
    use dbus_serialize::types::{Value,BasicValue,Signature};

    #[test]
    fn test_demarshal_u32() {
        let mut buf = Vec::new();
        let x = 16 as u32;
        let mut sig = x.get_type().to_string();
        x.dbus_encode(&mut buf);

        let mut offset = 0;
        let v = demarshal(&mut buf, &mut offset, &mut sig).unwrap();
        assert_eq!(v, Value::BasicValue(BasicValue::Uint32(16)));
        assert_eq!(buf.len(), 0);
        assert_eq!(sig, "");
    }

    #[test]
    fn test_demarshal_u32_offset() {
        let mut buf = Vec::new();
        buf.insert(0, 0);
        let x = 16 as u32;
        let mut sig = x.get_type();
        x.dbus_encode(&mut buf);

        buf.remove(0);
        let mut offset = 1;
        let v = demarshal(&mut buf, &mut offset, &mut sig).unwrap();
        assert_eq!(v, Value::BasicValue(BasicValue::Uint32(16)));
        assert_eq!(buf.len(), 0);
        assert_eq!(sig, "");
    }

    #[test]
    fn test_string() {
        let mut buf = Vec::new();
        let x = "swalter".to_string();
        let mut sig = x.get_type();
        x.dbus_encode(&mut buf);

        let mut offset = 0;
        let v = demarshal(&mut buf, &mut offset, &mut sig).unwrap();
        assert_eq!(v, Value::BasicValue(BasicValue::String("swalter".to_string())));
        assert_eq!(buf.len(), 0);
        assert_eq!(sig, "");
    }

    #[test]
    fn test_array() {
        let mut buf = Vec::new();
        let x = vec![1 as u32, 2 as u32, 3 as u32];
        let mut sig = "au".to_string();
        x.dbus_encode(&mut buf);

        let mut offset = 0;
        let v = demarshal(&mut buf, &mut offset, &mut sig).unwrap();
        let arr = match v {
            Value::Array(x) => x,
            _ => panic!("Bad return from demarshal {:?}", v)
        };
        let golden = vec![
            Value::BasicValue(BasicValue::Uint32(1)),
            Value::BasicValue(BasicValue::Uint32(2)),
            Value::BasicValue(BasicValue::Uint32(3)),
        ];
        assert_eq!(arr.objects, golden);
        assert_eq!(buf.len(), 0);
        assert_eq!(sig, "");
    }

    #[test]
    fn test_array_bytes() {
        let mut buf = Vec::new();
        let x = vec![1 as u8, 2 as u8, 3 as u8];
        let mut sig = "ay".to_string();
        x.dbus_encode(&mut buf);

        let mut offset = 0;
        let v = demarshal(&mut buf, &mut offset, &mut sig).unwrap();
        let arr = match v {
            Value::Array(x) => x,
            _ => panic!("Bad return from demarshal {:?}", v)
        };
        let golden = vec![
            Value::BasicValue(BasicValue::Byte(1)),
            Value::BasicValue(BasicValue::Byte(2)),
            Value::BasicValue(BasicValue::Byte(3)),
        ];
        assert_eq!(arr.objects, golden);
        assert_eq!(buf.len(), 0);
        assert_eq!(sig, "");
    }

    #[test]
    fn test_struct() {
        let mut buf = Vec::new();
        let x = "swalter".to_string();
        let mut sig = "(ss)".to_string();
        x.dbus_encode(&mut buf);
        x.dbus_encode(&mut buf);

        let mut offset = 0;
        let v = demarshal(&mut buf, &mut offset, &mut sig).unwrap();
        assert_eq!(buf.len(), 0);
        assert_eq!(sig, "");
        let s = match v {
            Value::Struct(x) => x,
            _ => panic!("Bad return from demarshal {:?}", v)
        };
        assert_eq!(s.signature, Signature("(ss)".to_string()));
    }
}
<commit_msg>clippy: address needless_bool warning<commit_after>use std::collections::HashMap;
use std::mem::transmute;

use dbus_serialize::types::{Value,BasicValue,Path,Signature,Struct,Variant,Array,Dictionary};

#[derive(Debug)]
pub enum DemarshalError {
    MessageTooShort,
    CorruptedMessage,
    BadUTF8,
    BadSignature,
    ElementTooBig,
    MismatchedParens,
}

pub fn get_alignment(sig: char) -> usize {
    match sig {
        'y' => 1,
        'b' => 1,
        'n' => 2,
        'q' => 2,
        'i' => 4,
        'u' => 4,
        'x' => 8,
        't' => 8,
        's' => 4,
        'o' => 4,
        'g' => 1,

        'a' => 4,
        '(' => 8,
        '{' => 8,
        'v' => 1,
        _ => panic!("Bogus type")
    }
}

fn demarshal_byte(buf: &mut Vec<u8>, offset: &mut usize) -> Result<Value,DemarshalError> {
    if buf.len() < 1 {
        return Err(DemarshalError::MessageTooShort);
    }
    let byte = buf.remove(0);
    *offset += 1;
    Ok(Value::BasicValue(BasicValue::Byte(byte)))
}

fn align_to(buf: &mut Vec<u8>, offset: &mut usize, align: usize) -> Result<(),DemarshalError> {
    if *offset % align == 0 {
        return Ok(());
    }
    let delta = align - (*offset % align);
    if buf.len() < delta {
        return Err(DemarshalError::MessageTooShort);
    }
    for _ in 0..delta {
        buf.remove(0);
        *offset += 1;
    }
    Ok(())
}

fn demarshal_bool(buf: &mut Vec<u8>, offset: &mut usize) -> Result<Value,DemarshalError> {
    try!(align_to(buf, offset, 4));
    if buf.len() < 4 {
        return Err(DemarshalError::MessageTooShort);
    }
    let byte = buf.remove(0);
    *offset += 1;
    // XXX: assumes LE
    for _ in 0..3 {
        *offset += 1;
        // Only the first byte should have a non-zero value
        if buf.remove(0) != 0 {
            return Err(DemarshalError::CorruptedMessage);
        }
    }
    match byte {
        0 => Ok(Value::BasicValue(BasicValue::Boolean(false))),
        1 => Ok(Value::BasicValue(BasicValue::Boolean(true))),
        _ => Err(DemarshalError::CorruptedMessage)
    }
}

fn demarshal_int(buf: &mut Vec<u8>, offset: &mut usize, len: usize, is_signed: bool) -> Result<Value,DemarshalError> {
    try!(align_to(buf, offset, len));
    if buf.len() < len {
        return Err(DemarshalError::MessageTooShort);
    }
    let mut intbuf = [0; 8];
    for i in 0..len {
        intbuf[i] = buf.remove(0);
        *offset += 1;
    }
    // Check for sign-extension
    if is_signed && (intbuf[len-1] & 128 == 128) {
        for i in len..8 {
            intbuf[i] = 0xff;
        }
    }
    let val : u64 = unsafe { transmute(intbuf) };
    if is_signed {
        match len {
            2 => Ok(Value::BasicValue(BasicValue::Int16(val as i16))),
            4 => Ok(Value::BasicValue(BasicValue::Int32(val as i32))),
            8 => Ok(Value::BasicValue(BasicValue::Int64(val as i64))),
            _ => panic!("Bogus length {}", len)
        }
    } else {
        match len {
            1 => Ok(Value::BasicValue(BasicValue::Byte(val as u8))),
            2 => Ok(Value::BasicValue(BasicValue::Uint16(val as u16))),
            4 => Ok(Value::BasicValue(BasicValue::Uint32(val as u32))),
            8 => Ok(Value::BasicValue(BasicValue::Uint64(val))),
            _ => panic!("Bogus length {}", len)
        }
    }
}

fn demarshal_string(buf: &mut Vec<u8>, offset: &mut usize, count_size: usize, is_path: bool) -> Result<Value,DemarshalError> {
    // demarshal_int ensure we're correctly aligned with input
    let len = match demarshal_int(buf, offset, count_size, false) {
        Ok(Value::BasicValue(BasicValue::Uint32(x))) => x,
        Ok(Value::BasicValue(BasicValue::Byte(x))) => x as u32,
        _ => return Err(DemarshalError::CorruptedMessage),
    };
    let mut strbuf = Vec::new();
    for _ in 0..len {
        strbuf.push(buf.remove(0));
        *offset += 1
    }
    // Check the NUL byte
    if buf.remove(0) != 0 {
        return Err(DemarshalError::CorruptedMessage);
    }
    *offset += 1;
    let val = try!(String::from_utf8(strbuf).or(Err(DemarshalError::BadUTF8)));
    if is_path {
        Ok(Value::BasicValue(BasicValue::ObjectPath(Path(val))))
    } else {
        if count_size == 4 {
            Ok(Value::BasicValue(BasicValue::String(val)))
        } else {
            Ok(Value::BasicValue(BasicValue::Signature(Signature(val))))
        }
    }
}

fn demarshal_array(buf: &mut Vec<u8>, offset: &mut usize, sig: &mut String) -> Result<Value,DemarshalError> {
    if sig.len() < 1 {
        return Err(DemarshalError::BadSignature);
    }
    let typ = sig.chars().next().unwrap();
    let is_dict = typ == '{';
    // demarshal_int ensure we're correctly aligned with input
    let array_len = match demarshal_int(buf, offset, 4, false) {
        Ok(Value::BasicValue(BasicValue::Uint32(x))) => x,
        _ => return Err(DemarshalError::CorruptedMessage),
    };
    if array_len > 1 << 26 {
        return Err(DemarshalError::ElementTooBig);
    }
    try!(align_to(buf, offset, get_alignment(typ)));
    if buf.len() < (array_len as usize) {
        return Err(DemarshalError::MessageTooShort);
    }

    let mut vec = Vec::new();
    let start_offset = *offset;
    let mut sig_copy = "".to_owned();
    while *offset < start_offset+(array_len as usize) {
        // We want to pass the same signature to each call of demarshal
        sig_copy = sig.to_owned();
        vec.push(try!(demarshal(buf, offset, &mut sig_copy)));
    }
    // Now that we're done with our elements we can forget the elements consumed by demarshal
    let mut mysig = sig.clone();
    mysig.truncate(sig.len() - sig_copy.len());
    mysig.insert(0, 'a');
    *sig = sig_copy;

    if is_dict {
        let mut map : HashMap<BasicValue,Value> = HashMap::new();
        for x in vec {
            let mut s = match x {
                Value::Struct(x) => x,
                _ => panic!("Dictionaries should contain structs")
            };
            let val = s.objects.remove(1);
            let key = match s.objects[0] {
                Value::BasicValue(ref x) => x,
                _ => panic!("Dictionaries require BasicValue keys")
            };
            map.insert(key.clone(), val);
        }
        return Ok(Value::Dictionary(Dictionary::new_with_sig(map, mysig)));
    }

    Ok(Value::Array(Array::new_with_sig(vec, mysig)))
}

fn demarshal_struct(buf: &mut Vec<u8>, offset: &mut usize, sig: &mut String) -> Result<Value,DemarshalError> {
    if sig.len() < 1 {
        return Err(DemarshalError::BadSignature);
    }
    try!(align_to(buf, offset, 8));

    let mut vec = Vec::new();
    let mut mysig = sig.to_owned();
    loop {
        let typ = match sig.chars().next() {
            Some(x) => x,
            None => return Err(DemarshalError::MismatchedParens)
        };
        if typ == ')' {
            sig.remove(0);
            break;
        }
        vec.push(try!(demarshal(buf, offset, sig)));
    }
    // Only keep the characters that were consumed by demarshal
    let oldlen = mysig.len();
    mysig.truncate(oldlen - sig.len());
    mysig.insert(0, '(');

    Ok(Value::Struct(Struct{
        objects: vec,
        signature: Signature(mysig)
    }))
}

fn demarshal_variant(buf: &mut Vec<u8>, offset: &mut usize) -> Result<Value,DemarshalError> {
    let mut variant_sig = "g".to_owned();
    let sigval = try!(demarshal(buf, offset, &mut variant_sig));
    let sig = match sigval {
        Value::BasicValue(BasicValue::Signature(x)) => x,
        _ => return Err(DemarshalError::CorruptedMessage)
    };
    let mut s = sig.0.to_owned();
    let var = try!(demarshal(buf, offset, &mut s));
    Ok(Value::Variant(Variant{
        object: Box::new(var),
        signature: sig
    }))
}

pub fn demarshal(buf: &mut Vec<u8>, offset: &mut usize, sig: &mut String) -> Result<Value,DemarshalError> {
    let typ = sig.remove(0);
    match typ {
        'y' => demarshal_byte(buf, offset),
        'b' => demarshal_bool(buf, offset),
        'n' => demarshal_int(buf, offset, 2, true),
        'q' => demarshal_int(buf, offset, 2, false),
        'i' => demarshal_int(buf, offset, 4, true),
        'u' => demarshal_int(buf, offset, 4, false),
        'x' => demarshal_int(buf, offset, 8, true),
        't' => demarshal_int(buf, offset, 8, false),
        's' => demarshal_string(buf, offset, 4, false),
        'o' => demarshal_string(buf, offset, 4, true),
        'g' => demarshal_string(buf, offset, 1, false),

        'a' => demarshal_array(buf, offset, sig),
        '(' => demarshal_struct(buf, offset, sig),
        '{' => demarshal_struct(buf, offset, sig),
        'v' => demarshal_variant(buf, offset),
        _ => Err(DemarshalError::BadSignature)
    }
}

#[cfg(test)]
mod test {
    use marshal::Marshal;
    use demarshal::demarshal;
    use dbus_serialize::types::{Value,BasicValue,Signature};

    #[test]
    fn test_demarshal_u32() {
        let mut buf = Vec::new();
        let x = 16 as u32;
        let mut sig = x.get_type().to_string();
        x.dbus_encode(&mut buf);

        let mut offset = 0;
        let v = demarshal(&mut buf, &mut offset, &mut sig).unwrap();
        assert_eq!(v, Value::BasicValue(BasicValue::Uint32(16)));
        assert_eq!(buf.len(), 0);
        assert_eq!(sig, "");
    }

    #[test]
    fn test_demarshal_u32_offset() {
        let mut buf = Vec::new();
        buf.insert(0, 0);
        let x = 16 as u32;
        let mut sig = x.get_type();
        x.dbus_encode(&mut buf);

        buf.remove(0);
        let mut offset = 1;
        let v = demarshal(&mut buf, &mut offset, &mut sig).unwrap();
        assert_eq!(v, Value::BasicValue(BasicValue::Uint32(16)));
        assert_eq!(buf.len(), 0);
        assert_eq!(sig, "");
    }

    #[test]
    fn test_string() {
        let mut buf = Vec::new();
        let x = "swalter".to_string();
        let mut sig = x.get_type();
        x.dbus_encode(&mut buf);

        let mut offset = 0;
        let v = demarshal(&mut buf, &mut offset, &mut sig).unwrap();
        assert_eq!(v, Value::BasicValue(BasicValue::String("swalter".to_string())));
        assert_eq!(buf.len(), 0);
        assert_eq!(sig, "");
    }

    #[test]
    fn test_array() {
        let mut buf = Vec::new();
        let x = vec![1 as u32, 2 as u32, 3 as u32];
        let mut sig = "au".to_string();
        x.dbus_encode(&mut buf);

        let mut offset = 0;
        let v = demarshal(&mut buf, &mut offset, &mut sig).unwrap();
        let arr = match v {
            Value::Array(x) => x,
            _ => panic!("Bad return from demarshal {:?}", v)
        };
        let golden = vec![
            Value::BasicValue(BasicValue::Uint32(1)),
            Value::BasicValue(BasicValue::Uint32(2)),
            Value::BasicValue(BasicValue::Uint32(3)),
        ];
        assert_eq!(arr.objects, golden);
        assert_eq!(buf.len(), 0);
        assert_eq!(sig, "");
    }

    #[test]
    fn test_array_bytes() {
        let mut buf = Vec::new();
        let x = vec![1 as u8, 2 as u8, 3 as u8];
        let mut sig = "ay".to_string();
        x.dbus_encode(&mut buf);

        let mut offset = 0;
        let v = demarshal(&mut buf, &mut offset, &mut sig).unwrap();
        let arr = match v {
            Value::Array(x) => x,
            _ => panic!("Bad return from demarshal {:?}", v)
        };
        let golden = vec![
            Value::BasicValue(BasicValue::Byte(1)),
            Value::BasicValue(BasicValue::Byte(2)),
            Value::BasicValue(BasicValue::Byte(3)),
        ];
        assert_eq!(arr.objects, golden);
        assert_eq!(buf.len(), 0);
        assert_eq!(sig, "");
    }

    #[test]
    fn test_struct() {
        let mut buf = Vec::new();
        let x = "swalter".to_string();
        let mut sig = "(ss)".to_string();
        x.dbus_encode(&mut buf);
        x.dbus_encode(&mut buf);

        let mut offset = 0;
        let v = demarshal(&mut buf, &mut offset, &mut sig).unwrap();
        assert_eq!(buf.len(), 0);
        assert_eq!(sig, "");
        let s = match v {
            Value::Struct(x) => x,
            _ => panic!("Bad return from demarshal {:?}", v)
        };
        assert_eq!(s.signature, Signature("(ss)".to_string()));
    }
}
<|endoftext|>


<commit_before>extern crate quadtree;

fn main() {
    let origin = quadtree::geometry::Point::new(0., 0.);
    let size = quadtree::geometry::Size::new(1., 1.);
    let rect = quadtree::geometry::Rect::new(origin, size);
    let qt = quadtree::quadtree::QuadTree::newAutosized(rect);
}
<commit_msg>Show the resulting quadtree in the demo.<commit_after>extern crate quadtree;

fn main() {
    let origin = quadtree::geometry::Point::new(0., 0.);
    let size = quadtree::geometry::Size::new(1., 1.);
    let rect = quadtree::geometry::Rect::new(origin, size);
    let qt = quadtree::quadtree::QuadTree::newAutosized(rect);

    println!("tree: {}", qt);
}
<|endoftext|>


<commit_before>//! This module contains the `InterpCx` methods for executing a single step of the interpreter.
//!
//! The main entry point is the `step` method.

use rustc_middle::mir;
use rustc_middle::mir::interpret::{InterpResult, Scalar};
use rustc_middle::ty::layout::LayoutOf;

use super::{InterpCx, Machine};

/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
/// same type as the result.
#[inline]
fn binop_left_homogeneous(op: mir::BinOp) -> bool {
    use rustc_middle::mir::BinOp::*;
    match op {
        Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Offset | Shl | Shr => true,
        Eq | Ne | Lt | Le | Gt | Ge => false,
    }
}
/// Classify whether an operator is "right-homogeneous", i.e., the RHS has the
/// same type as the LHS.
#[inline]
fn binop_right_homogeneous(op: mir::BinOp) -> bool {
    use rustc_middle::mir::BinOp::*;
    match op {
        Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Eq | Ne | Lt | Le | Gt | Ge => true,
        Offset | Shl | Shr => false,
    }
}

impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
    pub fn run(&mut self) -> InterpResult<'tcx> {
        while self.step()? {}
        Ok(())
    }

    /// Returns `true` as long as there are more things to do.
    ///
    /// This is used by [priroda](https://github.com/oli-obk/priroda)
    ///
    /// This is marked `#inline(always)` to work around adverserial codegen when `opt-level = 3`
    #[inline(always)]
    pub fn step(&mut self) -> InterpResult<'tcx, bool> {
        if self.stack().is_empty() {
            return Ok(false);
        }

        let loc = match self.frame().loc {
            Ok(loc) => loc,
            Err(_) => {
                // We are unwinding and this fn has no cleanup code.
                // Just go on unwinding.
                trace!("unwinding: skipping frame");
                self.pop_stack_frame(/* unwinding */ true)?;
                return Ok(true);
            }
        };
        let basic_block = &self.body().basic_blocks()[loc.block];

        let old_frames = self.frame_idx();

        if let Some(stmt) = basic_block.statements.get(loc.statement_index) {
            assert_eq!(old_frames, self.frame_idx());
            self.statement(stmt)?;
            return Ok(true);
        }

        M::before_terminator(self)?;

        let terminator = basic_block.terminator();
        assert_eq!(old_frames, self.frame_idx());
        self.terminator(terminator)?;
        Ok(true)
    }

    /// Runs the interpretation logic for the given `mir::Statement` at the current frame and
    /// statement counter. This also moves the statement counter forward.
    pub fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> {
        info!("{:?}", stmt);

        use rustc_middle::mir::StatementKind::*;

        // Some statements (e.g., box) push new stack frames.
        // We have to record the stack frame number *before* executing the statement.
        let frame_idx = self.frame_idx();

        match &stmt.kind {
            Assign(box (place, rvalue)) => self.eval_rvalue_into_place(rvalue, *place)?,

            SetDiscriminant { place, variant_index } => {
                let dest = self.eval_place(**place)?;
                self.write_discriminant(*variant_index, &dest)?;
            }

            // Mark locals as alive
            StorageLive(local) => {
                self.storage_live(*local)?;
            }

            // Mark locals as dead
            StorageDead(local) => {
                self.storage_dead(*local)?;
            }

            // No dynamic semantics attached to `FakeRead`; MIR
            // interpreter is solely intended for borrowck'ed code.
            FakeRead(..) => {}

            // Stacked Borrows.
            Retag(kind, place) => {
                let dest = self.eval_place(**place)?;
                M::retag(self, *kind, &dest)?;
            }

            // Call CopyNonOverlapping
            CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { src, dst, count }) => {
                let src = self.eval_operand(src, None)?;
                let dst = self.eval_operand(dst, None)?;
                let count = self.eval_operand(count, None)?;
                self.copy_intrinsic(&src, &dst, &count, /* nonoverlapping */ true)?;
            }

            // Statements we do not track.
            AscribeUserType(..) => {}

            // Currently, Miri discards Coverage statements. Coverage statements are only injected
            // via an optional compile time MIR pass and have no side effects. Since Coverage
            // statements don't exist at the source level, it is safe for Miri to ignore them, even
            // for undefined behavior (UB) checks.
            //
            // A coverage counter inside a const expression (for example, a counter injected in a
            // const function) is discarded when the const is evaluated at compile time. Whether
            // this should change, and/or how to implement a const eval counter, is a subject of the
            // following issue:
            //
            // FIXME(#73156): Handle source code coverage in const eval
            Coverage(..) => {}

            // Defined to do nothing. These are added by optimization passes, to avoid changing the
            // size of MIR constantly.
            Nop => {}

            LlvmInlineAsm { .. } => throw_unsup_format!("inline assembly is not supported"),
        }

        self.stack_mut()[frame_idx].loc.as_mut().unwrap().statement_index += 1;
        Ok(())
    }

    /// Evaluate an assignment statement.
    ///
    /// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue
    /// type writes its results directly into the memory specified by the place.
    pub fn eval_rvalue_into_place(
        &mut self,
        rvalue: &mir::Rvalue<'tcx>,
        place: mir::Place<'tcx>,
    ) -> InterpResult<'tcx> {
        let dest = self.eval_place(place)?;

        use rustc_middle::mir::Rvalue::*;
        match *rvalue {
            ThreadLocalRef(did) => {
                let ptr = M::thread_local_static_base_pointer(self, did)?;
                self.write_pointer(ptr, &dest)?;
            }

            Use(ref operand) => {
                // Avoid recomputing the layout
                let op = self.eval_operand(operand, Some(dest.layout))?;
                self.copy_op(&op, &dest)?;
            }

            BinaryOp(bin_op, box (ref left, ref right)) => {
                let layout = binop_left_homogeneous(bin_op).then_some(dest.layout);
                let left = self.read_immediate(&self.eval_operand(left, layout)?)?;
                let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
                let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
                self.binop_ignore_overflow(bin_op, &left, &right, &dest)?;
            }

            CheckedBinaryOp(bin_op, box (ref left, ref right)) => {
                // Due to the extra boolean in the result, we can never reuse the `dest.layout`.
                let left = self.read_immediate(&self.eval_operand(left, None)?)?;
                let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
                let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
                self.binop_with_overflow(bin_op, &left, &right, &dest)?;
            }

            UnaryOp(un_op, ref operand) => {
                // The operand always has the same type as the result.
                let val = self.read_immediate(&self.eval_operand(operand, Some(dest.layout))?)?;
                let val = self.unary_op(un_op, &val)?;
                assert_eq!(val.layout, dest.layout, "layout mismatch for result of {:?}", un_op);
                self.write_immediate(*val, &dest)?;
            }

            Aggregate(ref kind, ref operands) => {
                let (dest, active_field_index) = match **kind {
                    mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => {
                        self.write_discriminant(variant_index, &dest)?;
                        if adt_def.is_enum() {
                            (self.place_downcast(&dest, variant_index)?, active_field_index)
                        } else {
                            (dest, active_field_index)
                        }
                    }
                    _ => (dest, None),
                };

                for (i, operand) in operands.iter().enumerate() {
                    let op = self.eval_operand(operand, None)?;
                    // Ignore zero-sized fields.
                    if !op.layout.is_zst() {
                        let field_index = active_field_index.unwrap_or(i);
                        let field_dest = self.place_field(&dest, field_index)?;
                        self.copy_op(&op, &field_dest)?;
                    }
                }
            }

            Repeat(ref operand, _) => {
                let src = self.eval_operand(operand, None)?;
                assert!(!src.layout.is_unsized());
                let dest = self.force_allocation(&dest)?;
                let length = dest.len(self)?;

                if length == 0 {
                    // Nothing to copy... but let's still make sure that `dest` as a place is valid.
                    self.get_alloc_mut(&dest)?;
                } else {
                    // Write the src to the first element.
                    let first = self.mplace_field(&dest, 0)?;
                    self.copy_op(&src, &first.into())?;

                    // This is performance-sensitive code for big static/const arrays! So we
                    // avoid writing each operand individually and instead just make many copies
                    // of the first element.
                    let elem_size = first.layout.size;
                    let first_ptr = first.ptr;
                    let rest_ptr = first_ptr.offset(elem_size, self)?;
                    self.memory.copy_repeatedly(
                        first_ptr,
                        first.align,
                        rest_ptr,
                        first.align,
                        elem_size,
                        length - 1,
                        /*nonoverlapping:*/ true,
                    )?;
                }
            }

            Len(place) => {
                // FIXME(CTFE): don't allow computing the length of arrays in const eval
                let src = self.eval_place(place)?;
                let mplace = self.force_allocation(&src)?;
                let len = mplace.len(self)?;
                self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?;
            }

            AddressOf(_, place) | Ref(_, _, place) => {
                let src = self.eval_place(place)?;
                let place = self.force_allocation(&src)?;
                self.write_immediate(place.to_ref(self), &dest)?;
            }

            NullaryOp(mir::NullOp::Box, _) => {
                M::box_alloc(self, &dest)?;
            }

            NullaryOp(null_op, ty) => {
                let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty);
                let layout = self.layout_of(ty)?;
                if layout.is_unsized() {
                    // FIXME: This should be a span_bug (#80742)
                    self.tcx.sess.delay_span_bug(
                        self.frame().current_span(),
                        &format!("Nullary MIR operator called for unsized type {}", ty),
                    );
                    throw_inval!(SizeOfUnsizedType(ty));
                }
                let val = match null_op {
                    mir::NullOp::SizeOf => layout.size.bytes(),
                    mir::NullOp::AlignOf => layout.align.abi.bytes(),
                    mir::NullOp::Box => unreachable!(),
                };
                self.write_scalar(Scalar::from_machine_usize(val, self), &dest)?;
            }

            ShallowInitBox(ref operand, _) => {
                let src = self.eval_operand(operand, None)?;
                let v = self.read_immediate(&src)?;
                self.write_immediate(*v, &dest)?;
            }

            Cast(cast_kind, ref operand, cast_ty) => {
                let src = self.eval_operand(operand, None)?;
                let cast_ty = self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty);
                self.cast(&src, cast_kind, cast_ty, &dest)?;
            }

            Discriminant(place) => {
                let op = self.eval_place_to_op(place, None)?;
                let discr_val = self.read_discriminant(&op)?.0;
                self.write_scalar(discr_val, &dest)?;
            }
        }

        trace!("{:?}", self.dump_place(*dest));

        Ok(())
    }

    fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> InterpResult<'tcx> {
        info!("{:?}", terminator.kind);

        self.eval_terminator(terminator)?;
        if !self.stack().is_empty() {
            if let Ok(loc) = self.frame().loc {
                info!("// executing {:?}", loc.block);
            }
        }
        Ok(())
    }
}
<commit_msg>remove outdated comment<commit_after>//! This module contains the `InterpCx` methods for executing a single step of the interpreter.
//!
//! The main entry point is the `step` method.

use rustc_middle::mir;
use rustc_middle::mir::interpret::{InterpResult, Scalar};
use rustc_middle::ty::layout::LayoutOf;

use super::{InterpCx, Machine};

/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
/// same type as the result.
#[inline]
fn binop_left_homogeneous(op: mir::BinOp) -> bool {
    use rustc_middle::mir::BinOp::*;
    match op {
        Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Offset | Shl | Shr => true,
        Eq | Ne | Lt | Le | Gt | Ge => false,
    }
}
/// Classify whether an operator is "right-homogeneous", i.e., the RHS has the
/// same type as the LHS.
#[inline]
fn binop_right_homogeneous(op: mir::BinOp) -> bool {
    use rustc_middle::mir::BinOp::*;
    match op {
        Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Eq | Ne | Lt | Le | Gt | Ge => true,
        Offset | Shl | Shr => false,
    }
}

impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
    pub fn run(&mut self) -> InterpResult<'tcx> {
        while self.step()? {}
        Ok(())
    }

    /// Returns `true` as long as there are more things to do.
    ///
    /// This is used by [priroda](https://github.com/oli-obk/priroda)
    ///
    /// This is marked `#inline(always)` to work around adverserial codegen when `opt-level = 3`
    #[inline(always)]
    pub fn step(&mut self) -> InterpResult<'tcx, bool> {
        if self.stack().is_empty() {
            return Ok(false);
        }

        let loc = match self.frame().loc {
            Ok(loc) => loc,
            Err(_) => {
                // We are unwinding and this fn has no cleanup code.
                // Just go on unwinding.
                trace!("unwinding: skipping frame");
                self.pop_stack_frame(/* unwinding */ true)?;
                return Ok(true);
            }
        };
        let basic_block = &self.body().basic_blocks()[loc.block];

        let old_frames = self.frame_idx();

        if let Some(stmt) = basic_block.statements.get(loc.statement_index) {
            assert_eq!(old_frames, self.frame_idx());
            self.statement(stmt)?;
            return Ok(true);
        }

        M::before_terminator(self)?;

        let terminator = basic_block.terminator();
        assert_eq!(old_frames, self.frame_idx());
        self.terminator(terminator)?;
        Ok(true)
    }

    /// Runs the interpretation logic for the given `mir::Statement` at the current frame and
    /// statement counter. This also moves the statement counter forward.
    pub fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> {
        info!("{:?}", stmt);

        use rustc_middle::mir::StatementKind::*;

        // Some statements (e.g., box) push new stack frames.
        // We have to record the stack frame number *before* executing the statement.
        let frame_idx = self.frame_idx();

        match &stmt.kind {
            Assign(box (place, rvalue)) => self.eval_rvalue_into_place(rvalue, *place)?,

            SetDiscriminant { place, variant_index } => {
                let dest = self.eval_place(**place)?;
                self.write_discriminant(*variant_index, &dest)?;
            }

            // Mark locals as alive
            StorageLive(local) => {
                self.storage_live(*local)?;
            }

            // Mark locals as dead
            StorageDead(local) => {
                self.storage_dead(*local)?;
            }

            // No dynamic semantics attached to `FakeRead`; MIR
            // interpreter is solely intended for borrowck'ed code.
            FakeRead(..) => {}

            // Stacked Borrows.
            Retag(kind, place) => {
                let dest = self.eval_place(**place)?;
                M::retag(self, *kind, &dest)?;
            }

            // Call CopyNonOverlapping
            CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { src, dst, count }) => {
                let src = self.eval_operand(src, None)?;
                let dst = self.eval_operand(dst, None)?;
                let count = self.eval_operand(count, None)?;
                self.copy_intrinsic(&src, &dst, &count, /* nonoverlapping */ true)?;
            }

            // Statements we do not track.
            AscribeUserType(..) => {}

            // Currently, Miri discards Coverage statements. Coverage statements are only injected
            // via an optional compile time MIR pass and have no side effects. Since Coverage
            // statements don't exist at the source level, it is safe for Miri to ignore them, even
            // for undefined behavior (UB) checks.
            //
            // A coverage counter inside a const expression (for example, a counter injected in a
            // const function) is discarded when the const is evaluated at compile time. Whether
            // this should change, and/or how to implement a const eval counter, is a subject of the
            // following issue:
            //
            // FIXME(#73156): Handle source code coverage in const eval
            Coverage(..) => {}

            // Defined to do nothing. These are added by optimization passes, to avoid changing the
            // size of MIR constantly.
            Nop => {}

            LlvmInlineAsm { .. } => throw_unsup_format!("inline assembly is not supported"),
        }

        self.stack_mut()[frame_idx].loc.as_mut().unwrap().statement_index += 1;
        Ok(())
    }

    /// Evaluate an assignment statement.
    ///
    /// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue
    /// type writes its results directly into the memory specified by the place.
    pub fn eval_rvalue_into_place(
        &mut self,
        rvalue: &mir::Rvalue<'tcx>,
        place: mir::Place<'tcx>,
    ) -> InterpResult<'tcx> {
        let dest = self.eval_place(place)?;

        use rustc_middle::mir::Rvalue::*;
        match *rvalue {
            ThreadLocalRef(did) => {
                let ptr = M::thread_local_static_base_pointer(self, did)?;
                self.write_pointer(ptr, &dest)?;
            }

            Use(ref operand) => {
                // Avoid recomputing the layout
                let op = self.eval_operand(operand, Some(dest.layout))?;
                self.copy_op(&op, &dest)?;
            }

            BinaryOp(bin_op, box (ref left, ref right)) => {
                let layout = binop_left_homogeneous(bin_op).then_some(dest.layout);
                let left = self.read_immediate(&self.eval_operand(left, layout)?)?;
                let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
                let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
                self.binop_ignore_overflow(bin_op, &left, &right, &dest)?;
            }

            CheckedBinaryOp(bin_op, box (ref left, ref right)) => {
                // Due to the extra boolean in the result, we can never reuse the `dest.layout`.
                let left = self.read_immediate(&self.eval_operand(left, None)?)?;
                let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
                let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
                self.binop_with_overflow(bin_op, &left, &right, &dest)?;
            }

            UnaryOp(un_op, ref operand) => {
                // The operand always has the same type as the result.
                let val = self.read_immediate(&self.eval_operand(operand, Some(dest.layout))?)?;
                let val = self.unary_op(un_op, &val)?;
                assert_eq!(val.layout, dest.layout, "layout mismatch for result of {:?}", un_op);
                self.write_immediate(*val, &dest)?;
            }

            Aggregate(ref kind, ref operands) => {
                let (dest, active_field_index) = match **kind {
                    mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => {
                        self.write_discriminant(variant_index, &dest)?;
                        if adt_def.is_enum() {
                            (self.place_downcast(&dest, variant_index)?, active_field_index)
                        } else {
                            (dest, active_field_index)
                        }
                    }
                    _ => (dest, None),
                };

                for (i, operand) in operands.iter().enumerate() {
                    let op = self.eval_operand(operand, None)?;
                    // Ignore zero-sized fields.
                    if !op.layout.is_zst() {
                        let field_index = active_field_index.unwrap_or(i);
                        let field_dest = self.place_field(&dest, field_index)?;
                        self.copy_op(&op, &field_dest)?;
                    }
                }
            }

            Repeat(ref operand, _) => {
                let src = self.eval_operand(operand, None)?;
                assert!(!src.layout.is_unsized());
                let dest = self.force_allocation(&dest)?;
                let length = dest.len(self)?;

                if length == 0 {
                    // Nothing to copy... but let's still make sure that `dest` as a place is valid.
                    self.get_alloc_mut(&dest)?;
                } else {
                    // Write the src to the first element.
                    let first = self.mplace_field(&dest, 0)?;
                    self.copy_op(&src, &first.into())?;

                    // This is performance-sensitive code for big static/const arrays! So we
                    // avoid writing each operand individually and instead just make many copies
                    // of the first element.
                    let elem_size = first.layout.size;
                    let first_ptr = first.ptr;
                    let rest_ptr = first_ptr.offset(elem_size, self)?;
                    self.memory.copy_repeatedly(
                        first_ptr,
                        first.align,
                        rest_ptr,
                        first.align,
                        elem_size,
                        length - 1,
                        /*nonoverlapping:*/ true,
                    )?;
                }
            }

            Len(place) => {
                let src = self.eval_place(place)?;
                let mplace = self.force_allocation(&src)?;
                let len = mplace.len(self)?;
                self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?;
            }

            AddressOf(_, place) | Ref(_, _, place) => {
                let src = self.eval_place(place)?;
                let place = self.force_allocation(&src)?;
                self.write_immediate(place.to_ref(self), &dest)?;
            }

            NullaryOp(mir::NullOp::Box, _) => {
                M::box_alloc(self, &dest)?;
            }

            NullaryOp(null_op, ty) => {
                let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty);
                let layout = self.layout_of(ty)?;
                if layout.is_unsized() {
                    // FIXME: This should be a span_bug (#80742)
                    self.tcx.sess.delay_span_bug(
                        self.frame().current_span(),
                        &format!("Nullary MIR operator called for unsized type {}", ty),
                    );
                    throw_inval!(SizeOfUnsizedType(ty));
                }
                let val = match null_op {
                    mir::NullOp::SizeOf => layout.size.bytes(),
                    mir::NullOp::AlignOf => layout.align.abi.bytes(),
                    mir::NullOp::Box => unreachable!(),
                };
                self.write_scalar(Scalar::from_machine_usize(val, self), &dest)?;
            }

            ShallowInitBox(ref operand, _) => {
                let src = self.eval_operand(operand, None)?;
                let v = self.read_immediate(&src)?;
                self.write_immediate(*v, &dest)?;
            }

            Cast(cast_kind, ref operand, cast_ty) => {
                let src = self.eval_operand(operand, None)?;
                let cast_ty = self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty);
                self.cast(&src, cast_kind, cast_ty, &dest)?;
            }

            Discriminant(place) => {
                let op = self.eval_place_to_op(place, None)?;
                let discr_val = self.read_discriminant(&op)?.0;
                self.write_scalar(discr_val, &dest)?;
            }
        }

        trace!("{:?}", self.dump_place(*dest));

        Ok(())
    }

    fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> InterpResult<'tcx> {
        info!("{:?}", terminator.kind);

        self.eval_terminator(terminator)?;
        if !self.stack().is_empty() {
            if let Ok(loc) = self.frame().loc {
                info!("// executing {:?}", loc.block);
            }
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use super::*;
use redox::prelude::v1::*;
use redox::fs::File;
use redox::io::Read;

pub enum OpenStatus {
    Ok,
    NotFound,
}

impl Editor {
    /// Open a file
    pub fn open(&mut self, path: &str) -> OpenStatus {
        if let Some(mut file) = File::open(path) {
            let mut con = String::new();
            file.read_to_string(&mut con);

            self.text = con.lines().map(|x| x.chars().collect::<VecDeque<char>>()).collect::<VecDeque<VecDeque<char>>>();

            OpenStatus::Ok
        } else {
            OpenStatus::NotFound
        }
    }
}
<commit_msg>Show file name in status bar<commit_after>use super::*;
use redox::prelude::v1::*;
use redox::fs::File;
use redox::io::Read;

pub enum OpenStatus {
    Ok,
    NotFound,
}

impl Editor {
    /// Open a file
    pub fn open(&mut self, path: &str) -> OpenStatus {
        self.status_bar.file = path.to_string();
        if let Some(mut file) = File::open(path) {
            let mut con = String::new();
            file.read_to_string(&mut con);

            self.text = con.lines().map(|x| x.chars().collect::<VecDeque<char>>()).collect::<VecDeque<VecDeque<char>>>();

            OpenStatus::Ok
        } else {
            OpenStatus::NotFound
        }

    }
}
<|endoftext|>


<commit_before>//! Error and Result module

pub use actix_http::error::*;
use derive_more::{Display, Error, From};
use serde_json::error::Error as JsonError;
use serde_urlencoded::de::Error as FormDeError;
use serde_urlencoded::ser::Error as FormError;
use url::ParseError as UrlParseError;

use crate::http::StatusCode;

#[allow(clippy::module_inception)]
mod error;
mod internal;
mod macros;
mod response_error;

pub use self::error::Error;
pub use self::internal::*;
pub use self::response_error::ResponseError;
pub(crate) use macros::{downcast_dyn, downcast_get_type_id};

/// A convenience [`Result`](std::result::Result) for Actix Web operations.
///
/// This type alias is generally used to avoid writing out `actix_http::Error` directly.
pub type Result<T, E = Error> = std::result::Result<T, E>;

/// Errors which can occur when attempting to generate resource uri.
#[derive(Debug, PartialEq, Display, Error, From)]
#[non_exhaustive]
pub enum UrlGenerationError {
    /// Resource not found.
    #[display(fmt = "Resource not found")]
    ResourceNotFound,

    /// Not all URL parameters covered.
    #[display(fmt = "Not all URL parameters covered")]
    NotEnoughElements,

    /// URL parse error.
    #[display(fmt = "{}", _0)]
    ParseError(UrlParseError),
}

impl ResponseError for UrlGenerationError {}

/// A set of errors that can occur during parsing urlencoded payloads
#[derive(Debug, Display, Error, From)]
#[non_exhaustive]
pub enum UrlencodedError {
    /// Can not decode chunked transfer encoding.
    #[display(fmt = "Can not decode chunked transfer encoding.")]
    Chunked,

    /// Payload size is larger than allowed. (default limit: 256kB).
    #[display(
        fmt = "URL encoded payload is larger ({} bytes) than allowed (limit: {} bytes).",
        size,
        limit
    )]
    Overflow { size: usize, limit: usize },

    /// Payload size is now known.
    #[display(fmt = "Payload size is now known.")]
    UnknownLength,

    /// Content type error.
    #[display(fmt = "Content type error.")]
    ContentType,

    /// Parse error.
    #[display(fmt = "Parse error: {}.", _0)]
    Parse(FormDeError),

    /// Encoding error.
    #[display(fmt = "Encoding error.")]
    Encoding,

    /// Serialize error.
    #[display(fmt = "Serialize error: {}.", _0)]
    Serialize(FormError),

    /// Payload error.
    #[display(fmt = "Error that occur during reading payload: {}.", _0)]
    Payload(PayloadError),
}

impl ResponseError for UrlencodedError {
    fn status_code(&self) -> StatusCode {
        match self {
            Self::Overflow { .. } => StatusCode::PAYLOAD_TOO_LARGE,
            Self::UnknownLength => StatusCode::LENGTH_REQUIRED,
            Self::Payload(err) => err.status_code(),
            _ => StatusCode::BAD_REQUEST,
        }
    }
}

/// A set of errors that can occur during parsing json payloads
#[derive(Debug, Display, Error)]
#[non_exhaustive]
pub enum JsonPayloadError {
    /// Payload size is bigger than allowed & content length header set. (default: 2MB)
    #[display(
        fmt = "JSON payload ({} bytes) is larger than allowed (limit: {} bytes).",
        length,
        limit
    )]
    OverflowKnownLength { length: usize, limit: usize },

    /// Payload size is bigger than allowed but no content length header set. (default: 2MB)
    #[display(fmt = "JSON payload has exceeded limit ({} bytes).", limit)]
    Overflow { limit: usize },

    /// Content type error
    #[display(fmt = "Content type error")]
    ContentType,

    /// Deserialize error
    #[display(fmt = "Json deserialize error: {}", _0)]
    Deserialize(JsonError),

    /// Serialize error
    #[display(fmt = "Json serialize error: {}", _0)]
    Serialize(JsonError),

    /// Payload error
    #[display(fmt = "Error that occur during reading payload: {}", _0)]
    Payload(PayloadError),
}

impl From<PayloadError> for JsonPayloadError {
    fn from(err: PayloadError) -> Self {
        Self::Payload(err)
    }
}

impl ResponseError for JsonPayloadError {
    fn status_code(&self) -> StatusCode {
        match self {
            Self::OverflowKnownLength {
                length: _,
                limit: _,
            } => StatusCode::PAYLOAD_TOO_LARGE,
            Self::Overflow { limit: _ } => StatusCode::PAYLOAD_TOO_LARGE,
            Self::Serialize(_) => StatusCode::INTERNAL_SERVER_ERROR,
            Self::Payload(err) => err.status_code(),
            _ => StatusCode::BAD_REQUEST,
        }
    }
}

/// A set of errors that can occur during parsing request paths
#[derive(Debug, Display, Error)]
#[non_exhaustive]
pub enum PathError {
    /// Deserialize error
    #[display(fmt = "Path deserialize error: {}", _0)]
    Deserialize(serde::de::value::Error),
}

/// Return `BadRequest` for `PathError`
impl ResponseError for PathError {
    fn status_code(&self) -> StatusCode {
        StatusCode::BAD_REQUEST
    }
}

/// A set of errors that can occur during parsing query strings.
#[derive(Debug, Display, Error, From)]
#[non_exhaustive]
pub enum QueryPayloadError {
    /// Query deserialize error.
    #[display(fmt = "Query deserialize error: {}", _0)]
    Deserialize(serde::de::value::Error),
}

impl ResponseError for QueryPayloadError {
    fn status_code(&self) -> StatusCode {
        StatusCode::BAD_REQUEST
    }
}

/// Error type returned when reading body as lines.
#[derive(Debug, Display, Error, From)]
#[non_exhaustive]
pub enum ReadlinesError {
    #[display(fmt = "Encoding error")]
    /// Payload size is bigger than allowed. (default: 256kB)
    EncodingError,

    /// Payload error.
    #[display(fmt = "Error that occur during reading payload: {}", _0)]
    Payload(PayloadError),

    /// Line limit exceeded.
    #[display(fmt = "Line limit exceeded")]
    LimitOverflow,

    /// ContentType error.
    #[display(fmt = "Content-type error")]
    ContentTypeError(ContentTypeError),
}

impl ResponseError for ReadlinesError {
    fn status_code(&self) -> StatusCode {
        match *self {
            ReadlinesError::LimitOverflow => StatusCode::PAYLOAD_TOO_LARGE,
            _ => StatusCode::BAD_REQUEST,
        }
    }
}

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

    #[test]
    fn test_urlencoded_error() {
        let resp = UrlencodedError::Overflow { size: 0, limit: 0 }.error_response();
        assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
        let resp = UrlencodedError::UnknownLength.error_response();
        assert_eq!(resp.status(), StatusCode::LENGTH_REQUIRED);
        let resp = UrlencodedError::ContentType.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
    }

    #[test]
    fn test_json_payload_error() {
        let resp = JsonPayloadError::OverflowKnownLength {
            length: 0,
            limit: 0,
        }
        .error_response();
        assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
        let resp = JsonPayloadError::Overflow { limit: 0 }.error_response();
        assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
        let resp = JsonPayloadError::ContentType.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
    }

    #[test]
    fn test_query_payload_error() {
        let resp = QueryPayloadError::Deserialize(
            serde_urlencoded::from_str::<i32>("bad query").unwrap_err(),
        )
        .error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
    }

    #[test]
    fn test_readlines_error() {
        let resp = ReadlinesError::LimitOverflow.error_response();
        assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
        let resp = ReadlinesError::EncodingError.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
    }
}
<commit_msg>workaround rustdoc bug for Error (#2489)<commit_after>//! Error and Result module

/// This is meant to be a glob import of the whole error module, but rustdoc can't handle
/// shadowing `Error` type, so it is expanded manually.
/// See https://github.com/rust-lang/rust/issues/83375
pub use actix_http::error::{
    BlockingError, ContentTypeError, DispatchError, HttpError, ParseError, PayloadError,
};

use derive_more::{Display, Error, From};
use serde_json::error::Error as JsonError;
use serde_urlencoded::de::Error as FormDeError;
use serde_urlencoded::ser::Error as FormError;
use url::ParseError as UrlParseError;

use crate::http::StatusCode;

#[allow(clippy::module_inception)]
mod error;
mod internal;
mod macros;
mod response_error;

pub use self::error::Error;
pub use self::internal::*;
pub use self::response_error::ResponseError;
pub(crate) use macros::{downcast_dyn, downcast_get_type_id};

/// A convenience [`Result`](std::result::Result) for Actix Web operations.
///
/// This type alias is generally used to avoid writing out `actix_http::Error` directly.
pub type Result<T, E = Error> = std::result::Result<T, E>;

/// Errors which can occur when attempting to generate resource uri.
#[derive(Debug, PartialEq, Display, Error, From)]
#[non_exhaustive]
pub enum UrlGenerationError {
    /// Resource not found.
    #[display(fmt = "Resource not found")]
    ResourceNotFound,

    /// Not all URL parameters covered.
    #[display(fmt = "Not all URL parameters covered")]
    NotEnoughElements,

    /// URL parse error.
    #[display(fmt = "{}", _0)]
    ParseError(UrlParseError),
}

impl ResponseError for UrlGenerationError {}

/// A set of errors that can occur during parsing urlencoded payloads
#[derive(Debug, Display, Error, From)]
#[non_exhaustive]
pub enum UrlencodedError {
    /// Can not decode chunked transfer encoding.
    #[display(fmt = "Can not decode chunked transfer encoding.")]
    Chunked,

    /// Payload size is larger than allowed. (default limit: 256kB).
    #[display(
        fmt = "URL encoded payload is larger ({} bytes) than allowed (limit: {} bytes).",
        size,
        limit
    )]
    Overflow { size: usize, limit: usize },

    /// Payload size is now known.
    #[display(fmt = "Payload size is now known.")]
    UnknownLength,

    /// Content type error.
    #[display(fmt = "Content type error.")]
    ContentType,

    /// Parse error.
    #[display(fmt = "Parse error: {}.", _0)]
    Parse(FormDeError),

    /// Encoding error.
    #[display(fmt = "Encoding error.")]
    Encoding,

    /// Serialize error.
    #[display(fmt = "Serialize error: {}.", _0)]
    Serialize(FormError),

    /// Payload error.
    #[display(fmt = "Error that occur during reading payload: {}.", _0)]
    Payload(PayloadError),
}

impl ResponseError for UrlencodedError {
    fn status_code(&self) -> StatusCode {
        match self {
            Self::Overflow { .. } => StatusCode::PAYLOAD_TOO_LARGE,
            Self::UnknownLength => StatusCode::LENGTH_REQUIRED,
            Self::Payload(err) => err.status_code(),
            _ => StatusCode::BAD_REQUEST,
        }
    }
}

/// A set of errors that can occur during parsing json payloads
#[derive(Debug, Display, Error)]
#[non_exhaustive]
pub enum JsonPayloadError {
    /// Payload size is bigger than allowed & content length header set. (default: 2MB)
    #[display(
        fmt = "JSON payload ({} bytes) is larger than allowed (limit: {} bytes).",
        length,
        limit
    )]
    OverflowKnownLength { length: usize, limit: usize },

    /// Payload size is bigger than allowed but no content length header set. (default: 2MB)
    #[display(fmt = "JSON payload has exceeded limit ({} bytes).", limit)]
    Overflow { limit: usize },

    /// Content type error
    #[display(fmt = "Content type error")]
    ContentType,

    /// Deserialize error
    #[display(fmt = "Json deserialize error: {}", _0)]
    Deserialize(JsonError),

    /// Serialize error
    #[display(fmt = "Json serialize error: {}", _0)]
    Serialize(JsonError),

    /// Payload error
    #[display(fmt = "Error that occur during reading payload: {}", _0)]
    Payload(PayloadError),
}

impl From<PayloadError> for JsonPayloadError {
    fn from(err: PayloadError) -> Self {
        Self::Payload(err)
    }
}

impl ResponseError for JsonPayloadError {
    fn status_code(&self) -> StatusCode {
        match self {
            Self::OverflowKnownLength {
                length: _,
                limit: _,
            } => StatusCode::PAYLOAD_TOO_LARGE,
            Self::Overflow { limit: _ } => StatusCode::PAYLOAD_TOO_LARGE,
            Self::Serialize(_) => StatusCode::INTERNAL_SERVER_ERROR,
            Self::Payload(err) => err.status_code(),
            _ => StatusCode::BAD_REQUEST,
        }
    }
}

/// A set of errors that can occur during parsing request paths
#[derive(Debug, Display, Error)]
#[non_exhaustive]
pub enum PathError {
    /// Deserialize error
    #[display(fmt = "Path deserialize error: {}", _0)]
    Deserialize(serde::de::value::Error),
}

/// Return `BadRequest` for `PathError`
impl ResponseError for PathError {
    fn status_code(&self) -> StatusCode {
        StatusCode::BAD_REQUEST
    }
}

/// A set of errors that can occur during parsing query strings.
#[derive(Debug, Display, Error, From)]
#[non_exhaustive]
pub enum QueryPayloadError {
    /// Query deserialize error.
    #[display(fmt = "Query deserialize error: {}", _0)]
    Deserialize(serde::de::value::Error),
}

impl ResponseError for QueryPayloadError {
    fn status_code(&self) -> StatusCode {
        StatusCode::BAD_REQUEST
    }
}

/// Error type returned when reading body as lines.
#[derive(Debug, Display, Error, From)]
#[non_exhaustive]
pub enum ReadlinesError {
    #[display(fmt = "Encoding error")]
    /// Payload size is bigger than allowed. (default: 256kB)
    EncodingError,

    /// Payload error.
    #[display(fmt = "Error that occur during reading payload: {}", _0)]
    Payload(PayloadError),

    /// Line limit exceeded.
    #[display(fmt = "Line limit exceeded")]
    LimitOverflow,

    /// ContentType error.
    #[display(fmt = "Content-type error")]
    ContentTypeError(ContentTypeError),
}

impl ResponseError for ReadlinesError {
    fn status_code(&self) -> StatusCode {
        match *self {
            ReadlinesError::LimitOverflow => StatusCode::PAYLOAD_TOO_LARGE,
            _ => StatusCode::BAD_REQUEST,
        }
    }
}

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

    #[test]
    fn test_urlencoded_error() {
        let resp = UrlencodedError::Overflow { size: 0, limit: 0 }.error_response();
        assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
        let resp = UrlencodedError::UnknownLength.error_response();
        assert_eq!(resp.status(), StatusCode::LENGTH_REQUIRED);
        let resp = UrlencodedError::ContentType.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
    }

    #[test]
    fn test_json_payload_error() {
        let resp = JsonPayloadError::OverflowKnownLength {
            length: 0,
            limit: 0,
        }
        .error_response();
        assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
        let resp = JsonPayloadError::Overflow { limit: 0 }.error_response();
        assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
        let resp = JsonPayloadError::ContentType.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
    }

    #[test]
    fn test_query_payload_error() {
        let resp = QueryPayloadError::Deserialize(
            serde_urlencoded::from_str::<i32>("bad query").unwrap_err(),
        )
        .error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
    }

    #[test]
    fn test_readlines_error() {
        let resp = ReadlinesError::LimitOverflow.error_response();
        assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
        let resp = ReadlinesError::EncodingError.error_response();
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
    }
}
<|endoftext|>


<commit_before>//! Asynchronous signal handling for Tokio
//!
//! Note that signal handling is in general a very tricky topic and should be
//! used with great care. This crate attempts to implement 'best practice' for
//! signal handling, but it should be evaluated for your own applications' needs
//! to see if it's suitable.
//!
//! The are some fundamental limitations of this crate documented on the OS
//! specific structures, as well.
//!
//! # Examples
//!
//! Print on "ctrl-c" notification.
//!
//! ```rust,no_run
//! use tokio::signal;
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//!     signal::ctrl_c().await?;
//!     println!("ctrl-c received!");
//!     Ok(())
//! }
//! ```
//!
//! Wait for SIGHUP on Unix
//!
//! ```rust,no_run
//! # #[cfg(unix)] {
//! use tokio::signal::unix::{signal, SignalKind};
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//!     // An infinite stream of hangup signals.
//!     let mut stream = signal(SignalKind::hangup())?;
//!
//!     // Print whenever a HUP signal is received
//!     loop {
//!         stream.recv().await;
//!         println!("got signal HUP");
//!     }
//! }
//! # }
//! ```

mod ctrl_c;
pub use ctrl_c::ctrl_c;

mod registry;

mod os {
    #[cfg(unix)]
    pub(crate) use super::unix::{OsExtraData, OsStorage};

    #[cfg(windows)]
    pub(crate) use super::windows::{OsExtraData, OsStorage};
}

pub mod unix;
pub mod windows;
<commit_msg>docs: fix typo in signal module documentation (#3249)<commit_after>//! Asynchronous signal handling for Tokio
//!
//! Note that signal handling is in general a very tricky topic and should be
//! used with great care. This crate attempts to implement 'best practice' for
//! signal handling, but it should be evaluated for your own applications' needs
//! to see if it's suitable.
//!
//! There are some fundamental limitations of this crate documented on the OS
//! specific structures, as well.
//!
//! # Examples
//!
//! Print on "ctrl-c" notification.
//!
//! ```rust,no_run
//! use tokio::signal;
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//!     signal::ctrl_c().await?;
//!     println!("ctrl-c received!");
//!     Ok(())
//! }
//! ```
//!
//! Wait for SIGHUP on Unix
//!
//! ```rust,no_run
//! # #[cfg(unix)] {
//! use tokio::signal::unix::{signal, SignalKind};
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//!     // An infinite stream of hangup signals.
//!     let mut stream = signal(SignalKind::hangup())?;
//!
//!     // Print whenever a HUP signal is received
//!     loop {
//!         stream.recv().await;
//!         println!("got signal HUP");
//!     }
//! }
//! # }
//! ```

mod ctrl_c;
pub use ctrl_c::ctrl_c;

mod registry;

mod os {
    #[cfg(unix)]
    pub(crate) use super::unix::{OsExtraData, OsStorage};

    #[cfg(windows)]
    pub(crate) use super::windows::{OsExtraData, OsStorage};
}

pub mod unix;
pub mod windows;
<|endoftext|>


<commit_before>use crate::backend::{Backend, SupportsOnConflictClause};
use crate::expression::Expression;
use crate::query_builder::upsert::on_conflict_target::{ConflictTarget, NoConflictTarget};
use crate::query_builder::where_clause::{NoWhereClause, WhereAnd, WhereClause};
use crate::query_builder::{AstPass, QueryFragment, QueryResult};
use crate::sql_types::BoolOrNullableBool;

pub trait UndecoratedConflictTarget {}

impl UndecoratedConflictTarget for NoConflictTarget {}
impl<T> UndecoratedConflictTarget for ConflictTarget<T> {}

/// Interface to add information to conflict targets.
/// Designed to be open for further additions to conflict targets like constraints
pub trait DecoratableTarget<U, P> {
    /// Output type of filter_target operation
    type FilterOutput;
    /// equivalent to filter of FilterDsl but aimed at conflict targets
    fn filter_target(self, predicate: P) -> Self::FilterOutput;
}

#[derive(Debug)]
pub struct DecoratedConflictTarget<T, U> {
    target: T,
    where_clause: U,
}

impl<T, P> DecoratableTarget<WhereClause<P>, P> for T
where
    P: Expression,
    P::SqlType: BoolOrNullableBool,
    T: UndecoratedConflictTarget,
{
    type FilterOutput = DecoratedConflictTarget<T, WhereClause<P>>;
    fn filter_target(self, predicate: P) -> Self::FilterOutput {
        DecoratedConflictTarget {
            target: self,
            where_clause: NoWhereClause.and(predicate),
        }
    }
}

impl<T, U, P> DecoratableTarget<<U as WhereAnd<P>>::Output, P> for DecoratedConflictTarget<T, U>
where
    P: Expression,
    P::SqlType: BoolOrNullableBool,
    U: WhereAnd<P>,
{
    type FilterOutput = DecoratedConflictTarget<T, <U as WhereAnd<P>>::Output>;
    fn filter_target(self, predicate: P) -> Self::FilterOutput {
        DecoratedConflictTarget {
            target: self.target,
            where_clause: self.where_clause.and(predicate),
        }
    }
}

impl<DB, T, U> QueryFragment<DB> for DecoratedConflictTarget<T, U>
where
    T: QueryFragment<DB>,
    U: QueryFragment<DB>,
    DB: Backend + SupportsOnConflictClause,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        self.target.walk_ast(out.reborrow())?;
        self.where_clause.walk_ast(out.reborrow())?;
        Ok(())
    }
}
<commit_msg>fix trait bound for backend<commit_after>use crate::backend::{Backend, SupportsOnConflictClause, SupportsOnConflictTargetDecorations};
use crate::expression::Expression;
use crate::query_builder::upsert::on_conflict_target::{ConflictTarget, NoConflictTarget};
use crate::query_builder::where_clause::{NoWhereClause, WhereAnd, WhereClause};
use crate::query_builder::{AstPass, QueryFragment, QueryResult};
use crate::sql_types::BoolOrNullableBool;

pub trait UndecoratedConflictTarget {}

impl UndecoratedConflictTarget for NoConflictTarget {}
impl<T> UndecoratedConflictTarget for ConflictTarget<T> {}

/// Interface to add information to conflict targets.
/// Designed to be open for further additions to conflict targets like constraints
pub trait DecoratableTarget<U, P> {
    /// Output type of filter_target operation
    type FilterOutput;
    /// equivalent to filter of FilterDsl but aimed at conflict targets
    fn filter_target(self, predicate: P) -> Self::FilterOutput;
}

#[derive(Debug)]
pub struct DecoratedConflictTarget<T, U> {
    target: T,
    where_clause: U,
}

impl<T, P> DecoratableTarget<WhereClause<P>, P> for T
where
    P: Expression,
    P::SqlType: BoolOrNullableBool,
    T: UndecoratedConflictTarget,
{
    type FilterOutput = DecoratedConflictTarget<T, WhereClause<P>>;
    fn filter_target(self, predicate: P) -> Self::FilterOutput {
        DecoratedConflictTarget {
            target: self,
            where_clause: NoWhereClause.and(predicate),
        }
    }
}

impl<T, U, P> DecoratableTarget<<U as WhereAnd<P>>::Output, P> for DecoratedConflictTarget<T, U>
where
    P: Expression,
    P::SqlType: BoolOrNullableBool,
    U: WhereAnd<P>,
{
    type FilterOutput = DecoratedConflictTarget<T, <U as WhereAnd<P>>::Output>;
    fn filter_target(self, predicate: P) -> Self::FilterOutput {
        DecoratedConflictTarget {
            target: self.target,
            where_clause: self.where_clause.and(predicate),
        }
    }
}

impl<DB, T, U> QueryFragment<DB> for DecoratedConflictTarget<T, U>
where
    T: QueryFragment<DB>,
    U: QueryFragment<DB>,
    DB: Backend + SupportsOnConflictClause + SupportsOnConflictTargetDecorations,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        self.target.walk_ast(out.reborrow())?;
        self.where_clause.walk_ast(out.reborrow())?;
        Ok(())
    }
}
<|endoftext|>


<commit_before>mod score;
pub mod consts;

use std::ascii::AsciiExt;
pub use self::score::*;

/// Compares two characters case-insensitively
///
/// # Examples
///
/// ```
/// assert!(rff::fuzzy::eq('a', 'A'));
/// ```
#[inline(always)]
pub fn eq(a: char, b: char) -> bool {
    match a {
        a if a == b => true,
        a if a.is_ascii() && !b.is_ascii() => false,
        a if !a.is_ascii() && b.is_ascii() => false,
        a if a.is_ascii() && b.is_ascii() => {
            a.to_ascii_lowercase().eq(&b.to_ascii_lowercase())
        },
        a => a.to_lowercase().eq(b.to_lowercase())
    }
}

/// Searches for needle's chars in the haystack
///
/// # Examples
///
/// ```
/// assert!(rff::fuzzy::matches("amo", "app/models/order"));
/// ```
pub fn matches(needle: &str, haystack: &str) -> bool {
    let mut hchars = haystack.chars();

    'outer: for n in needle.chars() {
        loop {
            match hchars.next() {
                Some(h) if eq(h, n) => continue 'outer,
                Some(_) => continue,
                None => return false
            }
        }
    }

    true
}

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

    #[test]
    fn test_eq() {
        assert!(eq('a', 'A'));
        assert!(eq('山', '山'));
        assert!(!eq('a', 'b'));
    }

    #[test]
    fn test_matches() {
        assert!(matches("a", "a"));
        assert!(matches("a", "abc"));
        assert!(matches("abc", "abc"));
        assert!(matches("ABC", "abc"));
        assert!(matches("abc", "a1b2c3"));
        assert!(matches("abc", "a1b2c3"));
        assert!(matches("test", "t/e/s/t"));
        assert!(matches("test", "t💣e💣s💣t"));
        assert!(matches("💣💣💣", "t💣e💣s💣t"));

        assert!(!matches("abc", "ab"));
        assert!(!matches("abc", "cab"));
        assert!(!matches("abc", ""));

        assert!(matches("", ""));
        assert!(matches("", "ab"));

        // UTF-8 case testing
        assert!(matches("a", "A"));
        assert!(matches("A", "a"));
        assert!(matches("山", "山"));
        assert!(matches("café", "CAFÉ"))
    }

    #[bench]
    fn bench_eq_same(b: &mut Bencher) {
        b.iter(|| eq('a', 'a'));
    }

    #[bench]
    fn bench_eq_ascii(b: &mut Bencher) {
        b.iter(|| eq('a', 'A'));
    }

    #[bench]
    fn bench_eq_utf8(b: &mut Bencher) {
        b.iter(|| eq('ø', 'Ø'));
    }

    #[bench]
    fn bench_eq_mixed(b: &mut Bencher) {
        b.iter(|| eq('a', 'Ø'));
    }

    #[bench]
    fn bench_matches(b: &mut Bencher) {
        b.iter(|| matches("amor", "app/models/order.rb"))
    }

    #[bench]
    fn bench_matches_mixed_case(b: &mut Bencher) {
        b.iter(|| matches("AMOr", "App/Models/Order.rb"))
    }

    #[bench]
    fn bench_matches_multiple(b: &mut Bencher) {
        b.iter(|| {
            matches("amor", "app/models/order.rb");
            matches("amor", "spec/models/order_spec.rb");
            matches("amor", "other_garbage.rb");
            matches("amor", "Gemfile");
            matches("amor", "node_modules/test/a/thing.js");
            matches("amor", "vendor/bundle/ruby/gem.rb")
        })
    }
}
<commit_msg>Optimize identical input strings to fuzzy::matches<commit_after>mod score;
pub mod consts;

use std::ascii::AsciiExt;
pub use self::score::*;

/// Compares two characters case-insensitively
///
/// # Examples
///
/// ```
/// assert!(rff::fuzzy::eq('a', 'A'));
/// ```
#[inline(always)]
pub fn eq(a: char, b: char) -> bool {
    match a {
        a if a == b => true,
        a if a.is_ascii() && !b.is_ascii() => false,
        a if !a.is_ascii() && b.is_ascii() => false,
        a if a.is_ascii() && b.is_ascii() => {
            a.to_ascii_lowercase().eq(&b.to_ascii_lowercase())
        },
        a => a.to_lowercase().eq(b.to_lowercase())
    }
}

/// Searches for needle's chars in the haystack
///
/// # Examples
///
/// ```
/// assert!(rff::fuzzy::matches("amo", "app/models/order"));
/// ```
pub fn matches(needle: &str, haystack: &str) -> bool {
    let mut hchars = haystack.chars();

    if needle == haystack {
        return true;
    }

    'outer: for n in needle.chars() {
        loop {
            match hchars.next() {
                Some(h) if eq(h, n) => continue 'outer,
                Some(_) => continue,
                None => return false
            }
        }
    }

    true
}

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

    #[test]
    fn test_eq() {
        assert!(eq('a', 'A'));
        assert!(eq('山', '山'));
        assert!(!eq('a', 'b'));
    }

    #[test]
    fn test_matches() {
        assert!(matches("a", "a"));
        assert!(matches("a", "abc"));
        assert!(matches("abc", "abc"));
        assert!(matches("ABC", "abc"));
        assert!(matches("abc", "a1b2c3"));
        assert!(matches("abc", "a1b2c3"));
        assert!(matches("test", "t/e/s/t"));
        assert!(matches("test", "t💣e💣s💣t"));
        assert!(matches("💣💣💣", "t💣e💣s💣t"));

        assert!(!matches("abc", "ab"));
        assert!(!matches("abc", "cab"));
        assert!(!matches("abc", ""));

        assert!(matches("", ""));
        assert!(matches("", "ab"));

        // UTF-8 case testing
        assert!(matches("a", "A"));
        assert!(matches("A", "a"));
        assert!(matches("山", "山"));
        assert!(matches("café", "CAFÉ"))
    }

    #[bench]
    fn bench_eq_same(b: &mut Bencher) {
        b.iter(|| eq('a', 'a'));
    }

    #[bench]
    fn bench_eq_ascii(b: &mut Bencher) {
        b.iter(|| eq('a', 'A'));
    }

    #[bench]
    fn bench_eq_utf8(b: &mut Bencher) {
        b.iter(|| eq('ø', 'Ø'));
    }

    #[bench]
    fn bench_eq_mixed(b: &mut Bencher) {
        b.iter(|| eq('a', 'Ø'));
    }

    #[bench]
    fn bench_matches(b: &mut Bencher) {
        b.iter(|| matches("amor", "app/models/order.rb"))
    }

    #[bench]
    fn bench_matches_mixed_case(b: &mut Bencher) {
        b.iter(|| matches("AMOr", "App/Models/Order.rb"))
    }

    #[bench]
    fn bench_matches_multiple(b: &mut Bencher) {
        b.iter(|| {
            matches("amor", "app/models/order.rb");
            matches("amor", "spec/models/order_spec.rb");
            matches("amor", "other_garbage.rb");
            matches("amor", "Gemfile");
            matches("amor", "node_modules/test/a/thing.js");
            matches("amor", "vendor/bundle/ruby/gem.rb")
        })
    }

    #[bench]
    fn bench_matches_eq(b: &mut Bencher) {
        b.iter(|| {
            matches("Gemfile", "Gemfile");
            matches("gemfile", "Gemfile")
        })
    }
}
<|endoftext|>


<commit_before>fn main() {
    // Fake-main technique. This allows the main() function to return an int (i32) status code.
    std::process::exit(fake_main());
}

fn fake_main() -> i32 {
    println!("Hello from fakemain.");
    return 0;
}
<commit_msg>Reorganize main.rs<commit_after>fn fake_main() -> i32 {
    println!("Hello from fakemain.");
    return 0;
}

fn main() {
    // Fake-main technique. This allows the main() function to return an int (i32) status code.
    std::process::exit(fake_main());
}
<|endoftext|>