<commit_before>//! An asymmetric frustum with an arbitrary 3D pose.

use crate::math::sat::{ConvexPolyhedron, Intersector};
use crate::math::{Isometry3, PointCulling};
use arrayvec::ArrayVec;
use cgmath::{
    BaseFloat, Decomposed, InnerSpace, Matrix4, Perspective, Point3, Quaternion, Transform, Vector3,
};
use collision::{Aabb3, Relation};
use serde::{Deserialize, Serialize};

/// A frustum is defined in eye coordinates, where x points right, y points up,
/// and z points against the viewing direction. This is not how e.g. OpenCV
/// defines a camera coordinate system. To get from OpenCV camera coordinates
/// to eye coordinates, you need to rotate 180 deg around the x axis before
/// creating the perspective projection, see also the frustum unit test below.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Frustum<S: BaseFloat> {
    query_from_eye: Isometry3<S>,
    clip_from_eye: Perspective<S>,
    query_from_clip: Matrix4<S>,
    frustum: collision::Frustum<S>,
}

impl<S: BaseFloat> Frustum<S> {
    pub fn new(query_from_eye: Isometry3<S>, clip_from_eye: Perspective<S>) -> Self {
        let eye_from_query: Decomposed<Vector3<S>, Quaternion<S>> = query_from_eye.inverse().into();
        let clip_from_query =
            Matrix4::<S>::from(clip_from_eye) * Matrix4::<S>::from(eye_from_query);
        let query_from_clip = clip_from_query.inverse_transform().unwrap();
        let frustum = collision::Frustum::from_matrix4(clip_from_query).unwrap();
        Frustum {
            query_from_eye,
            clip_from_eye,
            query_from_clip,
            frustum,
        }
    }

    pub fn transformed(&self, global_from_query: &Isometry3<S>) -> Self {
        Self::new(global_from_query * &self.query_from_eye, self.clip_from_eye)
    }
}

impl<S> PointCulling<S> for Frustum<S>
where
    S: 'static + BaseFloat + Sync + Send,
{
    fn contains(&self, point: &Point3<S>) -> bool {
        match self.frustum.contains(point) {
            Relation::Cross => true,
            Relation::In => true,
            Relation::Out => false,
        }
    }
    fn intersects_aabb3(&self, aabb: &Aabb3<S>) -> bool {
        match self.frustum.contains(aabb) {
            Relation::Cross => true,
            Relation::In => true,
            Relation::Out => false,
        }
    }
}

impl<S> ConvexPolyhedron<S> for Frustum<S>
where
    S: BaseFloat,
{
    fn compute_corners(&self) -> [Point3<S>; 8] {
        let corner_from = |x, y, z| self.query_from_clip.transform_point(Point3::new(x, y, z));
        [
            corner_from(-S::one(), -S::one(), -S::one()),
            corner_from(-S::one(), -S::one(), S::one()),
            corner_from(-S::one(), S::one(), -S::one()),
            corner_from(-S::one(), S::one(), S::one()),
            corner_from(S::one(), -S::one(), -S::one()),
            corner_from(S::one(), -S::one(), S::one()),
            corner_from(S::one(), S::one(), -S::one()),
            corner_from(S::one(), S::one(), S::one()),
        ]
    }

    fn intersector(&self) -> Intersector<S> {
        let corners = self.compute_corners();

        let edges = ArrayVec::from([
            (corners[4] - corners[0]).normalize(), // x
            (corners[2] - corners[0]).normalize(), // y
            (corners[1] - corners[0]).normalize(), // z lower left
            (corners[3] - corners[2]).normalize(), // z upper left
            (corners[5] - corners[4]).normalize(), // z lower right
            (corners[7] - corners[6]).normalize(), // z upper right
        ]);

        let mut face_normals = ArrayVec::new();
        face_normals.push((edges[0].cross(edges[1])).normalize()); // Front and back sides
        face_normals.push((edges[0].cross(edges[2])).normalize()); // Lower side
        face_normals.push((edges[0].cross(edges[3])).normalize()); // Upper side
        face_normals.push((edges[1].cross(edges[2])).normalize()); // Left side
        face_normals.push((edges[1].cross(edges[4])).normalize()); // Right side

        Intersector {
            corners,
            edges,
            face_normals,
        }
    }
}
<commit_msg>Remove transform() method on Frustum (#426)<commit_after>//! An asymmetric frustum with an arbitrary 3D pose.

use crate::math::sat::{ConvexPolyhedron, Intersector};
use crate::math::{Isometry3, PointCulling};
use arrayvec::ArrayVec;
use cgmath::{
    BaseFloat, Decomposed, InnerSpace, Matrix4, Perspective, Point3, Quaternion, Transform, Vector3,
};
use collision::{Aabb3, Relation};
use serde::{Deserialize, Serialize};

/// A frustum is defined in eye coordinates, where x points right, y points up,
/// and z points against the viewing direction. This is not how e.g. OpenCV
/// defines a camera coordinate system. To get from OpenCV camera coordinates
/// to eye coordinates, you need to rotate 180 deg around the x axis before
/// creating the perspective projection, see also the frustum unit test below.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Frustum<S: BaseFloat> {
    /// The "query" coordinates are basically our world coordinates.
    query_from_clip: Matrix4<S>,
    /// The inverse of the above matrix, suitable for intersection tests.
    frustum: collision::Frustum<S>,
}

impl<S: BaseFloat> Frustum<S> {
    pub fn new(query_from_eye: Isometry3<S>, clip_from_eye: Perspective<S>) -> Self {
        let eye_from_query: Decomposed<Vector3<S>, Quaternion<S>> = query_from_eye.inverse().into();
        let clip_from_query =
            Matrix4::<S>::from(clip_from_eye) * Matrix4::<S>::from(eye_from_query);
        let query_from_clip = clip_from_query.inverse_transform().unwrap();
        let frustum = collision::Frustum::from_matrix4(clip_from_query).unwrap();
        Frustum {
            query_from_clip,
            frustum,
        }
    }
}

impl<S> PointCulling<S> for Frustum<S>
where
    S: 'static + BaseFloat + Sync + Send,
{
    fn contains(&self, point: &Point3<S>) -> bool {
        match self.frustum.contains(point) {
            Relation::Cross => true,
            Relation::In => true,
            Relation::Out => false,
        }
    }
    fn intersects_aabb3(&self, aabb: &Aabb3<S>) -> bool {
        match self.frustum.contains(aabb) {
            Relation::Cross => true,
            Relation::In => true,
            Relation::Out => false,
        }
    }
}

impl<S> ConvexPolyhedron<S> for Frustum<S>
where
    S: BaseFloat,
{
    fn compute_corners(&self) -> [Point3<S>; 8] {
        let corner_from = |x, y, z| self.query_from_clip.transform_point(Point3::new(x, y, z));
        [
            corner_from(-S::one(), -S::one(), -S::one()),
            corner_from(-S::one(), -S::one(), S::one()),
            corner_from(-S::one(), S::one(), -S::one()),
            corner_from(-S::one(), S::one(), S::one()),
            corner_from(S::one(), -S::one(), -S::one()),
            corner_from(S::one(), -S::one(), S::one()),
            corner_from(S::one(), S::one(), -S::one()),
            corner_from(S::one(), S::one(), S::one()),
        ]
    }

    fn intersector(&self) -> Intersector<S> {
        let corners = self.compute_corners();

        let edges = ArrayVec::from([
            (corners[4] - corners[0]).normalize(), // x
            (corners[2] - corners[0]).normalize(), // y
            (corners[1] - corners[0]).normalize(), // z lower left
            (corners[3] - corners[2]).normalize(), // z upper left
            (corners[5] - corners[4]).normalize(), // z lower right
            (corners[7] - corners[6]).normalize(), // z upper right
        ]);

        let mut face_normals = ArrayVec::new();
        face_normals.push((edges[0].cross(edges[1])).normalize()); // Front and back sides
        face_normals.push((edges[0].cross(edges[2])).normalize()); // Lower side
        face_normals.push((edges[0].cross(edges[3])).normalize()); // Upper side
        face_normals.push((edges[1].cross(edges[2])).normalize()); // Left side
        face_normals.push((edges[1].cross(edges[4])).normalize()); // Right side

        Intersector {
            corners,
            edges,
            face_normals,
        }
    }
}
<|endoftext|>


<commit_before>// xfail-win32
use std;
import std::task;
import std::comm;
import std::uint;

fn die(&&_i: ()) {
    fail;
}

fn iloop(&&_i: ()) {
    task::unsupervise();
    task::spawn((), die);
    let p = comm::port::<()>();
    let c = comm::chan(p);
    while true {
        comm::send(c, ());
    }
}

fn main() {
    uint::range(0u, 16u) {|_i|
        task::spawn((), iloop);
    }
}<commit_msg>test: Don't fill queue in run-pass/send-iloop. Closes #1244<commit_after>// xfail-win32
use std;
import std::task;
import std::comm;
import std::uint;

fn die(&&_i: ()) {
    fail;
}

fn iloop(&&_i: ()) {
    task::unsupervise();
    task::spawn((), die);
    let p = comm::port::<()>();
    let c = comm::chan(p);
    while true {
        // Sending and receiving here because these actions yield,
        // at which point our child can kill us
        comm::send(c, ());
        comm::recv(p);
    }
}

fn main() {
    uint::range(0u, 16u) {|_i|
        task::spawn((), iloop);
    }
}<|endoftext|>


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

// GetLastError doesn't seem to work with stack switching
// xfail-test

#[cfg(target_os = "win32")]
extern "stdcall" mod kernel32 {
    fn SetLastError(err: uint);
    fn GetLastError() -> uint;
}

#[cfg(target_os = "win32")]
pub fn main() {
    unsafe {
        let expected = 1234u;
        kernel32::SetLastError(expected);
        let actual = kernel32::GetLastError();
        log(error, actual);
        assert_eq!(expected, actual);
    }
}

#[cfg(target_os = "macos")]
#[cfg(target_os = "linux")]
#[cfg(target_os = "freebsd")]
pub fn main() { }
<commit_msg>Fix XFailed test x86stdcall<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// GetLastError doesn't seem to work with stack switching

#[cfg(windows)]
mod kernel32 {
  extern "system" {
    pub fn SetLastError(err: uint);
    pub fn GetLastError() -> uint;
  }
}

#[cfg(windows)]
pub fn main() {
    unsafe {
        let expected = 1234u;
        kernel32::SetLastError(expected);
        let actual = kernel32::GetLastError();
        info!("actual = {}", actual);
        assert_eq!(expected, actual);
    }
}

#[cfg(target_os = "macos")]
#[cfg(target_os = "linux")]
#[cfg(target_os = "freebsd")]
pub fn main() { }
<|endoftext|>


<commit_before>// compile-flags: --show-type-layout -Z unstable-options

// @has type_layout/struct.Foo.html 'Size: '
// @has - ' bytes'
pub struct Foo {
    pub a: usize,
    b: Vec<String>,
}

// @has type_layout/enum.Bar.html 'Size: '
// @has - ' bytes'
pub enum Bar<'a> {
    A(String),
    B(&'a str, (std::collections::HashMap<String, usize>, Foo)),
}

// @has type_layout/union.Baz.html 'Size: '
// @has - ' bytes'
pub union Baz {
    a: &'static str,
    b: usize,
    c: &'static [u8],
}

// @has type_layout/struct.X.html 'Size: '
// @has - ' bytes'
pub struct X(usize);

// @has type_layout/struct.Y.html 'Size: '
// @has - ' byte'
// @!has - ' bytes'
pub struct Y(u8);

// @!has type_layout/struct.Generic.html 'Size: '
pub struct Generic<T>(T);

// @has type_layout/struct.Unsized.html 'Size: '
// @has - '(unsized)'
pub struct Unsized([u8]);

// @has type_layout/type.TypeAlias.html 'Size: '
// @has - ' bytes'
pub type TypeAlias = X;

// @!has type_layout/trait.MyTrait.html 'Size: '
pub trait MyTrait {}
<commit_msg>Make test more specific<commit_after>// compile-flags: --show-type-layout -Z unstable-options

// @has type_layout/struct.Foo.html 'Size: '
// @has - ' bytes'
pub struct Foo {
    pub a: usize,
    b: Vec<String>,
}

// @has type_layout/enum.Bar.html 'Size: '
// @has - ' bytes'
pub enum Bar<'a> {
    A(String),
    B(&'a str, (std::collections::HashMap<String, usize>, Foo)),
}

// @has type_layout/union.Baz.html 'Size: '
// @has - ' bytes'
pub union Baz {
    a: &'static str,
    b: usize,
    c: &'static [u8],
}

// @has type_layout/struct.X.html 'Size: '
// @has - ' bytes'
pub struct X(usize);

// @has type_layout/struct.Y.html 'Size: '
// @has - '1 byte'
// @!has - ' bytes'
pub struct Y(u8);

// @!has type_layout/struct.Generic.html 'Size: '
pub struct Generic<T>(T);

// @has type_layout/struct.Unsized.html 'Size: '
// @has - '(unsized)'
pub struct Unsized([u8]);

// @has type_layout/type.TypeAlias.html 'Size: '
// @has - ' bytes'
pub type TypeAlias = X;

// @!has type_layout/trait.MyTrait.html 'Size: '
pub trait MyTrait {}
<|endoftext|>


<commit_before>use rand;
use rand::Rng;

use aes::BLOCK_SIZE;
use aes::{Aes128, MODE};

use serialize::from_base64;

use errors::*;
use failure::Error;

use set2::decode_profile;
use set2::random_block;

pub trait Oracle {
    fn encrypt(&self, u: &[u8]) -> Result<Vec<u8>, Error>;
    fn verify_suffix(&self, candidate: &[u8]) -> Result<(), Error>;
}

// Marker trait for oracles where repeated calls to
// `encrypt` for the same `u` produce the same result.
// This excludes oracles in CBC mode with random iv.
pub trait DeterministicOracle: Oracle {}

struct Common {
    key: Vec<u8>,
    prefix: Vec<u8>,
    suffix: Vec<u8>,
    mode: MODE,
}

impl Oracle for Common {
    fn encrypt(&self, u: &[u8]) -> Result<Vec<u8>, Error> {
        let key = &self.key;
        let prefix = &self.prefix;
        let suffix = &self.suffix;
        let mode = self.mode;

        let mut cleartext = Vec::with_capacity(prefix.len() + u.len() + suffix.len());
        cleartext.extend_from_slice(prefix);
        cleartext.extend_from_slice(u);
        cleartext.extend_from_slice(suffix);

        match mode {
            MODE::CBC => {
                // We would normally also return iv, but our callers do not need it
                let iv = random_block();
                cleartext.encrypt(key, Some(&iv), mode)
            }
            _ => cleartext.encrypt(key, None, mode),
        }
    }

    fn verify_suffix(&self, candidate: &[u8]) -> Result<(), Error> {
        compare_eq(&self.suffix[..], candidate)
    }
}

pub struct Oracle11 {
    common: Common,
    already_called: bool,
}

impl Oracle11 {
    pub fn new() -> Result<Self, Error> {
        let mut rng = rand::thread_rng();
        let key = random_block();
        let prefix_len = rng.gen_range(5, 11);
        let prefix: Vec<u8> = rng.gen_iter().take(prefix_len).collect();
        let suffix_len = rng.gen_range(5, 11);
        let suffix: Vec<u8> = rng.gen_iter().take(suffix_len).collect();

        let use_ecb = rng.gen();
        let mode = if use_ecb { MODE::ECB } else { MODE::CBC };

        Ok(Oracle11 {
            common: Common {
                key,
                prefix,
                suffix,
                mode,
            },
            already_called: false,
        })
    }

    pub fn encrypt(&mut self, u: &[u8]) -> Result<Vec<u8>, Error> {
        if self.already_called {
            bail!("Method has already been called. Please generate a fresh oracle.");
        }

        self.already_called = true;
        self.common.encrypt(u)
    }

    pub fn verify_solution(&self, uses_ecb: bool) -> Result<(), Error> {
        compare_eq(self.common.mode == MODE::ECB, uses_ecb)
    }
}

pub struct Oracle12 {
    common: Common,
}

impl DeterministicOracle for Oracle12 {}

impl Oracle for Oracle12 {
    fn encrypt(&self, u: &[u8]) -> Result<Vec<u8>, Error> {
        self.common.encrypt(u)
    }

    fn verify_suffix(&self, candidate: &[u8]) -> Result<(), Error> {
        self.common.verify_suffix(candidate)
    }
}

impl Oracle12 {
    pub fn new() -> Result<Self, Error> {
        let key = random_block();

        let suffix = from_base64(
            "Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRv\
             d24gc28gbXkgaGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvb\
             iBzdGFuZGJ5IHdhdmluZyBqdXN0IHRvIHNheSBoaQpEaWQgeW\
             91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUgYnkK",
        )?;

        Ok(Oracle12 {
            common: Common {
                key,
                prefix: Vec::new(),
                suffix,
                mode: MODE::ECB,
            },
        })
    }
}

pub struct Oracle13 {
    common: Common,
}

impl DeterministicOracle for Oracle13 {}

impl Oracle for Oracle13 {
    fn encrypt(&self, u: &[u8]) -> Result<Vec<u8>, Error> {
        if u.iter().any(|&c| !c.is_ascii() || c == b'&' || c == b'=') {
            panic!("Invalid input.");
        }

        self.common.encrypt(u)
    }

    fn verify_suffix(&self, candidate: &[u8]) -> Result<(), Error> {
        self.common.verify_suffix(candidate)
    }
}

impl Oracle13 {
    pub fn new() -> Result<Self, Error> {
        let key = random_block();

        let prefix = b"email=".to_vec();
        let suffix = b"&uid=10&role=user".to_vec();

        Ok(Oracle13 {
            common: Common {
                key,
                prefix,
                suffix,
                mode: MODE::ECB,
            },
        })
    }

    pub fn verify_solution(&self, ciphertext: &[u8]) -> Result<(), Error> {
        compare_eq(
            Some(b"admin".as_ref()),
            decode_profile(
                &ciphertext.decrypt(&self.common.key, None, MODE::ECB)?,
                b'&',
            ).remove(b"role".as_ref()),
        )
    }
}

pub struct Oracle14 {
    common: Common,
}

impl DeterministicOracle for Oracle14 {}

impl Oracle for Oracle14 {
    fn encrypt(&self, u: &[u8]) -> Result<Vec<u8>, Error> {
        self.common.encrypt(u)
    }

    fn verify_suffix(&self, candidate: &[u8]) -> Result<(), Error> {
        self.common.verify_suffix(candidate)
    }
}

impl Oracle14 {
    pub fn new() -> Result<Self, Error> {
        let mut rng = rand::thread_rng();
        let key: Vec<u8> = rng.gen_iter().take(BLOCK_SIZE).collect();
        let prefix_len = rng.gen_range(1, 200);
        let prefix: Vec<u8> = rng.gen_iter().take(prefix_len).collect();

        let suffix = from_base64(
            "Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRv\
             d24gc28gbXkgaGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvb\
             iBzdGFuZGJ5IHdhdmluZyBqdXN0IHRvIHNheSBoaQpEaWQgeW\
             91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUgYnkK",
        )?;

        Ok(Oracle14 {
            common: Common {
                key,
                prefix,
                suffix,
                mode: MODE::ECB,
            },
        })
    }
}

pub struct Oracle16 {
    common: Common,
}

impl Oracle for Oracle16 {
    fn encrypt(&self, u: &[u8]) -> Result<Vec<u8>, Error> {
        if u.iter().any(|&c| !c.is_ascii() || c == b';' || c == b'=') {
            panic!("Invalid input.");
        }

        self.common.encrypt(u)
    }

    fn verify_suffix(&self, candidate: &[u8]) -> Result<(), Error> {
        self.common.verify_suffix(candidate)
    }
}

impl Oracle16 {
    pub fn new() -> Result<Self, Error> {
        let key = random_block();

        let prefix = b"comment1=cooking%20MCs;userdata=".to_vec();
        let suffix = b";comment2=%20like%20a%20pound%20of%20bacon".to_vec();

        Ok(Oracle16 {
            common: Common {
                key,
                prefix,
                suffix,
                mode: MODE::CBC,
            },
        })
    }

    pub fn verify_solution(&self, ciphertext: &[u8]) -> Result<(), Error> {
        // The flipped next to last block will decrypt to arbitrary cleartext. Depending on the
        // precise implementation of decode_profile, this might cause problems, because this
        // cleartext could for example contain `;foo;`, or `foo=bar=baz`. For now we rely on
        // the fact that decode_profile accepts such inputs.

        compare_eq(
            Some(b"true".as_ref()),
            decode_profile(
                &ciphertext.decrypt(&self.common.key, Some(&[0; BLOCK_SIZE]), MODE::CBC)?,
                b';',
            ).remove(b"admin".as_ref()),
        )
    }
}

pub struct Oracle26 {
    common: Common,
}

impl DeterministicOracle for Oracle26 {}

impl Oracle for Oracle26 {
    fn encrypt(&self, u: &[u8]) -> Result<Vec<u8>, Error> {
        if u.iter().any(|&c| !c.is_ascii() || c == b';' || c == b'=') {
            panic!("Invalid input.");
        }

        self.common.encrypt(u)
    }

    fn verify_suffix(&self, candidate: &[u8]) -> Result<(), Error> {
        self.common.verify_suffix(candidate)
    }
}

impl Oracle26 {
    pub fn new() -> Result<Self, Error> {
        let key = random_block();

        let prefix = b"comment1=cooking%20MCs;userdata=".to_vec();
        let suffix = b";comment2=%20like%20a%20pound%20of%20bacon".to_vec();

        Ok(Oracle26 {
            common: Common {
                key,
                prefix,
                suffix,
                mode: MODE::CTR,
            },
        })
    }

    pub fn verify_solution(&self, ciphertext: &[u8]) -> Result<(), Error> {
        compare_eq(
            Some(b"true".as_ref()),
            decode_profile(
                &ciphertext.decrypt(&self.common.key, None, MODE::CTR)?,
                b';',
            ).remove(b"admin".as_ref()),
        )
    }
}

#[cfg(test)]
mod tests {
    use aes::MODE;
    use failure::Error;

    use super::*;
    use set2::{prefix_length, random_block, suffix_length};

    struct TestOracle {
        common: Common,
    }

    impl DeterministicOracle for TestOracle {}

    impl Oracle for TestOracle {
        fn encrypt(&self, u: &[u8]) -> Result<Vec<u8>, Error> {
            self.common.encrypt(u)
        }

        fn verify_suffix(&self, candidate: &[u8]) -> Result<(), Error> {
            self.common.verify_suffix(candidate)
        }
    }

    impl TestOracle {
        pub fn new(
            key: Vec<u8>,
            prefix: Vec<u8>,
            suffix: Vec<u8>,
            mode: MODE,
        ) -> Result<Self, Error> {
            assert!(mode == MODE::ECB || mode == MODE::CTR);
            Ok(TestOracle {
                common: Common {
                    key,
                    prefix,
                    suffix,
                    mode,
                },
            })
        }
    }

    #[test]
    fn test_length_functions() {
        let key = random_block();
        let mut prefix = Vec::new();
        let mut suffix = Vec::new();
        for i in 0..=1 {
            let mode = if i == 0 { MODE::ECB } else { MODE::CTR };
            for _ in 0..64 {
                for _ in 0..64 {
                    {
                        let oracle =
                            TestOracle::new(key.clone(), prefix.clone(), suffix.clone(), mode)
                                .ok()
                                .unwrap();

                        println!("{}", prefix.len());
                        println!("{}", prefix_length(&oracle).unwrap());
                        assert!(prefix.len() == prefix_length(&oracle).unwrap());
                        assert!(suffix.len() == suffix_length(&oracle).unwrap());
                    }
                    suffix.push(1);
                }
                suffix.clear();
                prefix.push(0);
            }
        }
    }
}
<commit_msg>Minor<commit_after>use rand;
use rand::Rng;

use aes::BLOCK_SIZE;
use aes::{Aes128, MODE};

use serialize::from_base64;

use errors::*;
use failure::Error;

use set2::decode_profile;
use set2::random_block;

pub trait Oracle {
    fn encrypt(&self, u: &[u8]) -> Result<Vec<u8>, Error>;
    fn verify_suffix(&self, candidate: &[u8]) -> Result<(), Error>;
}

// Marker trait for oracles where repeated calls to
// `encrypt` for the same `u` produce the same result.
// This excludes oracles in CBC mode with random iv.
pub trait DeterministicOracle: Oracle {}

struct Common {
    key: Vec<u8>,
    prefix: Vec<u8>,
    suffix: Vec<u8>,
    mode: MODE,
}

impl Oracle for Common {
    fn encrypt(&self, u: &[u8]) -> Result<Vec<u8>, Error> {
        let key = &self.key;
        let prefix = &self.prefix;
        let suffix = &self.suffix;
        let mode = self.mode;

        let mut cleartext = Vec::with_capacity(prefix.len() + u.len() + suffix.len());
        cleartext.extend_from_slice(prefix);
        cleartext.extend_from_slice(u);
        cleartext.extend_from_slice(suffix);

        match mode {
            MODE::CBC => {
                // We would normally also return iv, but our callers do not need it
                let iv = random_block();
                cleartext.encrypt(key, Some(&iv), mode)
            }
            _ => cleartext.encrypt(key, None, mode),
        }
    }

    fn verify_suffix(&self, candidate: &[u8]) -> Result<(), Error> {
        compare_eq(&self.suffix[..], candidate)
    }
}

pub struct Oracle11 {
    common: Common,
    already_called: bool,
}

impl Oracle11 {
    pub fn new() -> Result<Self, Error> {
        let mut rng = rand::thread_rng();
        let key = random_block();
        let prefix_len = rng.gen_range(5, 11);
        let prefix: Vec<u8> = rng.gen_iter().take(prefix_len).collect();
        let suffix_len = rng.gen_range(5, 11);
        let suffix: Vec<u8> = rng.gen_iter().take(suffix_len).collect();

        let use_ecb = rng.gen();
        let mode = if use_ecb { MODE::ECB } else { MODE::CBC };

        Ok(Oracle11 {
            common: Common {
                key,
                prefix,
                suffix,
                mode,
            },
            already_called: false,
        })
    }

    pub fn encrypt(&mut self, u: &[u8]) -> Result<Vec<u8>, Error> {
        if self.already_called {
            bail!("Method has already been called. Please generate a fresh oracle.");
        }

        self.already_called = true;
        self.common.encrypt(u)
    }

    pub fn verify_solution(&self, uses_ecb: bool) -> Result<(), Error> {
        compare_eq(self.common.mode == MODE::ECB, uses_ecb)
    }
}

pub struct Oracle12 {
    common: Common,
}

impl DeterministicOracle for Oracle12 {}

impl Oracle for Oracle12 {
    fn encrypt(&self, u: &[u8]) -> Result<Vec<u8>, Error> {
        self.common.encrypt(u)
    }

    fn verify_suffix(&self, candidate: &[u8]) -> Result<(), Error> {
        self.common.verify_suffix(candidate)
    }
}

impl Oracle12 {
    pub fn new() -> Result<Self, Error> {
        let key = random_block();

        let suffix = from_base64(
            "Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRv\
             d24gc28gbXkgaGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvb\
             iBzdGFuZGJ5IHdhdmluZyBqdXN0IHRvIHNheSBoaQpEaWQgeW\
             91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUgYnkK",
        )?;

        Ok(Oracle12 {
            common: Common {
                key,
                prefix: Vec::new(),
                suffix,
                mode: MODE::ECB,
            },
        })
    }
}

pub struct Oracle13 {
    common: Common,
}

impl DeterministicOracle for Oracle13 {}

impl Oracle for Oracle13 {
    fn encrypt(&self, u: &[u8]) -> Result<Vec<u8>, Error> {
        if u.iter().any(|&c| !c.is_ascii() || c == b'&' || c == b'=') {
            panic!("Invalid input.");
        }

        self.common.encrypt(u)
    }

    fn verify_suffix(&self, candidate: &[u8]) -> Result<(), Error> {
        self.common.verify_suffix(candidate)
    }
}

impl Oracle13 {
    pub fn new() -> Result<Self, Error> {
        let key = random_block();

        let prefix = b"email=".to_vec();
        let suffix = b"&uid=10&role=user".to_vec();

        Ok(Oracle13 {
            common: Common {
                key,
                prefix,
                suffix,
                mode: MODE::ECB,
            },
        })
    }

    pub fn verify_solution(&self, ciphertext: &[u8]) -> Result<(), Error> {
        compare_eq(
            Some(b"admin".as_ref()),
            decode_profile(
                &ciphertext.decrypt(&self.common.key, None, MODE::ECB)?,
                b'&',
            ).remove(b"role".as_ref()),
        )
    }
}

pub struct Oracle14 {
    common: Common,
}

impl DeterministicOracle for Oracle14 {}

impl Oracle for Oracle14 {
    fn encrypt(&self, u: &[u8]) -> Result<Vec<u8>, Error> {
        self.common.encrypt(u)
    }

    fn verify_suffix(&self, candidate: &[u8]) -> Result<(), Error> {
        self.common.verify_suffix(candidate)
    }
}

impl Oracle14 {
    pub fn new() -> Result<Self, Error> {
        let mut rng = rand::thread_rng();
        let key: Vec<u8> = rng.gen_iter().take(BLOCK_SIZE).collect();
        let prefix_len = rng.gen_range(1, 200);
        let prefix: Vec<u8> = rng.gen_iter().take(prefix_len).collect();

        let suffix = from_base64(
            "Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRv\
             d24gc28gbXkgaGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvb\
             iBzdGFuZGJ5IHdhdmluZyBqdXN0IHRvIHNheSBoaQpEaWQgeW\
             91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUgYnkK",
        )?;

        Ok(Oracle14 {
            common: Common {
                key,
                prefix,
                suffix,
                mode: MODE::ECB,
            },
        })
    }
}

pub struct Oracle16 {
    common: Common,
}

impl Oracle for Oracle16 {
    fn encrypt(&self, u: &[u8]) -> Result<Vec<u8>, Error> {
        if u.iter().any(|&c| !c.is_ascii() || c == b';' || c == b'=') {
            panic!("Invalid input.");
        }

        self.common.encrypt(u)
    }

    fn verify_suffix(&self, candidate: &[u8]) -> Result<(), Error> {
        self.common.verify_suffix(candidate)
    }
}

impl Oracle16 {
    pub fn new() -> Result<Self, Error> {
        let key = random_block();

        let prefix = b"comment1=cooking%20MCs;userdata=".to_vec();
        let suffix = b";comment2=%20like%20a%20pound%20of%20bacon".to_vec();

        Ok(Oracle16 {
            common: Common {
                key,
                prefix,
                suffix,
                mode: MODE::CBC,
            },
        })
    }

    pub fn verify_solution(&self, ciphertext: &[u8]) -> Result<(), Error> {
        // The flipped next to last block will decrypt to arbitrary cleartext. Depending on the
        // precise implementation of decode_profile, this might cause problems, because this
        // cleartext could for example contain `;foo;`, or `foo=bar=baz`. For now we rely on
        // the fact that decode_profile accepts such inputs.

        compare_eq(
            Some(b"true".as_ref()),
            decode_profile(
                &ciphertext.decrypt(&self.common.key, Some(&[0; BLOCK_SIZE]), MODE::CBC)?,
                b';',
            ).remove(b"admin".as_ref()),
        )
    }
}

pub struct Oracle26 {
    common: Common,
}

impl DeterministicOracle for Oracle26 {}

impl Oracle for Oracle26 {
    fn encrypt(&self, u: &[u8]) -> Result<Vec<u8>, Error> {
        if u.iter().any(|&c| !c.is_ascii() || c == b';' || c == b'=') {
            panic!("Invalid input.");
        }

        self.common.encrypt(u)
    }

    fn verify_suffix(&self, candidate: &[u8]) -> Result<(), Error> {
        self.common.verify_suffix(candidate)
    }
}

impl Oracle26 {
    pub fn new() -> Result<Self, Error> {
        let key = random_block();

        let prefix = b"comment1=cooking%20MCs;userdata=".to_vec();
        let suffix = b";comment2=%20like%20a%20pound%20of%20bacon".to_vec();

        Ok(Oracle26 {
            common: Common {
                key,
                prefix,
                suffix,
                mode: MODE::CTR,
            },
        })
    }

    pub fn verify_solution(&self, ciphertext: &[u8]) -> Result<(), Error> {
        compare_eq(
            Some(b"true".as_ref()),
            decode_profile(
                &ciphertext.decrypt(&self.common.key, None, MODE::CTR)?,
                b';',
            ).remove(b"admin".as_ref()),
        )
    }
}

#[cfg(test)]
mod tests {
    use aes::MODE;
    use failure::Error;

    use super::*;
    use set2::{prefix_length, random_block, suffix_length};

    struct TestOracle {
        common: Common,
    }

    impl DeterministicOracle for TestOracle {}

    impl Oracle for TestOracle {
        fn encrypt(&self, u: &[u8]) -> Result<Vec<u8>, Error> {
            self.common.encrypt(u)
        }

        fn verify_suffix(&self, candidate: &[u8]) -> Result<(), Error> {
            self.common.verify_suffix(candidate)
        }
    }

    impl TestOracle {
        pub fn new(
            key: Vec<u8>,
            prefix: Vec<u8>,
            suffix: Vec<u8>,
            mode: MODE,
        ) -> Result<Self, Error> {
            assert!(mode == MODE::ECB || mode == MODE::CTR);
            Ok(TestOracle {
                common: Common {
                    key,
                    prefix,
                    suffix,
                    mode,
                },
            })
        }
    }

    #[test]
    fn test_length_functions() {
        let key = random_block();
        let mut prefix = Vec::new();
        let mut suffix = Vec::new();
        for i in 0..=1 {
            let mode = if i == 0 { MODE::ECB } else { MODE::CTR };
            for _ in 0..64 {
                for _ in 0..64 {
                    let oracle =
                        TestOracle::new(key.clone(), prefix.clone(), suffix.clone(), mode)
                        .ok()
                        .unwrap();

                    assert!(prefix.len() == prefix_length(&oracle).unwrap());
                    assert!(suffix.len() == suffix_length(&oracle).unwrap());
                    suffix.push(1);
                }
                suffix.clear();
                prefix.push(0);
            }
            suffix.clear();
            prefix.clear();
        }
    }
}
<|endoftext|>


<commit_before>mod entryline;
mod displayarea;
mod window;

use std;
use std::sync::mpsc::Receiver;

use ncurses::*;

use irc::client::prelude::*;

use self::entryline::EntryLine;
use self::displayarea::DisplayArea;
use self::window::{Windows, Window};

pub type MessageReceiver = Receiver<std::io::Result<Message>>;

pub struct Tui {
    entry_line: EntryLine,
    message_rx: MessageReceiver,
    server: IrcServer,
    windows: Windows,
    running: bool,
}

impl Drop for Tui {
    fn drop(&mut self) {
        endwin();
    }
}

impl Tui {
    pub fn new(message_rx: MessageReceiver, server: IrcServer) -> Tui {
        setlocale(LcCategory::all, "");
        initscr();
        keypad(stdscr, true);
        raw();
        noecho();
        nonl();
        start_color();
        timeout(50);
        let entry_line = EntryLine::new();
        Tui {
            entry_line: entry_line,
            message_rx: message_rx,
            server: server.clone(),
            windows: Windows::new(server),
            running: true,
        }
    }

    pub fn event_loop(&mut self) {
        'main_loop:
        loop {
            if let Some(ch) = get_wch() {
                if let Some(line) = self.entry_line.key_input(ch) {
                    self.handle_line(line);
                }
            }
            if !self.running { break; }
            loop {
                use std::sync::mpsc::TryRecvError::*;
                match self.message_rx.try_recv() {
                    Ok(message) => self.windows.handle_message(message.unwrap()),
                    Err(Empty) => break,
                    Err(Disconnected) => break 'main_loop,
                }
            }
            self.windows.draw();
            self.entry_line.draw();
            doupdate();
        }
    }

    fn handle_line(&mut self, line: String) {
        if line.len() == 0 {
            return;
        }
        if line.chars().nth(0) == Some('/') {
            let mut line = line[1..].splitn(1, ' ');
            let command = line.next().unwrap_or("");
            let body = line.next().unwrap_or("");
            self.handle_command(command, body);
            return;
        }
        if let Some(target) = self.windows.current_target() {
            self.server.send_privmsg(target.name(), &line);
        } else {
            // TODO: Show error
        }
    }

    fn handle_command(&mut self, command: &str, body: &str) {
        match command {
            "join" => self.server.send_join(body).unwrap(),
            "part" => {
                if let Some(name) = self.windows.current_channel() {
                    self.server.send(Command::PART(String::from(name), Some(String::from(body)))).unwrap();
                }
            },
            "quit" => self.server.send_quit(body).unwrap(),
            "win" | "w" => {
                if let Some(number) = body.parse::<usize>().ok() {
                    self.windows.change_to(number);
                }
            }
            _ => {} // TODO: Handle unknown command
        }
    }
}
<commit_msg>Shut down user interface straight away on quit.<commit_after>mod entryline;
mod displayarea;
mod window;

use std;
use std::sync::mpsc::Receiver;

use ncurses::*;

use irc::client::prelude::*;

use self::entryline::EntryLine;
use self::displayarea::DisplayArea;
use self::window::{Windows, Window};

pub type MessageReceiver = Receiver<std::io::Result<Message>>;

pub struct Tui {
    entry_line: EntryLine,
    message_rx: MessageReceiver,
    server: IrcServer,
    windows: Windows,
    running: bool,
}

impl Drop for Tui {
    fn drop(&mut self) {
        endwin();
    }
}

impl Tui {
    pub fn new(message_rx: MessageReceiver, server: IrcServer) -> Tui {
        setlocale(LcCategory::all, "");
        initscr();
        keypad(stdscr, true);
        raw();
        noecho();
        nonl();
        start_color();
        timeout(50);
        let entry_line = EntryLine::new();
        Tui {
            entry_line: entry_line,
            message_rx: message_rx,
            server: server.clone(),
            windows: Windows::new(server),
            running: true,
        }
    }

    pub fn event_loop(&mut self) {
        'main_loop:
        loop {
            if let Some(ch) = get_wch() {
                if let Some(line) = self.entry_line.key_input(ch) {
                    self.handle_line(line);
                }
            }
            if !self.running { break; }
            loop {
                use std::sync::mpsc::TryRecvError::*;
                match self.message_rx.try_recv() {
                    Ok(message) => self.windows.handle_message(message.unwrap()),
                    Err(Empty) => break,
                    Err(Disconnected) => break 'main_loop,
                }
            }
            self.windows.draw();
            self.entry_line.draw();
            doupdate();
        }
    }

    fn handle_line(&mut self, line: String) {
        if line.len() == 0 {
            return;
        }
        if line.chars().nth(0) == Some('/') {
            let mut line = line[1..].splitn(1, ' ');
            let command = line.next().unwrap_or("");
            let body = line.next().unwrap_or("");
            self.handle_command(command, body);
            return;
        }
        if let Some(target) = self.windows.current_target() {
            self.server.send_privmsg(target.name(), &line);
        } else {
            // TODO: Show error
        }
    }

    fn handle_command(&mut self, command: &str, body: &str) {
        match command {
            "join" => self.server.send_join(body).unwrap(),
            "part" => {
                if let Some(name) = self.windows.current_channel() {
                    self.server.send(Command::PART(String::from(name), Some(String::from(body)))).unwrap();
                }
            },
            "quit" => {
                self.server.send_quit(body).unwrap();
                self.running = false;
            },
            "win" | "w" => {
                if let Some(number) = body.parse::<usize>().ok() {
                    self.windows.change_to(number);
                }
            }
            _ => {} // TODO: Handle unknown command
        }
    }
}
<|endoftext|>


<commit_before>pub mod client;
pub mod lsm;
pub mod sm;
mod trees;

#[cfg(test)]
mod tests {
    use super::lsm::btree::storage;
    use super::lsm::btree::Ordering;
    use super::*;
    use crate::client::*;
    use crate::index::ranged::lsm::btree;
    use crate::index::EntryKey;
    use crate::ram::schema::*;
    use crate::ram::types::Id;
    use crate::server::*;
    use dovahkiin::types::Type;
    use futures::stream::FuturesUnordered;
    use itertools::Itertools;
    use rand::seq::SliceRandom;
    use std::sync::Arc;
    use std::time::Duration;
    use tokio_stream::StreamExt;

    // #[ignore]
    #[tokio::test(flavor = "multi_thread")]
    async fn general() {
        let _ = env_logger::try_init();
        let server_group = "ranged_index_test";
        let server_addr = String::from("127.0.0.1:5711");
        let server = NebServer::new_from_opts(
            &ServerOptions {
                chunk_count: 1,
                memory_size: 32 * 1024 * 1024 * 1024, // G
                backup_storage: None,
                wal_storage: None,
                index_enabled: false, // We don't use the high level index builder here
                services: vec![Service::Cell, Service::RangedIndexer],
            },
            &server_addr,
            server_group,
        )
        .await;
        let client = Arc::new(
            AsyncClient::new(
                &server.rpc,
                &server.membership,
                &vec![server_addr],
                server_group,
            )
            .await
            .unwrap(),
        );
        let index_client = Arc::new(client::RangedQueryClient::new(
            &server.consh,
            &server.raft_client,
        ));
        info!("Tree stat {:?}", index_client.tree_stats().await.unwrap());
        client.new_schema_with_id(schema()).await.unwrap().unwrap();
        let test_capacity = btree::ideal_capacity_from_node_size(btree::level::LEVEL_1) * 3;
        let mut futs = FuturesUnordered::new();
        info!(
            "Testing ranged indexer preesure test with {} items",
            test_capacity
        );
        info!("Generating test set");
        let mut rng = rand::thread_rng();
        let nums = (0..test_capacity).collect_vec();
        let mut nums_2 = nums.clone();
        let mut nums_3 = nums.clone();
        nums_2.as_mut_slice().shuffle(&mut rng);
        nums_3.as_mut_slice().shuffle(&mut rng);
        info!("Adding insertion tasks");
        for i in nums_2 {
            let index_client = index_client.clone();
            futs.push(tokio::spawn(async move {
                let id = Id::new(1, i as u64);
                let key = EntryKey::from_id(&id);
                index_client.insert(&key).await
            }));
        }
        info!("All tasks queued, waiting for finish");
        while let Some(result) = futs.next().await {
            assert!(result.unwrap().unwrap(), "Insertion return false");
        }
        info!("All keys inserted. The background task should merging trees. Doing searches.");
        let mut futs = FuturesUnordered::new();
        for (i, num) in nums_3.into_iter().enumerate() {
            let index_client = index_client.clone();
            futs.push(tokio::spawn(async move {
                trace!("Seeking Id at {}, index {}", num, i);
                let id = Id::new(1, num as u64);
                let key = EntryKey::from_id(&id);
                let rt_cursor =
                    client::RangedQueryClient::seek(&index_client, &key, Ordering::Forward, 1)
                        .await
                        .unwrap()
                        .unwrap();
                assert_eq!(&id, rt_cursor.current().unwrap(), "at {}", i);
                trace!("Id at {}, index {} have been checked", num, i);
            }));
        }
        while let Some(_) = futs.next().await {}
        debug!("Selection check pased, waiting for 10 secs");
        tokio::time::sleep(Duration::from_secs(10)).await;
        info!("Waiting tree storage");
        storage::wait_until_updated().await;
        info!(
            "Total cells {}, Tree stat {:?}",
            client.count().await.unwrap(),
            index_client.tree_stats().await.unwrap()
        );
        info!("Scanning forward...");
        let start_id = Id::new(1, 0);
        let mut rt_cursor = client::RangedQueryClient::seek(
            &index_client,
            &EntryKey::from_id(&start_id),
            Ordering::Forward,
            128,
        )
        .await
        .unwrap()
        .unwrap();
        assert_eq!(rt_cursor.current(), Some(&start_id));
        for (i, num) in nums.iter().enumerate() {
            let id = Id::new(1, *num as u64);
            let current = rt_cursor.current().expect(&format!("Checking {}", num));
            assert_eq!(
                &id,
                current,
                "Expecting {:?}, key {:?}, got {:?}, list index {}, cursor ids {:?}, cursor pos {:?}",
                id,
                EntryKey::from_id(&id),
                current,
                i,
                rt_cursor.ids,
                rt_cursor.pos
            );
            let _ = rt_cursor.next().await.unwrap();
            if num % (test_capacity / 128) == 0 {
                debug!("Scanned {} of {}", num, test_capacity);
            }
        }
        info!("Scan finished");
        let end_of_list = rt_cursor.next().await.unwrap();
        assert!(
            end_of_list.is_none(),
            "End of the list have id {:?}",
            end_of_list.unwrap()
        );
        assert!(
            end_of_list.is_none(),
            "After end of the list have id {:?}",
            end_of_list.unwrap()
        );
        debug!("All check pased, waiting for 10 secs for statistics");
        tokio::time::sleep(Duration::from_secs(10)).await;
        info!(
            "Total cells {}, Tree stat {:?}",
            client.count().await.unwrap(),
            index_client.tree_stats().await.unwrap()
        );
    }

    fn schema() -> Schema {
        Schema::new_with_id(
            11,
            &String::from("test"),
            None,
            Field::new(
                "*",
                Type::Id,
                false,
                false,
                Some(vec![Field::new(
                    "data",
                    Type::U8,
                    false,
                    false,
                    None,
                    vec![],
                )]),
                vec![],
            ),
            false,
            false,
        )
    }
}
<commit_msg>set timeout for btree test<commit_after>pub mod client;
pub mod lsm;
pub mod sm;
mod trees;

#[cfg(test)]
mod tests {
    use super::lsm::btree::storage;
    use super::lsm::btree::Ordering;
    use super::*;
    use crate::client::*;
    use crate::index::ranged::lsm::btree;
    use crate::index::EntryKey;
    use crate::ram::schema::*;
    use crate::ram::types::Id;
    use crate::server::*;
    use dovahkiin::types::Type;
    use futures::stream::FuturesUnordered;
    use itertools::Itertools;
    use rand::seq::SliceRandom;
    use std::sync::Arc;
    use std::time::Duration;
    use tokio_stream::StreamExt;

    // #[ignore]
    #[tokio::test(flavor = "multi_thread")]
    async fn general() {
        let _ = env_logger::try_init();
        let server_group = "ranged_index_test";
        let server_addr = String::from("127.0.0.1:5711");
        let server = NebServer::new_from_opts(
            &ServerOptions {
                chunk_count: 1,
                memory_size: 32 * 1024 * 1024 * 1024, // G
                backup_storage: None,
                wal_storage: None,
                index_enabled: false, // We don't use the high level index builder here
                services: vec![Service::Cell, Service::RangedIndexer],
            },
            &server_addr,
            server_group,
        )
        .await;
        let client = Arc::new(
            AsyncClient::new(
                &server.rpc,
                &server.membership,
                &vec![server_addr],
                server_group,
            )
            .await
            .unwrap(),
        );
        let index_client = Arc::new(client::RangedQueryClient::new(
            &server.consh,
            &server.raft_client,
        ));
        info!("Tree stat {:?}", index_client.tree_stats().await.unwrap());
        client.new_schema_with_id(schema()).await.unwrap().unwrap();
        let test_capacity = btree::ideal_capacity_from_node_size(btree::level::LEVEL_1) * 3;
        let mut futs = FuturesUnordered::new();
        info!(
            "Testing ranged indexer preesure test with {} items",
            test_capacity
        );
        info!("Generating test set");
        let mut rng = rand::thread_rng();
        let nums = (0..test_capacity).collect_vec();
        let mut nums_2 = nums.clone();
        let mut nums_3 = nums.clone();
        nums_2.as_mut_slice().shuffle(&mut rng);
        nums_3.as_mut_slice().shuffle(&mut rng);
        info!("Adding insertion tasks");
        for i in nums_2 {
            let index_client = index_client.clone();
            futs.push(tokio::time::timeout(
                Duration::from_secs(240),
                tokio::spawn(async move {
                    let id = Id::new(1, i as u64);
                    let key = EntryKey::from_id(&id);
                    index_client.insert(&key).await
                }),
            ));
        }
        info!("All tasks queued, waiting for finish");
        while let Some(result) = futs.next().await {
            assert!(result.unwrap().unwrap().unwrap(), "Insertion return false");
        }
        info!("All keys inserted. The background task should merging trees. Doing searches.");
        let mut futs = FuturesUnordered::new();
        for (i, num) in nums_3.into_iter().enumerate() {
            let index_client = index_client.clone();
            futs.push(tokio::spawn(async move {
                trace!("Seeking Id at {}, index {}", num, i);
                let id = Id::new(1, num as u64);
                let key = EntryKey::from_id(&id);
                let rt_cursor =
                    client::RangedQueryClient::seek(&index_client, &key, Ordering::Forward, 1)
                        .await
                        .unwrap()
                        .unwrap();
                assert_eq!(&id, rt_cursor.current().unwrap(), "at {}", i);
                trace!("Id at {}, index {} have been checked", num, i);
            }));
        }
        while let Some(_) = futs.next().await {}
        debug!("Selection check pased, waiting for 10 secs");
        tokio::time::sleep(Duration::from_secs(10)).await;
        info!("Waiting tree storage");
        storage::wait_until_updated().await;
        info!(
            "Total cells {}, Tree stat {:?}",
            client.count().await.unwrap(),
            index_client.tree_stats().await.unwrap()
        );
        info!("Scanning forward...");
        let start_id = Id::new(1, 0);
        let mut rt_cursor = client::RangedQueryClient::seek(
            &index_client,
            &EntryKey::from_id(&start_id),
            Ordering::Forward,
            128,
        )
        .await
        .unwrap()
        .unwrap();
        assert_eq!(rt_cursor.current(), Some(&start_id));
        for (i, num) in nums.iter().enumerate() {
            let id = Id::new(1, *num as u64);
            let current = rt_cursor.current().expect(&format!("Checking {}", num));
            assert_eq!(
                &id,
                current,
                "Expecting {:?}, key {:?}, got {:?}, list index {}, cursor ids {:?}, cursor pos {:?}",
                id,
                EntryKey::from_id(&id),
                current,
                i,
                rt_cursor.ids,
                rt_cursor.pos
            );
            let _ = rt_cursor.next().await.unwrap();
            if num % (test_capacity / 128) == 0 {
                debug!("Scanned {} of {}", num, test_capacity);
            }
        }
        info!("Scan finished");
        let end_of_list = rt_cursor.next().await.unwrap();
        assert!(
            end_of_list.is_none(),
            "End of the list have id {:?}",
            end_of_list.unwrap()
        );
        assert!(
            end_of_list.is_none(),
            "After end of the list have id {:?}",
            end_of_list.unwrap()
        );
        debug!("All check pased, waiting for 10 secs for statistics");
        tokio::time::sleep(Duration::from_secs(10)).await;
        info!(
            "Total cells {}, Tree stat {:?}",
            client.count().await.unwrap(),
            index_client.tree_stats().await.unwrap()
        );
    }

    fn schema() -> Schema {
        Schema::new_with_id(
            11,
            &String::from("test"),
            None,
            Field::new(
                "*",
                Type::Id,
                false,
                false,
                Some(vec![Field::new(
                    "data",
                    Type::U8,
                    false,
                    false,
                    None,
                    vec![],
                )]),
                vec![],
            ),
            false,
            false,
        )
    }
}
<|endoftext|>


<commit_before>use cell_gc::{GcHeapSession, GcLeaf};
use cell_gc::collections::VecRef;
use compile;
use std::borrow::Borrow;
use std::fmt;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use std::collections::HashSet;
use vm::{EnvironmentRef, Trampoline};

#[derive(Debug, IntoHeap)]
pub struct Pair<'h> {
    pub car: Value<'h>,
    pub cdr: Value<'h>,
}

#[derive(Clone, Debug, PartialEq, IntoHeap)]
pub enum Value<'h> {
    Nil,
    Bool(bool),
    Int(i32),
    Char(char),
    Symbol(GcLeaf<InternedString>),
    ImmString(GcLeaf<InternedString>),
    Lambda(PairRef<'h>),
    Code(compile::CodeRef<'h>),
    Builtin(GcLeaf<BuiltinFnPtr>),
    Cons(PairRef<'h>),
    Vector(VecRef<'h, Value<'h>>),
    Environment(EnvironmentRef<'h>),
}

pub use self::Value::*;

pub type BuiltinFn =
    for<'b> fn(&mut GcHeapSession<'b>, Vec<Value<'b>>)
        -> Result<Trampoline<'b>, String>;

pub struct BuiltinFnPtr(pub BuiltinFn);

// This can't be #[derive]d because function pointers aren't Clone.
// But they are Copy. A very weird thing about Rust.
impl Clone for BuiltinFnPtr {
    fn clone(&self) -> BuiltinFnPtr {
        BuiltinFnPtr(self.0)
    }
}

impl PartialEq for BuiltinFnPtr {
    fn eq(&self, other: &BuiltinFnPtr) -> bool {
        self.0 as usize == other.0 as usize
    }
}

impl fmt::Debug for BuiltinFnPtr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "BuiltinFn({:p})", self.0 as usize as *mut ())?;
        Ok(())
    }
}

impl<'h> fmt::Display for Value<'h> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // Note that this will need to add a set of already-printed pairs if we add
        // `set-car!` and/or `set-cdr!` and introduce the possibility of cycles.
        match *self {
            Nil => write!(f, "()"),
            Bool(true) => write!(f, "#t"),
            Bool(false) => write!(f, "#f"),
            Char(c) => write!(f, "#\\{}", c),
            Int(n) => write!(f, "{}", n),
            Symbol(ref s) => write!(f, "{}", s.as_str()),
            ImmString(ref s) => write!(f, "{:?}", s.as_str()),
            Lambda(_) => write!(f, "#lambda"),
            Code(_) => write!(f, "#code"),
            Builtin(_) => write!(f, "#builtin"),
            Cons(ref p) => {
                write!(f, "(")?;
                write_pair(f, p.clone())?;
                write!(f, ")")
            }
            Vector(ref v) => {
                write!(f, "#(")?;
                for i in 0..v.len() {
                    if i != 0 {
                        write!(f, " ")?;
                    }
                    write!(f, "{}", v.get(i))?;
                }
                write!(f, ")")
            }
            Environment(_) => write!(f, "#environment"),
        }
    }
}

fn write_pair<'h>(f: &mut fmt::Formatter, pair: PairRef<'h>) -> fmt::Result {
    write!(f, "{}", pair.car())?;
    match pair.cdr() {
        Nil => Ok(()),
        Cons(p) => {
            write!(f, " ")?;
            write_pair(f, p)
        }
        otherwise => {
            write!(f, " . ")?;
            write!(f, "{}", otherwise)
        }
    }
}

macro_rules! pattern_predicate {
    { $method:ident, $pat:pat } => {
        pub fn $method(&self) -> bool {
            match *self {
                $pat => true,
                _ => false
            }
        }
    }
}

impl<'h> Value<'h> {
    pattern_predicate!(is_nil, Nil);
    pattern_predicate!(is_boolean, Bool(_));

    /// True unless this value is `#f`. Conditional expressions (`if`, `cond`,
    /// etc.) should use this to check whether a value is a "true value".
    pub fn to_bool(&self) -> bool {
        match *self {
            Bool(false) => false,
            _ => true,
        }
    }

    pattern_predicate!(is_char, Char(_));

    pub fn as_char(self, error_msg: &str) -> Result<char, String> {
        match self {
            Char(c) => Ok(c),
            _ => Err(format!("{}: character required", error_msg))
        }
    }

    pattern_predicate!(is_number, Int(_));

    pub fn as_int(self, error_msg: &str) -> Result<i32, String> {
        match self {
            Int(i) => Ok(i),
            _ => Err(format!("{}: number required", error_msg)),
        }
    }

    pub fn as_index(self, error_msg: &str) -> Result<usize, String> {
        match self {
            Int(i) => {
                if i >= 0 {
                    Ok(i as usize)
                } else {
                    Err(format!("{}: negative vector index", error_msg))
                }
            }
            _ => Err(format!("{}: vector index required", error_msg)),
        }
    }

    pattern_predicate!(is_pair, Cons(_));

    pub fn as_pair(self, msg: &'static str) -> Result<(Value<'h>, Value<'h>), String> {
        match self {
            Cons(r) => Ok((r.car(), r.cdr())),
            _ => Err(msg.to_string()),
        }
    }

    pattern_predicate!(is_vector, Vector(_));

    pub fn as_vector(self, error_msg: &str) -> Result<VecRef<'h, Value<'h>>, String> {
        match self {
            Vector(v) => Ok(v),
            _ => Err(format!("{}: vector expected", error_msg)),
        }
    }

    pattern_predicate!(is_symbol, Symbol(_));

    pub fn as_symbol(self, error_msg: &str) -> Result<InternedString, String> {
        match self {
            Symbol(s) => Ok(s.unwrap()),
            _ => Err(error_msg.to_string()),
        }
    }

    pattern_predicate!(is_string, ImmString(_));

    pub fn as_string(self, error_msg: &str) -> Result<InternedString, String> {
        match self {
            ImmString(s) => Ok(s.unwrap()),
            _ => Err(error_msg.to_string()),
        }
    }

    pub fn is_procedure(&self) -> bool {
        match *self {
            Lambda(_) => true,
            Builtin(_) => true,
            _ => false,
        }
    }

    pub fn as_environment(self, error_msg: &str) -> Result<EnvironmentRef<'h>, String> {
        match self {
            Environment(env) => Ok(env),
            _ => Err(error_msg.to_string())
        }
    }
}

impl<'h> Iterator for Value<'h> {
    type Item = Result<Value<'h>, String>;

    fn next(&mut self) -> Option<Self::Item> {
        let (car, cdr) = match *self {
            Nil => return None,
            Cons(ref pair) => (pair.car(), pair.cdr()),
            _ => return Some(Err("improper list".into())),
        };
        *self = cdr;
        Some(Ok(car))
    }
}

#[derive(Clone, Debug)]
pub struct InternedString(Arc<String>);

// Note: If we ever impl Hash for InternedString, it will be better to use a
// custom pointer-based implementation than to use derive(Hash), which would
// hash the contents of the string.
impl PartialEq for InternedString {
    fn eq(&self, other: &InternedString) -> bool {
        Arc::ptr_eq(&self.0, &other.0)
    }
}

impl Eq for InternedString {}

lazy_static! {
    static ref STRINGS: Mutex<HashSet<InternedStringByValue>> = Mutex::new(HashSet::new());
}

static GENSYM_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;

#[derive(Eq, Hash, PartialEq)]
struct InternedStringByValue(Arc<String>);

impl Borrow<str> for InternedStringByValue {
    fn borrow(&self) -> &str {
        &self.0
    }
}

impl InternedString {
    /// Return an InternedString that is not interned.
    pub fn gensym() -> InternedString {
        let n = GENSYM_COUNT.fetch_add(1, Ordering::SeqCst);
        InternedString(Arc::new(format!("#<gensym{}>", n)))
    }

    pub fn get<T: AsRef<str> + Into<String>>(t: T) -> InternedString {
        let mut guard = STRINGS.lock().unwrap();
        if let Some(x) = guard.get(t.as_ref()) {
            return InternedString(x.0.clone());
        }
        let s = Arc::new(t.into());
        guard.insert(InternedStringByValue(s.clone()));
        InternedString(s)
    }

    pub fn really_intern(self) -> InternedString {
        if !self.0.starts_with("#<gensym") {
            return self;
        }
        let mut guard = STRINGS.lock().unwrap();
        {
            let s: &str = &self.0;
            match guard.get(s) {
                Some(interned) => return InternedString(interned.0.clone()),
                None => {}
            }
        }

        // Don't cause other references to this string to become interned!
        let new_arc = {
            let s: &str = &self.0;
            Arc::new(s.to_string())
        };
        guard.insert(InternedStringByValue(new_arc));
        self
    }

    pub fn as_str(&self) -> &str {
        &self.0
    }

    pub fn is_interned(&self) -> bool {
        let guard = STRINGS.lock().unwrap();
        let s: &str = &self.0;
        match guard.get(s) {
            None => false,
            Some(interned) => Arc::ptr_eq(&interned.0, &self.0)
        }
    }

    pub fn is_gensym(&self) -> bool { !self.is_interned() }
}

impl Borrow<str> for InternedString {
    fn borrow(&self) -> &str {
        self.as_str()
    }
}
<commit_msg>Derive `Hash` for `Value` and necessary super trait impls therein<commit_after>use cell_gc::{GcHeapSession, GcLeaf};
use cell_gc::collections::VecRef;
use compile;
use std::borrow::Borrow;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use std::collections::HashSet;
use vm::{EnvironmentRef, Trampoline};

#[derive(Debug, IntoHeap)]
pub struct Pair<'h> {
    pub car: Value<'h>,
    pub cdr: Value<'h>,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, IntoHeap)]
pub enum Value<'h> {
    Nil,
    Bool(bool),
    Int(i32),
    Char(char),
    Symbol(GcLeaf<InternedString>),
    ImmString(GcLeaf<InternedString>),
    Lambda(PairRef<'h>),
    Code(compile::CodeRef<'h>),
    Builtin(GcLeaf<BuiltinFnPtr>),
    Cons(PairRef<'h>),
    Vector(VecRef<'h, Value<'h>>),
    Environment(EnvironmentRef<'h>),
}

pub use self::Value::*;

pub type BuiltinFn =
    for<'b> fn(&mut GcHeapSession<'b>, Vec<Value<'b>>)
        -> Result<Trampoline<'b>, String>;

#[derive(Copy)]
pub struct BuiltinFnPtr(pub BuiltinFn);

// This can't be #[derive]d because function pointers aren't Clone.
// But they are Copy. A very weird thing about Rust.
impl Clone for BuiltinFnPtr {
    fn clone(&self) -> BuiltinFnPtr {
        BuiltinFnPtr(self.0)
    }
}

impl Hash for BuiltinFnPtr {
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.0.hash(state);
    }
}

impl PartialEq for BuiltinFnPtr {
    fn eq(&self, other: &BuiltinFnPtr) -> bool {
        self.0 as usize == other.0 as usize
    }
}

impl Eq for BuiltinFnPtr {}

impl fmt::Debug for BuiltinFnPtr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "BuiltinFn({:p})", self.0 as usize as *mut ())?;
        Ok(())
    }
}

impl<'h> fmt::Display for Value<'h> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // Note that this will need to add a set of already-printed pairs if we add
        // `set-car!` and/or `set-cdr!` and introduce the possibility of cycles.
        match *self {
            Nil => write!(f, "()"),
            Bool(true) => write!(f, "#t"),
            Bool(false) => write!(f, "#f"),
            Char(c) => write!(f, "#\\{}", c),
            Int(n) => write!(f, "{}", n),
            Symbol(ref s) => write!(f, "{}", s.as_str()),
            ImmString(ref s) => write!(f, "{:?}", s.as_str()),
            Lambda(_) => write!(f, "#lambda"),
            Code(_) => write!(f, "#code"),
            Builtin(_) => write!(f, "#builtin"),
            Cons(ref p) => {
                write!(f, "(")?;
                write_pair(f, p.clone())?;
                write!(f, ")")
            }
            Vector(ref v) => {
                write!(f, "#(")?;
                for i in 0..v.len() {
                    if i != 0 {
                        write!(f, " ")?;
                    }
                    write!(f, "{}", v.get(i))?;
                }
                write!(f, ")")
            }
            Environment(_) => write!(f, "#environment"),
        }
    }
}

fn write_pair<'h>(f: &mut fmt::Formatter, pair: PairRef<'h>) -> fmt::Result {
    write!(f, "{}", pair.car())?;
    match pair.cdr() {
        Nil => Ok(()),
        Cons(p) => {
            write!(f, " ")?;
            write_pair(f, p)
        }
        otherwise => {
            write!(f, " . ")?;
            write!(f, "{}", otherwise)
        }
    }
}

macro_rules! pattern_predicate {
    { $method:ident, $pat:pat } => {
        pub fn $method(&self) -> bool {
            match *self {
                $pat => true,
                _ => false
            }
        }
    }
}

impl<'h> Value<'h> {
    pattern_predicate!(is_nil, Nil);
    pattern_predicate!(is_boolean, Bool(_));

    /// True unless this value is `#f`. Conditional expressions (`if`, `cond`,
    /// etc.) should use this to check whether a value is a "true value".
    pub fn to_bool(&self) -> bool {
        match *self {
            Bool(false) => false,
            _ => true,
        }
    }

    pattern_predicate!(is_char, Char(_));

    pub fn as_char(self, error_msg: &str) -> Result<char, String> {
        match self {
            Char(c) => Ok(c),
            _ => Err(format!("{}: character required", error_msg))
        }
    }

    pattern_predicate!(is_number, Int(_));

    pub fn as_int(self, error_msg: &str) -> Result<i32, String> {
        match self {
            Int(i) => Ok(i),
            _ => Err(format!("{}: number required", error_msg)),
        }
    }

    pub fn as_index(self, error_msg: &str) -> Result<usize, String> {
        match self {
            Int(i) => {
                if i >= 0 {
                    Ok(i as usize)
                } else {
                    Err(format!("{}: negative vector index", error_msg))
                }
            }
            _ => Err(format!("{}: vector index required", error_msg)),
        }
    }

    pattern_predicate!(is_pair, Cons(_));

    pub fn as_pair(self, msg: &'static str) -> Result<(Value<'h>, Value<'h>), String> {
        match self {
            Cons(r) => Ok((r.car(), r.cdr())),
            _ => Err(msg.to_string()),
        }
    }

    pattern_predicate!(is_vector, Vector(_));

    pub fn as_vector(self, error_msg: &str) -> Result<VecRef<'h, Value<'h>>, String> {
        match self {
            Vector(v) => Ok(v),
            _ => Err(format!("{}: vector expected", error_msg)),
        }
    }

    pattern_predicate!(is_symbol, Symbol(_));

    pub fn as_symbol(self, error_msg: &str) -> Result<InternedString, String> {
        match self {
            Symbol(s) => Ok(s.unwrap()),
            _ => Err(error_msg.to_string()),
        }
    }

    pattern_predicate!(is_string, ImmString(_));

    pub fn as_string(self, error_msg: &str) -> Result<InternedString, String> {
        match self {
            ImmString(s) => Ok(s.unwrap()),
            _ => Err(error_msg.to_string()),
        }
    }

    pub fn is_procedure(&self) -> bool {
        match *self {
            Lambda(_) => true,
            Builtin(_) => true,
            _ => false,
        }
    }

    pub fn as_environment(self, error_msg: &str) -> Result<EnvironmentRef<'h>, String> {
        match self {
            Environment(env) => Ok(env),
            _ => Err(error_msg.to_string())
        }
    }
}

impl<'h> Iterator for Value<'h> {
    type Item = Result<Value<'h>, String>;

    fn next(&mut self) -> Option<Self::Item> {
        let (car, cdr) = match *self {
            Nil => return None,
            Cons(ref pair) => (pair.car(), pair.cdr()),
            _ => return Some(Err("improper list".into())),
        };
        *self = cdr;
        Some(Ok(car))
    }
}

#[derive(Clone, Debug)]
pub struct InternedString(Arc<String>);

// Note: If we ever impl Hash for InternedString, it will be better to use a
// custom pointer-based implementation than to use derive(Hash), which would
// hash the contents of the string.
impl PartialEq for InternedString {
    fn eq(&self, other: &InternedString) -> bool {
        Arc::ptr_eq(&self.0, &other.0)
    }
}

impl Eq for InternedString {}

impl Hash for InternedString {
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        let ptr: &str = &**self.0;
        let ptr = ptr as *const str;
        let ptr = ptr as *const ();
        let ptr = ptr as usize;
        ptr.hash(state);
    }
}

lazy_static! {
    static ref STRINGS: Mutex<HashSet<InternedStringByValue>> = Mutex::new(HashSet::new());
}

static GENSYM_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;

#[derive(Eq, Hash, PartialEq)]
struct InternedStringByValue(Arc<String>);

impl Borrow<str> for InternedStringByValue {
    fn borrow(&self) -> &str {
        &self.0
    }
}

impl InternedString {
    /// Return an InternedString that is not interned.
    pub fn gensym() -> InternedString {
        let n = GENSYM_COUNT.fetch_add(1, Ordering::SeqCst);
        InternedString(Arc::new(format!("#<gensym{}>", n)))
    }

    pub fn get<T: AsRef<str> + Into<String>>(t: T) -> InternedString {
        let mut guard = STRINGS.lock().unwrap();
        if let Some(x) = guard.get(t.as_ref()) {
            return InternedString(x.0.clone());
        }
        let s = Arc::new(t.into());
        guard.insert(InternedStringByValue(s.clone()));
        InternedString(s)
    }

    pub fn really_intern(self) -> InternedString {
        if !self.0.starts_with("#<gensym") {
            return self;
        }
        let mut guard = STRINGS.lock().unwrap();
        {
            let s: &str = &self.0;
            match guard.get(s) {
                Some(interned) => return InternedString(interned.0.clone()),
                None => {}
            }
        }

        // Don't cause other references to this string to become interned!
        let new_arc = {
            let s: &str = &self.0;
            Arc::new(s.to_string())
        };
        guard.insert(InternedStringByValue(new_arc));
        self
    }

    pub fn as_str(&self) -> &str {
        &self.0
    }

    pub fn is_interned(&self) -> bool {
        let guard = STRINGS.lock().unwrap();
        let s: &str = &self.0;
        match guard.get(s) {
            None => false,
            Some(interned) => Arc::ptr_eq(&interned.0, &self.0)
        }
    }

    pub fn is_gensym(&self) -> bool { !self.is_interned() }
}

impl Borrow<str> for InternedString {
    fn borrow(&self) -> &str {
        self.as_str()
    }
}
<|endoftext|>


<commit_before>use std::{ffi::{OsStr,OsString}, io, os::windows::ffi::OsStrExt, ptr};

use std::os::raw::c_int;
use windows_sys::Win32::UI::Shell::ShellExecuteW;

use crate::IntoResult;

fn convert_path(path: &OsStr) -> io::Result<Vec<u16>> {
    // Surround path with double quotes "" to handle spaces in path.
    let mut quoted_path = OsString::with_capacity(path.len());
    quoted_path.push("\"");
    quoted_path.push(&path);
    quoted_path.push("\"");

    let mut maybe_result: Vec<_> = quoted_path.encode_wide().collect();
    if maybe_result.iter().any(|&u| u == 0) {
        return Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            "path contains NUL byte(s)",
        ));
    }
    maybe_result.push(0);
    Ok(maybe_result)
}

pub fn that<T: AsRef<OsStr>>(path: T) -> io::Result<()> {
    const SW_SHOW: c_int = 5;

    let path = convert_path(path.as_ref())?;
    let operation: Vec<u16> = OsStr::new("open\0").encode_wide().collect();
    let result = unsafe {
        ShellExecuteW(
            0,
            operation.as_ptr(),
            path.as_ptr(),
            ptr::null(),
            ptr::null(),
            SW_SHOW,
        )
    };
    (result as c_int).into_result()
}

pub fn with<T: AsRef<OsStr>>(path: T, app: impl Into<String>) -> io::Result<()> {
    const SW_SHOW: c_int = 5;

    let path = convert_path(path.as_ref())?;
    let operation: Vec<u16> = OsStr::new("open\0").encode_wide().collect();
    let app_name: Vec<u16> = OsStr::new(&format!("{}\0", app.into()))
        .encode_wide()
        .collect();
    let result = unsafe {
        ShellExecuteW(
            0,
            operation.as_ptr(),
            app_name.as_ptr(),
            path.as_ptr(),
            ptr::null(),
            SW_SHOW,
        )
    };
    (result as c_int).into_result()
}
<commit_msg>refactor<commit_after>use std::{
    ffi::{OsStr, OsString},
    io,
    os::windows::ffi::OsStrExt,
    ptr,
};

use std::os::raw::c_int;
use windows_sys::Win32::UI::Shell::ShellExecuteW;

use crate::IntoResult;

fn convert_path(path: &OsStr) -> io::Result<Vec<u16>> {
    let mut quoted_path = OsString::with_capacity(path.len());

    // Surround path with double quotes "" to handle spaces in path.
    quoted_path.push("\"");
    quoted_path.push(&path);
    quoted_path.push("\"");

    let mut wide_chars: Vec<_> = quoted_path.encode_wide().collect();
    if wide_chars.iter().any(|&u| u == 0) {
        return Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            "path contains NUL byte(s)",
        ));
    }
    wide_chars.push(0);
    Ok(wide_chars)
}

pub fn that<T: AsRef<OsStr>>(path: T) -> io::Result<()> {
    const SW_SHOW: c_int = 5;

    let path = convert_path(path.as_ref())?;
    let operation: Vec<u16> = OsStr::new("open\0").encode_wide().collect();
    let result = unsafe {
        ShellExecuteW(
            0,
            operation.as_ptr(),
            path.as_ptr(),
            ptr::null(),
            ptr::null(),
            SW_SHOW,
        )
    };
    (result as c_int).into_result()
}

pub fn with<T: AsRef<OsStr>>(path: T, app: impl Into<String>) -> io::Result<()> {
    const SW_SHOW: c_int = 5;

    let path = convert_path(path.as_ref())?;
    let operation: Vec<u16> = OsStr::new("open\0").encode_wide().collect();
    let app_name: Vec<u16> = OsStr::new(&format!("{}\0", app.into()))
        .encode_wide()
        .collect();
    let result = unsafe {
        ShellExecuteW(
            0,
            operation.as_ptr(),
            app_name.as_ptr(),
            path.as_ptr(),
            ptr::null(),
            SW_SHOW,
        )
    };
    (result as c_int).into_result()
}
<|endoftext|>